Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

sqlite3odbc.c

Go to the documentation of this file.
00001 
00014 #if defined(SQLITE_HAS_CODEC) && defined(SQLITE_API)
00015 #undef WITH_SQLITE_DLLS
00016 #undef SQLITE_DYNLOAD
00017 #include "sqlite3.c"
00018 #endif
00019 
00020 #if defined(WITH_SQLITE_DLLS) && (WITH_SQLITE_DLLS > 1)
00021 #define SQLITE_DYNLOAD 1
00022 #undef  HAVE_SQLITE3CLOSEV2
00023 #endif
00024 
00025 #include "sqlite3odbc.h"
00026 
00027 #ifdef SQLITE_DYNLOAD
00028 
00029 #undef MEMORY_DEBUG
00030 
00031 #if defined(_WIN32) || defined(_WIN64)
00032 static void dls_init(void);
00033 static void dls_fini(void);
00034 #else
00035 void dls_init(void);
00036 void dls_fini(void);
00037 #endif
00038 
00039 static struct dl_sqlite3_funcs {
00040     void (*activate_see)(const char *p0);
00041     int (*bind_blob)(sqlite3_stmt *p0, int p1, const void *p2, int p3,
00042                      void (*p4)(void *));
00043     int (*bind_double)(sqlite3_stmt *p0, int p1, double p2);
00044     int (*bind_int)(sqlite3_stmt *p0, int p1, int p2);
00045     int (*bind_int64)(sqlite3_stmt *p0, int p1, sqlite_int64 p2);
00046     int (*bind_null)(sqlite3_stmt *p0, int p1);
00047     int (*bind_parameter_count)(sqlite3_stmt *p0);
00048     int (*bind_text)(sqlite3_stmt *p0, int p1, const char *p2, int p3,
00049                      void (*p4)(void *));
00050     int (*busy_handler)(sqlite3 *p0, int (*p2)(void *, int), void *p3);
00051     int (*changes)(sqlite3 *p0);
00052     int (*close)(sqlite3 *p0);
00053     const void * (*column_blob)(sqlite3_stmt *p0, int p1);
00054     int (*column_bytes)(sqlite3_stmt *p0, int p1);
00055     int (*column_count)(sqlite3_stmt *p0);
00056     const char * (*column_database_name)(sqlite3_stmt *p0, int p1);
00057     const char * (*column_decltype)(sqlite3_stmt *p0, int p1);
00058     double (*column_double)(sqlite3_stmt *p0, int p1);
00059     const char * (*column_name)(sqlite3_stmt *p0, int p1);
00060     const char * (*column_origin_name)(sqlite3_stmt *p0, int p1);
00061     const char * (*column_table_name)(sqlite3_stmt *p0, int p1);
00062     const unsigned char * (*column_text)(sqlite3_stmt *p0, int p1);
00063     int (*column_type)(sqlite3_stmt *p0, int p1);
00064     int (*create_function)(sqlite3 *p0, const char *p1, int p2, int p3,
00065                            void *p4,
00066                            void (*p5)(sqlite3_context *, int, sqlite3_value **),
00067                            void (*p6)(sqlite3_context *, int, sqlite3_value **),
00068                            void (*p7)(sqlite3_context *));
00069     int (*enable_load_extension)(sqlite3 *p0, int p1);
00070     int (*errcode)(sqlite3 *p0);
00071     const char * (*errmsg)(sqlite3 *p0);
00072     int (*exec)(sqlite3 *p0, const char *p1,
00073                 int (*p2)(void *, int, char **, char **),
00074                 void *p3, char **p4);
00075     int (*finalize)(sqlite3_stmt *p0);
00076     void (*free)(void *p0);
00077     void (*free_table)(char **p0);
00078     int (*get_table)(sqlite3 *p0, const char *p1, char ***p2,
00079                      int *p3, int *p4, char **p5);
00080     void (*interrupt)(sqlite3 *p0);
00081     int (*key)(sqlite3 *p0, const void *p1, int p2);
00082     sqlite_int64 (*last_insert_rowid)(sqlite3 *p0);
00083     const char * (*libversion)(void);
00084     int (*load_extension)(sqlite3 *p0, const char *p1, const char *p2,
00085                           char **p3);
00086     void * (*malloc)(int p0);
00087     char * (*mprintf)(const char *p0, ...);
00088     int (*open)(const char *p0, sqlite3 **p1);
00089     int (*open16)(const void *p0, sqlite3 **p1);
00090     int (*open_v2)(const char *p0, sqlite3 **p1, int p2, const char *p3);
00091     int (*prepare)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
00092                    const char **p4);
00093     int (*prepare_v2)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
00094                       const char **p4);
00095     void * (*profile)(sqlite3 *p0,
00096                       void (*p1)(void *, const char *, sqlite3_uint64),
00097                       void *p2);
00098     void * (*realloc)(void *p0, int p1);
00099     int (*rekey)(sqlite3 *p0, const void *p1, int p2);
00100     int (*reset)(sqlite3_stmt *p0);
00101     void (*result_blob)(sqlite3_context *p0, const void *p1,
00102                         int p2, void (*p3)(void *));
00103     void (*result_error)(sqlite3_context *p0, const char *p1, int p2);
00104     void (*result_int)(sqlite3_context *p0, int p1);
00105     void (*result_null)(sqlite3_context *p0);
00106     int (*step)(sqlite3_stmt *p0);
00107     int (*xstrnicmp)(const char *p0, const char *p1, int p2);
00108     int (*table_column_metadata)(sqlite3 *p0, const char *p1,
00109                                  const char *p2, const char *p3,
00110                                  char const **p4, char const **p5,
00111                                  int *p6, int *p7, int *p8);
00112     void * (*trace)(sqlite3 *p0, void (*p1)(void *, const char *), void *p2);
00113     void * (*user_data)(sqlite3_context *p0);
00114     const void * (*value_blob)(sqlite3_value *p0);
00115     int (*value_bytes)(sqlite3_value *p0);
00116     const unsigned char * (*value_text)(sqlite3_value *p0);
00117     int (*value_type)(sqlite3_value *p0);
00118 } dls_funcs;
00119 
00120 #define sqlite3_activate_see          dls_funcs.activate_see
00121 #define sqlite3_bind_blob             dls_funcs.bind_blob
00122 #define sqlite3_bind_double           dls_funcs.bind_double
00123 #define sqlite3_bind_int              dls_funcs.bind_int
00124 #define sqlite3_bind_int64            dls_funcs.bind_int64
00125 #define sqlite3_bind_null             dls_funcs.bind_null
00126 #define sqlite3_bind_parameter_count  dls_funcs.bind_parameter_count
00127 #define sqlite3_bind_text             dls_funcs.bind_text
00128 #define sqlite3_busy_handler          dls_funcs.busy_handler
00129 #define sqlite3_changes               dls_funcs.changes
00130 #define sqlite3_close                 dls_funcs.close
00131 #define sqlite3_column_blob           dls_funcs.column_blob
00132 #define sqlite3_column_bytes          dls_funcs.column_bytes
00133 #define sqlite3_column_count          dls_funcs.column_count
00134 #define sqlite3_column_database_name  dls_funcs.column_database_name
00135 #define sqlite3_column_decltype       dls_funcs.column_decltype
00136 #define sqlite3_column_double         dls_funcs.column_double
00137 #define sqlite3_column_name           dls_funcs.column_name
00138 #define sqlite3_column_origin_name    dls_funcs.column_origin_name
00139 #define sqlite3_column_table_name     dls_funcs.column_table_name
00140 #define sqlite3_column_text           dls_funcs.column_text
00141 #define sqlite3_column_type           dls_funcs.column_type
00142 #define sqlite3_create_function       dls_funcs.create_function
00143 #define sqlite3_enable_load_extension dls_funcs.enable_load_extension
00144 #define sqlite3_errcode               dls_funcs.errcode
00145 #define sqlite3_errmsg                dls_funcs.errmsg
00146 #define sqlite3_exec                  dls_funcs.exec
00147 #define sqlite3_finalize              dls_funcs.finalize
00148 #define sqlite3_free                  dls_funcs.free
00149 #define sqlite3_free_table            dls_funcs.free_table
00150 #define sqlite3_get_table             dls_funcs.get_table
00151 #define sqlite3_interrupt             dls_funcs.interrupt
00152 #define sqlite3_key                   dls_funcs.key
00153 #define sqlite3_last_insert_rowid     dls_funcs.last_insert_rowid
00154 #define sqlite3_libversion            dls_funcs.libversion
00155 #define sqlite3_load_extension        dls_funcs.load_extension
00156 #define sqlite3_malloc                dls_funcs.malloc
00157 #define sqlite3_mprintf               dls_funcs.mprintf
00158 #define sqlite3_open                  dls_funcs.open
00159 #define sqlite3_open16                dls_funcs.open16
00160 #define sqlite3_open_v2               dls_funcs.open_v2
00161 #define sqlite3_prepare               dls_funcs.prepare
00162 #define sqlite3_prepare_v2            dls_funcs.prepare_v2
00163 #define sqlite3_profile               dls_funcs.profile
00164 #define sqlite3_realloc               dls_funcs.realloc
00165 #define sqlite3_rekey                 dls_funcs.rekey
00166 #define sqlite3_reset                 dls_funcs.reset
00167 #define sqlite3_result_blob           dls_funcs.result_blob
00168 #define sqlite3_result_error          dls_funcs.result_error
00169 #define sqlite3_result_int            dls_funcs.result_int
00170 #define sqlite3_result_null           dls_funcs.result_null
00171 #define sqlite3_step                  dls_funcs.step
00172 #define sqlite3_strnicmp              dls_funcs.xstrnicmp
00173 #define sqlite3_table_column_metadata dls_funcs.table_column_metadata
00174 #define sqlite3_trace                 dls_funcs.trace
00175 #define sqlite3_user_data             dls_funcs.user_data
00176 #define sqlite3_value_blob            dls_funcs.value_blob
00177 #define sqlite3_value_bytes           dls_funcs.value_bytes
00178 #define sqlite3_value_text            dls_funcs.value_text
00179 #define sqlite3_value_type            dls_funcs.value_type
00180 
00181 #endif
00182 
00183 #ifndef WITHOUT_WINTERFACE
00184 #define WINTERFACE
00185 #define WCHARSUPPORT
00186 #endif
00187 
00188 #if !defined(_WIN32) && !defined(_WIN64)
00189 #if !defined(WCHARSUPPORT) && defined(HAVE_SQLWCHAR) && (HAVE_SQLWCHAR)
00190 #define WCHARSUPPORT
00191 #endif
00192 #endif
00193 
00194 #if defined(WINTERFACE)
00195 #include <sqlucode.h>
00196 #endif
00197 
00198 #if defined(_WIN32) || defined(_WIN64)
00199 #include "resource3.h"
00200 #define ODBC_INI "ODBC.INI"
00201 #ifndef DRIVER_VER_INFO
00202 #define DRIVER_VER_INFO VERSION
00203 #endif
00204 #else
00205 #define ODBC_INI ".odbc.ini"
00206 #endif
00207 
00208 #ifndef DRIVER_VER_INFO
00209 #define DRIVER_VER_INFO "0.0"
00210 #endif
00211 
00212 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
00213 #ifdef _WIN64
00214 #define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
00215 #else
00216 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
00217 #endif
00218 #endif
00219 
00220 #ifndef SETSTMTOPTION_LAST_ARG_TYPE
00221 #define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
00222 #endif
00223 
00224 #undef min
00225 #define min(a, b) ((a) < (b) ? (a) : (b))
00226 #undef max
00227 #define max(a, b) ((a) < (b) ? (b) : (a))
00228 
00229 #ifndef PTRDIFF_T
00230 #define PTRDIFF_T int
00231 #endif
00232 
00233 #define array_size(x) (sizeof (x) / sizeof (x[0]))
00234 
00235 #define stringify1(s) #s
00236 #define stringify(s) stringify1(s)
00237 
00238 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
00239 
00240 /* Column meta data from SQLite support */
00241 #undef FULL_METADATA
00242 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
00243 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
00244 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
00245 #if defined(HAVE_SQLITE3COLUMNORIGINNAME) && (HAVE_SQLITE3COLUMNORIGINNAME)
00246 #define FULL_METADATA 1
00247 #endif
00248 #endif
00249 #endif
00250 #endif
00251 
00252 /* Column types for static string column descriptions (SQLTables etc.) */
00253 
00254 #if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
00255 #define SCOL_VARCHAR SQL_WVARCHAR
00256 #define SCOL_CHAR SQL_WCHAR
00257 #else
00258 #define SCOL_VARCHAR SQL_VARCHAR
00259 #define SCOL_CHAR SQL_CHAR
00260 #endif
00261 
00262 #define ENV_MAGIC  0x53544145
00263 #define DBC_MAGIC  0x53544144
00264 #define DEAD_MAGIC 0xdeadbeef
00265 
00272 typedef struct dstr {
00273     int len;            
00274     int max;            
00275     int oom;            
00276     char buffer[1];     
00277 } dstr;
00278 
00279 static const char *xdigits = "0123456789ABCDEFabcdef";
00280 
00281 #ifdef MEMORY_DEBUG
00282 
00283 static void *
00284 xmalloc_(int n, char *file, int line)
00285 {
00286     int nn = n + 4 * sizeof (long);
00287     long *p;
00288 
00289     p = malloc(nn);
00290     if (!p) {
00291 #if (MEMORY_DEBUG > 1)
00292         fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
00293 #endif
00294         return NULL;
00295     }
00296     p[0] = 0xdead1234;
00297     nn = nn / sizeof (long) - 1;
00298     p[1] = n;
00299     p[nn] = 0xdead5678;
00300 #if (MEMORY_DEBUG > 1)
00301     fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
00302 #endif
00303     return (void *) &p[2];
00304 }
00305 
00306 static void *
00307 xrealloc_(void *old, int n, char *file, int line)
00308 {
00309     int nn = n + 4 * sizeof (long), nnn;
00310     long *p, *pp;
00311 
00312     if (n == 0 || !old) {
00313         return xmalloc_(n, file, line);
00314     }
00315     p = &((long *) old)[-2];
00316     if (p[0] != 0xdead1234) {
00317         fprintf(stderr, "*** low end corruption @ %p\n", old);
00318         abort();
00319     }
00320     nnn = p[1] + 4 * sizeof (long);
00321     nnn = nnn / sizeof (long) - 1;
00322     if (p[nnn] != 0xdead5678) {
00323         fprintf(stderr, "*** high end corruption @ %p\n", old);
00324         abort();
00325     }
00326     pp = realloc(p, nn);
00327     if (!pp) {
00328 #if (MEMORY_DEBUG > 1)
00329         fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
00330 #endif
00331         return NULL;
00332     }
00333 #if (MEMORY_DEBUG > 1)
00334     fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
00335 #endif
00336     p = pp;
00337     p[1] = n;
00338     nn = nn / sizeof (long) - 1;
00339     p[nn] = 0xdead5678;
00340     return (void *) &p[2];
00341 }
00342 
00343 static void
00344 xfree_(void *x, char *file, int line)
00345 {
00346     long *p;
00347     int n;
00348 
00349     if (!x) {
00350         return;
00351     }
00352     p = &((long *) x)[-2];
00353     if (p[0] != 0xdead1234) {
00354         fprintf(stderr, "*** low end corruption @ %p\n", x);
00355         abort();
00356     }
00357     n = p[1] + 4 * sizeof (long);
00358     n = n / sizeof (long) - 1;
00359     if (p[n] != 0xdead5678) {
00360         fprintf(stderr, "*** high end corruption @ %p\n", x);
00361         abort();
00362     }
00363 #if (MEMORY_DEBUG > 1)
00364     fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
00365 #endif
00366     free(p);
00367 }
00368 
00369 static void
00370 xfree__(void *x)
00371 {
00372     xfree_(x, "unknown location", 0);
00373 }
00374 
00375 static char *
00376 xstrdup_(const char *str, char *file, int line)
00377 {
00378     char *p;
00379 
00380     if (!str) {
00381 #if (MEMORY_DEBUG > 1)
00382         fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
00383 #endif
00384         return NULL;
00385     }
00386     p = xmalloc_(strlen(str) + 1, file, line);
00387     if (p) {
00388         strcpy(p, str);
00389     }
00390 #if (MEMORY_DEBUG > 1)
00391     fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
00392 #endif
00393     return p;
00394 }
00395 
00396 #define xmalloc(x)    xmalloc_(x, __FILE__, __LINE__)
00397 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
00398 #define xfree(x)      xfree_(x, __FILE__, __LINE__)
00399 #define xstrdup(x)    xstrdup_(x, __FILE__, __LINE__)
00400 
00401 #else
00402 
00403 #define xmalloc(x)    sqlite3_malloc(x)
00404 #define xrealloc(x,y) sqlite3_realloc(x, y)
00405 #define xfree(x)      sqlite3_free(x)
00406 #define xstrdup(x)    strdup_(x)
00407 
00408 #endif
00409 
00410 #if defined(_WIN32) || defined(_WIN64)
00411 
00412 #define vsnprintf   _vsnprintf
00413 #define snprintf    _snprintf
00414 #define strcasecmp  _stricmp
00415 #define strncasecmp _strnicmp
00416 
00417 #ifdef _MSC_VER
00418 #define strtoll     _strtoi64
00419 #define strtoull    _strtoui64
00420 #endif
00421 
00422 static HINSTANCE NEAR hModule;  /* Saved module handle for resources */
00423 
00424 #endif
00425 
00426 #ifdef HAVE_SQLITE3STRNICMP
00427 #undef  strncasecmp
00428 #define strncasecmp(A,B,C) sqlite3_strnicmp(A,B,C)
00429 #undef  strcasecmp
00430 #define strcasecmp(A,B) strcasecmp_(A,B)
00431 
00432 #if defined(__GNUC__) && (__GNUC__ >= 2)
00433 static int strcasecmp_(const char *a, const char *b)
00434     __attribute__((__unused__));
00435 #endif
00436 
00437 static int strcasecmp_(const char *a, const char *b)
00438 {
00439     int c = strlen(a), d = strlen(b);
00440 
00441     if (c > d) {
00442         return strncasecmp(a, b, c);
00443     }
00444     return strncasecmp(a, b, d);
00445 }
00446 #endif
00447 
00448 #if defined(_WIN32) || defined(_WIN64)
00449 
00450 /*
00451  * SQLHENV, SQLHDBC, and SQLHSTMT synchronization
00452  * is done using a critical section in ENV and DBC
00453  * structures.
00454  */
00455 
00456 #define HDBC_LOCK(hdbc)                         \
00457 {                                               \
00458     DBC *d;                                     \
00459                                                 \
00460     if ((hdbc) == SQL_NULL_HDBC) {              \
00461         return SQL_INVALID_HANDLE;              \
00462     }                                           \
00463     d = (DBC *) (hdbc);                         \
00464     if (d->magic != DBC_MAGIC) {                \
00465         return SQL_INVALID_HANDLE;              \
00466     }                                           \
00467     EnterCriticalSection(&d->cs);               \
00468     d->owner = GetCurrentThreadId();            \
00469 }
00470 
00471 #define HDBC_UNLOCK(hdbc)                       \
00472     if ((hdbc) != SQL_NULL_HDBC) {              \
00473         DBC *d;                                 \
00474                                                 \
00475         d = (DBC *) (hdbc);                     \
00476         if (d->magic == DBC_MAGIC) {            \
00477             d->owner = 0;                       \
00478             LeaveCriticalSection(&d->cs);       \
00479         }                                       \
00480     }
00481 
00482 #define HSTMT_LOCK(hstmt)                       \
00483 {                                               \
00484     DBC *d;                                     \
00485                                                 \
00486     if ((hstmt) == SQL_NULL_HSTMT) {            \
00487         return SQL_INVALID_HANDLE;              \
00488     }                                           \
00489     d = (DBC *) ((STMT *) (hstmt))->dbc;        \
00490     if (d->magic != DBC_MAGIC) {                \
00491         return SQL_INVALID_HANDLE;              \
00492     }                                           \
00493     EnterCriticalSection(&d->cs);               \
00494     d->owner = GetCurrentThreadId();            \
00495 }
00496 
00497 #define HSTMT_UNLOCK(hstmt)                     \
00498     if ((hstmt) != SQL_NULL_HSTMT) {            \
00499         DBC *d;                                 \
00500                                                 \
00501         d = (DBC *) ((STMT *) (hstmt))->dbc;    \
00502         if (d->magic == DBC_MAGIC) {            \
00503             d->owner = 0;                       \
00504             LeaveCriticalSection(&d->cs);       \
00505         }                                       \
00506     }
00507 
00508 #else
00509 
00510 /*
00511  * On UN*X assume that we are single-threaded or
00512  * the driver manager provides serialization for us.
00513  *
00514  * In iODBC (3.52.x) serialization can be turned
00515  * on using the DSN property "ThreadManager=yes".
00516  *
00517  * In unixODBC that property is named
00518  * "Threading=0-3" and takes one of these values:
00519  *
00520  *   0 - no protection
00521  *   1 - statement level protection
00522  *   2 - connection level protection
00523  *   3 - environment level protection
00524  *
00525  * unixODBC 2.2.11 uses environment level protection
00526  * by default when it has been built with pthread
00527  * support.
00528  */
00529 
00530 #define HDBC_LOCK(hdbc)
00531 #define HDBC_UNLOCK(hdbc)
00532 #define HSTMT_LOCK(hdbc)
00533 #define HSTMT_UNLOCK(hdbc)
00534 
00535 #endif
00536 
00537 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
00538 extern void nvfs_init(void);
00539 extern const char *nvfs_makevfs(const char *);
00540 #endif
00541 
00542 /*
00543  * tolower() replacement w/o locale
00544  */
00545 
00546 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00547 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
00548 
00549 static int
00550 TOLOWER(int c)
00551 {
00552     if (c) {
00553         char *p = strchr(upper_chars, c);
00554 
00555         if (p) {
00556             c = lower_chars[p - upper_chars];
00557         }
00558     }
00559     return c;
00560 }
00561 
00562 /*
00563  * isdigit() replacement w/o ctype.h
00564  */
00565 
00566 static const char digit_chars[] = "0123456789";
00567 
00568 #define ISDIGIT(c) \
00569     ((c) && strchr(digit_chars, (c)) != NULL)
00570 
00571 /*
00572  * isspace() replacement w/o ctype.h
00573  */
00574 
00575 static const char space_chars[] = " \f\n\r\t\v";
00576 
00577 #define ISSPACE(c) \
00578     ((c) && strchr(space_chars, (c)) != NULL)
00579 
00580 
00581 /*
00582  * Forward declarations of static functions.
00583  */
00584 
00585 static void dbtraceapi(DBC *d, char *fn, const char *sql);
00586 static void freedyncols(STMT *s);
00587 static void freeresult(STMT *s, int clrcols);
00588 static void freerows(char **rowp);
00589 static void unbindcols(STMT *s);
00590 static void s3stmt_drop(STMT *s);
00591 
00592 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
00593 static SQLRETURN freestmt(HSTMT stmt);
00594 static SQLRETURN mkbindcols(STMT *s, int ncols);
00595 static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp);
00596 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
00597 static SQLRETURN starttran(STMT *s);
00598 static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
00599 static SQLRETURN getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
00600                             SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp,
00601                             int partial);
00602 
00603 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
00604 /* MS Access hack part 1 (reserved error -7748) */
00605 static COL *statSpec2P, *statSpec3P;
00606 #endif
00607 
00608 #if (MEMORY_DEBUG < 1)
00609 
00615 static char *
00616 strdup_(const char *str)
00617 {
00618     char *p = NULL;
00619 
00620     if (str) {
00621         p = xmalloc(strlen(str) + 1);
00622         if (p) {
00623             strcpy(p, str);
00624         }
00625     }
00626     return p;
00627 }
00628 #endif
00629 
00637 static dstr *
00638 dsappend(dstr *dsp, const char *str)
00639 {
00640     int len;
00641 
00642     if (!str) {
00643         return dsp;
00644     }
00645     len = strlen(str);
00646     if (!dsp) {
00647         int max = 256;
00648 
00649         if (max < len) {
00650             max += len;
00651         }
00652         dsp = xmalloc(max);
00653         if (dsp) {
00654             dsp->max = max;
00655             dsp->len = dsp->oom = 0;
00656             goto copy;
00657         }
00658         return dsp;
00659     }
00660     if (dsp->oom) {
00661         return dsp;
00662     }
00663     if (dsp->len + len > dsp->max) {
00664         int max = dsp->max + len + 256;
00665         dstr *ndsp = xrealloc(dsp, max);
00666 
00667         if (!ndsp) {
00668             strcpy(dsp->buffer, "OUT OF MEMORY");
00669             dsp->max = dsp->len = 13;
00670             dsp->oom = 1;
00671             return dsp;
00672         }
00673         dsp = ndsp;
00674         dsp->max = max;
00675     }
00676 copy:
00677     strcpy(dsp->buffer + dsp->len, str);
00678     dsp->len += len;
00679     return dsp;
00680 }
00681 
00689 static dstr *
00690 dsappendq(dstr *dsp, const char *str)
00691 {
00692     int len;
00693     const char *p;
00694     char *q;
00695 
00696     if (!str) {
00697         return dsp;
00698     }
00699     len = strlen(str);
00700     for (p = str; *p; ++p) {
00701         if (p[0] == '"') {
00702             ++len;
00703         }
00704     }
00705     len += 2;
00706     if (!dsp) {
00707         int max = 256;
00708 
00709         if (max < len) {
00710             max += len;
00711         }
00712         dsp = xmalloc(max);
00713         if (dsp) {
00714             dsp->max = max;
00715             dsp->len = dsp->oom = 0;
00716             goto copy;
00717         }
00718         return dsp;
00719     }
00720     if (dsp->oom) {
00721         return dsp;
00722     }
00723     if (dsp->len + len > dsp->max) {
00724         int max = dsp->max + len + 256;
00725         dstr *ndsp = xrealloc(dsp, max);
00726 
00727         if (!ndsp) {
00728             strcpy(dsp->buffer, "OUT OF MEMORY");
00729             dsp->max = dsp->len = 13;
00730             dsp->oom = 1;
00731             return dsp;
00732         }
00733         dsp = ndsp;
00734         dsp->max = max;
00735     }
00736 copy:
00737     q = dsp->buffer + dsp->len;
00738     *q++ = '"';
00739     for (p = str; *p; ++p) {
00740         *q++ = *p;
00741         if (p[0] == '"') {
00742             *q++ = '"';
00743         }
00744     }
00745     *q++ = '"';
00746     *q = '\0';
00747     dsp->len += len;
00748     return dsp;
00749 }
00750 
00757 static const char *
00758 dsval(dstr *dsp)
00759 {
00760     if (dsp) {
00761         return (const char *) dsp->buffer;
00762     }
00763     return "ERROR";
00764 }
00765 
00772 static int
00773 dserr(dstr *dsp)
00774 {
00775     return !dsp || dsp->oom;
00776 }
00777 
00783 static void
00784 dsfree(dstr *dsp)
00785 {
00786     if (dsp) {
00787         xfree(dsp);
00788     }
00789 }
00790 
00791 #ifdef WCHARSUPPORT
00792 
00799 static int
00800 uc_strlen(SQLWCHAR *str)
00801 {
00802     int len = 0;
00803 
00804     if (str) {
00805         while (*str) {
00806             ++len;
00807             ++str;
00808         }
00809     }
00810     return len;
00811 }
00812 
00821 static SQLWCHAR *
00822 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
00823 {
00824     int i = 0;
00825 
00826     while (i < len) {
00827         if (!src[i]) {
00828             break;
00829         }
00830         dest[i] = src[i];
00831         ++i;
00832     }
00833     if (i < len) {
00834         dest[i] = 0;
00835     }
00836     return dest;
00837 }
00838 
00847 static void
00848 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
00849 {
00850     ucLen = ucLen / sizeof (SQLWCHAR);
00851     if (!uc || ucLen < 0) {
00852         return;
00853     }
00854     if (len < 0) {
00855         len = ucLen * 5;
00856     }
00857     uc[0] = 0;
00858     if (str) {
00859         int i = 0;
00860 
00861         while (i < len && *str && i < ucLen) {
00862             unsigned char c = str[0];
00863 
00864             if (c < 0x80) {
00865                 uc[i++] = c;
00866                 ++str;
00867             } else if (c <= 0xc1 || c >= 0xf5) {
00868                 /* illegal, ignored */
00869                 ++str;
00870             } else if (c < 0xe0) {
00871                 if ((str[1] & 0xc0) == 0x80) {
00872                     unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
00873 
00874                     uc[i++] = t;
00875                     str += 2;
00876                 } else {
00877                     uc[i++] = c;
00878                     ++str;
00879                 }
00880             } else if (c < 0xf0) {
00881                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
00882                     unsigned long t = ((c & 0x0f) << 12) |
00883                         ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
00884 
00885                     uc[i++] = t;
00886                     str += 3;
00887                 } else {
00888                     uc[i++] = c;
00889                     ++str;
00890                 }
00891             } else if (c < 0xf8) {
00892                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00893                     (str[3] & 0xc0) == 0x80) {
00894                     unsigned long t = ((c & 0x03) << 18) |
00895                         ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
00896                         (str[3] & 0x3f);
00897 
00898                     if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00899                         t >= 0x10000) {
00900                         t -= 0x10000;
00901                         uc[i++] = 0xd800 | ((t >> 10) & 0x3ff);
00902                         if (i >= ucLen) {
00903                             break;
00904                         }
00905                         t = 0xdc00 | (t & 0x3ff);
00906                     }
00907                     uc[i++] = t;
00908                     str += 4;
00909                 } else {
00910                     uc[i++] = c;
00911                     ++str;
00912                 }
00913             } else {
00914                 /* ignore */
00915                 ++str;
00916             }
00917         }
00918         if (i < ucLen) {
00919             uc[i] = 0;
00920         }
00921     }
00922 }
00923 
00931 static SQLWCHAR *
00932 uc_from_utf(unsigned char *str, int len)
00933 {
00934     SQLWCHAR *uc = NULL;
00935     int ucLen;
00936 
00937     if (str) {
00938         if (len == SQL_NTS) {
00939             len = strlen((char *) str);
00940         }
00941         ucLen = sizeof (SQLWCHAR) * (len + 1);
00942         uc = xmalloc(ucLen);
00943         if (uc) {
00944             uc_from_utf_buf(str, len, uc, ucLen);
00945         }
00946     }
00947     return uc;
00948 }
00949 
00957 static char *
00958 uc_to_utf(SQLWCHAR *str, int len)
00959 {
00960     int i;
00961     char *cp, *ret = NULL;
00962 
00963     if (!str) {
00964         return ret;
00965     }
00966     if (len == SQL_NTS) {
00967         len = uc_strlen(str);
00968     } else {
00969         len = len / sizeof (SQLWCHAR);
00970     }
00971     cp = xmalloc(len * 6 + 1);
00972     if (!cp) {
00973         return ret;
00974     }
00975     ret = cp;
00976     for (i = 0; i < len; i++) {
00977         unsigned long c = str[i];
00978 
00979         if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
00980             c &= 0xffff;
00981         }
00982         if (c < 0x80) {
00983             *cp++ = c;
00984         } else if (c < 0x800) {
00985             *cp++ = 0xc0 | ((c >> 6) & 0x1f);
00986             *cp++ = 0x80 | (c & 0x3f);
00987         } else if (c < 0x10000) {
00988             if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00989                 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
00990                 unsigned long c2 = str[i + 1] & 0xffff;
00991 
00992                 if (c2 >= 0xdc00 && c2 <= 0xdfff) {
00993                     c = (((c & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
00994                     *cp++ = 0xf0 | ((c >> 18) & 0x07);
00995                     *cp++ = 0x80 | ((c >> 12) & 0x3f);
00996                     *cp++ = 0x80 | ((c >> 6) & 0x3f);
00997                     *cp++ = 0x80 | (c & 0x3f);
00998                     ++i;
00999                     continue;
01000                 }
01001             }
01002             *cp++ = 0xe0 | ((c >> 12) & 0x0f);
01003             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01004             *cp++ = 0x80 | (c & 0x3f);
01005         } else if (c <= 0x10ffff) {
01006             *cp++ = 0xf0 | ((c >> 18) & 0x07);
01007             *cp++ = 0x80 | ((c >> 12) & 0x3f);
01008             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01009             *cp++ = 0x80 | (c & 0x3f);
01010         }
01011     }
01012     *cp = '\0';
01013     return ret;
01014 }
01015 
01016 #endif
01017 
01018 #ifdef WINTERFACE
01019 
01027 static char *
01028 uc_to_utf_c(SQLWCHAR *str, int len)
01029 {
01030     if (len != SQL_NTS) {
01031         len = len * sizeof (SQLWCHAR);
01032     }
01033     return uc_to_utf(str, len);
01034 }
01035 
01036 #endif
01037 
01038 #if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
01039 
01045 static void
01046 uc_free(void *str)
01047 {
01048     if (str) {
01049         xfree(str);
01050     }
01051 }
01052 
01053 #endif
01054 
01055 #if defined(_WIN32) || defined(_WIN64)
01056 
01064 static char *
01065 wmb_to_utf(char *str, int len)
01066 {
01067     WCHAR *wstr;
01068     OSVERSIONINFO ovi;
01069     int nchar, is2k, cp = CP_OEMCP;
01070 
01071     ovi.dwOSVersionInfoSize = sizeof (ovi);
01072     GetVersionEx(&ovi);
01073     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01074     if (AreFileApisANSI()) {
01075         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01076     }
01077     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01078     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01079     if (!wstr) {
01080         return NULL;
01081     }
01082     wstr[0] = 0;
01083     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01084     wstr[nchar] = 0;
01085     str = xmalloc((nchar + 1) * 7);
01086     if (!str) {
01087         xfree(wstr);
01088         return NULL;
01089     }
01090     str[0] = '\0';
01091     nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
01092     str[nchar] = '\0';
01093     xfree(wstr);
01094     return str;
01095 }
01096 
01097 #ifndef WINTERFACE
01098 
01106 static char *
01107 wmb_to_utf_c(char *str, int len)
01108 {
01109     if (len == SQL_NTS) {
01110         len = strlen(str);
01111     }
01112     return wmb_to_utf(str, len);
01113 }
01114 
01115 #endif
01116 
01124 static char *
01125 utf_to_wmb(char *str, int len)
01126 {
01127     WCHAR *wstr;
01128     OSVERSIONINFO ovi;
01129     int nchar, is2k, cp = CP_OEMCP;
01130 
01131     ovi.dwOSVersionInfoSize = sizeof (ovi);
01132     GetVersionEx(&ovi);
01133     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01134     if (AreFileApisANSI()) {
01135         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01136     }
01137     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
01138     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01139     if (!wstr) {
01140         return NULL;
01141     }
01142     wstr[0] = 0;
01143     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
01144     wstr[nchar] = 0;
01145     str = xmalloc((nchar + 1) * 7);
01146     if (!str) {
01147         xfree(wstr);
01148         return NULL;
01149     }
01150     str[0] = '\0';
01151     nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
01152     str[nchar] = '\0';
01153     xfree(wstr);
01154     return str;
01155 }
01156 
01157 #ifdef WINTERFACE
01158 
01166 static WCHAR *
01167 wmb_to_uc(char *str, int len)
01168 {
01169     WCHAR *wstr;
01170     OSVERSIONINFO ovi;
01171     int nchar, is2k, cp = CP_OEMCP;
01172 
01173     ovi.dwOSVersionInfoSize = sizeof (ovi);
01174     GetVersionEx(&ovi);
01175     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01176     if (AreFileApisANSI()) {
01177         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01178     }
01179     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01180     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01181     if (!wstr) {
01182         return NULL;
01183     }
01184     wstr[0] = 0;
01185     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01186     wstr[nchar] = 0;
01187     return wstr;
01188 }
01189 
01197 static char *
01198 uc_to_wmb(WCHAR *wstr, int len)
01199 {
01200     char *str;
01201     OSVERSIONINFO ovi;
01202     int nchar, is2k, cp = CP_OEMCP;
01203 
01204     ovi.dwOSVersionInfoSize = sizeof (ovi);
01205     GetVersionEx(&ovi);
01206     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01207     if (AreFileApisANSI()) {
01208         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01209     }
01210     nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
01211     str = xmalloc((nchar + 1) * 2);
01212     if (!str) {
01213         return NULL;
01214     }
01215     str[0] = '\0';
01216     nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
01217     str[nchar] = '\0';
01218     return str;
01219 }
01220 
01221 #endif /* WINTERFACE */
01222 
01223 #endif /* _WIN32 || _WIN64 */
01224 
01225 
01226 #ifdef USE_DLOPEN_FOR_GPPS
01227 
01228 #include <dlfcn.h>
01229 
01230 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
01231 
01232 /*
01233  * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
01234  * dlopen(), in theory this makes the driver independent from the
01235  * driver manager, i.e. the same driver binary can run with iODBC
01236  * and unixODBC.
01237  */
01238 
01239 static void
01240 drvgetgpps(DBC *d)
01241 {
01242     void *lib;
01243     int (*gpps)();
01244 
01245     lib = dlopen("libodbcinst.so.2", RTLD_LAZY);
01246     if (!lib) {
01247         lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
01248     }
01249     if (!lib) {
01250         lib = dlopen("libodbcinst.so", RTLD_LAZY);
01251     }
01252     if (!lib) {
01253         lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
01254     }
01255     if (!lib) {
01256         lib = dlopen("libiodbcinst.so", RTLD_LAZY);
01257     }
01258     if (lib) {
01259         gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
01260         if (!gpps) {
01261             dlclose(lib);
01262             return;
01263         }
01264         d->instlib = lib;
01265         d->gpps = gpps;
01266     }
01267 }
01268 
01269 static void
01270 drvrelgpps(DBC *d)
01271 {
01272     if (d->instlib) {
01273         dlclose(d->instlib);
01274         d->instlib = 0;
01275     }
01276 }
01277 
01278 static int
01279 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
01280         int bufsiz, char *fname)
01281 {
01282     if (d->gpps) {
01283         return d->gpps(sect, ent, def, buf, bufsiz, fname);
01284     }
01285     strncpy(buf, def, bufsiz);
01286     buf[bufsiz - 1] = '\0';
01287     return 1;
01288 }
01289 #else
01290 #include <odbcinst.h>
01291 #define drvgetgpps(d)
01292 #define drvrelgpps(d)
01293 #endif
01294 
01295 /*
01296  * Internal function to bind SQLite3 parameters.
01297  */
01298 
01299 static void
01300 s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
01301 {
01302     int i;
01303 
01304     if (stmt && p && nparams > 0) {
01305         for (i = 0; i < nparams; i++, p++) {
01306             switch (p->s3type) {
01307             default:
01308             case SQLITE_NULL:
01309                 sqlite3_bind_null(stmt, i + 1);
01310                 if (d->trace) {
01311                     fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
01312                     fflush(d->trace);
01313                 }
01314                 break;
01315             case SQLITE_TEXT:
01316                 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
01317                                   SQLITE_STATIC);
01318                 if (d->trace) {
01319                     fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
01320                             p->s3size, (char *) p->s3val);
01321                     fflush(d->trace);
01322                 }
01323                 break;
01324             case SQLITE_BLOB:
01325                 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
01326                                   SQLITE_STATIC);
01327                 if (d->trace) {
01328                     fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
01329                     fflush(d->trace);
01330                 }
01331                 break;
01332             case SQLITE_FLOAT:
01333                 sqlite3_bind_double(stmt, i + 1, p->s3dval);
01334                 if (d->trace) {
01335                     fprintf(d->trace, "-- parameter %d: %g\n",
01336                             i + 1, p->s3dval);
01337                     fflush(d->trace);
01338                 }
01339                 break;
01340             case SQLITE_INTEGER:
01341                 if (p->s3size > sizeof (int)) {
01342                     sqlite3_bind_int64(stmt, i + 1, p->s3lival);
01343                     if (d->trace) {
01344                         fprintf(d->trace,
01345 #ifdef _WIN32
01346                                 "-- parameter %d: %I64d\n",
01347 #else
01348                                 "-- parameter %d: %lld\n",
01349 #endif
01350                                 i + 1, p->s3lival);
01351                         fflush(d->trace);
01352                     }
01353                 } else {
01354                     sqlite3_bind_int(stmt, i + 1, p->s3ival);
01355                     if (d->trace) {
01356                         fprintf(d->trace, "-- parameter %d: %d\n",
01357                                 i + 1, p->s3ival);
01358                         fflush(d->trace);
01359                     }
01360                 }
01361                 break;
01362             }
01363         }
01364     }
01365 }
01366 
01374 typedef struct tblres {
01375     char **resarr;      
01376     char *errmsg;       
01377     sqlite3_stmt *stmt; 
01378     STMT *s;            
01379     int nalloc;         
01380     int nrow;           
01381     int ncol;           
01382     PTRDIFF_T ndata;    
01383     int rc;             
01384 } TBLRES;
01385 
01386 /*
01387  * Driver's version of sqlite3_get_table() and friends which are
01388  * capable of dealing with blobs.
01389  */
01390 
01391 static int
01392 drvgettable_row(TBLRES *t, int ncol, int rc)
01393 {
01394     int need;
01395     int i;
01396     char *p;
01397 
01398     if (t->nrow == 0 && rc == SQLITE_ROW) {
01399         need = ncol * 2;
01400     } else {
01401         need = ncol;
01402     }
01403     if (t->ndata + need >= t->nalloc) {
01404         char **resnew;
01405         int nalloc = t->nalloc * 2 + need + 1;
01406 
01407         resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
01408         if (!resnew) {
01409 nomem:
01410             t->rc = SQLITE_NOMEM;
01411             return 1;
01412         }
01413         t->nalloc = nalloc;
01414         t->resarr = resnew;
01415     }
01416     /* column names when first row */
01417     if (t->nrow == 0) {
01418         t->ncol = ncol;
01419         for (i = 0; i < ncol; i++) {
01420             p = (char *) sqlite3_column_name(t->stmt, i);
01421             if (p) {
01422                 char *q = xmalloc(strlen(p) + 1);
01423 
01424                 if (!q) {
01425                     goto nomem;
01426                 }
01427                 strcpy(q, p);
01428                 p = q;
01429             }
01430             t->resarr[t->ndata++] = p;
01431         }
01432         if (t->s && t->s->guessed_types) {
01433             int ncol2 = ncol;
01434 
01435             setupdyncols(t->s, t->stmt, &ncol2);
01436             t->s->guessed_types = 0;
01437             t->s->ncols = ncol;
01438         }
01439     } else if (t->ncol != ncol) {
01440         t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
01441                                     " more incompatible queries");
01442         t->rc = SQLITE_ERROR;
01443         return 1;
01444     }
01445     /* copy row data */
01446     if (rc == SQLITE_ROW) {
01447         for (i = 0; i < ncol; i++) {
01448             int coltype = sqlite3_column_type(t->stmt, i);
01449 
01450             p = NULL;
01451             if (coltype == SQLITE_BLOB) {
01452                 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
01453                 char *qp;
01454                 unsigned const char *bp;
01455 
01456                 bp = sqlite3_column_blob(t->stmt, i);
01457                 qp = xmalloc(nbytes * 2 + 4);
01458                 if (!qp) {
01459                     goto nomem;
01460                 }
01461                 p = qp;
01462                 *qp++ = 'X';
01463                 *qp++ = '\'';
01464                 for (k = 0; k < nbytes; k++) {
01465                     *qp++ = xdigits[(bp[k] >> 4)];
01466                     *qp++ = xdigits[(bp[k] & 0xF)];
01467                 }
01468                 *qp++ = '\'';
01469                 *qp = '\0';
01470 #ifdef _MSC_VER
01471             } else if (coltype == SQLITE_FLOAT) {
01472                 struct lconv *lc = 0;
01473                 double val = sqlite3_column_double(t->stmt, i);
01474                 char buffer[128];
01475 
01476                 /*
01477                  * This avoids floating point rounding
01478                  * and formatting problems of some SQLite
01479                  * versions in conjunction with MSVC 2010.
01480                  */
01481                 snprintf(buffer, sizeof (buffer), "%.15g", val);
01482                 lc = localeconv();
01483                 if (lc && lc->decimal_point && lc->decimal_point[0] &&
01484                     lc->decimal_point[0] != '.') {
01485                     p = strchr(buffer, lc->decimal_point[0]);
01486                     if (p) {
01487                         *p = '.';
01488                     }
01489                 }
01490                 p = xstrdup(buffer);
01491                 if (!p) {
01492                     goto nomem;
01493                 }
01494 #endif
01495             } else if (coltype != SQLITE_NULL) {
01496                 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
01497                 if (!p) {
01498                     goto nomem;
01499                 }
01500             }
01501             t->resarr[t->ndata++] = p;
01502         }
01503         t->nrow++;
01504     }
01505     return 0;
01506 }
01507 
01508 static int
01509 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
01510             int *ncolp, char **errp, int nparam, BINDPARM *p)
01511 {
01512     DBC *d = (DBC *) s->dbc;
01513     int rc = SQLITE_OK, keep = sql == NULL;
01514     TBLRES tres;
01515     const char *sqlleft = 0;
01516     int nretry = 0, haveerr = 0;
01517 
01518     if (!resp) {
01519         return SQLITE_ERROR;
01520     }
01521     *resp = NULL;
01522     if (nrowp) {
01523         *nrowp = 0;
01524     }
01525     if (ncolp) {
01526         *ncolp = 0;
01527     }
01528     tres.errmsg = NULL;
01529     tres.nrow = 0;
01530     tres.ncol = 0;
01531     tres.ndata = 1;
01532     tres.nalloc = 20;
01533     tres.rc = SQLITE_OK;
01534     tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
01535     tres.stmt = NULL;
01536     tres.s = s;
01537     if (!tres.resarr) {
01538         return SQLITE_NOMEM;
01539     }
01540     tres.resarr[0] = 0;
01541     if (sql == NULL) {
01542         tres.stmt = s->s3stmt;
01543         if (tres.stmt == NULL) {
01544             return SQLITE_NOMEM;
01545         }
01546         goto retrieve;
01547     }
01548     while (sql && *sql && (rc == SQLITE_OK ||
01549                            (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
01550         int ncol;
01551 
01552         tres.stmt = NULL;
01553 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
01554         dbtraceapi(d, "sqlite3_prepare_v2", sql);
01555         rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01556 #else
01557         dbtraceapi(d, "sqlite3_prepare", sql);
01558         rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01559 #endif
01560         if (rc != SQLITE_OK) {
01561             if (tres.stmt) {
01562                 dbtraceapi(d, "sqlite3_finalize", 0);
01563                 sqlite3_finalize(tres.stmt);
01564                 tres.stmt = NULL;
01565             }
01566             continue;
01567         }
01568         if (!tres.stmt) {
01569             /* this happens for a comment or white-space */
01570             sql = sqlleft;
01571             continue;
01572         }
01573 retrieve:
01574         if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
01575             if (errp) {
01576                 *errp =
01577                     sqlite3_mprintf("%s", "parameter marker count incorrect");
01578             }
01579             haveerr = 1;
01580             rc = SQLITE_ERROR;
01581             goto tbldone;
01582         }
01583         s3bind(d, tres.stmt, nparam, p);
01584         ncol = sqlite3_column_count(tres.stmt);
01585         while (1) {
01586             if (s->max_rows && tres.nrow >= s->max_rows) {
01587                 rc = SQLITE_OK;
01588                 break;
01589             }
01590             rc = sqlite3_step(tres.stmt);
01591             if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
01592                 if (drvgettable_row(&tres, ncol, rc)) {
01593                     rc = SQLITE_ABORT;
01594                     goto tbldone;
01595                 }
01596             }
01597             if (rc != SQLITE_ROW) {
01598                 if (keep) {
01599                     dbtraceapi(d, "sqlite3_reset", 0);
01600                     rc = sqlite3_reset(tres.stmt);
01601                     s->s3stmt_noreset = 1;
01602                 } else {
01603                     dbtraceapi(d, "sqlite3_finalize", 0);
01604                     rc = sqlite3_finalize(tres.stmt);
01605                 }
01606                 tres.stmt = 0;
01607                 if (rc != SQLITE_SCHEMA) {
01608                     nretry = 0;
01609                     sql = sqlleft;
01610                     while (sql && ISSPACE(*sql)) {
01611                         sql++;
01612                     }
01613                 }
01614                 if (rc == SQLITE_DONE) {
01615                     rc = SQLITE_OK;
01616                 }
01617                 break;
01618             }
01619         }
01620     }
01621 tbldone:
01622     if (tres.stmt) {
01623         if (keep) {
01624             if (!s->s3stmt_noreset) {
01625                 dbtraceapi(d, "sqlite3_reset", 0);
01626                 sqlite3_reset(tres.stmt);
01627                 s->s3stmt_noreset = 1;
01628             }
01629         } else {
01630             dbtraceapi(d, "sqlite3_finalize", 0);
01631             sqlite3_finalize(tres.stmt);
01632         }
01633     }
01634     if (haveerr) {
01635         /* message already in *errp if any */
01636     } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
01637         *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
01638     } else if (errp) {
01639         *errp = NULL;
01640     }
01641     if (tres.resarr) {
01642         tres.resarr[0] = (char *) (tres.ndata - 1);
01643     }
01644     if (rc == SQLITE_ABORT) {
01645         freerows(&tres.resarr[1]);
01646         if (tres.errmsg) {
01647             if (errp) {
01648                 if (*errp) {
01649                     sqlite3_free(*errp);
01650                 }
01651                 *errp = tres.errmsg;
01652             } else {
01653                 sqlite3_free(tres.errmsg);
01654             }
01655         }
01656         return tres.rc;
01657     }
01658     sqlite3_free(tres.errmsg);
01659     if (rc != SQLITE_OK) {
01660         freerows(&tres.resarr[1]);
01661         return rc;
01662     }
01663     *resp = &tres.resarr[1];
01664     if (ncolp) {
01665         *ncolp = tres.ncol;
01666     }
01667     if (nrowp) {
01668         *nrowp = tres.nrow;
01669     }
01670     return rc;
01671 }
01672 
01681 #if defined(__GNUC__) && (__GNUC__ >= 2)
01682 static void setstatd(DBC *, int, char *, char *, ...)
01683     __attribute__((format (printf, 3, 5)));
01684 #endif
01685 
01686 static void
01687 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
01688 {
01689     va_list ap;
01690 
01691     if (!d) {
01692         return;
01693     }
01694     d->naterr = naterr;
01695     d->logmsg[0] = '\0';
01696     if (msg) {
01697         int count;
01698 
01699         va_start(ap, st);
01700         count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
01701         va_end(ap);
01702         if (count < 0) {
01703             d->logmsg[sizeof (d->logmsg) - 1] = '\0';
01704         }
01705     }
01706     if (!st) {
01707         st = "?????";
01708     }
01709     strncpy(d->sqlstate, st, 5);
01710     d->sqlstate[5] = '\0';
01711 }
01712 
01721 #if defined(__GNUC__) && (__GNUC__ >= 2)
01722 static void setstat(STMT *, int, char *, char *, ...)
01723     __attribute__((format (printf, 3, 5)));
01724 #endif
01725 
01726 static void
01727 setstat(STMT *s, int naterr, char *msg, char *st, ...)
01728 {
01729     va_list ap;
01730 
01731     if (!s) {
01732         return;
01733     }
01734     s->naterr = naterr;
01735     s->logmsg[0] = '\0';
01736     if (msg) {
01737         int count;
01738 
01739         va_start(ap, st);
01740         count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
01741         va_end(ap);
01742         if (count < 0) {
01743             s->logmsg[sizeof (s->logmsg) - 1] = '\0';
01744         }
01745     }
01746     if (!st) {
01747         st = "?????";
01748     }
01749     strncpy(s->sqlstate, st, 5);
01750     s->sqlstate[5] = '\0';
01751 }
01752 
01759 static SQLRETURN
01760 drvunimpldbc(HDBC dbc)
01761 {
01762     DBC *d;
01763 
01764     if (dbc == SQL_NULL_HDBC) {
01765         return SQL_INVALID_HANDLE;
01766     }
01767     d = (DBC *) dbc;
01768     setstatd(d, -1, "not supported", "IM001");
01769     return SQL_ERROR;
01770 }
01771 
01778 static SQLRETURN
01779 drvunimplstmt(HSTMT stmt)
01780 {
01781     STMT *s;
01782 
01783     if (stmt == SQL_NULL_HSTMT) {
01784         return SQL_INVALID_HANDLE;
01785     }
01786     s = (STMT *) stmt;
01787     setstat(s, -1, "not supported", "IM001");
01788     return SQL_ERROR;
01789 }
01790 
01796 static void
01797 freep(void *x)
01798 {
01799     if (x && ((char **) x)[0]) {
01800         xfree(((char **) x)[0]);
01801         ((char **) x)[0] = NULL;
01802     }
01803 }
01804 
01811 static SQLRETURN
01812 nomem(STMT *s)
01813 {
01814     setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
01815     return SQL_ERROR;
01816 }
01817 
01824 static SQLRETURN
01825 noconn(STMT *s)
01826 {
01827     setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
01828     return SQL_ERROR;
01829 }
01830 
01838 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
01839 
01840 static double
01841 ln_strtod(const char *data, char **endp)
01842 {
01843     struct lconv *lc = 0;
01844     char buf[128], *p, *end;
01845     double value;
01846 
01847     lc = localeconv();
01848     if (lc && lc->decimal_point && lc->decimal_point[0] &&
01849         lc->decimal_point[0] != '.') {
01850         strncpy(buf, data, sizeof (buf) - 1);
01851         buf[sizeof (buf) - 1] = '\0';
01852         p = strchr(buf, '.');
01853         if (p) {
01854             *p = lc->decimal_point[0];
01855         }
01856         p = buf;
01857     } else {
01858         p = (char *) data;
01859     }
01860     value = strtod(p, &end);
01861     end = (char *) data + (end - p);
01862     if (endp) {
01863         *endp = end;
01864     }
01865     return value;
01866 }
01867 
01868 #else
01869 
01870 #define ln_strtod(A,B) strtod(A,B)
01871 
01872 #endif
01873 
01879 static char *
01880 unquote(char *str)
01881 {
01882     if (str) {
01883         int len = strlen(str);
01884 
01885         if (len > 1) {
01886             int end = len - 1;
01887 
01888             if ((str[0] == '\'' && str[end] == '\'') ||
01889                 (str[0] == '"' && str[end] == '"') ||
01890                 (str[0] == '[' && str[end] == ']')) {
01891                 memmove(str, str + 1, end - 1);
01892                 str[end - 1] = '\0';
01893             }
01894         }
01895     }
01896     return str;
01897 }
01898 
01906 static int
01907 unescpat(char *str)
01908 {
01909     char *p, *q;
01910     int count = 0;
01911 
01912     p = str;
01913     while ((q = strchr(p, '_')) != NULL) {
01914         if (q == str || q[-1] != '\\') {
01915             count++;
01916         }
01917         p = q + 1;
01918     }
01919     p = str;
01920     while ((q = strchr(p, '%')) != NULL) {
01921         if (q == str || q[-1] != '\\') {
01922             count++;
01923         }
01924         p = q + 1;
01925     }
01926     p = str;
01927     while ((q = strchr(p, '\\')) != NULL) {
01928         if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
01929             memmove(q, q + 1, strlen(q));
01930         }
01931         p = q + 1;
01932     }
01933     return count;
01934 }
01935 
01944 static int
01945 namematch(char *str, char *pat, int esc)
01946 {
01947     int cp, ch;
01948 
01949     while (1) {
01950         cp = TOLOWER(*pat);
01951         if (cp == '\0') {
01952             if (*str != '\0') {
01953                 goto nomatch;
01954             }
01955             break;
01956         }
01957         if (*str == '\0' && cp != '%') {
01958             goto nomatch;
01959         }
01960         if (cp == '%') {
01961             while (*pat == '%') {
01962                 ++pat;
01963             }
01964             cp = TOLOWER(*pat);
01965             if (cp == '\0') {
01966                 break;
01967             }
01968             while (1) {
01969                 if (cp != '_' && cp != '\\') {
01970                     while (*str) {
01971                         ch = TOLOWER(*str);
01972                         if (ch == cp) {
01973                             break;
01974                         }
01975                         ++str;
01976                     }
01977                 }
01978                 if (namematch(str, pat, esc)) {
01979                     goto match;
01980                 }
01981                 if (*str == '\0') {
01982                     goto nomatch;
01983                 }
01984                 ch = TOLOWER(*str);
01985                 ++str;
01986             }
01987         }
01988         if (cp == '_') {
01989             pat++;
01990             str++;
01991             continue;
01992         }
01993         if (esc && cp == '\\' &&
01994             (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
01995             ++pat;
01996             cp = TOLOWER(*pat);
01997         }
01998         ch = TOLOWER(*str++);
01999         ++pat;
02000         if (ch != cp) {
02001             goto nomatch;
02002         }
02003     }
02004 match:
02005     return 1;
02006 nomatch:
02007     return 0;
02008 }
02009 
02017 static int
02018 busy_handler(void *udata, int count)
02019 {
02020     DBC *d = (DBC *) udata;
02021     long t1;
02022     int ret = 0;
02023 #if !defined(_WIN32) && !defined(_WIN64)
02024     struct timeval tv;
02025 #ifdef HAVE_NANOSLEEP
02026     struct timespec ts;
02027 #endif
02028 #endif
02029 
02030     if (d->busyint) {
02031         d->busyint = 0;
02032         return ret;
02033     }
02034     if (d->timeout <= 0) {
02035         return ret;
02036     }
02037     if (count <= 1) {
02038 #if defined(_WIN32) || defined(_WIN64)
02039         d->t0 = GetTickCount();
02040 #else
02041         gettimeofday(&tv, NULL);
02042         d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02043 #endif
02044     }
02045 #if defined(_WIN32) || defined(_WIN64)
02046     t1 = GetTickCount();
02047 #else
02048     gettimeofday(&tv, NULL);
02049     t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02050 #endif
02051     if (t1 - d->t0 > d->timeout) {
02052         goto done;
02053     }
02054 #if defined(_WIN32) || defined(_WIN64)
02055     Sleep(10);
02056 #else
02057 #ifdef HAVE_NANOSLEEP
02058     ts.tv_sec = 0;
02059     ts.tv_nsec = 10000000;
02060     do {
02061         ret = nanosleep(&ts, &ts);
02062         if (ret < 0 && errno != EINTR) {
02063             ret = 0;
02064         }
02065     } while (ret);
02066 #else
02067 #ifdef HAVE_USLEEP
02068     usleep(10000);
02069 #else
02070     tv.tv_sec = 0;
02071     tv.tv_usec = 10000;
02072     select(0, NULL, NULL, NULL, &tv);
02073 #endif
02074 #endif
02075 #endif
02076     ret = 1;
02077 done:
02078     return ret;
02079 }
02080 
02092 static int
02093 setsqliteopts(sqlite3 *x, DBC *d)
02094 {
02095     int count = 0, step = 0, max, rc = SQLITE_ERROR;
02096 
02097 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
02098     max = d->longnames ? 3 : 1;
02099 #else
02100     max = 3;
02101 #endif
02102     if (d->shortnames) {
02103         max = 3;
02104     }
02105     while (step < max) {
02106         if (step < 1) {
02107             rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
02108                               NULL, NULL, NULL);
02109             if (rc == SQLITE_OK) {
02110                 rc = sqlite3_exec(x, d->fksupport ?
02111                                   "PRAGMA foreign_keys = on;" :
02112                                   "PRAGMA foreign_keys = off;",
02113                                   NULL, NULL, NULL);
02114             }
02115         } else if (step < 2) {
02116             rc = sqlite3_exec(x, d->shortnames ?
02117                               "PRAGMA full_column_names = off;" :
02118                               "PRAGMA full_column_names = on;",
02119                               NULL, NULL, NULL);
02120         } else if (step < 3) {
02121             rc = sqlite3_exec(x, d->shortnames ?
02122                               "PRAGMA short_column_names = on;" :
02123                               "PRAGMA short_column_names = off;",
02124                               NULL, NULL, NULL);
02125         }
02126         if (rc != SQLITE_OK) {
02127             if (rc != SQLITE_BUSY ||
02128                 !busy_handler((void *) d, ++count)) {
02129                 return rc;
02130             }
02131             continue;
02132         }
02133         count = 0;
02134         ++step;
02135     }
02136     sqlite3_busy_handler(x, busy_handler, (void *) d);
02137     return SQLITE_OK;
02138 }
02139 
02149 static void
02150 freerows(char **rowp)
02151 {
02152     PTRDIFF_T size, i;
02153 
02154     if (!rowp) {
02155         return;
02156     }
02157     --rowp;
02158     size = (PTRDIFF_T) rowp[0];
02159     for (i = 1; i <= size; i++) {
02160         freep(&rowp[i]);
02161     }
02162     freep(&rowp);
02163 }
02164 
02175 static int
02176 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
02177            int dobigint)
02178 {
02179     char *p, *q;
02180     int testsign = 0, result;
02181 
02182 #ifdef WINTERFACE
02183     result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
02184 #else
02185     result = SQL_VARCHAR;
02186 #endif
02187     if (!typename) {
02188         return result;
02189     }
02190     q = p = xmalloc(strlen(typename) + 1);
02191     if (!p) {
02192         return result;
02193     }
02194     strcpy(p, typename);
02195     while (*q) {
02196         *q = TOLOWER(*q);
02197         ++q;
02198     }
02199     if (strncmp(p, "inter", 5) == 0) {
02200     } else if (strncmp(p, "int", 3) == 0 ||
02201         strncmp(p, "mediumint", 9) == 0) {
02202         testsign = 1;
02203         result = SQL_INTEGER;
02204     } else if (strncmp(p, "numeric", 7) == 0) {
02205         result = SQL_DOUBLE;
02206     } else if (strncmp(p, "tinyint", 7) == 0) {
02207         testsign = 1;
02208         result = SQL_TINYINT;
02209     } else if (strncmp(p, "smallint", 8) == 0) {
02210         testsign = 1;
02211         result = SQL_SMALLINT;
02212     } else if (strncmp(p, "float", 5) == 0) {
02213         result = SQL_DOUBLE;
02214     } else if (strncmp(p, "double", 6) == 0 ||
02215         strncmp(p, "real", 4) == 0) {
02216         result = SQL_DOUBLE;
02217     } else if (strncmp(p, "timestamp", 9) == 0) {
02218 #ifdef SQL_TYPE_TIMESTAMP
02219         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02220 #else
02221         result = SQL_TIMESTAMP;
02222 #endif
02223     } else if (strncmp(p, "datetime", 8) == 0) {
02224 #ifdef SQL_TYPE_TIMESTAMP
02225         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02226 #else
02227         result = SQL_TIMESTAMP;
02228 #endif
02229     } else if (strncmp(p, "time", 4) == 0) {
02230 #ifdef SQL_TYPE_TIME
02231         result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
02232 #else
02233         result = SQL_TIME;
02234 #endif
02235     } else if (strncmp(p, "date", 4) == 0) {
02236 #ifdef SQL_TYPE_DATE
02237         result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
02238 #else
02239         result = SQL_DATE;
02240 #endif
02241 #ifdef SQL_LONGVARCHAR
02242     } else if (strncmp(p, "text", 4) == 0 ||
02243                strncmp(p, "memo", 4) == 0 ||
02244                strncmp(p, "longvarchar", 11) == 0) {
02245 #ifdef WINTERFACE
02246         result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
02247 #else
02248         result = SQL_LONGVARCHAR;
02249 #endif
02250 #ifdef WINTERFACE
02251     } else if (strncmp(p, "wtext", 5) == 0 ||
02252                strncmp(p, "wvarchar", 8) == 0 ||
02253                strncmp(p, "longwvarchar", 12) == 0) {
02254         result = SQL_WLONGVARCHAR;
02255 #endif
02256 #endif
02257 #ifdef SQL_BIT
02258     } else if (strncmp(p, "bool", 4) == 0 ||
02259                strncmp(p, "bit", 3) == 0) {
02260         result = SQL_BIT;
02261 #endif
02262 #ifdef SQL_BIGINT
02263     } else if (strncmp(p, "bigint", 6) == 0) {
02264         testsign = 1;
02265         result = SQL_BIGINT;
02266 #endif
02267     } else if (strncmp(p, "blob", 4) == 0) {
02268         result = SQL_BINARY;
02269     } else if (strncmp(p, "varbinary", 9) == 0) {
02270         result = SQL_VARBINARY;
02271     } else if (strncmp(p, "longvarbinary", 13) == 0) {
02272         result = SQL_LONGVARBINARY;
02273     }
02274     if (nosign) {
02275         if (testsign) {
02276             *nosign = strstr(p, "unsigned") != NULL;
02277         } else {
02278             *nosign = 1;
02279         }
02280     }
02281 #ifdef SQL_BIGINT
02282     if (dobigint && result == SQL_INTEGER) {
02283         result = SQL_BIGINT;
02284     }
02285 #endif
02286     xfree(p);
02287     return result;
02288 }
02289 
02299 static void
02300 getmd(const char *typename, int sqltype, int *mp, int *dp)
02301 {
02302     int m = 0, d = 0;
02303 
02304     switch (sqltype) {
02305     case SQL_INTEGER:       m = 10; d = 9; break;
02306     case SQL_TINYINT:       m = 4; d = 3; break;
02307     case SQL_SMALLINT:      m = 6; d = 5; break;
02308     case SQL_FLOAT:         m = 25; d = 24; break;
02309     case SQL_DOUBLE:        m = 54; d = 53; break;
02310     case SQL_VARCHAR:       m = 255; d = 0; break;
02311 #ifdef WINTERFACE
02312 #ifdef SQL_WVARCHAR
02313     case SQL_WVARCHAR:      m = 255; d = 0; break;
02314 #endif
02315 #endif
02316 #ifdef SQL_TYPE_DATE
02317     case SQL_TYPE_DATE:
02318 #endif
02319     case SQL_DATE:          m = 10; d = 0; break;
02320 #ifdef SQL_TYPE_TIME
02321     case SQL_TYPE_TIME:
02322 #endif
02323     case SQL_TIME:          m = 8; d = 0; break;
02324 #ifdef SQL_TYPE_TIMESTAMP
02325     case SQL_TYPE_TIMESTAMP:
02326 #endif
02327     case SQL_TIMESTAMP:     m = 32; d = 3; break;
02328 #ifdef SQL_LONGVARCHAR
02329     case SQL_LONGVARCHAR :  m = 65536; d = 0; break;
02330 #endif
02331 #ifdef WINTERFACE
02332 #ifdef SQL_WLONGVARCHAR
02333     case SQL_WLONGVARCHAR:  m = 65536; d = 0; break;
02334 #endif
02335 #endif
02336     case SQL_BINARY:
02337     case SQL_VARBINARY:     m = 255; d = 0; break;
02338     case SQL_LONGVARBINARY: m = 65536; d = 0; break;
02339 #ifdef SQL_BIGINT
02340     case SQL_BIGINT:        m = 20; d = 19; break;
02341 #endif
02342 #ifdef SQL_BIT
02343     case SQL_BIT:           m = 1; d = 1; break;
02344 #endif
02345     }
02346     if (m && typename) {
02347         int mm, dd;
02348         char clbr[4];
02349 
02350         if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
02351             m = mm;
02352             d = dd;
02353         } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
02354             if (sqltype == SQL_TIMESTAMP) {
02355                 d = mm;
02356             }
02357 #ifdef SQL_TYPE_TIMESTAMP
02358             else if (sqltype == SQL_TYPE_TIMESTAMP) {
02359                 d = mm;
02360             }
02361 #endif
02362             else {
02363                 m = d = mm;
02364             }
02365         }
02366     }
02367     if (mp) {
02368         *mp = m;
02369     }
02370     if (dp) {
02371         *dp = d;
02372     }
02373 }
02374 
02384 static int
02385 mapdeftype(int type, int stype, int nosign, int nowchar)
02386 {
02387     if (type == SQL_C_DEFAULT) {
02388         switch (stype) {
02389         case SQL_INTEGER:
02390             type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
02391             break;
02392         case SQL_TINYINT:
02393             type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
02394             break;
02395         case SQL_SMALLINT:
02396             type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
02397             break;
02398         case SQL_FLOAT:
02399             type = SQL_C_FLOAT;
02400             break;
02401         case SQL_DOUBLE:
02402             type = SQL_C_DOUBLE;
02403             break;
02404         case SQL_TIMESTAMP:
02405             type = SQL_C_TIMESTAMP;
02406             break;
02407         case SQL_TIME:
02408             type = SQL_C_TIME;
02409             break;
02410         case SQL_DATE:
02411             type = SQL_C_DATE;
02412             break;
02413 #ifdef SQL_C_TYPE_TIMESTAMP
02414         case SQL_TYPE_TIMESTAMP:
02415             type = SQL_C_TYPE_TIMESTAMP;
02416             break;
02417 #endif
02418 #ifdef SQL_C_TYPE_TIME
02419         case SQL_TYPE_TIME:
02420             type = SQL_C_TYPE_TIME;
02421             break;
02422 #endif
02423 #ifdef SQL_C_TYPE_DATE
02424         case SQL_TYPE_DATE:
02425             type = SQL_C_TYPE_DATE;
02426             break;
02427 #endif
02428 #ifdef WINTERFACE
02429         case SQL_WVARCHAR:
02430         case SQL_WCHAR:
02431 #ifdef SQL_WLONGVARCHAR
02432         case SQL_WLONGVARCHAR:
02433 #endif
02434             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02435             break;
02436 #endif
02437         case SQL_BINARY:
02438         case SQL_VARBINARY:
02439         case SQL_LONGVARBINARY:
02440             type = SQL_C_BINARY;
02441             break;
02442 #ifdef SQL_BIT
02443         case SQL_BIT:
02444             type = SQL_C_BIT;
02445             break;
02446 #endif
02447 #ifdef SQL_BIGINT
02448         case SQL_BIGINT:
02449             type = SQL_C_CHAR;
02450             break;
02451 #endif
02452         default:
02453 #ifdef WINTERFACE
02454             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02455 #else
02456             type = SQL_C_CHAR;
02457 #endif
02458             break;
02459         }
02460     }
02461     return type;
02462 }
02463 
02470 static int
02471 checkddl(char *sql)
02472 {
02473     int isddl = 0;
02474 
02475     while (*sql && ISSPACE(*sql)) {
02476         ++sql;
02477     }
02478     if (*sql && *sql != ';') {
02479         int i, size;
02480         static const struct {
02481             int len;
02482             const char *str;
02483         } ddlstr[] = {
02484             { 5, "alter" },
02485             { 7, "analyze" },
02486             { 6, "attach" },
02487             { 5, "begin" },
02488             { 6, "commit" },
02489             { 6, "create" },
02490             { 6, "detach" },
02491             { 4, "drop" },
02492             { 3, "end" },
02493             { 7, "reindex" },
02494             { 7, "release" },
02495             { 8, "rollback" },
02496             { 9, "savepoint" },
02497             { 6, "vacuum" }
02498         };
02499 
02500         size = strlen(sql);
02501         for (i = 0; i < array_size(ddlstr); i++) {
02502             if (size >= ddlstr[i].len &&
02503                 strncasecmp(sql, ddlstr[i].str, ddlstr[i].len) == 0) {
02504                 isddl = 1;
02505                 break;
02506             }
02507         }
02508     }
02509     return isddl;
02510 }
02511 
02523 static char *
02524 fixupsql(char *sql, int sqlLen, int cte, int *nparam, int *isselect,
02525          char **errmsg)
02526 {
02527     char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
02528     int np = 0, isddl = -1, size;
02529 
02530     if (errmsg) {
02531         *errmsg = NULL;
02532     }
02533     if (sqlLen != SQL_NTS) {
02534         qz = q = xmalloc(sqlLen + 1);
02535         if (!qz) {
02536             return NULL;
02537         }
02538         memcpy(q, sql, sqlLen);
02539         q[sqlLen] = '\0';
02540         size = sqlLen * 4;
02541     } else {
02542         size = strlen(sql) * 4;
02543     }
02544     size += sizeof (char *) - 1;
02545     size &= ~(sizeof (char *) - 1);
02546     p = xmalloc(size);
02547     if (!p) {
02548 errout:
02549         freep(&qz);
02550         return NULL;
02551     }
02552     memset(p, 0, size);
02553     out = p;
02554     while (*q) {
02555         switch (*q) {
02556         case '\'':
02557         case '\"':
02558             if (q == inq) {
02559                 inq = NULL;
02560             } else if (!inq) {
02561                 inq = q + 1;
02562 
02563                 while (*inq) {
02564                     if (*inq == *q) {
02565                         if (inq[1] == *q) {
02566                             inq++;
02567                         } else {
02568                             break;
02569                         }
02570                     }
02571                     inq++;
02572                 }
02573             }
02574             *p++ = *q;
02575             break;
02576         case '?':
02577             *p++ = *q;
02578             if (!inq) {
02579                 np++;
02580             }
02581             break;
02582         case ';':
02583             if (!inq) {
02584                 if (isddl < 0) {
02585                     isddl = checkddl(out);
02586                 }
02587                 if (isddl == 0) {
02588                     char *qq = q;
02589 
02590                     do {
02591                         ++qq;
02592                     } while (*qq && ISSPACE(*qq));
02593                     if (*qq && *qq != ';') {
02594                         freep(&out);
02595                         if (errmsg) {
02596                             *errmsg = "only one SQL statement allowed";
02597                         }
02598                         goto errout;
02599                     }
02600                 }
02601             }
02602             *p++ = *q;
02603             break;
02604         case '{':
02605             /*
02606              * Deal with escape sequences:
02607              * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
02608              * {oj ...}, {fn ...} etc.
02609              */
02610             if (!inq) {
02611                 int ojfn = 0, brc = 0;
02612                 char *inq2 = NULL, *end = q + 1, *start;
02613 
02614                 while (*end && ISSPACE(*end)) {
02615                     ++end;
02616                 }
02617                 if (*end != 'd' && *end != 'D' &&
02618                     *end != 't' && *end != 'T') {
02619                     ojfn = 1;
02620                 }
02621                 start = end;
02622                 while (*end) {
02623                     if (inq2 && *end == *inq2) {
02624                         inq2 = NULL;
02625                     } else if (inq2 == NULL && *end == '{') {
02626                         char *nerr = 0, *nsql;
02627 
02628                         nsql = fixupsql(end, SQL_NTS, cte, 0, 0, &nerr);
02629                         if (nsql && !nerr) {
02630                             strcpy(end, nsql);
02631                         } else {
02632                             brc++;
02633                         }
02634                         freep(&nsql);
02635                     } else if (inq2 == NULL && *end == '}') {
02636                         if (brc-- <= 0) {
02637                             break;
02638                         }
02639                     } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
02640                         inq2 = end;
02641                     } else if (inq2 == NULL && *end == '?') {
02642                         np++;
02643                     }
02644                     ++end;
02645                 }
02646                 if (*end == '}') {
02647                     char *end2 = end - 1;
02648 
02649                     if (ojfn) {
02650                         while (start < end) {
02651                             if (ISSPACE(*start)) {
02652                                 break;
02653                             }
02654                             ++start;
02655                         }
02656                         while (start < end) {
02657                             *p++ = *start;
02658                             ++start;
02659                         }
02660                         q = end;
02661                         break;
02662                     } else {
02663                         while (start < end2 && *start != '\'') {
02664                             ++start;
02665                         }
02666                         while (end2 > start && *end2 != '\'') {
02667                             --end2;
02668                         }
02669                         if (*start == '\'' && *end2 == '\'') {
02670                             while (start <= end2) {
02671                                 *p++ = *start;
02672                                 ++start;
02673                             }
02674                             q = end;
02675                             break;
02676                         }
02677                     }
02678                 }
02679             }
02680             /* FALL THROUGH */
02681         default:
02682             *p++ = *q;
02683         }
02684         ++q;
02685     }
02686     freep(&qz);
02687     *p = '\0';
02688     if (nparam) {
02689         *nparam = np;
02690     }
02691     if (isselect) {
02692         if (isddl < 0) {
02693             isddl = checkddl(out);
02694         }
02695         if (isddl > 0) {
02696             *isselect = 2;
02697         } else {
02698             int incom = 0;
02699 
02700             p = out;
02701             while (*p) {
02702                 switch (*p) {
02703                 case '-':
02704                     if (!incom && p[1] == '-') {
02705                         incom = -1;
02706                     }
02707                     break;
02708                 case '\n':
02709                     if (incom < 0) {
02710                         incom = 0;
02711                     }
02712                     break;
02713                 case '/':
02714                     if (incom > 0 && p[-1] == '*') {
02715                         incom = 0;
02716                         p++;
02717                         continue;
02718                     } else if (!incom && p[1] == '*') {
02719                         incom = 1;
02720                     }
02721                     break;
02722                 }
02723                 if (!incom && !ISSPACE(*p)) {
02724                     break;
02725                 }
02726                 p++;
02727             }
02728             size = strlen(p);
02729             if (size >= 6 &&
02730                 (strncasecmp(p, "select", 6) == 0 ||
02731                  strncasecmp(p, "pragma", 6) == 0)) {
02732                 *isselect = 1;
02733             } else if (cte && size >= 4 && strncasecmp(p, "with", 4) == 0) {
02734                 *isselect = 1;
02735             } else if (size >= 7 && strncasecmp(p, "explain", 7) == 0) {
02736                 *isselect = 1;
02737             } else {
02738                 *isselect = 0;
02739             }
02740         }
02741     }
02742     return out;
02743 }
02744 
02753 static int
02754 findcol(char **cols, int ncols, char *name)
02755 {
02756     int i;
02757 
02758     if (cols) {
02759         for (i = 0; i < ncols; i++) {
02760             if (strcmp(cols[i], name) == 0) {
02761                 return i;
02762             }
02763         }
02764     }
02765     return -1;
02766 }
02767 
02784 static void
02785 fixupdyncols(STMT *s, DBC *d)
02786 {
02787     int i, k;
02788 #ifndef FULL_METADATA
02789     int pk, nn, t, r, nrows, ncols;
02790     char **rowp, *flagp, flags[128];
02791 #endif
02792 
02793     if (!s->dyncols) {
02794         return;
02795     }
02796     /* fixup labels */
02797     if (!s->longnames) {
02798         if (s->dcols > 1) {
02799             char *table = s->dyncols[0].table;
02800 
02801             for (i = 1; table[0] && i < s->dcols; i++) {
02802                 if (strcmp(s->dyncols[i].table, table)) {
02803                     break;
02804                 }
02805             }
02806             if (i >= s->dcols) {
02807                 for (i = 0; i < s->dcols; i++) {
02808                     s->dyncols[i].label = s->dyncols[i].column;
02809                 }
02810             }
02811         } else if (s->dcols == 1) {
02812             s->dyncols[0].label = s->dyncols[0].column;
02813         }
02814     }
02815     for (i = 0; i < s->dcols; i++) {
02816         s->dyncols[i].type =
02817             mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
02818                        s->nowchar[0] || s->nowchar[1], s->dobigint);
02819         getmd(s->dyncols[i].typename, s->dyncols[i].type,
02820               &s->dyncols[i].size, &s->dyncols[i].prec);
02821 #ifdef SQL_LONGVARCHAR
02822         if (s->dyncols[i].type == SQL_VARCHAR &&
02823             s->dyncols[i].size > 255) {
02824             s->dyncols[i].type = SQL_LONGVARCHAR;
02825         }
02826 #endif
02827 #ifdef WINTERFACE
02828 #ifdef SQL_WLONGVARCHAR
02829         if (s->dyncols[i].type == SQL_WVARCHAR &&
02830             s->dyncols[i].size > 255) {
02831             s->dyncols[i].type = SQL_WLONGVARCHAR;
02832         }
02833 #endif
02834 #endif
02835         if (s->dyncols[i].type == SQL_VARBINARY &&
02836             s->dyncols[i].size > 255) {
02837             s->dyncols[i].type = SQL_LONGVARBINARY;
02838         }
02839     }
02840 #ifndef FULL_METADATA
02841     if (s->dcols > array_size(flags)) {
02842         flagp = xmalloc(sizeof (flags[0]) * s->dcols);
02843         if (flagp == NULL) {
02844             return;
02845         }
02846     } else {
02847         flagp = flags;
02848     }
02849     memset(flagp, 0, sizeof (flags[0]) * s->dcols);
02850     for (i = 0; i < s->dcols; i++) {
02851         s->dyncols[i].autoinc = SQL_FALSE;
02852         s->dyncols[i].notnull = SQL_NULLABLE;
02853     }
02854     for (i = 0; i < s->dcols; i++) {
02855         int ret, lastpk = -1, autoinccount = 0;
02856         char *sql;
02857 
02858         if (!s->dyncols[i].table[0]) {
02859             continue;
02860         }
02861         if (flagp[i]) {
02862             continue;
02863         }
02864         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
02865         if (!sql) {
02866             continue;
02867         }
02868         dbtraceapi(d, "sqlite3_get_table", sql);
02869         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
02870         sqlite3_free(sql);
02871         if (ret != SQLITE_OK) {
02872             continue;
02873         }
02874         k = findcol(rowp, ncols, "name");
02875         t = findcol(rowp, ncols, "type");
02876         pk = findcol(rowp, ncols, "pk");
02877         nn = findcol(rowp, ncols, "notnull");
02878         if (k < 0 || t < 0) {
02879             goto freet;
02880         }
02881         for (r = 1; r <= nrows; r++) {
02882             int m;
02883 
02884             for (m = i; m < s->dcols; m++) {
02885                 char *colname = s->dyncols[m].column;
02886 
02887                 if (s->longnames) {
02888                     char *dotp = strchr(colname, '.');
02889 
02890                     if (dotp) {
02891                         colname = dotp + 1;
02892                     }
02893                 }
02894                 if (!flagp[m] &&
02895                     strcmp(colname, rowp[r * ncols + k]) == 0 &&
02896                     strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
02897                     char *typename = rowp[r * ncols + t];
02898 
02899                     flagp[m] = i + 1;
02900                     freep(&s->dyncols[m].typename);
02901                     s->dyncols[m].typename = xstrdup(typename);
02902                     s->dyncols[m].type =
02903                         mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
02904                                    s->nowchar[0] || s->nowchar[1],
02905                                    s->dobigint);
02906                     getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
02907                           &s->dyncols[m].prec);
02908 #ifdef SQL_LONGVARCHAR
02909                     if (s->dyncols[m].type == SQL_VARCHAR &&
02910                         s->dyncols[m].size > 255) {
02911                         s->dyncols[m].type = SQL_LONGVARCHAR;
02912                     }
02913 #endif
02914 #ifdef WINTERFACE
02915 #ifdef SQL_WLONGVARCHAR
02916                     if (s->dyncols[i].type == SQL_WVARCHAR &&
02917                         s->dyncols[i].size > 255) {
02918                         s->dyncols[i].type = SQL_WLONGVARCHAR;
02919                     }
02920 #endif
02921 #endif
02922                     if (s->dyncols[i].type == SQL_VARBINARY &&
02923                         s->dyncols[i].size > 255) {
02924                         s->dyncols[i].type = SQL_LONGVARBINARY;
02925                     }
02926                     if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
02927                         s->dyncols[m].ispk = 1;
02928                         if (++autoinccount > 1) {
02929                             if (lastpk >= 0) {
02930                                 s->dyncols[lastpk].autoinc = SQL_FALSE;
02931                                 lastpk = -1;
02932                             }
02933                         } else {
02934                             lastpk = m;
02935                             if (strlen(typename) == 7 &&
02936                                 strncasecmp(typename, "integer", 7) == 0) {
02937                                 s->dyncols[m].autoinc = SQL_TRUE;
02938                             }
02939                         }
02940                     } else {
02941                         s->dyncols[m].ispk = 0;
02942                     }
02943                     if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
02944                         s->dyncols[m].notnull = SQL_NO_NULLS;
02945                     }
02946                 }
02947             }
02948         }
02949 freet:
02950         sqlite3_free_table(rowp);
02951     }
02952     for (i = k = 0; i < s->dcols; i++) {
02953         if (flagp[i] == 0) {
02954             break;
02955         }
02956         if (k == 0) {
02957             k = flagp[i];
02958         } else if (flagp[i] != k) {
02959             k = 0;
02960             break;
02961         }
02962     }
02963     s->one_tbl = k ? 1 : 0;
02964     k = 0;
02965     if (s->one_tbl) {
02966         for (i = 0; i < s->dcols; i++) {
02967             if (s->dyncols[i].ispk > 0) {
02968                 ++k;
02969             }
02970         }
02971     }
02972     s->has_pk = k;
02973     if (flagp != flags) {
02974         freep(&flagp);
02975     }
02976 #else
02977     for (i = 1, k = 0; i < s->dcols; i++) {
02978         if (strcmp(s->dyncols[i].table, s->dyncols[0].table) == 0) {
02979             k++;
02980         }
02981     }
02982     s->one_tbl = (k && k + 1 == s->dcols) ? 1 : 0;
02983     k = 0;
02984     if (s->one_tbl) {
02985         for (i = 0; i < s->dcols; i++) {
02986             if (s->dyncols[i].ispk > 0) {
02987                 ++k;
02988                 if (s->has_rowid < 0 && s->dyncols[i].isrowid > 0) {
02989                     s->has_rowid = i;
02990                 }
02991             }
02992         }
02993     }
02994     s->has_pk = k;
02995 #endif
02996 }
02997 
03004 static void
03005 convJD2YMD(double jd, DATE_STRUCT *ds)
03006 {
03007     int z, a, b, c, d, e, x1;
03008     sqlite_int64 ijd;
03009 
03010     ijd = jd * 86400000.0 + 0.5;
03011     z = (int) ((ijd + 43200000) / 86400000);
03012     a = (int) ((z - 1867216.25) / 36524.25);
03013     a = z + 1 + a - (a / 4);
03014     b = a + 1524;
03015     c = (int) ((b - 122.1) / 365.25);
03016     d = (36525 * c) / 100;
03017     e = (int) ((b - d) / 30.6001);
03018     x1 = (int) (30.6001 * e);
03019     ds->day = b - d - x1;
03020     ds->month = (e < 14) ? (e - 1) : (e - 13);
03021     ds->year = (ds->month > 2) ? (c - 4716) : (c - 4715);
03022 }
03023 
03024 
03032 static void
03033 convJD2HMS(double jd, TIME_STRUCT *ts, int *fp)
03034 {
03035     int s;
03036     double ds;
03037     sqlite_int64 ijd;
03038 
03039     ijd = jd * 86400000.0 + 0.5;
03040     s = (int)((ijd + 43200000) % 86400000);
03041     ds = s / 1000.0;
03042     if (fp) {
03043         *fp = (s % 1000) * 1000000;
03044     }
03045     s = (int) ds;
03046     ds -= s;
03047     ts->hour = s / 3600;
03048     s -= ts->hour * 3600;
03049     ts->minute = s / 60;
03050     ds += s - ts->minute *60;
03051     ts->second = (int) ds;
03052 }
03053 
03061 static int
03062 getmdays(int year, int month)
03063 {
03064     static const int mdays[] = {
03065         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
03066     };
03067     int mday;
03068 
03069     if (month < 1) {
03070         return 0;
03071     }
03072     mday = mdays[(month - 1) % 12];
03073     if (mday == 28 && year % 4 == 0 &&
03074         (!(year % 100 == 0) || year % 400 == 0)) {
03075         mday++;
03076     }
03077     return mday;
03078 }
03079 
03095 static int
03096 str2date(int jdconv, char *str, DATE_STRUCT *ds)
03097 {
03098     int i, err = 0;
03099     double jd;
03100     char *p, *q, sepc = '\0';
03101 
03102     ds->year = ds->month = ds->day = 0;
03103     if (jdconv) {
03104         p = strchr(str, '.');
03105         if (p) {
03106             /* julian day format */
03107             p = 0;
03108             jd = ln_strtod(str, &p);
03109             if (p && p > str) {
03110                 convJD2YMD(jd, ds);
03111                 return 0;
03112             }
03113         }
03114     }
03115     p = str;
03116     while (*p && !ISDIGIT(*p)) {
03117         ++p;
03118     }
03119     q = p;
03120     i = 0;
03121     while (*q && !ISDIGIT(*q)) {
03122         ++i;
03123         ++q;
03124     }
03125     if (i >= 8) {
03126         char buf[8];
03127 
03128         strncpy(buf, p + 0, 4); buf[4] = '\0';
03129         ds->year = strtol(buf, NULL, 10);
03130         strncpy(buf, p + 4, 2); buf[2] = '\0';
03131         ds->month = strtol(buf, NULL, 10);
03132         strncpy(buf, p + 6, 2); buf[2] = '\0';
03133         ds->day = strtol(buf, NULL, 10);
03134         goto done;
03135     }
03136     i = 0;
03137     while (i < 3) {
03138         int n;
03139 
03140         q = NULL;
03141         n = strtol(p, &q, 10);
03142         if (!q || q == p) {
03143             if (*q == '\0') {
03144                 if (i == 0) {
03145                     err = 1;
03146                 }
03147                 goto done;
03148             }
03149         }
03150         if (!sepc) {
03151             sepc = *q;
03152         }
03153         if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
03154             switch (i) {
03155             case 0: ds->year = n; break;
03156             case 1: ds->month = n; break;
03157             case 2: ds->day = n; break;
03158             }
03159             ++i;
03160             if (*q) {
03161                 ++q;
03162             }
03163         } else {
03164             i = 0;
03165             while (*q && !ISDIGIT(*q)) {
03166                 ++q;
03167             }
03168         }
03169         p = q;
03170     }
03171 done:
03172     /* final check for overflow */
03173     if (err ||
03174         ds->month < 1 || ds->month > 12 ||
03175         ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
03176         if (sepc == '/') {
03177             /* Try MM/DD/YYYY format */
03178             int t[3];
03179 
03180             t[0] = ds->year;
03181             t[1] = ds->month;
03182             t[2] = ds->day;
03183             ds->year = t[2];
03184             ds->day = t[1];
03185             ds->month = t[0];
03186             if (ds->month >= 1 && ds->month <= 12 &&
03187                 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
03188                 return 0;
03189             }
03190         }
03191         return -1;
03192     }
03193     return 0;
03194 }
03195 
03210 static int
03211 str2time(int jdconv, char *str, TIME_STRUCT *ts)
03212 {
03213     int i, err = 0, ampm = -1;
03214     double jd;
03215     char *p, *q;
03216 
03217     ts->hour = ts->minute = ts->second = 0;
03218     if (jdconv) {
03219         p = strchr(str, '.');
03220         if (p) {
03221             /* julian day format */
03222             p = 0;
03223             jd = ln_strtod(str, &p);
03224             if (p && p > str) {
03225                 convJD2HMS(jd, ts, 0);
03226                 return 0;
03227             }
03228         }
03229     }
03230     p = str;
03231     while (*p && !ISDIGIT(*p)) {
03232         ++p;
03233     }
03234     q = p;
03235     i = 0;
03236     while (*q && ISDIGIT(*q)) {
03237         ++i;
03238         ++q;
03239     }
03240     if (i >= 6) {
03241         char buf[4];
03242 
03243         strncpy(buf, p + 0, 2); buf[2] = '\0';
03244         ts->hour = strtol(buf, NULL, 10);
03245         strncpy(buf, p + 2, 2); buf[2] = '\0';
03246         ts->minute = strtol(buf, NULL, 10);
03247         strncpy(buf, p + 4, 2); buf[2] = '\0';
03248         ts->second = strtol(buf, NULL, 10);
03249         goto done;
03250     }
03251     i = 0;
03252     while (i < 3) {
03253         int n;
03254 
03255         q = NULL;
03256         n = strtol(p, &q, 10);
03257         if (!q || q == p) {
03258             if (*q == '\0') {
03259                 if (i == 0) {
03260                     err = 1;
03261                 }
03262                 goto done;
03263             }
03264         }
03265         if (*q == ':' || *q == '\0' || i == 2) {
03266             switch (i) {
03267             case 0: ts->hour = n; break;
03268             case 1: ts->minute = n; break;
03269             case 2: ts->second = n; break;
03270             }
03271             ++i;
03272             if (*q) {
03273                 ++q;
03274             }
03275         } else {
03276             i = 0;
03277             while (*q && !ISDIGIT(*q)) {
03278                 ++q;
03279             }
03280         }
03281         p = q;
03282     }
03283     if (!err) {
03284         while (*p) {
03285             if ((p[0] == 'p' || p[0] == 'P') &&
03286                 (p[1] == 'm' || p[1] == 'M')) {
03287                 ampm = 1;
03288             } else if ((p[0] == 'a' || p[0] == 'A') &&
03289                 (p[1] == 'm' || p[1] == 'M')) {
03290                 ampm = 0;
03291             }
03292             ++p;
03293         }
03294         if (ampm > 0) {
03295             if (ts->hour < 12) {
03296                 ts->hour += 12;
03297             }
03298         } else if (ampm == 0) {
03299             if (ts->hour == 12) {
03300                 ts->hour = 0;
03301             }
03302         }
03303     }
03304 done:
03305     /* final check for overflow */
03306     if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
03307         return -1;
03308     }
03309     return 0;
03310 }
03311 
03331 static int
03332 str2timestamp(int jdconv, char *str, TIMESTAMP_STRUCT *tss)
03333 {
03334     int i, m, n, err = 0, ampm = -1;
03335     double jd;
03336     char *p, *q, in = '\0', sepc = '\0';
03337 
03338     tss->year = tss->month = tss->day = 0;
03339     tss->hour = tss->minute = tss->second = 0;
03340     tss->fraction = 0;
03341     if (jdconv) {
03342         p = strchr(str, '.');
03343         if (p) {
03344             q = strchr(str, '-');
03345             if (q == str) {
03346                 q = 0;
03347             }
03348             if (!q) {
03349                 q = strchr(str, '/');
03350                 if (!q) {
03351                     q = strchr(str, ':');
03352                 }
03353             }
03354             if (!q || q > p) {
03355                 /* julian day format */
03356                 p = 0;
03357                 jd = ln_strtod(str, &p);
03358                 if (p && p > str) {
03359                     DATE_STRUCT ds;
03360                     TIME_STRUCT ts;
03361 
03362                     convJD2YMD(jd, &ds);
03363                     convJD2HMS(jd, &ts, &n);
03364                     tss->year = ds.year;
03365                     tss->month = ds.month;
03366                     tss->day = ds.day;
03367                     tss->hour = ts.hour;
03368                     tss->minute = ts.minute;
03369                     tss->second = ts.second;
03370                     tss->fraction = n;
03371                     return 0;
03372                 }
03373             }
03374         }
03375     }
03376     p = str;
03377     while (*p && !ISDIGIT(*p)) {
03378         ++p;
03379     }
03380     q = p;
03381     i = 0;
03382     while (*q && ISDIGIT(*q)) {
03383         ++i;
03384         ++q;
03385     }
03386     if (i >= 14) {
03387         char buf[16];
03388 
03389         strncpy(buf, p + 0, 4); buf[4] = '\0';
03390         tss->year = strtol(buf, NULL, 10);
03391         strncpy(buf, p + 4, 2); buf[2] = '\0';
03392         tss->month = strtol(buf, NULL, 10);
03393         strncpy(buf, p + 6, 2); buf[2] = '\0';
03394         tss->day = strtol(buf, NULL, 10);
03395         strncpy(buf, p + 8, 2); buf[2] = '\0';
03396         tss->hour = strtol(buf, NULL, 10);
03397         strncpy(buf, p + 10, 2); buf[2] = '\0';
03398         tss->minute = strtol(buf, NULL, 10);
03399         strncpy(buf, p + 12, 2); buf[2] = '\0';
03400         tss->second = strtol(buf, NULL, 10);
03401         if (i > 14) {
03402             m = i - 14;
03403             strncpy(buf, p + 14, m);
03404             while (m < 9) {
03405                 buf[m] = '0';
03406                 ++m;
03407             }
03408             buf[m] = '\0';
03409             tss->fraction = strtol(buf, NULL, 10);
03410         }
03411         m = 7;
03412         goto done;
03413     }
03414     m = i = 0;
03415     while ((m & 7) != 7) {
03416         q = NULL;
03417         n = strtol(p, &q, 10);
03418         if (!q || q == p) {
03419             if (*q == '\0') {
03420                 if (m < 1) {
03421                     err = 1;
03422                 }
03423                 goto done;
03424             }
03425         }
03426         if (in == '\0') {
03427             switch (*q) {
03428             case '-':
03429             case '/':
03430                 if ((m & 1) == 0) {
03431                     in = *q;
03432                     i = 0;
03433                 }
03434                 break;
03435             case ':':
03436                 if ((m & 2) == 0) {
03437                     in = *q;
03438                     i = 0;
03439                 }
03440                 break;
03441             case ' ':
03442             case '.':
03443                 break;
03444             default:
03445                 in = '\0';
03446                 i = 0;
03447                 break;
03448             }
03449         }
03450         switch (in) {
03451         case '-':
03452         case '/':
03453             if (!sepc) {
03454                 sepc = in;
03455             }
03456             switch (i) {
03457             case 0: tss->year = n; break;
03458             case 1: tss->month = n; break;
03459             case 2: tss->day = n; break;
03460             }
03461             if (++i >= 3) {
03462                 i = 0;
03463                 m |= 1;
03464                 if (!(m & 2)) {
03465                     m |= 8;
03466                 }
03467                 goto skip;
03468             } else {
03469                 ++q;
03470             }
03471             break;
03472         case ':':
03473             switch (i) {
03474             case 0: tss->hour = n; break;
03475             case 1: tss->minute = n; break;
03476             case 2: tss->second = n; break;
03477             }
03478             if (++i >= 3) {
03479                 i = 0;
03480                 m |= 2;
03481                 if (*q == '.') {
03482                     in = '.';
03483                     goto skip2;
03484                 }
03485                 if (*q == ' ') {
03486                     if ((m & 1) == 0) {
03487                         char *e = NULL;
03488 
03489                         (void) strtol(q + 1, &e, 10);
03490                         if (e && *e == '-') {
03491                             goto skip;
03492                         }
03493                     }
03494                     in = '.';
03495                     goto skip2;
03496                 }
03497                 goto skip;
03498             } else {
03499                 ++q;
03500             }
03501             break;
03502         case '.':
03503             if (++i >= 1) {
03504                 int ndig = q - p;
03505 
03506                 if (p[0] == '+' || p[0] == '-') {
03507                     ndig--;
03508                 }
03509                 while (ndig < 9) {
03510                     n = n * 10;
03511                     ++ndig;
03512                 }
03513                 tss->fraction = n;
03514                 m |= 4;
03515                 i = 0;
03516             }
03517         default:
03518         skip:
03519             in = '\0';
03520         skip2:
03521             while (*q && !ISDIGIT(*q)) {
03522                 if ((q[0] == 'a' || q[0] == 'A') &&
03523                     (q[1] == 'm' || q[1] == 'M')) {
03524                     ampm = 0;
03525                     ++q;
03526                 } else if ((q[0] == 'p' || q[0] == 'P') &&
03527                            (q[1] == 'm' || q[1] == 'M')) {
03528                     ampm = 1;
03529                     ++q;
03530                 }
03531                 ++q;
03532             }
03533         }
03534         p = q;
03535     }
03536     if ((m & 7) > 1 && (m & 8)) {
03537         /* ISO8601 timezone */
03538         if (p > str && ISDIGIT(*p)) {
03539             int nn, sign;
03540 
03541             q = p - 1;
03542             if (*q != '+' && *q != '-') {
03543                 goto done;
03544             }
03545             sign = (*q == '+') ? -1 : 1;
03546             q = NULL;
03547             n = strtol(p, &q, 10);
03548             if (!q || *q++ != ':' || !ISDIGIT(*q)) {
03549                 goto done;
03550             }
03551             p = q;
03552             q = NULL;
03553             nn = strtol(p, &q, 10);
03554             tss->minute += nn * sign;
03555             if ((SQLSMALLINT) tss->minute < 0) {
03556                 tss->hour -= 1;
03557                 tss->minute += 60;
03558             } else if (tss->minute >= 60) {
03559                 tss->hour += 1;
03560                 tss->minute -= 60;
03561             }
03562             tss->hour += n * sign;
03563             if ((SQLSMALLINT) tss->hour < 0) {
03564                 tss->day -= 1;
03565                 tss->hour += 24;
03566             } else if (tss->hour >= 24) {
03567                 tss->day += 1;
03568                 tss->hour -= 24;
03569             }
03570             if ((short) tss->day < 1 || tss->day >= 28) {
03571                 int mday, pday, pmon;
03572 
03573                 mday = getmdays(tss->year, tss->month);
03574                 pmon = tss->month - 1;
03575                 if (pmon < 1) {
03576                     pmon = 12;
03577                 }
03578                 pday = getmdays(tss->year, pmon);
03579                 if ((SQLSMALLINT) tss->day < 1) {
03580                     tss->month -= 1;
03581                     tss->day = pday;
03582                 } else if (tss->day > mday) {
03583                     tss->month += 1;
03584                     tss->day = 1;
03585                 }
03586                 if ((SQLSMALLINT) tss->month < 1) {
03587                     tss->year -= 1;
03588                     tss->month = 12;
03589                 } else if (tss->month > 12) {
03590                     tss->year += 1;
03591                     tss->month = 1;
03592                 }
03593             }
03594         }
03595     }
03596 done:
03597     if ((m & 1) &&
03598         (tss->month < 1 || tss->month > 12 ||
03599          tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
03600         if (sepc == '/') {
03601             /* Try MM/DD/YYYY format */
03602             int t[3];
03603 
03604             t[0] = tss->year;
03605             t[1] = tss->month;
03606             t[2] = tss->day;
03607             tss->year = t[2];
03608             tss->day = t[1];
03609             tss->month = t[0];
03610         }
03611     }
03612     /* Replace missing year/month/day with current date */
03613     if (!err && (m & 1) == 0) {
03614 #ifdef _WIN32
03615         SYSTEMTIME t;
03616 
03617         GetLocalTime(&t);
03618         tss->year = t.wYear;
03619         tss->month = t.wMonth;
03620         tss->day = t.wDay;
03621 #else
03622         struct timeval tv;
03623         struct tm tm;
03624 
03625         gettimeofday(&tv, NULL);
03626         tm = *localtime(&tv.tv_sec);
03627         tss->year = tm.tm_year + 1900;
03628         tss->month = tm.tm_mon + 1;
03629         tss->day = tm.tm_mday;
03630 #endif
03631     }
03632     /* Normalize fraction */
03633     if (tss->fraction < 0) {
03634         tss->fraction = 0;
03635     }
03636     /* Final check for overflow */
03637     if (err ||
03638         tss->month < 1 || tss->month > 12 ||
03639         tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
03640         tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
03641         return -1;
03642     }
03643     if ((m & 7) > 1) {
03644         if (ampm > 0) {
03645             if (tss->hour < 12) {
03646                 tss->hour += 12;
03647             }
03648         } else if (ampm == 0) {
03649             if (tss->hour == 12) {
03650                 tss->hour = 0;
03651             }
03652         }
03653     }
03654     return ((m & 7) < 1) ? -1 : 0;
03655 }
03656 
03663 static int
03664 getbool(char *string)
03665 {
03666     if (string) {
03667         return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
03668     }
03669     return 0;
03670 }
03671 
03679 static void
03680 blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03681 {
03682 #if 0
03683     DBC *d = (DBC *) sqlite3_user_data(ctx);
03684 #endif
03685     char *filename = 0;
03686 
03687     if (nargs > 0) {
03688         if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
03689             filename = (char *) sqlite3_value_text(args[0]);
03690         }
03691     }
03692     if (filename) {
03693 #ifdef _WIN32
03694         char *wname = utf_to_wmb(filename, -1);
03695         FILE *f;
03696 #else
03697         FILE *f = fopen(filename, "r");
03698 #endif
03699         char *p;
03700         long n, nn;
03701 
03702 #ifdef _WIN32
03703         if (wname) {
03704             f = fopen(wname, "rb");
03705         } else {
03706             sqlite3_result_error(ctx, "out of memory", -1);
03707             return;
03708         }
03709         uc_free(wname);
03710 #endif
03711         if (f) {
03712             if (fseek(f, 0, SEEK_END) == 0) {
03713                 n = ftell(f);
03714                 if (fseek(f, 0, SEEK_SET) == 0) {
03715                     p = sqlite3_malloc(n);
03716                     if (p) {
03717                         nn = fread(p, 1, n, f);
03718                         if (nn != n) {
03719                             sqlite3_result_error(ctx, "read error", -1);
03720                             sqlite3_free(p);
03721                         } else {
03722                             sqlite3_result_blob(ctx, p, n, sqlite3_free);
03723                         }
03724                     } else {
03725                         sqlite3_result_error(ctx, "out of memory", -1);
03726                     }
03727                 } else {
03728                     sqlite3_result_error(ctx, "seek error", -1);
03729                 }
03730             } else {
03731                 sqlite3_result_error(ctx, "seek error", -1);
03732             }
03733             fclose(f);
03734         } else {
03735             sqlite3_result_error(ctx, "cannot open file", -1);
03736         }
03737     } else {
03738         sqlite3_result_error(ctx, "no filename given", -1);
03739     }
03740 }
03741 
03749 static void
03750 blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03751 {
03752 #if 0
03753     DBC *d = (DBC *) sqlite3_user_data(ctx);
03754 #endif
03755     char *filename = 0;
03756     char *p = 0;
03757     int n = 0;
03758 
03759     if (nargs > 0) {
03760         p = (char *) sqlite3_value_blob(args[0]);
03761         n = sqlite3_value_bytes(args[0]);
03762     }
03763     if (nargs > 1) {
03764         if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
03765             filename = (char *) sqlite3_value_text(args[1]);
03766         }
03767     }
03768     if (p) {
03769         if (filename) {
03770 #ifdef _WIN32
03771             char *wname = utf_to_wmb(filename, -1);
03772             FILE *f;
03773 #else
03774             FILE *f = fopen(filename, "w");
03775 #endif
03776             int nn;
03777 
03778 #ifdef _WIN32
03779             if (wname) {
03780                 f = fopen(wname, "wb");
03781             } else {
03782                 sqlite3_result_error(ctx, "out of memory", -1);
03783                 return;
03784             }
03785             uc_free(wname);
03786 #endif
03787             if (f) {
03788                 nn = fwrite(p, 1, n, f);
03789                 fclose(f);
03790                 if (nn != n) {
03791                     sqlite3_result_error(ctx, "write error", -1);
03792                 } else {
03793                     sqlite3_result_int(ctx, nn);
03794                 }
03795             } else {
03796                 sqlite3_result_error(ctx, "cannot open file", -1);
03797             }
03798         } else {
03799             sqlite3_result_error(ctx, "no filename given", -1);
03800         }
03801     } else {
03802         sqlite3_result_null(ctx);
03803     }
03804 }
03805 
03813 static void
03814 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03815 dbtrace(void *arg, const char *msg, sqlite_uint64 et)
03816 #else
03817 dbtrace(void *arg, const char *msg)
03818 #endif
03819 {
03820     DBC *d = (DBC *) arg;
03821 
03822     if (msg && d->trace) {
03823         int len = strlen(msg);
03824 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03825         unsigned long s, f;
03826 #endif
03827 
03828         if (len > 0) {
03829             char *end = "\n";
03830 
03831             if (msg[len - 1] != ';') {
03832                 end = ";\n";
03833             }
03834             fprintf(d->trace, "%s%s", msg, end);
03835 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03836             s = et / 1000000000LL;
03837             f = et % 1000000000LL;
03838             fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
03839 #endif
03840             fflush(d->trace);
03841         }
03842     }
03843 }
03844 
03852 static void
03853 dbtraceapi(DBC *d, char *fn, const char *sql)
03854 {
03855     if (fn && d->trace) {
03856         if (sql) {
03857             fprintf(d->trace, "-- %s: %s\n", fn, sql);
03858         } else {
03859             fprintf(d->trace, "-- %s\n", fn);
03860         }
03861         fflush(d->trace);
03862     }
03863 }
03864 
03872 static void
03873 dbtracerc(DBC *d, int rc, char *err)
03874 {
03875     if (rc != SQLITE_OK && d->trace) {
03876         fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
03877         fprintf(d->trace, err ? ": %s\n" : "\n", err);
03878         fflush(d->trace);
03879     }
03880 }
03881 
03896 static SQLRETURN
03897 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
03898        char *spflag, char *ntflag, char *jmode, char *busy)
03899 {
03900     char *endp = NULL;
03901     int rc, tmp, busyto = 100000;
03902 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03903     int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
03904     char *uname = name;
03905     const char *vfs_name = NULL;
03906 #endif
03907 
03908     if (d->sqlite) {
03909         if (d->trace) {
03910             fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
03911                     d->dbname);
03912             fflush(d->trace);
03913         }
03914 #if defined(HAVE_SQLITE3CLOSEV2) && (HAVE_SQLITE3CLOSEV2)
03915         sqlite3_close_v2(d->sqlite);
03916 #else
03917         sqlite3_close(d->sqlite);
03918 #endif
03919         d->sqlite = NULL;
03920     }
03921 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03922     if (d->nocreat) {
03923         flags &= ~ SQLITE_OPEN_CREATE;
03924     }
03925 #if defined(_WIN32) || defined(_WIN64)
03926     if (!isu) {
03927         char expname[SQL_MAX_MESSAGE_LENGTH * 2];
03928 
03929         expname[0] = '\0';
03930         rc = ExpandEnvironmentStrings(name, expname, sizeof (expname));
03931         if (rc <= sizeof (expname)) {
03932             uname = wmb_to_utf(expname, rc - 1);
03933         } else {
03934             uname = wmb_to_utf(name, -1);
03935         }
03936         if (!uname) {
03937             rc = SQLITE_NOMEM;
03938             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
03939             return SQL_ERROR;
03940         }
03941     }
03942 #endif
03943 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
03944     vfs_name = nvfs_makevfs(uname);
03945 #endif
03946 #ifdef SQLITE_OPEN_URI
03947     flags |= SQLITE_OPEN_URI;
03948 #endif
03949     rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
03950 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
03951     if (uname != name) {
03952         uc_free(uname);
03953     }
03954 #endif
03955 #else
03956 #if defined(_WIN32) || defined(_WIN64)
03957     if (d->nocreat) {
03958         char *cname = NULL;
03959 
03960         if (isu) {
03961             cname = utf_to_wmb(name, -1);
03962         }
03963         if (GetFileAttributesA(cname ? cname : name) ==
03964             INVALID_FILE_ATTRIBUTES) {
03965             uc_free(cname);
03966             rc = SQLITE_CANTOPEN;
03967             setstatd(d, rc, "cannot open database",
03968                      (*d->ov3) ? "HY000" : "S1000");
03969             return SQL_ERROR;
03970         }
03971         uc_free(cname);
03972     }
03973 #else
03974     if (d->nocreat && access(name, 004) < 0) {
03975         rc = SQLITE_CANTOPEN;
03976         setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
03977         return SQL_ERROR;
03978     }
03979 #endif
03980 #if defined(_WIN32) || defined(_WIN64)
03981     if (!isu) {
03982         WCHAR *wname = wmb_to_uc(name, -1);
03983 
03984         if (!wname) {
03985             rc = SQLITE_NOMEM;
03986             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
03987             return SQL_ERROR;
03988         }
03989         rc = sqlite3_open16(wname, &d->sqlite);
03990         uc_free(wname);
03991     } else
03992 #endif
03993     rc = sqlite3_open(name, &d->sqlite);
03994 #endif /* !HAVE_SQLITE3VFS */
03995     if (rc != SQLITE_OK) {
03996 connfail:
03997         setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
03998         if (d->sqlite) {
03999             sqlite3_close(d->sqlite);
04000             d->sqlite = NULL;
04001         }
04002         return SQL_ERROR;
04003     }
04004 #if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
04005     if (d->pwd) {
04006         sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
04007     }
04008 #endif
04009     d->pwd = NULL;
04010     d->pwdLen = 0;
04011     if (d->trace) {
04012 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
04013         sqlite3_profile(d->sqlite, dbtrace, d);
04014 #else
04015         sqlite3_trace(d->sqlite, dbtrace, d);
04016 #endif
04017     }
04018     d->step_enable = getbool(sflag);
04019     d->trans_disable = getbool(ntflag);
04020     d->curtype = d->step_enable ?
04021         SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
04022     tmp = strtol(busy, &endp, 0);
04023     if (endp && *endp == '\0' && endp != busy) {
04024         busyto = tmp;
04025     }
04026     if (busyto < 1 || busyto > 1000000) {
04027         busyto = 1000000;
04028     }
04029     d->timeout = busyto;
04030     freep(&d->dbname);
04031     d->dbname = xstrdup(name);
04032     freep(&d->dsn);
04033     d->dsn = xstrdup(dsn);
04034     if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
04035         if (d->trace) {
04036             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
04037                     d->dbname);
04038             fflush(d->trace);
04039         }
04040         sqlite3_close(d->sqlite);
04041         d->sqlite = NULL;
04042         goto connfail;
04043     }
04044     if (!spflag || spflag[0] == '\0') {
04045         spflag = "NORMAL";
04046     }
04047     if (spflag[0] != '\0') {
04048         char syncp[128];
04049 
04050         sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
04051         sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
04052     }
04053     if (jmode[0] != '\0') {
04054         char jourp[128];
04055 
04056         sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
04057         sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
04058     }
04059     if (d->trace) {
04060         fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
04061         fflush(d->trace);
04062     }
04063 #if defined(_WIN32) || defined(_WIN64)
04064     {
04065         char pname[MAX_PATH];
04066         HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
04067                                FALSE, GetCurrentProcessId());
04068 
04069         pname[0] = '\0';
04070         if (h) {
04071             HMODULE m = NULL, l = LoadLibrary("psapi.dll");
04072             DWORD need;
04073             typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
04074             typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
04075             epmfunc epm;
04076             gmbfunc gmb;
04077 
04078             if (l) {
04079                 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
04080                 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
04081                 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
04082                     gmb(h, m, pname, sizeof (pname));
04083                 }
04084                 FreeLibrary(l);
04085             }
04086             CloseHandle(h);
04087         }
04088         d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
04089                      strncasecmp(pname, "MSQRY", 5) == 0;
04090         if (d->trace && d->xcelqrx) {
04091 
04092             fprintf(d->trace, "-- enabled EXCEL quirks\n");
04093             fflush(d->trace);
04094         }
04095     }
04096 #endif
04097     sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
04098                             d, blob_import, 0, 0);
04099     sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
04100                             d, blob_export, 0, 0);
04101     return SQL_SUCCESS;
04102 }
04103 
04110 static void
04111 dbloadext(DBC *d, char *exts)
04112 {
04113 #if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
04114     char *p;
04115     char path[SQL_MAX_MESSAGE_LENGTH];
04116     int plen = 0;
04117 
04118     if (!d->sqlite) {
04119         return;
04120     }
04121     sqlite3_enable_load_extension(d->sqlite, 1);
04122 #if defined(_WIN32) || defined(_WIN64)
04123     GetModuleFileName(hModule, path, sizeof (path));
04124     p = strrchr(path, '\\');
04125     plen = p ? ((p + 1) - path) : 0;
04126 #endif
04127     do {
04128         p = strchr(exts, ',');
04129         if (p) {
04130             strncpy(path + plen, exts, p - exts);
04131             path[plen + (p - exts)] = '\0';
04132         } else {
04133             strcpy(path + plen, exts);
04134         }
04135         if (exts[0]) {
04136             char *errmsg = NULL;
04137             int rc;
04138 #if defined(_WIN32) || defined(_WIN64)
04139             int i;
04140             char *q;
04141 
04142             q = path + plen;
04143             if (!(q[0] &&
04144                   ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
04145                    q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
04146                 q = path;
04147             }
04148             /* sqlite3_load_extension() dislikes backslashes */
04149             for (i = 0; q[i] != '\0'; i++) {
04150                 if (q[i] == '\\') {
04151                     q[i] = '/';
04152                 }
04153             }
04154             rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
04155 #else
04156             rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
04157 #endif
04158             if (rc != SQLITE_OK) {
04159 #if defined(_WIN32) || defined(_WIN64)
04160                 char buf[512], msg[512];
04161 
04162                 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
04163                 wsprintf(msg, buf, q, errmsg ?
04164                          errmsg : "no error info available");
04165                 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
04166                 MessageBox(NULL, msg, buf,
04167                            MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
04168                            MB_SETFOREGROUND);
04169 #else
04170                 fprintf(stderr, "extension '%s' did not load%s%s\n",
04171                         path, errmsg ? ": " : "", errmsg ? errmsg : "");
04172 #endif
04173             }
04174         }
04175         if (p) {
04176             exts = p + 1;
04177         }
04178     } while (p);
04179 #endif /* HAVE_SQLITE3LOADEXTENSION */
04180 }
04181 
04191 static char *
04192 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
04193 {
04194     char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
04195     char guess[64];
04196 
04197     guess[0] = '\0';
04198     if (!typename) {
04199         int coltype = sqlite3_column_type(s3stmt, col);
04200 
04201         if (guessed_types) {
04202             guessed_types[0]++;
04203         }
04204         if (d->trace) {
04205             sprintf(guess, " (guessed from %d)", coltype);
04206         }
04207         switch (coltype) {
04208         case SQLITE_INTEGER: typename = "integer"; break;
04209         case SQLITE_FLOAT:   typename = "double";  break;
04210         default:
04211         case SQLITE_TEXT:    typename = "varchar"; break;
04212         case SQLITE_BLOB:    typename = "blob";    break;
04213 #if 0
04214         case SQLITE_NULL:    typename = "null";    break;
04215 #endif
04216         }
04217     }
04218     if (d->trace) {
04219         fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
04220                 guess, typename);
04221         fflush(d->trace);
04222     }
04223     return typename;
04224 }
04225 
04226 #ifdef FULL_METADATA
04227 
04236 static void
04237 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
04238 {
04239     int nn = 0, pk = 0, ai = 0;
04240     const char *dn = NULL, *tn = NULL, *cn = NULL, *dummy[4];
04241 
04242     dn = sqlite3_column_database_name(s3stmt, col);
04243     tn = sqlite3_column_table_name(s3stmt, col);
04244     cn = sqlite3_column_origin_name(s3stmt, col);
04245     dummy[0] = dummy[1] = 0;
04246     if (tn && cn) {
04247         sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
04248                                       dummy, dummy + 1,
04249                                       &nn, &pk, &ai);
04250     }
04251     ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
04252     ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
04253     ci->ispk = pk ? 1 : 0;
04254     if (d->trace) {
04255         fprintf(d->trace, "-- column %d %s\n",
04256                 col + 1, nn ? "notnull" : "nullable");
04257         if (ai) {
04258             fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
04259         }
04260         fflush(d->trace);
04261     }
04262     ci->isrowid = 0;
04263     if (ci->ispk && tn) {
04264         nn = pk = ai = 0;
04265         dummy[2] = dummy[3] = 0;
04266 
04267         sqlite3_table_column_metadata(d->sqlite, dn, tn, "rowid",
04268                                       dummy + 2, dummy + 3,
04269                                       &nn, &pk, &ai);
04270         if (pk && dummy[0] && dummy[0] == dummy[2]) {
04271             ci->isrowid = 1;
04272         }
04273     }
04274 }
04275 
04276 #endif
04277 
04284 static int
04285 s3stmt_step(STMT *s)
04286 {
04287     DBC *d = (DBC *) s->dbc;
04288     char **rowd = NULL;
04289     const char *errp = NULL;
04290     int i, ncols, rc;
04291 
04292     if (s != d->cur_s3stmt || !s->s3stmt) {
04293         setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
04294         return SQL_ERROR;
04295     }
04296     rc = sqlite3_step(s->s3stmt);
04297     if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
04298         ++s->s3stmt_rownum;
04299         ncols = sqlite3_column_count(s->s3stmt);
04300         if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
04301             PTRDIFF_T size;
04302             char *p;
04303             COL *dyncols;
04304             const char *colname, *typename;
04305 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04306             char *tblname;
04307 #endif
04308 
04309             for (i = size = 0; i < ncols; i++) {
04310                 colname = sqlite3_column_name(s->s3stmt, i);
04311                 size += 3 + 3 * strlen(colname);
04312             }
04313 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04314             tblname = (char *) size;
04315             for (i = 0; i < ncols; i++) {
04316                 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
04317                 size += 2 + (p ? strlen(p) : 0);
04318             }
04319 #endif
04320             dyncols = xmalloc(ncols * sizeof (COL) + size);
04321             if (!dyncols) {
04322                 freedyncols(s);
04323                 s->ncols = 0;
04324                 dbtraceapi(d, "sqlite3_finalize", 0);
04325                 sqlite3_finalize(s->s3stmt);
04326                 s->s3stmt = NULL;
04327                 d->cur_s3stmt = NULL;
04328                 return nomem(s);
04329             }
04330             p = (char *) (dyncols + ncols);
04331 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04332             tblname = p + (PTRDIFF_T) tblname;
04333 #endif
04334             for (i = 0; i < ncols; i++) {
04335                 char *q;
04336 
04337                 colname = sqlite3_column_name(s->s3stmt, i);
04338                 if (d->trace) {
04339                     fprintf(d->trace, "-- column %d name: '%s'\n",
04340                             i + 1, colname);
04341                     fflush(d->trace);
04342                 }
04343 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04344                 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
04345                 strcpy(tblname, q ? q : "");
04346                 if (d->trace) {
04347                     fprintf(d->trace, "-- table %d name: '%s'\n",
04348                             i + 1, tblname);
04349                     fflush(d->trace);
04350                 }
04351                 dyncols[i].table = tblname;
04352                 tblname += strlen(tblname) + 1;
04353 #endif
04354                 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
04355                 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
04356                 strcpy(p, colname);
04357                 dyncols[i].label = p;
04358                 p += strlen(p) + 1;
04359                 q = strchr(colname, '.');
04360                 if (q) {
04361                     char *q2 = strchr(q + 1, '.');
04362 
04363                     /* SQLite 3.3.4 produces view.table.column sometimes */
04364                     if (q2) {
04365                         q = q2;
04366                     }
04367                 }
04368                 if (q) {
04369 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04370                     dyncols[i].table = p;
04371 #endif
04372                     strncpy(p, colname, q - colname);
04373                     p[q - colname] = '\0';
04374                     p += strlen(p) + 1;
04375                     strcpy(p, q + 1);
04376                     dyncols[i].column = p;
04377                     p += strlen(p) + 1;
04378                 } else {
04379 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04380                     dyncols[i].table = "";
04381 #endif
04382                     strcpy(p, colname);
04383                     dyncols[i].column = p;
04384                     p += strlen(p) + 1;
04385                 }
04386                 if (s->longnames) {
04387                     dyncols[i].column = dyncols[i].label;
04388                 }
04389 #ifdef SQL_LONGVARCHAR
04390                 dyncols[i].type = SQL_LONGVARCHAR;
04391                 dyncols[i].size = 65535;
04392 #else
04393                 dyncols[i].type = SQL_VARCHAR;
04394                 dyncols[i].size = 255;
04395 #endif
04396                 dyncols[i].index = i;
04397                 dyncols[i].scale = 0;
04398                 dyncols[i].prec = 0;
04399                 dyncols[i].nosign = 1;
04400                 dyncols[i].autoinc = SQL_FALSE;
04401                 dyncols[i].notnull = SQL_NULLABLE;
04402                 dyncols[i].ispk = -1;
04403                 dyncols[i].isrowid = -1;
04404 #ifdef FULL_METADATA
04405                 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
04406 #endif
04407                 dyncols[i].typename = xstrdup(typename);
04408             }
04409             freedyncols(s);
04410             s->ncols = s->dcols = ncols;
04411             s->dyncols = s->cols = dyncols;
04412             fixupdyncols(s, d);
04413             mkbindcols(s, s->ncols);
04414             d->s3stmt_needmeta = 0;
04415         }
04416         if (ncols <= 0) {
04417             goto killstmt;
04418         }
04419         if (rc == SQLITE_DONE) {
04420             freeresult(s, 0);
04421             s->nrows = 0;
04422             dbtraceapi(d, "sqlite3_finalize", 0);
04423             sqlite3_finalize(s->s3stmt);
04424             s->s3stmt = NULL;
04425             d->cur_s3stmt = NULL;
04426             return SQL_SUCCESS;
04427         }
04428         rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
04429         if (rowd) {
04430             const unsigned char *value;
04431 
04432             rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
04433             ++rowd;
04434             for (i = 0; i < ncols; i++) {
04435                 int coltype = sqlite3_column_type(s->s3stmt, i);
04436 
04437                 rowd[i] = rowd[i + ncols] = NULL;
04438                 if (coltype == SQLITE_BLOB) {
04439                     int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
04440                     char *qp;
04441                     unsigned const char *bp;
04442 
04443                     bp = sqlite3_column_blob(s->s3stmt, i);
04444                     qp = xmalloc(nbytes * 2 + 4);
04445                     if (qp) {
04446                         rowd[i + ncols] = qp;
04447                         *qp++ = 'X';
04448                         *qp++ = '\'';
04449                         for (k = 0; k < nbytes; k++) {
04450                             *qp++ = xdigits[(bp[k] >> 4)];
04451                             *qp++ = xdigits[(bp[k] & 0xF)];
04452                         }
04453                         *qp++ = '\'';
04454                         *qp = '\0';
04455                     }
04456 #ifdef _MSC_VER
04457                 } else if (coltype == SQLITE_FLOAT) {
04458                     struct lconv *lc = 0;
04459                     double d = sqlite3_column_double(s->s3stmt, i);
04460                     char *p, buffer[128];
04461 
04462                     /*
04463                      * This avoids floating point rounding
04464                      * and formatting problems of some SQLite
04465                      * versions in conjunction with MSVC 2010.
04466                      */
04467                     snprintf(buffer, sizeof (buffer), "%.15g", d);
04468                     lc = localeconv();
04469                     if (lc && lc->decimal_point && lc->decimal_point[0] &&
04470                         lc->decimal_point[0] != '.') {
04471                         p = strchr(buffer, lc->decimal_point[0]);
04472                         if (p) {
04473                             *p = '.';
04474                         }
04475                     }
04476                     rowd[i + ncols] = xstrdup(buffer);
04477 #endif
04478                 } else if (coltype != SQLITE_NULL) {
04479                     value = sqlite3_column_text(s->s3stmt, i);
04480                     rowd[i + ncols] = xstrdup((char *) value);
04481                 }
04482             }
04483             for (i = 0; i < ncols; i++) {
04484                 int coltype = sqlite3_column_type(s->s3stmt, i);
04485 
04486                 value = NULL;
04487                 if (coltype == SQLITE_BLOB) {
04488                     value = sqlite3_column_blob(s->s3stmt, i);
04489                 } else if (coltype != SQLITE_NULL) {
04490                     value = sqlite3_column_text(s->s3stmt, i);
04491                 }
04492                 if (value && !rowd[i + ncols]) {
04493                     freerows(rowd);
04494                     rowd = 0;
04495                     break;
04496                 }
04497             }
04498         }
04499         if (rowd) {
04500             freeresult(s, 0);
04501             s->nrows = 1;
04502             s->rows = rowd;
04503             s->rowfree = freerows;
04504             if (rc == SQLITE_DONE) {
04505                 dbtraceapi(d, "sqlite3_finalize", 0);
04506                 sqlite3_finalize(s->s3stmt);
04507                 s->s3stmt = NULL;
04508                 d->cur_s3stmt = NULL;
04509             }
04510             return SQL_SUCCESS;
04511         }
04512     }
04513 killstmt:
04514     dbtraceapi(d, "sqlite3_reset", 0);
04515     rc = sqlite3_reset(s->s3stmt);
04516     s->s3stmt_noreset = 1;
04517     errp = sqlite3_errmsg(d->sqlite);
04518     if (d->cur_s3stmt == s) {
04519         d->cur_s3stmt = NULL;
04520     }
04521     setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04522             errp ? errp : "unknown error", rc);
04523     return SQL_ERROR;
04524 }
04525 
04531 static void
04532 s3stmt_end(STMT *s)
04533 {
04534     DBC *d;
04535 
04536     if (!s || !s->s3stmt) {
04537         return;
04538     }
04539     d = (DBC *) s->dbc;
04540     if (d) {
04541         d->busyint = 0;
04542     }
04543     if (!s->s3stmt_noreset) {
04544         dbtraceapi(d, "sqlite3_reset", 0);
04545         sqlite3_reset(s->s3stmt);
04546         s->s3stmt_noreset = 1;
04547         s->s3stmt_rownum = -1;
04548     }
04549     if (d->cur_s3stmt == s) {
04550         d->cur_s3stmt = NULL;
04551     }
04552 }
04553 
04559 static void
04560 s3stmt_end_if(STMT *s)
04561 {
04562     DBC *d = (DBC *) s->dbc;
04563 
04564     if (d) {
04565         d->busyint = 0;
04566     }
04567     if (d && d->cur_s3stmt == s) {
04568         s3stmt_end(s);
04569     }
04570 }
04571 
04577 static void
04578 s3stmt_drop(STMT *s)
04579 {
04580     if (s->s3stmt) {
04581         DBC *d = (DBC *) s->dbc;
04582 
04583         if (d) {
04584             dbtraceapi(d, "sqlite3_finalize", 0);
04585         }
04586         sqlite3_finalize(s->s3stmt);
04587         s->s3stmt = NULL;
04588         s->s3stmt_rownum = 0;
04589     }
04590 }
04591 
04598 static SQLRETURN
04599 s3stmt_start(STMT *s)
04600 {
04601     DBC *d = (DBC *) s->dbc;
04602     const char *endp;
04603     sqlite3_stmt *s3stmt = NULL;
04604     int rc, nretry = 0;
04605 
04606     d->s3stmt_needmeta = 0;
04607     if (!s->s3stmt) {
04608 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04609         dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
04610 #else
04611         dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
04612 #endif
04613         do {
04614             s3stmt = NULL;
04615 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04616             rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
04617                                     &s3stmt, &endp);
04618 #else
04619             rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
04620                                  &s3stmt, &endp);
04621 #endif
04622             if (rc != SQLITE_OK) {
04623                 if (s3stmt) {
04624                     sqlite3_finalize(s3stmt);
04625                     s3stmt = NULL;
04626                 }
04627             }
04628         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
04629         dbtracerc(d, rc, NULL);
04630         if (rc != SQLITE_OK) {
04631             if (s3stmt) {
04632                 dbtraceapi(d, "sqlite3_finalize", NULL);
04633                 sqlite3_finalize(s3stmt);
04634             }
04635             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04636                     sqlite3_errmsg(d->sqlite), rc);
04637             return SQL_ERROR;
04638         }
04639         if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
04640             dbtraceapi(d, "sqlite3_finalize", 0);
04641             sqlite3_finalize(s3stmt);
04642             setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
04643                     (*s->ov3) ? "HY000" : "S1000");
04644             return SQL_ERROR;
04645         }
04646         s->s3stmt = s3stmt;
04647         s->s3stmt_noreset = 1;
04648         d->s3stmt_needmeta = 1;
04649     }
04650     d->cur_s3stmt = s;
04651     s->s3stmt_rownum = -1;
04652     s3bind(d, s->s3stmt, s->nparams, s->bindparms);
04653     return SQL_SUCCESS;
04654 }
04655 
04656 #ifndef WINTERFACE
04657 
04661 SQLRETURN SQL_API
04662 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
04663                SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04664                SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04665 {
04666     if (env == SQL_NULL_HENV) {
04667         return SQL_INVALID_HANDLE;
04668     }
04669     return SQL_ERROR;
04670 }
04671 #endif
04672 
04673 #ifdef WINTERFACE
04674 
04678 SQLRETURN SQL_API
04679 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
04680                 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04681                 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04682 {
04683     if (env == SQL_NULL_HENV) {
04684         return SQL_INVALID_HANDLE;
04685     }
04686     return SQL_ERROR;
04687 }
04688 #endif
04689 
04690 #ifndef WINTERFACE
04691 
04695 SQLRETURN SQL_API
04696 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
04697            SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04698            SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04699 {
04700     if (env == SQL_NULL_HENV) {
04701         return SQL_INVALID_HANDLE;
04702     }
04703     return SQL_ERROR;
04704 }
04705 #endif
04706 
04707 #ifdef WINTERFACE
04708 
04712 SQLRETURN SQL_API
04713 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
04714             SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04715             SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04716 {
04717     if (env == SQL_NULL_HENV) {
04718         return SQL_INVALID_HANDLE;
04719     }
04720     return SQL_ERROR;
04721 }
04722 #endif
04723 
04724 #ifndef WINTERFACE
04725 
04729 SQLRETURN SQL_API
04730 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
04731                  SQLCHAR *connout, SQLSMALLINT connoutMax,
04732                  SQLSMALLINT *connoutLen)
04733 {
04734     SQLRETURN ret;
04735 
04736     HDBC_LOCK(dbc);
04737     ret = drvunimpldbc(dbc);
04738     HDBC_UNLOCK(dbc);
04739     return ret;
04740 }
04741 #endif
04742 
04743 #ifdef WINTERFACE
04744 
04748 SQLRETURN SQL_API
04749 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
04750                   SQLWCHAR *connout, SQLSMALLINT connoutMax,
04751                   SQLSMALLINT *connoutLen)
04752 {
04753     SQLRETURN ret;
04754 
04755     HDBC_LOCK(dbc);
04756     ret = drvunimpldbc(dbc);
04757     HDBC_UNLOCK(dbc);
04758     return ret;
04759 }
04760 #endif
04761 
04770 static SQLRETURN
04771 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
04772 {
04773     STMT *s;
04774     int i, dlen, done = 0;
04775     BINDPARM *p;
04776 
04777     if (stmt == SQL_NULL_HSTMT) {
04778         return SQL_INVALID_HANDLE;
04779     }
04780     s = (STMT *) stmt;
04781     if (!s->query || s->nparams <= 0) {
04782 seqerr:
04783         setstat(s, -1, "sequence error", "HY010");
04784         return SQL_ERROR;
04785     }
04786     for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
04787         p = &s->bindparms[i];
04788         if (p->need > 0) {
04789             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
04790 
04791             if (len == SQL_NULL_DATA) {
04792                 freep(&p->parbuf);
04793                 p->param = NULL;
04794                 p->len = SQL_NULL_DATA;
04795                 p->need = -1;
04796             } else if (type != SQL_C_CHAR
04797 #ifdef WCHARSUPPORT
04798                        && type != SQL_C_WCHAR
04799 #endif
04800                        && type != SQL_C_BINARY) {
04801                 int size = 0;
04802 
04803                 switch (type) {
04804                 case SQL_C_TINYINT:
04805                 case SQL_C_UTINYINT:
04806                 case SQL_C_STINYINT:
04807 #ifdef SQL_BIT
04808                 case SQL_C_BIT:
04809 #endif
04810                     size = sizeof (SQLCHAR);
04811                     break;
04812                 case SQL_C_SHORT:
04813                 case SQL_C_USHORT:
04814                 case SQL_C_SSHORT:
04815                     size = sizeof (SQLSMALLINT);
04816                     break;
04817                 case SQL_C_LONG:
04818                 case SQL_C_ULONG:
04819                 case SQL_C_SLONG:
04820                     size = sizeof (SQLINTEGER);
04821                     break;
04822 #ifdef SQL_BIGINT
04823                 case SQL_C_UBIGINT:
04824                 case SQL_C_SBIGINT:
04825                     size = sizeof (SQLBIGINT);
04826                     break;
04827 #endif
04828                 case SQL_C_FLOAT:
04829                     size = sizeof (float);
04830                     break;
04831                 case SQL_C_DOUBLE:
04832                     size = sizeof (double);
04833                     break;
04834 #ifdef SQL_C_TYPE_DATE
04835                 case SQL_C_TYPE_DATE:
04836 #endif
04837                 case SQL_C_DATE:
04838                     size = sizeof (DATE_STRUCT);
04839                     break;
04840 #ifdef SQL_C_TYPE_DATE
04841                 case SQL_C_TYPE_TIME:
04842 #endif
04843                 case SQL_C_TIME:
04844                     size = sizeof (TIME_STRUCT);
04845                     break;
04846 #ifdef SQL_C_TYPE_DATE
04847                 case SQL_C_TYPE_TIMESTAMP:
04848 #endif
04849                 case SQL_C_TIMESTAMP:
04850                     size = sizeof (TIMESTAMP_STRUCT);
04851                     break;
04852                 }
04853                 freep(&p->parbuf);
04854                 p->parbuf = xmalloc(size);
04855                 if (!p->parbuf) {
04856                     return nomem(s);
04857                 }
04858                 p->param = p->parbuf;
04859                 memcpy(p->param, data, size);
04860                 p->len = size;
04861                 p->need = -1;
04862             } else if (len == SQL_NTS && (
04863                        type == SQL_C_CHAR
04864 #ifdef WCHARSUPPORT
04865                        || type == SQL_C_WCHAR
04866 #endif
04867                       )) {
04868                 char *dp = data;
04869 
04870 #ifdef WCHARSUPPORT
04871                 if (type == SQL_C_WCHAR) {
04872                     dp = uc_to_utf(data, len);
04873                     if (!dp) {
04874                         return nomem(s);
04875                     }
04876                 }
04877 #endif
04878 #if defined(_WIN32) || defined(_WIN64)
04879                 if (*s->oemcp) {
04880                     dp = wmb_to_utf(data, strlen (data));
04881                     if (!dp) {
04882                         return nomem(s);
04883                     }
04884                 }
04885 #endif
04886                 dlen = strlen(dp);
04887                 freep(&p->parbuf);
04888                 p->parbuf = xmalloc(dlen + 1);
04889                 if (!p->parbuf) {
04890                     if (dp != data) {
04891                         uc_free(dp);
04892                     }
04893                     return nomem(s);
04894                 }
04895                 p->param = p->parbuf;
04896                 strcpy(p->param, dp);
04897                 if (dp != data) {
04898                     uc_free(dp);
04899                 }
04900                 p->len = dlen;
04901                 p->need = -1;
04902             } else if (len < 0) {
04903                 setstat(s, -1, "invalid length", "HY090");
04904                 return SQL_ERROR;
04905             } else {
04906                 dlen = min(p->len - p->offs, len);
04907                 if (!p->param) {
04908                     setstat(s, -1, "no memory for parameter", "HY013");
04909                     return SQL_ERROR;
04910                 }
04911                 memcpy((char *) p->param + p->offs, data, dlen);
04912                 p->offs += dlen;
04913                 if (p->offs >= p->len) {
04914 #ifdef WCHARSUPPORT
04915                     if (type == SQL_C_WCHAR) {
04916                         char *dp = uc_to_utf(p->param, p->len);
04917                         char *np;
04918                         int nlen;
04919 
04920                         if (!dp) {
04921                             return nomem(s);
04922                         }
04923                         nlen = strlen(dp);
04924                         np = xmalloc(nlen + 1);
04925                         if (!np) {
04926                             uc_free(dp);
04927                             return nomem(s);
04928                         }
04929                         strcpy(np, dp);
04930                         uc_free(dp);
04931                         if (p->param == p->parbuf) {
04932                             freep(&p->parbuf);
04933                         }
04934                         p->parbuf = p->param = np;
04935                         p->len = nlen;
04936                     } else {
04937                         *((char *) p->param + p->len) = '\0';
04938                     }
04939                     p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
04940                             ? -1 : 0;
04941 #else
04942                     *((char *) p->param + p->len) = '\0';
04943                     p->need = (type == SQL_C_CHAR) ? -1 : 0;
04944 #endif
04945 #if defined(_WIN32) || defined(_WIN64)
04946                     if (type == SQL_C_CHAR && *s->oemcp &&
04947                         !(p->stype == SQL_BINARY ||
04948                           p->stype == SQL_VARBINARY ||
04949                           p->stype == SQL_LONGVARBINARY)) {
04950                         char *dp = wmb_to_utf(p->param, p->len);
04951 
04952                         if (!dp) {
04953                             return nomem(s);
04954                         }
04955                         if (p->param == p->parbuf) {
04956                             freep(&p->parbuf);
04957                         }
04958                         p->parbuf = p->param = dp;
04959                         p->len = strlen(dp);
04960                     }
04961                     if (p->type == SQL_C_WCHAR &&
04962                         (p->stype == SQL_VARCHAR ||
04963                          p->stype == SQL_LONGVARCHAR) &&
04964                          p->len == p->coldef * sizeof (SQLWCHAR)) {
04965                         /* fix for MS-Access */
04966                         p->len = p->coldef;
04967                     }
04968 #endif
04969                 }
04970             }
04971             done = 1;
04972             break;
04973         }
04974     }
04975     if (!done) {
04976         goto seqerr;
04977     }
04978     return SQL_SUCCESS;
04979 }
04980 
04989 SQLRETURN SQL_API
04990 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
04991 {
04992     SQLRETURN ret;
04993 
04994     HSTMT_LOCK(stmt);
04995     ret = drvputdata(stmt, data, len);
04996     HSTMT_UNLOCK(stmt);
04997     return ret;
04998 }
04999 
05005 static SQLRETURN
05006 freeparams(STMT *s)
05007 {
05008     if (s->bindparms) {
05009         int n;
05010 
05011         for (n = 0; n < s->nbindparms; n++) {
05012             freep(&s->bindparms[n].parbuf);
05013             memset(&s->bindparms[n], 0, sizeof (BINDPARM));
05014         }
05015     }
05016     return SQL_SUCCESS;
05017 }
05018 
05030 static SQLRETURN
05031 setupparam(STMT *s, char *sql, int pnum)
05032 {
05033     int type, len = 0, needalloc = 0;
05034     BINDPARM *p;
05035 
05036     if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
05037         goto error;
05038     }
05039     p = &s->bindparms[pnum];
05040     type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05041 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
05042     /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
05043     if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
05044         type = SQL_C_CHAR;
05045     }
05046 #endif
05047     if (p->need > 0) {
05048         return setupparbuf(s, p);
05049     }
05050     p->strbuf[0] = '\0';
05051     if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
05052         p->s3type = SQLITE_NULL;
05053         p->s3size = 0;
05054         return SQL_SUCCESS;
05055     }
05056     if (type == SQL_C_CHAR &&
05057         (p->stype == SQL_BINARY ||
05058          p->stype == SQL_VARBINARY ||
05059          p->stype == SQL_LONGVARBINARY)) {
05060         type = SQL_C_BINARY;
05061     }
05062     switch (type) {
05063     case SQL_C_BINARY:
05064         p->s3type = SQLITE_BLOB;
05065         p->s3size = p->len;
05066         p->s3val = p->param;
05067         if (p->need < 0) {
05068             break;
05069         }
05070         if (!p->lenp) {
05071             len = p->len;
05072         } else if (*p->lenp == SQL_DATA_AT_EXEC) {
05073             len = p->len;
05074         } else {
05075             len = *p->lenp;
05076             if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
05077                 len = SQL_LEN_DATA_AT_EXEC(len);
05078             }
05079         }
05080         if (len < 0) {
05081             setstat(s, -1, "invalid length", "HY009");
05082             return SQL_ERROR;
05083         }
05084         p->len = len;
05085         p->max = p->len;
05086         p->need = -1;
05087         p->s3size = len;
05088         break;
05089 #ifdef WCHARSUPPORT
05090     case SQL_C_WCHAR:
05091 #endif
05092     case SQL_C_CHAR:
05093         p->s3type = SQLITE_TEXT;
05094         p->s3size = -1;
05095         p->s3val = p->param;
05096         if (!p->parbuf) {
05097 #ifdef WCHARSUPPORT
05098             if (type == SQL_C_WCHAR) {
05099                 if (!p->lenp || *p->lenp == SQL_NTS) {
05100                     p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
05101                 } else if (*p->lenp >= 0) {
05102                     p->max = *p->lenp;
05103                 }
05104             } else
05105 #endif
05106             if (type == SQL_C_CHAR) {
05107                 if (!p->lenp || *p->lenp == SQL_NTS) {
05108                     p->len = p->max = strlen(p->param);
05109 #if defined(_WIN32) || defined(_WIN64)
05110                     needalloc = 1;
05111 #endif
05112                 } else if (*p->lenp >= 0) {
05113                     p->len = p->max = *p->lenp;
05114                     needalloc = 1;
05115                 }
05116             }
05117         }
05118         if (p->need < 0 && p->parbuf == p->param) {
05119             break;
05120         }
05121 #ifdef WCHARSUPPORT
05122         if (type == SQL_C_WCHAR) {
05123             char *dp = uc_to_utf(p->param, p->max);
05124 
05125             if (!dp) {
05126                 return nomem(s);
05127             }
05128             if (p->param == p->parbuf) {
05129                 freep(&p->parbuf);
05130             }
05131             p->parbuf = p->param = dp;
05132             p->need = -1;
05133             p->len = strlen(p->param);
05134             p->s3val = p->param;
05135             p->s3size = p->len;
05136         } else
05137 #endif
05138         if (type == SQL_C_CHAR) {
05139             p->s3val = p->param;
05140             if (needalloc) {
05141                 char *dp;
05142 
05143 #if defined(_WIN32) || defined(_WIN64)
05144                 if (*s->oemcp) {
05145                     dp = wmb_to_utf(p->param, p->len);
05146                 } else {
05147                     dp = xmalloc(p->len + 1);
05148                 }
05149 #else
05150                 dp = xmalloc(p->len + 1);
05151 #endif
05152                 if (!dp) {
05153                     return nomem(s);
05154                 }
05155 #if defined(_WIN32) || defined(_WIN64)
05156                 if (*s->oemcp) {
05157                     p->len = strlen(dp);
05158                 } else {
05159                     memcpy(dp, p->param, p->len);
05160                     dp[p->len] = '\0';
05161                 }
05162 #else
05163                 memcpy(dp, p->param, p->len);
05164                 dp[p->len] = '\0';
05165 #endif
05166                 if (p->param == p->parbuf) {
05167                     freep(&p->parbuf);
05168                 }
05169                 p->parbuf = p->param = dp;
05170                 p->need = -1;
05171                 p->s3val = p->param;
05172                 p->s3size = p->len;
05173             }
05174         }
05175         break;
05176     case SQL_C_UTINYINT:
05177     case SQL_C_TINYINT:
05178     case SQL_C_STINYINT:
05179         p->s3type = SQLITE_INTEGER;
05180         p->s3size = sizeof (int);
05181         p->s3ival = *((SQLCHAR *) p->param);
05182         break;
05183     case SQL_C_USHORT:
05184         p->s3type = SQLITE_INTEGER;
05185         p->s3size = sizeof (int);
05186         p->s3ival = *((SQLUSMALLINT *) p->param);
05187         break;
05188     case SQL_C_SHORT:
05189     case SQL_C_SSHORT:
05190         p->s3type = SQLITE_INTEGER;
05191         p->s3size = sizeof (int);
05192         p->s3ival = *((SQLSMALLINT *) p->param);
05193         break;
05194     case SQL_C_ULONG:
05195         p->s3type = SQLITE_INTEGER;
05196         p->s3size = sizeof (int);
05197         p->s3ival = *((SQLUINTEGER *) p->param);
05198         break;
05199     case SQL_C_LONG:
05200     case SQL_C_SLONG:
05201         p->s3type = SQLITE_INTEGER;
05202         p->s3size = sizeof (int);
05203         p->s3ival = *((SQLINTEGER *) p->param);
05204         break;
05205 #ifdef SQL_BIT
05206     case SQL_C_BIT:
05207         p->s3type = SQLITE_INTEGER;
05208         p->s3size = sizeof (int);
05209         p->s3ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
05210         break;
05211 #endif
05212 #ifdef SQL_BIGINT
05213     case SQL_C_SBIGINT:
05214         p->s3type = SQLITE_INTEGER;
05215         p->s3size = sizeof (sqlite_int64);
05216         p->s3lival = *((sqlite_int64 *) p->param);
05217         break;
05218     case SQL_C_UBIGINT:
05219         p->s3type = SQLITE_INTEGER;
05220         p->s3size = sizeof (sqlite_int64);
05221         p->s3lival = *((sqlite_uint64 *) p->param);
05222         break;
05223 #endif
05224     case SQL_C_FLOAT:
05225         p->s3type = SQLITE_FLOAT;
05226         p->s3size = sizeof (double);
05227         p->s3dval = *((float *) p->param);
05228         break;
05229     case SQL_C_DOUBLE:
05230         p->s3type = SQLITE_FLOAT;
05231         p->s3size = sizeof (double);
05232         p->s3dval = *((double *) p->param);
05233         break;
05234 #ifdef SQL_C_TYPE_DATE
05235     case SQL_C_TYPE_DATE:
05236 #endif
05237     case SQL_C_DATE:
05238         if (*s->jdconv) {
05239             int a, b, x1, x2, y, m, d;
05240 
05241             p->s3type = SQLITE_FLOAT;
05242             p->s3size = sizeof (double);
05243             y = ((DATE_STRUCT *) p->param)->year;
05244             m = ((DATE_STRUCT *) p->param)->month;
05245             d = ((DATE_STRUCT *) p->param)->day;
05246             if (m <= 2) {
05247                 y--;
05248                 m += 12;
05249             }
05250             a = y / 100;
05251             b = 2 - a + (a / 4);
05252             x1 = 36525 * (y + 4716) / 100;
05253             x2 = 306001 * (m + 1) / 10000;
05254             p->s3dval = x1 + x2 + d + b - 1524.5;
05255             break;
05256         }
05257         sprintf(p->strbuf, "%04d-%02d-%02d",
05258                 ((DATE_STRUCT *) p->param)->year,
05259                 ((DATE_STRUCT *) p->param)->month,
05260                 ((DATE_STRUCT *) p->param)->day);
05261         p->s3type = SQLITE_TEXT;
05262         p->s3size = -1;
05263         p->s3val = p->strbuf;
05264         break;
05265 #ifdef SQL_C_TYPE_TIME
05266     case SQL_C_TYPE_TIME:
05267 #endif
05268     case SQL_C_TIME:
05269         if (*s->jdconv) {
05270             p->s3type = SQLITE_FLOAT;
05271             p->s3size = sizeof (double);
05272             p->s3dval = 2451544.5 +
05273                (((TIME_STRUCT *) p->param)->hour * 3600000.0 +
05274                 ((TIME_STRUCT *) p->param)->minute * 60000.0 +
05275                 ((TIME_STRUCT *) p->param)->second * 1000.0) / 86400000.0;
05276             break;
05277         }
05278         sprintf(p->strbuf, "%02d:%02d:%02d",
05279                 ((TIME_STRUCT *) p->param)->hour,
05280                 ((TIME_STRUCT *) p->param)->minute,
05281                 ((TIME_STRUCT *) p->param)->second);
05282         p->s3type = SQLITE_TEXT;
05283         p->s3size = -1;
05284         p->s3val = p->strbuf;
05285         break;
05286 #ifdef SQL_C_TYPE_TIMESTAMP
05287     case SQL_C_TYPE_TIMESTAMP:
05288 #endif
05289     case SQL_C_TIMESTAMP:
05290         if (*s->jdconv) {
05291             int a, b, x1, x2, y, m, d;
05292 
05293             p->s3type = SQLITE_FLOAT;
05294             p->s3size = sizeof (double);
05295             y = ((TIMESTAMP_STRUCT *) p->param)->year;
05296             m = ((TIMESTAMP_STRUCT *) p->param)->month;
05297             d = ((TIMESTAMP_STRUCT *) p->param)->day;
05298             if (m <= 2) {
05299                 y--;
05300                 m += 12;
05301             }
05302             a = y / 100;
05303             b = 2 - a + (a / 4);
05304             x1 = 36525 * (y + 4716) / 100;
05305             x2 = 306001 * (m + 1) / 10000;
05306             p->s3dval = x1 + x2 + d + b - 1524.5 +
05307                (((TIMESTAMP_STRUCT *) p->param)->hour * 3600000.0 +
05308                 ((TIMESTAMP_STRUCT *) p->param)->minute * 60000.0 +
05309                 ((TIMESTAMP_STRUCT *) p->param)->second * 1000.0 +
05310                 ((TIMESTAMP_STRUCT *) p->param)->fraction / 1.0E6)
05311                / 86400000.0;
05312             break;
05313         }
05314         len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
05315         len /= 1000000;
05316         len = len % 1000;
05317         if (len < 0) {
05318             len = 0;
05319         }
05320         if (p->coldef && p->coldef <= 16) {
05321             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
05322                     ((TIMESTAMP_STRUCT *) p->param)->year,
05323                     ((TIMESTAMP_STRUCT *) p->param)->month,
05324                     ((TIMESTAMP_STRUCT *) p->param)->day,
05325                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05326                     ((TIMESTAMP_STRUCT *) p->param)->minute);
05327         } else if (p->coldef && p->coldef <= 19) {
05328             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
05329                     ((TIMESTAMP_STRUCT *) p->param)->year,
05330                     ((TIMESTAMP_STRUCT *) p->param)->month,
05331                     ((TIMESTAMP_STRUCT *) p->param)->day,
05332                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05333                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05334                     ((TIMESTAMP_STRUCT *) p->param)->second);
05335         } else {
05336             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
05337                     ((TIMESTAMP_STRUCT *) p->param)->year,
05338                     ((TIMESTAMP_STRUCT *) p->param)->month,
05339                     ((TIMESTAMP_STRUCT *) p->param)->day,
05340                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05341                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05342                     ((TIMESTAMP_STRUCT *) p->param)->second,
05343                     len);
05344         }
05345         p->s3type = SQLITE_TEXT;
05346         p->s3size = -1;
05347         p->s3val = p->strbuf;
05348         break;
05349     default:
05350     error:
05351         setstat(s, -1, "unsupported parameter type",
05352                 (*s->ov3) ? "07009" : "S1093");
05353         return SQL_ERROR;
05354     }
05355     return SQL_SUCCESS;
05356 }
05357 
05373 static SQLRETURN
05374 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05375              SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
05376              SQLSMALLINT scale,
05377              SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
05378 {
05379     STMT *s;
05380     BINDPARM *p;
05381 
05382     if (stmt == SQL_NULL_HSTMT) {
05383         return SQL_INVALID_HANDLE;
05384     }
05385     s = (STMT *) stmt;
05386     if (pnum == 0) {
05387         setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
05388         return SQL_ERROR;
05389     }
05390     if (!data && !len) {
05391         setstat(s, -1, "invalid buffer", "HY003");
05392         return SQL_ERROR;
05393     }
05394     --pnum;
05395     if (s->bindparms) {
05396         if (pnum >= s->nbindparms) {
05397             BINDPARM *newparms;
05398 
05399             newparms = xrealloc(s->bindparms,
05400                                 (pnum + 1) * sizeof (BINDPARM));
05401             if (!newparms) {
05402 outofmem:
05403                 return nomem(s);
05404             }
05405             s->bindparms = newparms;
05406             memset(&s->bindparms[s->nbindparms], 0,
05407                    (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
05408             s->nbindparms = pnum + 1;
05409         }
05410     } else {
05411         int npar = max(10, pnum + 1);
05412 
05413         s->bindparms = xmalloc(npar * sizeof (BINDPARM));
05414         if (!s->bindparms) {
05415             goto outofmem;
05416         }
05417         memset(s->bindparms, 0, npar * sizeof (BINDPARM));
05418         s->nbindparms = npar;
05419     }
05420     switch (buftype) {
05421     case SQL_C_STINYINT:
05422     case SQL_C_UTINYINT:
05423     case SQL_C_TINYINT:
05424 #ifdef SQL_C_BIT
05425     case SQL_C_BIT:
05426 #endif
05427         buflen = sizeof (SQLCHAR);
05428         break;
05429     case SQL_C_SHORT:
05430     case SQL_C_USHORT:
05431     case SQL_C_SSHORT:
05432         buflen = sizeof (SQLSMALLINT);
05433         break;
05434     case SQL_C_SLONG:
05435     case SQL_C_ULONG:
05436     case SQL_C_LONG:
05437         buflen = sizeof (SQLINTEGER);
05438         break;
05439     case SQL_C_FLOAT:
05440         buflen = sizeof (float);
05441         break;
05442     case SQL_C_DOUBLE:
05443         buflen = sizeof (double);
05444         break;
05445     case SQL_C_TIMESTAMP:
05446 #ifdef SQL_C_TYPE_TIMESTAMP
05447     case SQL_C_TYPE_TIMESTAMP:
05448 #endif
05449         buflen = sizeof (TIMESTAMP_STRUCT);
05450         break;
05451     case SQL_C_TIME:
05452 #ifdef SQL_C_TYPE_TIME
05453     case SQL_C_TYPE_TIME:
05454 #endif
05455         buflen = sizeof (TIME_STRUCT);
05456         break;
05457     case SQL_C_DATE:
05458 #ifdef SQL_C_TYPE_DATE
05459     case SQL_C_TYPE_DATE:
05460 #endif
05461         buflen = sizeof (DATE_STRUCT);
05462         break;
05463 #ifdef SQL_C_UBIGINT
05464     case SQL_C_UBIGINT:
05465         buflen = sizeof (SQLBIGINT);
05466         break;
05467 #endif
05468 #ifdef SQL_C_SBIGINT
05469     case SQL_C_SBIGINT:
05470         buflen = sizeof (SQLBIGINT);
05471         break;
05472 #endif
05473 #ifdef SQL_C_BIGINT
05474     case SQL_C_BIGINT:
05475         buflen = sizeof (SQLBIGINT);
05476         break;
05477 #endif
05478     }
05479     p = &s->bindparms[pnum];
05480     p->type = buftype;
05481     p->stype = ptype;
05482     p->coldef = coldef;
05483     p->scale = scale;
05484     p->max = buflen;
05485     p->inc = buflen;
05486     p->lenp = p->lenp0 = len;
05487     p->offs = 0;
05488     p->len = 0;
05489     p->param0 = data;
05490     freep(&p->parbuf);
05491     p->param = p->param0;
05492     p->bound = 1;
05493     p->need = 0;
05494     return SQL_SUCCESS;
05495 }
05496 
05512 SQLRETURN SQL_API
05513 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05514                  SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
05515                  SQLSMALLINT scale,
05516                  SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
05517 {
05518     SQLRETURN ret;
05519 
05520     HSTMT_LOCK(stmt);
05521     ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
05522                        scale, data, buflen, len);
05523     HSTMT_UNLOCK(stmt);
05524     return ret;
05525 }
05526 
05527 #ifndef HAVE_IODBC
05528 
05541 SQLRETURN SQL_API
05542 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
05543              SQLSMALLINT ptype, SQLULEN lenprec,
05544              SQLSMALLINT scale, SQLPOINTER val,
05545              SQLLEN *lenp)
05546 {
05547     SQLRETURN ret;
05548 
05549     HSTMT_LOCK(stmt);
05550     ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
05551                        lenprec, scale, val, 0, lenp);
05552     HSTMT_UNLOCK(stmt);
05553     return ret;
05554 }
05555 #endif
05556 
05564 SQLRETURN SQL_API
05565 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
05566 {
05567     STMT *s;
05568     SQLSMALLINT dummy;
05569 
05570     HSTMT_LOCK(stmt);
05571     if (stmt == SQL_NULL_HSTMT) {
05572         return SQL_INVALID_HANDLE;
05573     }
05574     s = (STMT *) stmt;
05575     if (!nparam) {
05576         nparam = &dummy;
05577     }
05578     *nparam = s->nparams;
05579     HSTMT_UNLOCK(stmt);
05580     return SQL_SUCCESS;
05581 }
05582 
05590 static SQLRETURN
05591 setupparbuf(STMT *s, BINDPARM *p)
05592 {
05593     if (!p->parbuf) {
05594         if (*p->lenp == SQL_DATA_AT_EXEC) {
05595             p->len = p->max;
05596         } else {
05597             p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
05598         }
05599         if (p->len < 0 && p->len != SQL_NTS &&
05600             p->len != SQL_NULL_DATA) {
05601             setstat(s, -1, "invalid length", "HY009");
05602             return SQL_ERROR;
05603         }
05604         if (p->len >= 0) {
05605             p->parbuf = xmalloc(p->len + 2);
05606             if (!p->parbuf) {
05607                 return nomem(s);
05608             }
05609             p->param = p->parbuf;
05610         } else {
05611             p->param = NULL;
05612         }
05613     }
05614     return SQL_NEED_DATA;
05615 }
05616 
05624 SQLRETURN SQL_API
05625 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
05626 {
05627     STMT *s;
05628     int i;
05629     SQLPOINTER dummy;
05630     SQLRETURN ret;
05631     BINDPARM *p;
05632 
05633     HSTMT_LOCK(stmt);
05634     if (stmt == SQL_NULL_HSTMT) {
05635         return SQL_INVALID_HANDLE;
05636     }
05637     s = (STMT *) stmt;
05638     if (!pind) {
05639         pind = &dummy;
05640     }
05641     if (s->pdcount < s->nparams) {
05642         s->pdcount++;
05643     }
05644     for (i = 0; i < s->pdcount; i++) {
05645         p = &s->bindparms[i];
05646         if (p->need > 0) {
05647             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05648 
05649             p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? -1 : 0;
05650         }
05651     }
05652     for (; i < s->nparams; i++) {
05653         p = &s->bindparms[i];
05654         if (p->need > 0) {
05655             *pind = (SQLPOINTER) p->param0;
05656             ret = setupparbuf(s, p);
05657             s->pdcount = i;
05658             goto done;
05659         }
05660     }
05661     ret = drvexecute(stmt, 0);
05662 done:
05663     HSTMT_UNLOCK(stmt);
05664     return ret;
05665 }
05666 
05678 SQLRETURN SQL_API
05679 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
05680                  SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
05681 {
05682     STMT *s;
05683     SQLRETURN ret = SQL_ERROR;
05684 
05685     HSTMT_LOCK(stmt);
05686     if (stmt == SQL_NULL_HSTMT) {
05687         return SQL_INVALID_HANDLE;
05688     }
05689     s = (STMT *) stmt;
05690     --pnum;
05691     if (pnum >= s->nparams) {
05692         setstat(s, -1, "invalid parameter index",
05693                 (*s->ov3) ? "HY000" : "S1000");
05694         goto done;
05695     }
05696     if (dtype) {
05697 #ifdef SQL_LONGVARCHAR
05698 #ifdef WINTERFACE
05699         *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
05700 #else
05701         *dtype = SQL_LONGVARCHAR;
05702 #endif
05703 #else
05704 #ifdef WINTERFACE
05705         *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
05706 #else
05707         *dtype = SQL_VARCHAR;
05708 #endif
05709 #endif
05710     }
05711     if (size) {
05712 #ifdef SQL_LONGVARCHAR
05713         *size = 65536;
05714 #else
05715         *size = 255;
05716 #endif
05717     }
05718     if (decdigits) {
05719         *decdigits = 0;
05720     }
05721     if (nullable) {
05722         *nullable = SQL_NULLABLE;
05723     }
05724     ret = SQL_SUCCESS;
05725 done:
05726     HSTMT_UNLOCK(stmt);
05727     return ret;
05728 }
05729 
05743 SQLRETURN SQL_API
05744 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
05745             SQLSMALLINT sqltype, SQLULEN coldef,
05746             SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
05747 {
05748     SQLRETURN ret;
05749 
05750     HSTMT_LOCK(stmt);
05751     ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
05752                        type, sqltype, coldef, scale, val,
05753                        SQL_SETPARAM_VALUE_MAX, nval);
05754     HSTMT_UNLOCK(stmt);
05755     return ret;
05756 }
05757 
05762 SQLRETURN SQL_API
05763 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
05764 {
05765     SQLRETURN ret;
05766 
05767     HSTMT_LOCK(stmt);
05768     ret = drvunimplstmt(stmt);
05769     HSTMT_UNLOCK(stmt);
05770     return ret;
05771 }
05772 
05773 #ifndef WINTERFACE
05774 
05778 SQLRETURN SQL_API
05779 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
05780                 SQLSMALLINT fieldid, SQLPOINTER value,
05781                 SQLINTEGER buflen, SQLINTEGER *strlen)
05782 {
05783     return SQL_ERROR;
05784 }
05785 #endif
05786 
05787 #ifdef WINTERFACE
05788 
05792 SQLRETURN SQL_API
05793 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05794                  SQLSMALLINT fieldid, SQLPOINTER value,
05795                  SQLINTEGER buflen, SQLINTEGER *strlen)
05796 {
05797     return SQL_ERROR;
05798 }
05799 #endif
05800 
05801 #ifndef WINTERFACE
05802 
05806 SQLRETURN SQL_API
05807 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
05808                 SQLSMALLINT fieldid, SQLPOINTER value,
05809                 SQLINTEGER buflen)
05810 {
05811     return SQL_ERROR;
05812 }
05813 #endif
05814 
05815 #ifdef WINTERFACE
05816 
05820 SQLRETURN SQL_API
05821 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05822                  SQLSMALLINT fieldid, SQLPOINTER value,
05823                  SQLINTEGER buflen)
05824 {
05825     return SQL_ERROR;
05826 }
05827 #endif
05828 
05829 #ifndef WINTERFACE
05830 
05834 SQLRETURN SQL_API
05835 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05836               SQLCHAR *name, SQLSMALLINT buflen,
05837               SQLSMALLINT *strlen, SQLSMALLINT *type,
05838               SQLSMALLINT *subtype, SQLLEN *len,
05839               SQLSMALLINT *prec, SQLSMALLINT *scale,
05840               SQLSMALLINT *nullable)
05841 {
05842     return SQL_ERROR;
05843 }
05844 #endif
05845 
05846 #ifdef WINTERFACE
05847 
05851 SQLRETURN SQL_API
05852 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
05853                SQLWCHAR *name, SQLSMALLINT buflen,
05854                SQLSMALLINT *strlen, SQLSMALLINT *type,
05855                SQLSMALLINT *subtype, SQLLEN *len,
05856                SQLSMALLINT *prec, SQLSMALLINT *scale,
05857                SQLSMALLINT *nullable)
05858 {
05859     return SQL_ERROR;
05860 }
05861 #endif
05862 
05867 SQLRETURN SQL_API
05868 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05869               SQLSMALLINT type, SQLSMALLINT subtype,
05870               SQLLEN len, SQLSMALLINT prec,
05871               SQLSMALLINT scale, SQLPOINTER data,
05872               SQLLEN *strlen, SQLLEN *indicator)
05873 {
05874     return SQL_ERROR;
05875 }
05876 
05888 static SQLRETURN
05889 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
05890             int ncols3, int *nret)
05891 {
05892     STMT *s;
05893     DBC *d;
05894 
05895     if (stmt == SQL_NULL_HSTMT) {
05896         return SQL_INVALID_HANDLE;
05897     }
05898     s = (STMT *) stmt;
05899     if (s->dbc == SQL_NULL_HDBC) {
05900 noconn:
05901         return noconn(s);
05902     }
05903     d = (DBC *) s->dbc;
05904     if (!d->sqlite) {
05905         goto noconn;
05906     }
05907     s3stmt_end_if(s);
05908     freeresult(s, 0);
05909     if (colspec3 && *s->ov3) {
05910         s->ncols = ncols3;
05911         s->cols = colspec3;
05912     } else {
05913         s->ncols = ncols;
05914         s->cols = colspec;
05915     }
05916     mkbindcols(s, s->ncols);
05917     s->nowchar[1] = 1;
05918     s->nrows = 0;
05919     s->rowp = s->rowprs = -1;
05920     s->isselect = -1;
05921     if (nret) {
05922         *nret = s->ncols;
05923     }
05924     return SQL_SUCCESS;
05925 }
05926 
05931 static COL tablePrivSpec2[] = {
05932     { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05933     { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
05934     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05935     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05936     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05937     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05938     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05939 };
05940 
05941 static COL tablePrivSpec3[] = {
05942     { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
05943     { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
05944     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05945     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05946     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05947     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05948     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05949 };
05950 
05963 static SQLRETURN
05964 drvtableprivileges(SQLHSTMT stmt,
05965                    SQLCHAR *cat, SQLSMALLINT catLen,
05966                    SQLCHAR *schema, SQLSMALLINT schemaLen,
05967                    SQLCHAR *table, SQLSMALLINT tableLen)
05968 {
05969     SQLRETURN ret;
05970     STMT *s;
05971     DBC *d;
05972     int ncols, rc, size, npatt;
05973     char *errp = NULL, *sql, tname[512];
05974 
05975     ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
05976                       tablePrivSpec3, array_size(tablePrivSpec3), NULL);
05977     if (ret != SQL_SUCCESS) {
05978         return ret;
05979     }
05980     s = (STMT *) stmt;
05981     d = (DBC *) s->dbc;
05982     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
05983         table = NULL;
05984         goto doit;
05985     }
05986     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
05987         schema[0] == '%') {
05988         if ((!cat || catLen == 0 || !cat[0]) &&
05989             (!table || tableLen == 0 || !table[0])) {
05990             table = NULL;
05991             goto doit;
05992         }
05993     }
05994 doit:
05995     if (!table) {
05996         size = 1;
05997         tname[0] = '%';
05998     } else {
05999         if (tableLen == SQL_NTS) {
06000             size = sizeof (tname) - 1;
06001         } else {
06002             size = min(sizeof (tname) - 1, tableLen);
06003         }
06004         strncpy(tname, (char *) table, size);
06005     }
06006     tname[size] = '\0';
06007     npatt = unescpat(tname);
06008 #if defined(_WIN32) || defined(_WIN64)
06009     sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
06010                           "%s as 'TABLE_OWNER', "
06011                           "tbl_name as 'TABLE_NAME', "
06012                           "'' as 'GRANTOR', "
06013                           "'' as 'GRANTEE', "
06014                           "'SELECT' AS 'PRIVILEGE', "
06015                           "NULL as 'IS_GRANTABLE' "
06016                           "from sqlite_master where "
06017                           "(type = 'table' or type = 'view') "
06018                           "and tbl_name %s %Q "
06019                           "UNION "
06020                           "select %s as 'TABLE_QUALIFIER', "
06021                           "%s as 'TABLE_OWNER', "
06022                           "tbl_name as 'TABLE_NAME', "
06023                           "'' as 'GRANTOR', "
06024                           "'' as 'GRANTEE', "
06025                           "'UPDATE' AS 'PRIVILEGE', "
06026                           "NULL as 'IS_GRANTABLE' "
06027                           "from sqlite_master where "
06028                           "(type = 'table' or type = 'view') "
06029                           "and tbl_name %s %Q "
06030                           "UNION "
06031                           "select %s as 'TABLE_QUALIFIER', "
06032                           "%s as 'TABLE_OWNER', "
06033                           "tbl_name as 'TABLE_NAME', "
06034                           "'' as 'GRANTOR', "
06035                           "'' as 'GRANTEE', "
06036                           "'DELETE' AS 'PRIVILEGE', "
06037                           "NULL as 'IS_GRANTABLE' "
06038                           "from sqlite_master where "
06039                           "(type = 'table' or type = 'view') "
06040                           "and tbl_name %s %Q "
06041                           "UNION "
06042                           "select %s as 'TABLE_QUALIFIER', "
06043                           "%s as 'TABLE_OWNER', "
06044                           "tbl_name as 'TABLE_NAME', "
06045                           "'' as 'GRANTOR', "
06046                           "'' as 'GRANTEE', "
06047                           "'INSERT' AS 'PRIVILEGE', "
06048                           "NULL as 'IS_GRANTABLE' "
06049                           "from sqlite_master where "
06050                           "(type = 'table' or type = 'view') "
06051                           "and tbl_name %s %Q "
06052                           "UNION "
06053                           "select %s as 'TABLE_QUALIFIER', "
06054                           "%s as 'TABLE_OWNER', "
06055                           "tbl_name as 'TABLE_NAME', "
06056                           "'' as 'GRANTOR', "
06057                           "'' as 'GRANTEE', "
06058                           "'REFERENCES' AS 'PRIVILEGE', "
06059                           "NULL as 'IS_GRANTABLE' "
06060                           "from sqlite_master where "
06061                           "(type = 'table' or type = 'view') "
06062                           "and tbl_name %s %Q",
06063                           d->xcelqrx ? "'main'" : "NULL",
06064                           d->xcelqrx ? "''" : "NULL",
06065                           npatt ? "like" : "=", tname,
06066                           d->xcelqrx ? "'main'" : "NULL",
06067                           d->xcelqrx ? "''" : "NULL",
06068                           npatt ? "like" : "=", tname,
06069                           d->xcelqrx ? "'main'" : "NULL",
06070                           d->xcelqrx ? "''" : "NULL",
06071                           npatt ? "like" : "=", tname,
06072                           d->xcelqrx ? "'main'" : "NULL",
06073                           d->xcelqrx ? "''" : "NULL",
06074                           npatt ? "like" : "=", tname,
06075                           d->xcelqrx ? "'main'" : "NULL",
06076                           d->xcelqrx ? "''" : "NULL",
06077                           npatt ? "like" : "=", tname);
06078 #else
06079     sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
06080                           "NULL as 'TABLE_OWNER', "
06081                           "tbl_name as 'TABLE_NAME', "
06082                           "'' as 'GRANTOR', "
06083                           "'' as 'GRANTEE', "
06084                           "'SELECT' AS 'PRIVILEGE', "
06085                           "NULL as 'IS_GRANTABLE' "
06086                           "from sqlite_master where "
06087                           "(type = 'table' or type = 'view') "
06088                           "and tbl_name %s %Q "
06089                           "UNION "
06090                           "select NULL as 'TABLE_QUALIFIER', "
06091                           "NULL as 'TABLE_OWNER', "
06092                           "tbl_name as 'TABLE_NAME', "
06093                           "'' as 'GRANTOR', "
06094                           "'' as 'GRANTEE', "
06095                           "'UPDATE' AS 'PRIVILEGE', "
06096                           "NULL as 'IS_GRANTABLE' "
06097                           "from sqlite_master where "
06098                           "(type = 'table' or type = 'view') "
06099                           "and tbl_name %s %Q "
06100                           "UNION "
06101                           "select NULL as 'TABLE_QUALIFIER', "
06102                           "NULL as 'TABLE_OWNER', "
06103                           "tbl_name as 'TABLE_NAME', "
06104                           "'' as 'GRANTOR', "
06105                           "'' as 'GRANTEE', "
06106                           "'DELETE' AS 'PRIVILEGE', "
06107                           "NULL as 'IS_GRANTABLE' "
06108                           "from sqlite_master where "
06109                           "(type = 'table' or type = 'view') "
06110                           "and tbl_name %s %Q "
06111                           "UNION "
06112                           "select NULL as 'TABLE_QUALIFIER', "
06113                           "NULL as 'TABLE_OWNER', "
06114                           "tbl_name as 'TABLE_NAME', "
06115                           "'' as 'GRANTOR', "
06116                           "'' as 'GRANTEE', "
06117                           "'INSERT' AS 'PRIVILEGE', "
06118                           "NULL as 'IS_GRANTABLE' "
06119                           "from sqlite_master where "
06120                           "(type = 'table' or type = 'view') "
06121                           "and tbl_name %s %Q "
06122                           "UNION "
06123                           "select NULL as 'TABLE_QUALIFIER', "
06124                           "NULL as 'TABLE_OWNER', "
06125                           "tbl_name as 'TABLE_NAME', "
06126                           "'' as 'GRANTOR', "
06127                           "'' as 'GRANTEE', "
06128                           "'REFERENCES' AS 'PRIVILEGE', "
06129                           "NULL as 'IS_GRANTABLE' "
06130                           "from sqlite_master where "
06131                           "(type = 'table' or type = 'view') "
06132                           "and tbl_name %s %Q",
06133                           npatt ? "like" : "=", tname,
06134                           npatt ? "like" : "=", tname,
06135                           npatt ? "like" : "=", tname,
06136                           npatt ? "like" : "=", tname,
06137                           npatt ? "like" : "=", tname);
06138 #endif
06139     if (!sql) {
06140         return nomem(s);
06141     }
06142     ret = starttran(s);
06143     if (ret != SQL_SUCCESS) {
06144         sqlite3_free(sql);
06145         return ret;
06146     }
06147     dbtraceapi(d, "sqlite3_get_table", sql);
06148     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
06149     sqlite3_free(sql);
06150     if (rc == SQLITE_OK) {
06151         if (ncols != s->ncols) {
06152             freeresult(s, 0);
06153             s->nrows = 0;
06154         } else {
06155             s->rowfree = sqlite3_free_table;
06156         }
06157     } else {
06158         s->nrows = 0;
06159         s->rows = NULL;
06160         s->rowfree = NULL;
06161     }
06162     if (errp) {
06163         sqlite3_free(errp);
06164         errp = NULL;
06165     }
06166     s->rowp = s->rowprs = -1;
06167     return SQL_SUCCESS;
06168 }
06169 
06170 
06171 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06172 
06184 SQLRETURN SQL_API
06185 SQLTablePrivileges(SQLHSTMT stmt,
06186                    SQLCHAR *catalog, SQLSMALLINT catalogLen,
06187                    SQLCHAR *schema, SQLSMALLINT schemaLen,
06188                    SQLCHAR *table, SQLSMALLINT tableLen)
06189 {
06190 #if defined(_WIN32) || defined(_WIN64)
06191     char *c = NULL, *s = NULL, *t = NULL;
06192 #endif
06193     SQLRETURN ret;
06194 
06195     HSTMT_LOCK(stmt);
06196 #if defined(_WIN32) || defined(_WIN64)
06197     if (!((STMT *) stmt)->oemcp[0]) {
06198         ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06199                                  table, tableLen);
06200         goto done2;
06201     }
06202     if (catalog) {
06203         c = wmb_to_utf_c((char *) catalog, catalogLen);
06204         if (!c) {
06205             ret = nomem((STMT *) stmt);
06206             goto done;
06207         }
06208     }
06209     if (schema) {
06210         s = wmb_to_utf_c((char *) schema, schemaLen);
06211         if (!s) {
06212             ret = nomem((STMT *) stmt);
06213             goto done;
06214         }
06215     }
06216     if (table) {
06217         t = wmb_to_utf_c((char *) table, tableLen);
06218         if (!t) {
06219             ret = nomem((STMT *) stmt);
06220             goto done;
06221         }
06222     }
06223     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06224                              (SQLCHAR *) s, SQL_NTS,
06225                              (SQLCHAR *) t, SQL_NTS);
06226 #else
06227     ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06228                              table, tableLen);
06229 #endif
06230 #if defined(_WIN32) || defined(_WIN64)
06231 done:
06232     uc_free(t);
06233     uc_free(s);
06234     uc_free(c);
06235 done2:
06236     ;
06237 #endif
06238     HSTMT_UNLOCK(stmt);
06239     return ret;
06240 }
06241 #endif
06242 
06243 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06244 #ifdef WINTERFACE
06245 
06257 SQLRETURN SQL_API
06258 SQLTablePrivilegesW(SQLHSTMT stmt,
06259                     SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06260                     SQLWCHAR *schema, SQLSMALLINT schemaLen,
06261                     SQLWCHAR *table, SQLSMALLINT tableLen)
06262 {
06263     char *c = NULL, *s = NULL, *t = NULL;
06264     SQLRETURN ret;
06265 
06266     HSTMT_LOCK(stmt);
06267     if (catalog) {
06268         c = uc_to_utf_c(catalog, catalogLen);
06269         if (!c) {
06270             ret = nomem((STMT *) stmt);
06271             goto done;
06272         }
06273     }
06274     if (schema) {
06275         s = uc_to_utf_c(schema, schemaLen);
06276         if (!s) {
06277             ret = nomem((STMT *) stmt);
06278             goto done;
06279         }
06280     }
06281     if (table) {
06282         t = uc_to_utf_c(table, tableLen);
06283         if (!t) {
06284             ret = nomem((STMT *) stmt);
06285             goto done;
06286         }
06287     }
06288     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06289                              (SQLCHAR *) s, SQL_NTS,
06290                              (SQLCHAR *) t, SQL_NTS);
06291 done:
06292     uc_free(t);
06293     uc_free(s);
06294     uc_free(c);
06295     HSTMT_UNLOCK(stmt);
06296     return ret;
06297 }
06298 #endif
06299 #endif
06300 
06305 static COL colPrivSpec2[] = {
06306     { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06307     { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06308     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06309     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06310     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06311     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06312     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06313 };
06314 
06315 static COL colPrivSpec3[] = {
06316     { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
06317     { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06318     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06319     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06320     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06321     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06322     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06323 };
06324 
06325 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06326 
06340 SQLRETURN SQL_API
06341 SQLColumnPrivileges(SQLHSTMT stmt,
06342                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
06343                     SQLCHAR *schema, SQLSMALLINT schemaLen,
06344                     SQLCHAR *table, SQLSMALLINT tableLen,
06345                     SQLCHAR *column, SQLSMALLINT columnLen)
06346 {
06347     SQLRETURN ret;
06348 
06349     HSTMT_LOCK(stmt);
06350     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06351                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06352     HSTMT_UNLOCK(stmt);
06353     return ret;
06354 }
06355 #endif
06356 
06357 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06358 #ifdef WINTERFACE
06359 
06373 SQLRETURN SQL_API
06374 SQLColumnPrivilegesW(SQLHSTMT stmt,
06375                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06376                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
06377                      SQLWCHAR *table, SQLSMALLINT tableLen,
06378                      SQLWCHAR *column, SQLSMALLINT columnLen)
06379 {
06380     SQLRETURN ret;
06381 
06382     HSTMT_LOCK(stmt);
06383     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06384                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06385     HSTMT_UNLOCK(stmt);
06386     return ret;
06387 }
06388 #endif
06389 #endif
06390 
06395 static COL pkeySpec2[] = {
06396     { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06397     { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06398     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06399     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06400     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06401     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06402 };
06403 
06404 static COL pkeySpec3[] = {
06405     { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
06406     { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06407     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06408     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06409     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06410     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06411 };
06412 
06425 static SQLRETURN
06426 drvprimarykeys(SQLHSTMT stmt,
06427                SQLCHAR *cat, SQLSMALLINT catLen,
06428                SQLCHAR *schema, SQLSMALLINT schemaLen,
06429                SQLCHAR *table, SQLSMALLINT tableLen)
06430 {
06431     STMT *s;
06432     DBC *d;
06433     SQLRETURN sret;
06434     int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
06435     int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
06436     PTRDIFF_T size;
06437     char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
06438 
06439     sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
06440                        pkeySpec3, array_size(pkeySpec3), &asize);
06441     if (sret != SQL_SUCCESS) {
06442         return sret;
06443     }
06444     s = (STMT *) stmt;
06445     d = (DBC *) s->dbc;
06446     if (!table || table[0] == '\0' || table[0] == '%') {
06447         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06448         return SQL_ERROR;
06449     }
06450     if (tableLen == SQL_NTS) {
06451         size = sizeof (tname) - 1;
06452     } else {
06453         size = min(sizeof (tname) - 1, tableLen);
06454     }
06455     strncpy(tname, (char *) table, size);
06456     tname[size] = '\0';
06457     unescpat(tname);
06458     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
06459     if (!sql) {
06460         return nomem(s);
06461     }
06462     sret = starttran(s);
06463     if (sret != SQL_SUCCESS) {
06464         sqlite3_free(sql);
06465         return sret;
06466     }
06467     dbtraceapi(d, "sqlite3_get_table", sql);
06468     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06469     sqlite3_free(sql);
06470     if (ret != SQLITE_OK) {
06471         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06472                 errp ? errp : "unknown error", ret);
06473         if (errp) {
06474             sqlite3_free(errp);
06475             errp = NULL;
06476         }
06477         return SQL_ERROR;
06478     }
06479     if (errp) {
06480         sqlite3_free(errp);
06481         errp = NULL;
06482     }
06483     size = 0;
06484     if (ncols * nrows > 0) {
06485         int typec;
06486 
06487         namec = findcol(rowp, ncols, "name");
06488         uniquec = findcol(rowp, ncols, "pk");
06489         typec = findcol(rowp, ncols, "type");
06490         if (namec >= 0 && uniquec >= 0 && typec >= 0) {
06491             for (i = 1; i <= nrows; i++) {
06492                 if (*rowp[i * ncols + uniquec] != '0') {
06493                     size++;
06494                 }
06495             }
06496         }
06497     }
06498     if (size == 0) {
06499         sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
06500         if (!sql) {
06501             sqlite3_free_table(rowp);
06502             return nomem(s);
06503         }
06504         dbtraceapi(d, "sqlite3_get_table", sql);
06505         ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
06506                                 &errp);
06507         sqlite3_free(sql);
06508         if (ret != SQLITE_OK) {
06509             sqlite3_free_table(rowp);
06510             sqlite3_free_table(rowp2);
06511             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06512                     errp ? errp : "unknown error", ret);
06513             if (errp) {
06514                 sqlite3_free(errp);
06515                 errp = NULL;
06516             }
06517             return SQL_ERROR;
06518         }
06519         if (errp) {
06520             sqlite3_free(errp);
06521             errp = NULL;
06522         }
06523     }
06524     if (ncols2 * nrows2 > 0) {
06525         namec2 = findcol(rowp2, ncols2, "name");
06526         uniquec2 = findcol(rowp2, ncols2, "unique");
06527         if (namec2 >= 0 && uniquec2 >=  0) {
06528             for (i = 1; i <= nrows2; i++) {
06529                 int nnrows, nncols, nlen = 0;
06530                 char **rowpp;
06531 
06532                 if (rowp2[i * ncols2 + namec2]) {
06533                     nlen = strlen(rowp2[i * ncols2 + namec2]);
06534                 }
06535                 if (nlen < 17 ||
06536                     strncmp(rowp2[i * ncols2 + namec2],
06537                             "sqlite_autoindex_", 17)) {
06538                     continue;
06539                 }
06540                 if (*rowp2[i * ncols2 + uniquec2] != '0') {
06541                     ret = SQLITE_ERROR;
06542                     sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06543                                           rowp2[i * ncols2 + namec2]);
06544                     if (sql) {
06545                         dbtraceapi(d, "sqlite3_get_table", sql);
06546                         ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06547                                                 &nnrows, &nncols, NULL);
06548                         sqlite3_free(sql);
06549                     }
06550                     if (ret == SQLITE_OK) {
06551                         size += nnrows;
06552                         sqlite3_free_table(rowpp);
06553                     }
06554                 }
06555             }
06556         }
06557     }
06558     if (size == 0) {
06559         sqlite3_free_table(rowp);
06560         sqlite3_free_table(rowp2);
06561         return SQL_SUCCESS;
06562     }
06563     s->nrows = size;
06564     size = (size + 1) * asize;
06565     s->rows = xmalloc((size + 1) * sizeof (char *));
06566     if (!s->rows) {
06567         s->nrows = 0;
06568         sqlite3_free_table(rowp);
06569         sqlite3_free_table(rowp2);
06570         return nomem(s);
06571     }
06572     s->rows[0] = (char *) size;
06573     s->rows += 1;
06574     memset(s->rows, 0, sizeof (char *) * size);
06575     s->rowfree = freerows;
06576     offs = s->ncols;
06577     if (rowp) {
06578         for (i = 1; i <= nrows; i++) {
06579             if (*rowp[i * ncols + uniquec] != '0') {
06580                 char buf[32];
06581 
06582 #if defined(_WIN32) || defined(_WIN64)
06583                 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
06584                 s->rows[offs + 1] = xstrdup("");
06585 #else
06586                 s->rows[offs + 0] = xstrdup("");
06587                 s->rows[offs + 1] = xstrdup("");
06588 #endif
06589                 s->rows[offs + 2] = xstrdup(tname);
06590                 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
06591                 sprintf(buf, "%d", seq++);
06592                 s->rows[offs + 4] = xstrdup(buf);
06593                 offs += s->ncols;
06594             }
06595         }
06596     }
06597     if (rowp2) {
06598         for (i = 1; i <= nrows2; i++) {
06599             int nnrows, nncols, nlen = 0;
06600             char **rowpp;
06601 
06602             if (rowp2[i * ncols2 + namec2]) {
06603                 nlen = strlen(rowp2[i * ncols2 + namec2]);
06604             }
06605             if (nlen < 17 ||
06606                 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
06607                 continue;
06608             }
06609             if (*rowp2[i * ncols2 + uniquec2] != '0') {
06610                 int k;
06611 
06612                 ret = SQLITE_ERROR;
06613                 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06614                                       rowp2[i * ncols2 + namec2]);
06615                 if (sql) {
06616                     dbtraceapi(d, "sqlite3_get_table", sql);
06617                     ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06618                                             &nnrows, &nncols, NULL);
06619                     sqlite3_free(sql);
06620                 }
06621                 if (ret != SQLITE_OK) {
06622                     continue;
06623                 }
06624                 for (k = 0; nnrows && k < nncols; k++) {
06625                     if (strcmp(rowpp[k], "name") == 0) {
06626                         int m;
06627 
06628                         for (m = 1; m <= nnrows; m++) {
06629                             int roffs = offs + (m - 1) * s->ncols;
06630 
06631 #if defined(_WIN32) || defined(_WIN64)
06632                             s->rows[roffs + 0] =
06633                                 xstrdup(d->xcelqrx ? "main" : "");
06634                             s->rows[roffs + 1] = xstrdup("");
06635 #else
06636                             s->rows[roffs + 0] = xstrdup("");
06637                             s->rows[roffs + 1] = xstrdup("");
06638 #endif
06639                             s->rows[roffs + 2] = xstrdup(tname);
06640                             s->rows[roffs + 3] =
06641                                 xstrdup(rowpp[m * nncols + k]);
06642                             s->rows[roffs + 5] =
06643                                 xstrdup(rowp2[i * ncols2 + namec2]);
06644                         }
06645                     } else if (strcmp(rowpp[k], "seqno") == 0) {
06646                         int m;
06647 
06648                         for (m = 1; m <= nnrows; m++) {
06649                             int roffs = offs + (m - 1) * s->ncols;
06650                             int pos = m - 1;
06651                             char buf[32];
06652 
06653                             sscanf(rowpp[m * nncols + k], "%d", &pos);
06654                             sprintf(buf, "%d", pos + 1);
06655                             s->rows[roffs + 4] = xstrdup(buf);
06656                         }
06657                     }
06658                 }
06659                 offs += nnrows * s->ncols;
06660                 sqlite3_free_table(rowpp);
06661             }
06662         }
06663     }
06664     sqlite3_free_table(rowp);
06665     sqlite3_free_table(rowp2);
06666     return SQL_SUCCESS;
06667 }
06668 
06669 #ifndef WINTERFACE
06670 
06682 SQLRETURN SQL_API
06683 SQLPrimaryKeys(SQLHSTMT stmt,
06684                SQLCHAR *cat, SQLSMALLINT catLen,
06685                SQLCHAR *schema, SQLSMALLINT schemaLen,
06686                SQLCHAR *table, SQLSMALLINT tableLen)
06687 {
06688 #if defined(_WIN32) || defined(_WIN64)
06689     char *c = NULL, *s = NULL, *t = NULL;
06690 #endif
06691     SQLRETURN ret;
06692 
06693     HSTMT_LOCK(stmt);
06694 #if defined(_WIN32) || defined(_WIN64)
06695     if (!((STMT *) stmt)->oemcp[0]) {
06696         ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06697                              table, tableLen);
06698         goto done2;
06699     }
06700     if (cat) {
06701         c = wmb_to_utf_c((char *) cat, catLen);
06702         if (!c) {
06703             ret = nomem((STMT *) stmt);
06704             goto done;
06705         }
06706     }
06707     if (schema) {
06708         s = wmb_to_utf_c((char *) schema, schemaLen);
06709         if (!s) {
06710             ret = nomem((STMT *) stmt);
06711             goto done;
06712         }
06713     }
06714     if (table) {
06715         t = wmb_to_utf_c((char *) table, tableLen);
06716         if (!t) {
06717             ret = nomem((STMT *) stmt);
06718             goto done;
06719         }
06720     }
06721     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06722                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06723 #else
06724     ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06725                          table, tableLen);
06726 #endif
06727 #if defined(_WIN32) || defined(_WIN64)
06728 done:
06729     uc_free(t);
06730     uc_free(s);
06731     uc_free(c);
06732 done2:
06733     ;
06734 #endif
06735     HSTMT_UNLOCK(stmt);
06736     return ret;
06737 }
06738 #endif
06739 
06740 #ifdef WINTERFACE
06741 
06753 SQLRETURN SQL_API
06754 SQLPrimaryKeysW(SQLHSTMT stmt,
06755                 SQLWCHAR *cat, SQLSMALLINT catLen,
06756                 SQLWCHAR *schema, SQLSMALLINT schemaLen,
06757                 SQLWCHAR *table, SQLSMALLINT tableLen)
06758 {
06759     char *c = NULL, *s = NULL, *t = NULL;
06760     SQLRETURN ret;
06761 
06762     HSTMT_LOCK(stmt);
06763     if (cat) {
06764         c = uc_to_utf_c(cat, catLen);
06765         if (!c) {
06766             ret = nomem((STMT *) stmt);
06767             goto done;
06768         }
06769     }
06770     if (schema) {
06771         s = uc_to_utf_c(schema, schemaLen);
06772         if (!s) {
06773             ret = nomem((STMT *) stmt);
06774             goto done;
06775         }
06776     }
06777     if (table) {
06778         t = uc_to_utf_c(table, tableLen);
06779         if (!t) {
06780             ret = nomem((STMT *) stmt);
06781             goto done;
06782         }
06783     }
06784     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06785                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06786 done:
06787     uc_free(t);
06788     uc_free(s);
06789     uc_free(c);
06790     HSTMT_UNLOCK(stmt);
06791     return ret;
06792 }
06793 #endif
06794 
06799 static COL scolSpec2[] = {
06800     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06801     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06802     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06803     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06804     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
06805     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
06806     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06807     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06808     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06809 };
06810 
06811 static COL scolSpec3[] = {
06812     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06813     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06814     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06815     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06816     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
06817     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
06818     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06819     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06820     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06821 };
06822 
06838 static SQLRETURN
06839 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
06840                   SQLCHAR *cat, SQLSMALLINT catLen,
06841                   SQLCHAR *schema, SQLSMALLINT schemaLen,
06842                   SQLCHAR *table, SQLSMALLINT tableLen,
06843                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
06844 {
06845     STMT *s;
06846     DBC *d;
06847     SQLRETURN sret;
06848     int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
06849     PTRDIFF_T size;
06850     int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
06851     int notnullcc = -1, mkrowid = 0;
06852     char *errp = NULL, *sql, tname[512];
06853     char **rowp = NULL, **rowppp = NULL;
06854 
06855     sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
06856                        scolSpec3, array_size(scolSpec3), &asize);
06857     if (sret != SQL_SUCCESS) {
06858         return sret;
06859     }
06860     s = (STMT *) stmt;
06861     d = (DBC *) s->dbc;
06862     if (!table || table[0] == '\0' || table[0] == '%') {
06863         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06864         return SQL_ERROR;
06865     }
06866     if (tableLen == SQL_NTS) {
06867         size = sizeof (tname) - 1;
06868     } else {
06869         size = min(sizeof (tname) - 1, tableLen);
06870     }
06871     strncpy(tname, (char *) table, size);
06872     tname[size] = '\0';
06873     unescpat(tname);
06874     if (id != SQL_BEST_ROWID) {
06875         return SQL_SUCCESS;
06876     }
06877     sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
06878     if (!sql) {
06879         return nomem(s);
06880     }
06881     sret = starttran(s);
06882     if (sret != SQL_SUCCESS) {
06883         sqlite3_free(sql);
06884         return sret;
06885     }
06886     dbtraceapi(d, "sqlite3_get_table", sql);
06887     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06888     sqlite3_free(sql);
06889     if (ret != SQLITE_OK) {
06890 doerr:
06891         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06892                 errp ? errp : "unknown error", ret);
06893         if (errp) {
06894             sqlite3_free(errp);
06895             errp = NULL;
06896         }
06897         return SQL_ERROR;
06898     }
06899     if (errp) {
06900         sqlite3_free(errp);
06901         errp = NULL;
06902     }
06903     size = 0; /* number result rows */
06904     if (ncols * nrows <= 0) {
06905         goto nodata_but_rowid;
06906     }
06907     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
06908     if (!sql) {
06909         return nomem(s);
06910     }
06911     dbtraceapi(d, "sqlite3_get_table", sql);
06912     ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
06913                             &errp);
06914     sqlite3_free(sql);
06915     if (ret != SQLITE_OK) {
06916         sqlite3_free_table(rowp);
06917         goto doerr;
06918     }
06919     if (errp) {
06920         sqlite3_free(errp);
06921         errp = NULL;
06922     }
06923     namec = findcol(rowp, ncols, "name");
06924     uniquec = findcol(rowp, ncols, "unique");
06925     if (namec < 0 || uniquec < 0) {
06926         goto nodata_but_rowid;
06927     }
06928     namecc = findcol(rowppp, nnncols, "name");
06929     typecc = findcol(rowppp, nnncols, "type");
06930     notnullcc = findcol(rowppp, nnncols, "notnull");
06931     for (i = 1; i <= nrows; i++) {
06932         int nnrows, nncols;
06933         char **rowpp = NULL;
06934 
06935         if (*rowp[i * ncols + uniquec] != '0') {
06936             ret = SQLITE_ERROR;
06937             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06938                                   rowp[i * ncols + namec]);
06939             if (sql) {
06940                 dbtraceapi(d, "sqlite3_get_table", sql);
06941                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06942                                         &nnrows, &nncols, NULL);
06943                 sqlite3_free(sql);
06944             }
06945             if (ret == SQLITE_OK) {
06946                 size += nnrows;
06947                 sqlite3_free_table(rowpp);
06948             }
06949         }
06950     }
06951 nodata_but_rowid:
06952     if (size == 0) {
06953         size = 1;
06954         mkrowid = 1;
06955     }
06956     s->nrows = size;
06957     size = (size + 1) * asize;
06958     s->rows = xmalloc((size + 1) * sizeof (char *));
06959     if (!s->rows) {
06960         s->nrows = 0;
06961         sqlite3_free_table(rowp);
06962         sqlite3_free_table(rowppp);
06963         return nomem(s);
06964     }
06965     s->rows[0] = (char *) size;
06966     s->rows += 1;
06967     memset(s->rows, 0, sizeof (char *) * size);
06968     s->rowfree = freerows;
06969     if (mkrowid) {
06970         s->nrows = 0;
06971         goto mkrowid;
06972     }
06973     offs = 0;
06974     for (i = 1; i <= nrows; i++) {
06975         int nnrows, nncols;
06976         char **rowpp = NULL;
06977 
06978         if (*rowp[i * ncols + uniquec] != '0') {
06979             int k;
06980 
06981             ret = SQLITE_ERROR;
06982             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06983                                   rowp[i * ncols + namec]);
06984             if (sql) {
06985                 dbtraceapi(d, "sqlite3_get_table", sql);
06986                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06987                                         &nnrows, &nncols, NULL);
06988                 sqlite3_free(sql);
06989             }
06990             if (ret != SQLITE_OK) {
06991                 continue;
06992             }
06993             for (k = 0; nnrows && k < nncols; k++) {
06994                 if (strcmp(rowpp[k], "name") == 0) {
06995                     int m;
06996 
06997                     for (m = 1; m <= nnrows; m++) {
06998                         int roffs = (offs + m) * s->ncols;
06999 
07000                         s->rows[roffs + 0] =
07001                             xstrdup(stringify(SQL_SCOPE_SESSION));
07002                         s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
07003                         s->rows[roffs + 4] = xstrdup("0");
07004                         s->rows[roffs + 7] =
07005                             xstrdup(stringify(SQL_PC_NOT_PSEUDO));
07006                         if (namecc >= 0 && typecc >= 0) {
07007                             int ii;
07008 
07009                             for (ii = 1; ii <= nnnrows; ii++) {
07010                                 if (strcmp(rowppp[ii * nnncols + namecc],
07011                                            rowpp[m * nncols + k]) == 0) {
07012                                     char *typen = rowppp[ii * nnncols + typecc];
07013                                     int sqltype, mm, dd, isnullable = 0;
07014                                     char buf[32];
07015 
07016                                     s->rows[roffs + 3] = xstrdup(typen);
07017                                     sqltype = mapsqltype(typen, NULL, *s->ov3,
07018                                                          s->nowchar[0],
07019                                                          s->dobigint);
07020                                     getmd(typen, sqltype, &mm, &dd);
07021 #ifdef SQL_LONGVARCHAR
07022                                     if (sqltype == SQL_VARCHAR && mm > 255) {
07023                                         sqltype = SQL_LONGVARCHAR;
07024                                     }
07025 #endif
07026 #ifdef WINTERFACE
07027 #ifdef SQL_WLONGVARCHAR
07028                                     if (sqltype == SQL_WVARCHAR && mm > 255) {
07029                                         sqltype = SQL_WLONGVARCHAR;
07030                                     }
07031 #endif
07032 #endif
07033                                     if (sqltype == SQL_VARBINARY && mm > 255) {
07034                                         sqltype = SQL_LONGVARBINARY;
07035                                     }
07036                                     sprintf(buf, "%d", sqltype);
07037                                     s->rows[roffs + 2] = xstrdup(buf);
07038                                     sprintf(buf, "%d", mm);
07039                                     s->rows[roffs + 5] = xstrdup(buf);
07040                                     sprintf(buf, "%d", dd);
07041                                     s->rows[roffs + 6] = xstrdup(buf);
07042                                     if (notnullcc >= 0) {
07043                                         char *inp =
07044                                            rowppp[ii * nnncols + notnullcc];
07045 
07046                                         isnullable = inp[0] != '0';
07047                                     }
07048                                     sprintf(buf, "%d", isnullable);
07049                                     s->rows[roffs + 8] = xstrdup(buf);
07050                                 }
07051                             }
07052                         }
07053                     }
07054                 }
07055             }
07056             offs += nnrows;
07057             sqlite3_free_table(rowpp);
07058         }
07059     }
07060     if (nullable == SQL_NO_NULLS) {
07061         for (i = 1; i < s->nrows; i++) {
07062             if (s->rows[i * s->ncols + 8][0] == '0') {
07063                 int m, i1 = i + 1;
07064 
07065                 for (m = 0; m < s->ncols; m++) {
07066                     freep(&s->rows[i * s->ncols + m]);
07067                 }
07068                 size = s->ncols * sizeof (char *) * (s->nrows - i1);
07069                 if (size > 0) {
07070                     memmove(s->rows + i * s->ncols,
07071                             s->rows + i1 * s->ncols,
07072                             size);
07073                     memset(s->rows + s->nrows * s->ncols, 0,
07074                            s->ncols * sizeof (char *));
07075                 }
07076                 s->nrows--;
07077                 --i;
07078             }
07079         }
07080     }
07081 mkrowid:
07082     sqlite3_free_table(rowp);
07083     sqlite3_free_table(rowppp);
07084     if (s->nrows == 0) {
07085         s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
07086         s->rows[s->ncols + 1] = xstrdup("_ROWID_");
07087         s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
07088         s->rows[s->ncols + 3] = xstrdup("integer");
07089         s->rows[s->ncols + 4] = xstrdup("0");
07090         s->rows[s->ncols + 5] = xstrdup("10");
07091         s->rows[s->ncols + 6] = xstrdup("9");
07092         s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
07093         s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
07094         s->nrows = 1;
07095     }
07096     return SQL_SUCCESS;
07097 }
07098 
07099 #ifndef WINTERFACE
07100 
07115 SQLRETURN SQL_API
07116 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
07117                   SQLCHAR *cat, SQLSMALLINT catLen,
07118                   SQLCHAR *schema, SQLSMALLINT schemaLen,
07119                   SQLCHAR *table, SQLSMALLINT tableLen,
07120                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
07121 {
07122 #if defined(_WIN32) || defined(_WIN64)
07123     char *c = NULL, *s = NULL, *t = NULL;
07124 #endif
07125     SQLRETURN ret;
07126 
07127     HSTMT_LOCK(stmt);
07128 #if defined(_WIN32) || defined(_WIN64)
07129     if (!((STMT *) stmt)->oemcp[0]) {
07130         ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07131                                 table, tableLen, scope, nullable);
07132         goto done2;
07133     }
07134     if (cat) {
07135         c = wmb_to_utf_c((char *) cat, catLen);
07136         if (!c) {
07137             ret = nomem((STMT *) stmt);
07138             goto done;
07139         }
07140     }
07141     if (schema) {
07142         s = wmb_to_utf_c((char *) schema, schemaLen);
07143         if (!s) {
07144             ret = nomem((STMT *) stmt);
07145             goto done;
07146         }
07147     }
07148     if (table) {
07149         t = wmb_to_utf_c((char *) table, tableLen);
07150         if (!t) {
07151             ret = nomem((STMT *) stmt);
07152             goto done;
07153         }
07154     }
07155     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07156                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07157                             scope, nullable);
07158 #else
07159     ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07160                             table, tableLen, scope, nullable);
07161 #endif
07162 #if defined(_WIN32) || defined(_WIN64)
07163 done:
07164     uc_free(t);
07165     uc_free(s);
07166     uc_free(c);
07167 done2:
07168     ;
07169 #endif
07170     HSTMT_UNLOCK(stmt);
07171     return ret;
07172 }
07173 #endif
07174 
07175 #ifdef WINTERFACE
07176 
07191 SQLRETURN SQL_API
07192 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
07193                    SQLWCHAR *cat, SQLSMALLINT catLen,
07194                    SQLWCHAR *schema, SQLSMALLINT schemaLen,
07195                    SQLWCHAR *table, SQLSMALLINT tableLen,
07196                    SQLUSMALLINT scope, SQLUSMALLINT nullable)
07197 {
07198     char *c = NULL, *s = NULL, *t = NULL;
07199     SQLRETURN ret;
07200 
07201     HSTMT_LOCK(stmt);
07202     if (cat) {
07203         c = uc_to_utf_c(cat, catLen);
07204         if (!c) {
07205             ret = nomem((STMT *) stmt);
07206             goto done;
07207         }
07208     }
07209     if (schema) {
07210         s = uc_to_utf_c(schema, schemaLen);
07211         if (!s) {
07212             ret = nomem((STMT *) stmt);
07213             goto done;
07214         }
07215     }
07216     if (table) {
07217         t = uc_to_utf_c(table, tableLen);
07218         if (!t) {
07219             ret = nomem((STMT *) stmt);
07220             goto done;
07221         }
07222     }
07223     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07224                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07225                             scope, nullable);
07226 done:
07227     uc_free(t);
07228     uc_free(s);
07229     uc_free(c);
07230     HSTMT_UNLOCK(stmt);
07231     return ret;
07232 }
07233 #endif
07234 
07239 static COL fkeySpec2[] = {
07240     { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07241     { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
07242     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07243     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07244     { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07245     { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
07246     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07247     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07248     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07249     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07250     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07251     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07252     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07253     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07254 };
07255 
07256 static COL fkeySpec3[] = {
07257     { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
07258     { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07259     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07260     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07261     { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
07262     { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07263     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07264     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07265     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07266     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07267     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07268     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07269     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07270     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07271 };
07272 
07291 static SQLRETURN SQL_API
07292 drvforeignkeys(SQLHSTMT stmt,
07293                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07294                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07295                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07296                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07297                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07298                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07299 {
07300     STMT *s;
07301     DBC *d;
07302     SQLRETURN sret;
07303     int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
07304     int onu, ond;
07305     PTRDIFF_T size;
07306     char **rowp, *errp = NULL, *sql, pname[512], fname[512];
07307 
07308     sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
07309                        fkeySpec3, array_size(fkeySpec3), &asize);
07310     if (sret != SQL_SUCCESS) {
07311         return sret;
07312     }
07313     s = (STMT *) stmt;
07314     sret = starttran(s);
07315     if (sret != SQL_SUCCESS) {
07316         return sret;
07317     }
07318     d = (DBC *) s->dbc;
07319     if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
07320         (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
07321         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
07322         return SQL_ERROR;
07323     }
07324     size = 0;
07325     if (PKtable) {
07326         if (PKtableLen == SQL_NTS) {
07327             size = sizeof (pname) - 1;
07328         } else {
07329             size = min(sizeof (pname) - 1, PKtableLen);
07330         }
07331         strncpy(pname, (char *) PKtable, size);
07332     }
07333     pname[size] = '\0';
07334     size = 0;
07335     if (FKtable) {
07336 
07337         if (FKtableLen == SQL_NTS) {
07338             size = sizeof (fname) - 1;
07339         } else {
07340             size = min(sizeof (fname) - 1, FKtableLen);
07341         }
07342         strncpy(fname, (char *) FKtable, size);
07343     }
07344     fname[size] = '\0';
07345     if (fname[0] != '\0') {
07346         int plen;
07347 
07348         ret = SQLITE_ERROR;
07349         sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
07350         if (sql) {
07351             dbtraceapi(d, "sqlite3_get_table", sql);
07352             ret = sqlite3_get_table(d->sqlite, sql, &rowp,
07353                                     &nrows, &ncols, &errp);
07354             sqlite3_free(sql);
07355         }
07356         if (ret != SQLITE_OK) {
07357             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07358                     errp ? errp : "unknown error", ret);
07359             if (errp) {
07360                 sqlite3_free(errp);
07361                 errp = NULL;
07362             }
07363             return SQL_ERROR;
07364         }
07365         if (errp) {
07366             sqlite3_free(errp);
07367             errp = NULL;
07368         }
07369         if (ncols * nrows <= 0) {
07370 nodata:
07371             sqlite3_free_table(rowp);
07372             return SQL_SUCCESS;
07373         }
07374         size = 0;
07375         namec = findcol(rowp, ncols, "table");
07376         seqc = findcol(rowp, ncols, "seq");
07377         fromc = findcol(rowp, ncols, "from");
07378         toc = findcol(rowp, ncols, "to");
07379         onu = findcol(rowp, ncols, "on_update");
07380         ond = findcol(rowp, ncols, "on_delete");
07381         if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07382             goto nodata;
07383         }
07384         plen = strlen(pname);
07385         for (i = 1; i <= nrows; i++) {
07386             char *ptab = unquote(rowp[i * ncols + namec]);
07387 
07388             if (plen && ptab) {
07389                 int len = strlen(ptab);
07390 
07391                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07392                     continue;
07393                 }
07394             }
07395             size++;
07396         }
07397         if (size == 0) {
07398             goto nodata;
07399         }
07400         s->nrows = size;
07401         size = (size + 1) * asize;
07402         s->rows = xmalloc((size + 1) * sizeof (char *));
07403         if (!s->rows) {
07404             s->nrows = 0;
07405             return nomem(s);
07406         }
07407         s->rows[0] = (char *) size;
07408         s->rows += 1;
07409         memset(s->rows, 0, sizeof (char *) * size);
07410         s->rowfree = freerows;
07411         offs = 0;
07412         for (i = 1; i <= nrows; i++) {
07413             int pos = 0, roffs = (offs + 1) * s->ncols;
07414             char *ptab = rowp[i * ncols + namec];
07415             char buf[32];
07416 
07417             if (plen && ptab) {
07418                 int len = strlen(ptab);
07419 
07420                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07421                     continue;
07422                 }
07423             }
07424 #if defined(_WIN32) || defined(_WIN64)
07425             s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07426             s->rows[roffs + 1] = xstrdup("");
07427 #else
07428             s->rows[roffs + 0] = xstrdup("");
07429             s->rows[roffs + 1] = xstrdup("");
07430 #endif
07431             s->rows[roffs + 2] = xstrdup(ptab);
07432             s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
07433             s->rows[roffs + 4] = xstrdup("");
07434             s->rows[roffs + 5] = xstrdup("");
07435             s->rows[roffs + 6] = xstrdup(fname);
07436             s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
07437             sscanf(rowp[i * ncols + seqc], "%d", &pos);
07438             sprintf(buf, "%d", pos + 1);
07439             s->rows[roffs + 8] = xstrdup(buf);
07440             if (onu < 0) {
07441                 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07442             } else {
07443                 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
07444                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07445                 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
07446                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
07447                 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
07448                     s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07449                 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
07450                     s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07451                 } else {
07452                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07453                 }
07454             }
07455             if (ond < 0) {
07456                 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07457             } else {
07458                 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
07459                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07460                 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
07461                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
07462                 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
07463                     s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07464                 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
07465                     s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07466                 } else {
07467                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07468                 }
07469             }
07470             s->rows[roffs + 11] = NULL;
07471             s->rows[roffs + 12] = NULL;
07472             s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07473             offs++;
07474         }
07475         sqlite3_free_table(rowp);
07476     } else {
07477         int nnrows, nncols, plen = strlen(pname);
07478         char **rowpp;
07479 
07480         sql = "select name from sqlite_master where type='table'";
07481         dbtraceapi(d, "sqlite3_get_table", sql);
07482         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
07483         if (ret != SQLITE_OK) {
07484             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07485                     errp ? errp : "unknown error", ret);
07486             if (errp) {
07487                 sqlite3_free(errp);
07488                 errp = NULL;
07489             }
07490             return SQL_ERROR;
07491         }
07492         if (errp) {
07493             sqlite3_free(errp);
07494             errp = NULL;
07495         }
07496         if (ncols * nrows <= 0) {
07497             goto nodata;
07498         }
07499         size = 0;
07500         for (i = 1; i <= nrows; i++) {
07501             int k;
07502 
07503             if (!rowp[i]) {
07504                 continue;
07505             }
07506             rowpp = NULL;
07507             ret = SQLITE_ERROR;
07508             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07509             if (sql) {
07510                 dbtraceapi(d, "sqlite3_get_table", sql);
07511                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07512                                       &nnrows, &nncols, NULL);
07513                 sqlite3_free(sql);
07514             }
07515             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07516                 sqlite3_free_table(rowpp);
07517                 continue;
07518             }
07519             namec = findcol(rowpp, nncols, "table");
07520             seqc = findcol(rowpp, nncols, "seq");
07521             fromc = findcol(rowpp, nncols, "from");
07522             toc = findcol(rowpp, nncols, "to");
07523             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07524                 sqlite3_free_table(rowpp);
07525                 continue;
07526             }
07527             for (k = 1; k <= nnrows; k++) {
07528                 char *ptab = unquote(rowpp[k * nncols + namec]);
07529 
07530                 if (plen && ptab) {
07531                     int len = strlen(ptab);
07532 
07533                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07534                         continue;
07535                     }
07536                 }
07537                 size++;
07538             }
07539             sqlite3_free_table(rowpp);
07540         }
07541         if (size == 0) {
07542             goto nodata;
07543         }
07544         s->nrows = size;
07545         size = (size + 1) * asize;
07546         s->rows = xmalloc((size + 1) * sizeof (char *));
07547         if (!s->rows) {
07548             s->nrows = 0;
07549             return nomem(s);
07550         }
07551         s->rows[0] = (char *) size;
07552         s->rows += 1;
07553         memset(s->rows, 0, sizeof (char *) * size);
07554         s->rowfree = freerows;
07555         offs = 0;
07556         for (i = 1; i <= nrows; i++) {
07557             int k;
07558 
07559             if (!rowp[i]) {
07560                 continue;
07561             }
07562             rowpp = NULL;
07563             ret = SQLITE_ERROR;
07564             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07565             if (sql) {
07566                 dbtraceapi(d, "sqlite3_get_table", sql);
07567                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07568                                         &nnrows, &nncols, NULL);
07569                 sqlite3_free(sql);
07570             }
07571             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07572                 sqlite3_free_table(rowpp);
07573                 continue;
07574             }
07575             namec = findcol(rowpp, nncols, "table");
07576             seqc = findcol(rowpp, nncols, "seq");
07577             fromc = findcol(rowpp, nncols, "from");
07578             toc = findcol(rowpp, nncols, "to");
07579             onu = findcol(rowpp, nncols, "on_update");
07580             ond = findcol(rowpp, nncols, "on_delete");
07581             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07582                 sqlite3_free_table(rowpp);
07583                 continue;
07584             }
07585             for (k = 1; k <= nnrows; k++) {
07586                 int pos = 0, roffs = (offs + 1) * s->ncols;
07587                 char *ptab = unquote(rowpp[k * nncols + namec]);
07588                 char buf[32];
07589 
07590                 if (plen && ptab) {
07591                     int len = strlen(ptab);
07592 
07593                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07594                         continue;
07595                     }
07596                 }
07597 #if defined(_WIN32) || defined(_WIN64)
07598                 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07599                 s->rows[roffs + 1] = xstrdup("");
07600 #else
07601                 s->rows[roffs + 0] = xstrdup("");
07602                 s->rows[roffs + 1] = xstrdup("");
07603 #endif
07604                 s->rows[roffs + 2] = xstrdup(ptab);
07605                 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
07606                 s->rows[roffs + 4] = xstrdup("");
07607                 s->rows[roffs + 5] = xstrdup("");
07608                 s->rows[roffs + 6] = xstrdup(rowp[i]);
07609                 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
07610                 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
07611                 sprintf(buf, "%d", pos + 1);
07612                 s->rows[roffs + 8] = xstrdup(buf);
07613                 if (onu < 0) {
07614                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07615                 } else {
07616                     if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
07617                         s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07618                     } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
07619                                == 0) {
07620                         s->rows[roffs + 9] =
07621                             xstrdup(stringify(SQL_SET_DEFAULT));
07622                     } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
07623                                == 0) {
07624                         s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07625                     } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
07626                                == 0) {
07627                         s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07628                     } else {
07629                         s->rows[roffs + 9] =
07630                             xstrdup(stringify(SQL_NO_ACTION));
07631                     }
07632                 }
07633                 if (ond < 0) {
07634                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07635                 } else {
07636                     if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
07637                         s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07638                     } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
07639                                == 0) {
07640                         s->rows[roffs + 10] =
07641                             xstrdup(stringify(SQL_SET_DEFAULT));
07642                     } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
07643                                == 0) {
07644                         s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07645                     } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
07646                                == 0) {
07647                         s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07648                     } else {
07649                         s->rows[roffs + 10] =
07650                             xstrdup(stringify(SQL_NO_ACTION));
07651                     }
07652                 }
07653                 s->rows[roffs + 11] = NULL;
07654                 s->rows[roffs + 12] = NULL;
07655                 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07656                 offs++;
07657             }
07658             sqlite3_free_table(rowpp);
07659         }
07660         sqlite3_free_table(rowp);
07661     }
07662     return SQL_SUCCESS;
07663 }
07664 
07665 #ifndef WINTERFACE
07666 
07684 SQLRETURN SQL_API
07685 SQLForeignKeys(SQLHSTMT stmt,
07686                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07687                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07688                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07689                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07690                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07691                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07692 {
07693 #if defined(_WIN32) || defined(_WIN64)
07694     char *pc = NULL, *ps = NULL, *pt = NULL;
07695     char *fc = NULL, *fs = NULL, *ft = NULL;
07696 #endif
07697     SQLRETURN ret;
07698 
07699     HSTMT_LOCK(stmt);
07700 #if defined(_WIN32) || defined(_WIN64)
07701     if (!((STMT *) stmt)->oemcp[0]) {
07702         ret = drvforeignkeys(stmt,
07703                              PKcatalog, PKcatalogLen,
07704                              PKschema, PKschemaLen, PKtable, PKtableLen,
07705                              FKcatalog, FKcatalogLen,
07706                              FKschema, FKschemaLen,
07707                              FKtable, FKtableLen);
07708         goto done2;
07709     }
07710     if (PKcatalog) {
07711         pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
07712         if (!pc) {
07713             ret = nomem((STMT *) stmt);
07714             goto done;
07715         }
07716     }
07717     if (PKschema) {
07718         ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
07719         if (!ps) {
07720             ret = nomem((STMT *) stmt);
07721             goto done;
07722         }
07723     }
07724     if (PKtable) {
07725         pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
07726         if (!pt) {
07727             ret = nomem((STMT *) stmt);
07728             goto done;
07729         }
07730     }
07731     if (FKcatalog) {
07732         fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
07733         if (!fc) {
07734             ret = nomem((STMT *) stmt);
07735             goto done;
07736         }
07737     }
07738     if (FKschema) {
07739         fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
07740         if (!fs) {
07741             ret = nomem((STMT *) stmt);
07742             goto done;
07743         }
07744     }
07745     if (FKtable) {
07746         ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
07747         if (!ft) {
07748             ret = nomem((STMT *) stmt);
07749             goto done;
07750         }
07751     }
07752     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
07753                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
07754                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
07755                          (SQLCHAR *) ft, SQL_NTS);
07756 #else
07757     ret = drvforeignkeys(stmt,
07758                          PKcatalog, PKcatalogLen,
07759                          PKschema, PKschemaLen, PKtable, PKtableLen,
07760                          FKcatalog, FKcatalogLen,
07761                          FKschema, FKschemaLen,
07762                          FKtable, FKtableLen);
07763 #endif
07764 #if defined(_WIN32) || defined(_WIN64)
07765 done:
07766     uc_free(ft);
07767     uc_free(fs);
07768     uc_free(fc);
07769     uc_free(pt);
07770     uc_free(ps);
07771     uc_free(pc);
07772 done2:
07773     ;
07774 #endif
07775     HSTMT_UNLOCK(stmt);
07776     return ret;
07777 }
07778 #endif
07779 
07780 #ifdef WINTERFACE
07781 
07799 SQLRETURN SQL_API
07800 SQLForeignKeysW(SQLHSTMT stmt,
07801                 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07802                 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
07803                 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
07804                 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07805                 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
07806                 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
07807 {
07808     char *pc = NULL, *ps = NULL, *pt = NULL;
07809     char *fc = NULL, *fs = NULL, *ft = NULL;
07810     SQLRETURN ret;
07811 
07812     HSTMT_LOCK(stmt);
07813     if (PKcatalog) {
07814         pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
07815         if (!pc) {
07816             ret = nomem((STMT *) stmt);
07817             goto done;
07818         }
07819     }
07820     if (PKschema) {
07821         ps = uc_to_utf_c(PKschema, PKschemaLen);
07822         if (!ps) {
07823             ret = nomem((STMT *) stmt);
07824             goto done;
07825         }
07826     }
07827     if (PKtable) {
07828         pt = uc_to_utf_c(PKtable, PKtableLen);
07829         if (!pt) {
07830             ret = nomem((STMT *) stmt);
07831             goto done;
07832         }
07833     }
07834     if (FKcatalog) {
07835         fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
07836         if (!fc) {
07837             ret = nomem((STMT *) stmt);
07838             goto done;
07839         }
07840     }
07841     if (FKschema) {
07842         fs = uc_to_utf_c(FKschema, FKschemaLen);
07843         if (!fs) {
07844             ret = nomem((STMT *) stmt);
07845             goto done;
07846         }
07847     }
07848     if (FKtable) {
07849         ft = uc_to_utf_c(FKtable, FKtableLen);
07850         if (!ft) {
07851             ret = nomem((STMT *) stmt);
07852             goto done;
07853         }
07854     }
07855     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
07856                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
07857                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
07858                          (SQLCHAR *) ft, SQL_NTS);
07859 done:
07860     uc_free(ft);
07861     uc_free(fs);
07862     uc_free(fc);
07863     uc_free(pt);
07864     uc_free(ps);
07865     uc_free(pc);
07866     HSTMT_UNLOCK(stmt);
07867     return ret;
07868 }
07869 #endif
07870 
07877 static SQLRETURN
07878 starttran(STMT *s)
07879 {
07880     int ret = SQL_SUCCESS, rc, busy_count = 0;
07881     char *errp = NULL;
07882     DBC *d = (DBC *) s->dbc;
07883 
07884     if (!d->autocommit && !d->intrans && !d->trans_disable) {
07885 begin_again:
07886         rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
07887         if (rc == SQLITE_BUSY) {
07888             if (busy_handler((void *) d, ++busy_count)) {
07889                 if (errp) {
07890                     sqlite3_free(errp);
07891                     errp = NULL;
07892                 }
07893                 goto begin_again;
07894             }
07895         }
07896         dbtracerc(d, rc, errp);
07897         if (rc != SQLITE_OK) {
07898             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07899                     errp ? errp : "unknown error", rc);
07900             ret = SQL_ERROR;
07901         } else {
07902             d->intrans = 1;
07903         }
07904         if (errp) {
07905             sqlite3_free(errp);
07906             errp = NULL;
07907         }
07908     }
07909     return ret;
07910 }
07911 
07920 static SQLRETURN
07921 endtran(DBC *d, SQLSMALLINT comptype, int force)
07922 {
07923     int ret, busy_count = 0;
07924     char *sql, *errp = NULL;
07925 
07926     if (!d->sqlite) {
07927         setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
07928         return SQL_ERROR;
07929     }
07930     if ((!force && d->autocommit) || !d->intrans) {
07931         return SQL_SUCCESS;
07932     }
07933     switch (comptype) {
07934     case SQL_COMMIT:
07935         sql = "COMMIT TRANSACTION";
07936         goto doit;
07937     case SQL_ROLLBACK:
07938         sql = "ROLLBACK TRANSACTION";
07939     doit:
07940         ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
07941         dbtracerc(d, ret, errp);
07942         if (ret == SQLITE_BUSY && busy_count < 10) {
07943             if (busy_handler((void *) d, ++busy_count)) {
07944                 if (errp) {
07945                     sqlite3_free(errp);
07946                     errp = NULL;
07947                 }
07948                 goto doit;
07949             }
07950         }
07951         if (ret != SQLITE_OK) {
07952             setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
07953                      errp ? errp : "transaction failed");
07954             if (errp) {
07955                 sqlite3_free(errp);
07956                 errp = NULL;
07957             }
07958             return SQL_ERROR;
07959         }
07960         if (errp) {
07961             sqlite3_free(errp);
07962             errp = NULL;
07963         }
07964         d->intrans = 0;
07965         return SQL_SUCCESS;
07966     }
07967     setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
07968     return SQL_ERROR;
07969 }
07970 
07979 static SQLRETURN
07980 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
07981 {
07982     DBC *dbc = NULL;
07983     int fail = 0;
07984     SQLRETURN ret;
07985 #if defined(_WIN32) || defined(_WIN64)
07986     ENV *env;
07987 #endif
07988 
07989     switch (type) {
07990     case SQL_HANDLE_DBC:
07991         HDBC_LOCK((SQLHDBC) handle);
07992         if (handle == SQL_NULL_HDBC) {
07993             return SQL_INVALID_HANDLE;
07994         }
07995         dbc = (DBC *) handle;
07996         ret = endtran(dbc, comptype, 0);
07997         HDBC_UNLOCK((SQLHDBC) handle);
07998         return ret;
07999     case SQL_HANDLE_ENV:
08000         if (handle == SQL_NULL_HENV) {
08001             return SQL_INVALID_HANDLE;
08002         }
08003 #if defined(_WIN32) || defined(_WIN64)
08004         env = (ENV *) handle;
08005         if (env->magic != ENV_MAGIC) {
08006             return SQL_INVALID_HANDLE;
08007         }
08008         EnterCriticalSection(&env->cs);
08009 #endif
08010         dbc = ((ENV *) handle)->dbcs;
08011         while (dbc) {
08012             HDBC_LOCK((SQLHDBC) dbc);
08013             ret = endtran(dbc, comptype, 0);
08014             HDBC_UNLOCK((SQLHDBC) dbc);
08015             if (ret != SQL_SUCCESS) {
08016                 fail++;
08017             }
08018             dbc = dbc->next;
08019         }
08020 #if defined(_WIN32) || defined(_WIN64)
08021         LeaveCriticalSection(&env->cs);
08022 #endif
08023         return fail ? SQL_ERROR : SQL_SUCCESS;
08024     }
08025     return SQL_INVALID_HANDLE;
08026 }
08027 
08036 SQLRETURN SQL_API
08037 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
08038 {
08039     return drvendtran(type, handle, comptype);
08040 }
08041 
08050 SQLRETURN SQL_API
08051 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
08052 {
08053     if (dbc != SQL_NULL_HDBC) {
08054         return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
08055     }
08056     return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
08057 }
08058 
08063 SQLRETURN SQL_API
08064 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
08065 {
08066     return SQL_ERROR;
08067 }
08068 
08069 #ifndef WINTERFACE
08070 
08081 SQLRETURN SQL_API
08082 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
08083              SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08084 {
08085     int outLen = 0;
08086     SQLRETURN ret = SQL_SUCCESS;
08087 
08088     HSTMT_LOCK(stmt);
08089     if (sqlinLen == SQL_NTS) {
08090         sqlinLen = strlen((char *) sqlin);
08091     }
08092     if (sql) {
08093         if (sqlMax > 0) {
08094             strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
08095             sqlin[sqlMax - 1] = '\0';
08096             outLen = min(sqlMax - 1, sqlinLen);
08097         }
08098     } else {
08099         outLen = sqlinLen;
08100     }
08101     if (sqlLen) {
08102         *sqlLen = outLen;
08103     }
08104     if (sql && outLen < sqlinLen) {
08105         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08106         ret = SQL_SUCCESS_WITH_INFO;
08107     }
08108     HSTMT_UNLOCK(stmt);
08109     return ret;
08110 }
08111 #endif
08112 
08113 #ifdef WINTERFACE
08114 
08125 SQLRETURN SQL_API
08126 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
08127               SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08128 {
08129     int outLen = 0;
08130     SQLRETURN ret = SQL_SUCCESS;
08131 
08132     HSTMT_LOCK(stmt);
08133     if (sqlinLen == SQL_NTS) {
08134         sqlinLen = uc_strlen(sqlin);
08135     }
08136     if (sql) {
08137         if (sqlMax > 0) {
08138             uc_strncpy(sql, sqlin, sqlMax - 1);
08139             sqlin[sqlMax - 1] = 0;
08140             outLen = min(sqlMax  - 1, sqlinLen);
08141         }
08142     } else {
08143         outLen = sqlinLen;
08144     }
08145     if (sqlLen) {
08146         *sqlLen = outLen;
08147     }
08148     if (sql && outLen < sqlinLen) {
08149         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08150         ret = SQL_SUCCESS_WITH_INFO;
08151     }
08152     HSTMT_UNLOCK(stmt);
08153     return ret;
08154 }
08155 #endif
08156 
08161 static COL procSpec2[] = {
08162     { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08163     { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08164     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08165     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08166     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08167     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08168     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08169     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08170 };
08171 
08172 static COL procSpec3[] = {
08173     { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08174     { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08175     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08176     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08177     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08178     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08179     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08180     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08181 };
08182 
08183 #ifndef WINTERFACE
08184 
08196 SQLRETURN SQL_API
08197 SQLProcedures(SQLHSTMT stmt,
08198               SQLCHAR *catalog, SQLSMALLINT catalogLen,
08199               SQLCHAR *schema, SQLSMALLINT schemaLen,
08200               SQLCHAR *proc, SQLSMALLINT procLen)
08201 {
08202     SQLRETURN ret;
08203 
08204     HSTMT_LOCK(stmt);
08205     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08206                       procSpec3, array_size(procSpec3), NULL);
08207     HSTMT_UNLOCK(stmt);
08208     return ret;
08209 }
08210 #endif
08211 
08212 #ifdef WINTERFACE
08213 
08225 SQLRETURN SQL_API
08226 SQLProceduresW(SQLHSTMT stmt,
08227                SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08228                SQLWCHAR *schema, SQLSMALLINT schemaLen,
08229                SQLWCHAR *proc, SQLSMALLINT procLen)
08230 {
08231     SQLRETURN ret;
08232 
08233     HSTMT_LOCK(stmt);
08234     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08235                       procSpec3, array_size(procSpec3), NULL);
08236     HSTMT_UNLOCK(stmt);
08237     return ret;
08238 }
08239 #endif
08240 
08245 static COL procColSpec2[] = {
08246     { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08247     { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08248     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08249     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08250     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08251     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08252     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08253     { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
08254     { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
08255     { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
08256     { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
08257     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08258     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08259     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08260     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08261     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08262     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08263     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08264     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08265 };
08266 
08267 static COL procColSpec3[] = {
08268     { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08269     { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08270     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08271     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08272     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08273     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08274     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08275     { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
08276     { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
08277     { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
08278     { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
08279     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08280     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08281     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08282     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08283     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08284     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08285     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08286     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08287 };
08288 
08289 #ifndef WINTERFACE
08290 
08304 SQLRETURN SQL_API
08305 SQLProcedureColumns(SQLHSTMT stmt,
08306                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
08307                     SQLCHAR *schema, SQLSMALLINT schemaLen,
08308                     SQLCHAR *proc, SQLSMALLINT procLen,
08309                     SQLCHAR *column, SQLSMALLINT columnLen)
08310 {
08311     SQLRETURN ret;
08312 
08313     HSTMT_LOCK(stmt);
08314     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08315                       procColSpec3, array_size(procColSpec3), NULL);
08316     HSTMT_UNLOCK(stmt);
08317     return ret;
08318 }
08319 #endif
08320 
08321 #ifdef WINTERFACE
08322 
08337 SQLRETURN SQL_API
08338 SQLProcedureColumnsW(SQLHSTMT stmt,
08339                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08340                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
08341                      SQLWCHAR *proc, SQLSMALLINT procLen,
08342                      SQLWCHAR *column, SQLSMALLINT columnLen)
08343 {
08344     SQLRETURN ret;
08345 
08346     HSTMT_LOCK(stmt);
08347     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08348                       procColSpec3, array_size(procColSpec3), NULL);
08349     HSTMT_UNLOCK(stmt);
08350     return ret;
08351 }
08352 #endif
08353 
08364 SQLRETURN SQL_API
08365 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
08366               SQLINTEGER len, SQLINTEGER *lenp)
08367 {
08368     ENV *e;
08369     SQLRETURN ret = SQL_ERROR;
08370 
08371     if (env == SQL_NULL_HENV) {
08372         return SQL_INVALID_HANDLE;
08373     }
08374     e = (ENV *) env;
08375     if (!e || e->magic != ENV_MAGIC) {
08376         return SQL_INVALID_HANDLE;
08377     }
08378 #if defined(_WIN32) || defined(_WIN64)
08379     EnterCriticalSection(&e->cs);
08380 #endif
08381     switch (attr) {
08382     case SQL_ATTR_CONNECTION_POOLING:
08383         if (val) {
08384             *((SQLINTEGER *) val) = e->pool ?
08385                 SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
08386         }
08387         if (lenp) {
08388             *lenp = sizeof (SQLINTEGER);
08389         }
08390         ret = SQL_SUCCESS;
08391         break;
08392     case SQL_ATTR_CP_MATCH:
08393         *((SQLINTEGER *) val) = SQL_CP_RELAXED_MATCH;
08394         if (lenp) {
08395             *lenp = sizeof (SQLINTEGER);
08396         }
08397         ret = SQL_SUCCESS;
08398         break;
08399     case SQL_ATTR_OUTPUT_NTS:
08400         if (val) {
08401             *((SQLINTEGER *) val) = SQL_TRUE;
08402         }
08403         if (lenp) {
08404             *lenp = sizeof (SQLINTEGER);
08405         }
08406         ret = SQL_SUCCESS;
08407         break;
08408     case SQL_ATTR_ODBC_VERSION:
08409         if (val) {
08410             *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
08411         }
08412         if (lenp) {
08413             *lenp = sizeof (SQLINTEGER);
08414         }
08415         ret = SQL_SUCCESS;
08416         break;
08417     }
08418 #if defined(_WIN32) || defined(_WIN64)
08419     LeaveCriticalSection(&e->cs);
08420 #endif
08421     return ret;
08422 }
08423 
08433 SQLRETURN SQL_API
08434 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
08435 {
08436     ENV *e;
08437     SQLRETURN ret = SQL_ERROR;
08438 
08439     if (env == SQL_NULL_HENV) {
08440         return SQL_INVALID_HANDLE;
08441     }
08442     e = (ENV *) env;
08443     if (!e || e->magic != ENV_MAGIC) {
08444         return SQL_INVALID_HANDLE;
08445     }
08446 #if defined(_WIN32) || defined(_WIN64)
08447     EnterCriticalSection(&e->cs);
08448 #endif
08449     switch (attr) {
08450     case SQL_ATTR_CONNECTION_POOLING:
08451         if (val == (SQLPOINTER) SQL_CP_ONE_PER_DRIVER) {
08452             e->pool = 1;
08453             ret = SQL_SUCCESS;
08454         } else if (val == (SQLPOINTER) SQL_CP_OFF) {
08455             e->pool = 0;
08456             ret = SQL_SUCCESS;
08457         }
08458         break;
08459     case SQL_ATTR_CP_MATCH:
08460         ret = SQL_SUCCESS;
08461         break;
08462     case SQL_ATTR_OUTPUT_NTS:
08463         if (val == (SQLPOINTER) SQL_TRUE) {
08464             ret = SQL_SUCCESS;
08465         }
08466         break;
08467     case SQL_ATTR_ODBC_VERSION:
08468         if (!val) {
08469             break;
08470         }
08471         if (val == (SQLPOINTER) SQL_OV_ODBC2) {
08472             e->ov3 = 0;
08473             ret = SQL_SUCCESS;
08474         } else if (val == (SQLPOINTER) SQL_OV_ODBC3) {
08475             e->ov3 = 1;
08476             ret = SQL_SUCCESS;
08477         }
08478         break;
08479     }
08480 #if defined(_WIN32) || defined(_WIN64)
08481     LeaveCriticalSection(&e->cs);
08482 #endif
08483     return ret;
08484 }
08485 
08499 static SQLRETURN
08500 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08501               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08502               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08503 {
08504     DBC *d = NULL;
08505     STMT *s = NULL;
08506     int len, naterr;
08507     char *logmsg, *sqlst;
08508     SQLRETURN ret = SQL_ERROR;
08509 
08510     if (handle == SQL_NULL_HANDLE) {
08511         return SQL_INVALID_HANDLE;
08512     }
08513     if (sqlstate) {
08514         sqlstate[0] = '\0';
08515     }
08516     if (msg && buflen > 0) {
08517         msg[0] = '\0';
08518     }
08519     if (msglen) {
08520         *msglen = 0;
08521     }
08522     if (nativeerr) {
08523         *nativeerr = 0;
08524     }
08525     switch (htype) {
08526     case SQL_HANDLE_ENV:
08527     case SQL_HANDLE_DESC:
08528         return SQL_NO_DATA;
08529     case SQL_HANDLE_DBC:
08530         HDBC_LOCK((SQLHDBC) handle);
08531         d = (DBC *) handle;
08532         logmsg = (char *) d->logmsg;
08533         sqlst = d->sqlstate;
08534         naterr = d->naterr;
08535         break;
08536     case SQL_HANDLE_STMT:
08537         HSTMT_LOCK((SQLHSTMT) handle);
08538         s = (STMT *) handle;
08539         logmsg = (char *) s->logmsg;
08540         sqlst = s->sqlstate;
08541         naterr = s->naterr;
08542         break;
08543     default:
08544         return SQL_INVALID_HANDLE;
08545     }
08546     if (buflen < 0) {
08547         goto done;
08548     }
08549     if (recno > 1) {
08550         ret = SQL_NO_DATA;
08551         goto done;
08552     }
08553     len = strlen(logmsg);
08554     if (len == 0) {
08555         ret = SQL_NO_DATA;
08556         goto done;
08557     }
08558     if (nativeerr) {
08559         *nativeerr = naterr;
08560     }
08561     if (sqlstate) {
08562         strcpy((char *) sqlstate, sqlst);
08563     }
08564     if (msglen) {
08565         *msglen = len;
08566     }
08567     if (len >= buflen) {
08568         if (msg && buflen > 0) {
08569             strncpy((char *) msg, logmsg, buflen);
08570             msg[buflen - 1] = '\0';
08571             logmsg[0] = '\0';
08572         }
08573     } else if (msg) {
08574         strcpy((char *) msg, logmsg);
08575         logmsg[0] = '\0';
08576     }
08577     ret = SQL_SUCCESS;
08578 done:
08579     switch (htype) {
08580     case SQL_HANDLE_DBC:
08581         HDBC_UNLOCK((SQLHDBC) handle);
08582         break;
08583     case SQL_HANDLE_STMT:
08584         HSTMT_UNLOCK((SQLHSTMT) handle);
08585         break;
08586     }
08587     return ret;
08588 }
08589 
08590 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
08591 
08604 SQLRETURN SQL_API
08605 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08606               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08607               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08608 {
08609     return drvgetdiagrec(htype, handle, recno, sqlstate,
08610                          nativeerr, msg, buflen, msglen);
08611 }
08612 #endif
08613 
08614 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
08615 #ifdef WINTERFACE
08616 
08630 SQLRETURN SQL_API
08631 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08632               SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
08633               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08634 {
08635     char state[16];
08636     SQLSMALLINT len;
08637     SQLRETURN ret;
08638 
08639     ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
08640                         nativeerr, (SQLCHAR *) msg, buflen, &len);
08641     if (ret == SQL_SUCCESS) {
08642         if (sqlstate) {
08643             uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
08644                             6 * sizeof (SQLWCHAR));
08645         }
08646         if (msg) {
08647             if (len > 0) {
08648                 SQLWCHAR *m = NULL;
08649 
08650                 m = uc_from_utf((unsigned char *) msg, len);
08651                 if (m) {
08652                     if (buflen) {
08653                         buflen /= sizeof (SQLWCHAR);
08654                         uc_strncpy(msg, m, buflen);
08655                         m[len] = 0;
08656                         len = min(buflen, uc_strlen(m));
08657                     } else {
08658                         len = uc_strlen(m);
08659                     }
08660                     uc_free(m);
08661                 } else {
08662                     len = 0;
08663                 }
08664             }
08665             if (len <= 0) {
08666                 len = 0;
08667                 if (buflen > 0) {
08668                     msg[0] = 0;
08669                 }
08670             }
08671         } else {
08672             /* estimated length !!! */
08673             len *= sizeof (SQLWCHAR);
08674         }
08675         if (msglen) {
08676             *msglen = len;
08677         }
08678     } else if (ret == SQL_NO_DATA) {
08679         if (sqlstate) {
08680             sqlstate[0] = 0;
08681         }
08682         if (msg) {
08683             if (buflen > 0) {
08684                 msg[0] = 0;
08685             }
08686         }
08687         if (msglen) {
08688             *msglen = 0;
08689         }
08690     }
08691     return ret;
08692 }
08693 #endif
08694 #endif
08695 
08708 static SQLRETURN
08709 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08710                 SQLSMALLINT id, SQLPOINTER info,
08711                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08712 {
08713     DBC *d = NULL;
08714     STMT *s = NULL;
08715     int len, naterr, strbuf = 1;
08716     char *logmsg, *sqlst, *clrmsg = NULL;
08717     SQLRETURN ret = SQL_ERROR;
08718 
08719     if (handle == SQL_NULL_HANDLE) {
08720         return SQL_INVALID_HANDLE;
08721     }
08722     if (stringlen) {
08723         *stringlen = 0;
08724     }
08725     switch (htype) {
08726     case SQL_HANDLE_ENV:
08727     case SQL_HANDLE_DESC:
08728         return SQL_NO_DATA;
08729     case SQL_HANDLE_DBC:
08730         HDBC_LOCK((SQLHDBC) handle);
08731         d = (DBC *) handle;
08732         logmsg = (char *) d->logmsg;
08733         sqlst = d->sqlstate;
08734         naterr = d->naterr;
08735         break;
08736     case SQL_HANDLE_STMT:
08737         HSTMT_LOCK((SQLHSTMT) handle);
08738         s = (STMT *) handle;
08739         d = (DBC *) s->dbc;
08740         logmsg = (char *) s->logmsg;
08741         sqlst = s->sqlstate;
08742         naterr = s->naterr;
08743         break;
08744     default:
08745         return SQL_INVALID_HANDLE;
08746     }
08747     if (buflen < 0) {
08748         switch (buflen) {
08749         case SQL_IS_POINTER:
08750         case SQL_IS_UINTEGER:
08751         case SQL_IS_INTEGER:
08752         case SQL_IS_USMALLINT:
08753         case SQL_IS_SMALLINT:
08754             strbuf = 0;
08755             break;
08756         default:
08757             ret = SQL_ERROR;
08758             goto done;
08759         }
08760     }
08761     if (recno > 1) {
08762         ret = SQL_NO_DATA;
08763         goto done;
08764     }
08765     switch (id) {
08766     case SQL_DIAG_CLASS_ORIGIN:
08767         logmsg = "ISO 9075";
08768         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
08769             logmsg = "ODBC 3.0";
08770         }
08771         break;
08772     case SQL_DIAG_SUBCLASS_ORIGIN:
08773         logmsg = "ISO 9075";
08774         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
08775             logmsg = "ODBC 3.0";
08776         } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
08777             logmsg = "ODBC 3.0";
08778         } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
08779             logmsg = "ODBC 3.0";
08780         }
08781         break;
08782     case SQL_DIAG_CONNECTION_NAME:
08783     case SQL_DIAG_SERVER_NAME:
08784         logmsg = d->dsn ? d->dsn : "No DSN";
08785         break;
08786     case SQL_DIAG_SQLSTATE:
08787         logmsg = sqlst;
08788         break;
08789     case SQL_DIAG_MESSAGE_TEXT:
08790         if (info) {
08791             clrmsg = logmsg;
08792         }
08793         break;
08794     case SQL_DIAG_NUMBER:
08795         naterr = 1;
08796         /* fall through */
08797     case SQL_DIAG_NATIVE:
08798         len = strlen(logmsg);
08799         if (len == 0) {
08800             ret = SQL_NO_DATA;
08801             goto done;
08802         }
08803         if (info) {
08804             *((SQLINTEGER *) info) = naterr;
08805         }
08806         ret = SQL_SUCCESS;
08807         goto done;
08808     case SQL_DIAG_DYNAMIC_FUNCTION:
08809         logmsg = "";
08810         break;
08811     case SQL_DIAG_CURSOR_ROW_COUNT:
08812         if (htype == SQL_HANDLE_STMT) {
08813             SQLULEN count;
08814 
08815             count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
08816             *((SQLULEN *) info) = count;
08817             ret = SQL_SUCCESS;
08818         }
08819         goto done;
08820     case SQL_DIAG_ROW_COUNT:
08821         if (htype == SQL_HANDLE_STMT) {
08822             SQLULEN count;
08823 
08824             count = s->isselect ? 0 : s->nrows;
08825             *((SQLULEN *) info) = count;
08826             ret = SQL_SUCCESS;
08827         }
08828         goto done;
08829     default:
08830         goto done;
08831     }
08832     if (info && buflen > 0) {
08833         ((char *) info)[0] = '\0';
08834     }
08835     len = strlen(logmsg);
08836     if (len == 0) {
08837         ret = SQL_NO_DATA;
08838         goto done;
08839     }
08840     if (stringlen) {
08841         *stringlen = len;
08842     }
08843     if (strbuf) {
08844         if (len >= buflen) {
08845             if (info && buflen > 0) {
08846                 if (stringlen) {
08847                     *stringlen = buflen - 1;
08848                 }
08849                 strncpy((char *) info, logmsg, buflen);
08850                 ((char *) info)[buflen - 1] = '\0';
08851             }
08852         } else if (info) {
08853             strcpy((char *) info, logmsg);
08854         }
08855     }
08856     if (clrmsg) {
08857         *clrmsg = '\0';
08858     }
08859     ret = SQL_SUCCESS;
08860 done:
08861     switch (htype) {
08862     case SQL_HANDLE_DBC:
08863         HDBC_UNLOCK((SQLHDBC) handle);
08864         break;
08865     case SQL_HANDLE_STMT:
08866         HSTMT_UNLOCK((SQLHSTMT) handle);
08867         break;
08868     }
08869     return ret;
08870 }
08871 
08872 #ifndef WINTERFACE
08873 
08885 SQLRETURN SQL_API
08886 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08887                 SQLSMALLINT id, SQLPOINTER info,
08888                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08889 {
08890     return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
08891 }
08892 #endif
08893 
08894 #ifdef WINTERFACE
08895 
08907 SQLRETURN SQL_API
08908 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08909                  SQLSMALLINT id, SQLPOINTER info,
08910                  SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08911 {
08912     SQLSMALLINT len;
08913     SQLRETURN ret;
08914 
08915     ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
08916     if (ret == SQL_SUCCESS) {
08917         if (info) {
08918             switch (id) {
08919             case SQL_DIAG_CLASS_ORIGIN:
08920             case SQL_DIAG_SUBCLASS_ORIGIN:
08921             case SQL_DIAG_CONNECTION_NAME:
08922             case SQL_DIAG_SERVER_NAME:
08923             case SQL_DIAG_SQLSTATE:
08924             case SQL_DIAG_MESSAGE_TEXT:
08925             case SQL_DIAG_DYNAMIC_FUNCTION:
08926                 if (len > 0) {
08927                     SQLWCHAR *m = NULL;
08928 
08929                     m = uc_from_utf((unsigned char *) info, len);
08930                     if (m) {
08931                         if (buflen) {
08932                             buflen /= sizeof (SQLWCHAR);
08933                             uc_strncpy(info, m, buflen);
08934                             m[len] = 0;
08935                             len = min(buflen, uc_strlen(m));
08936                         } else {
08937                             len = uc_strlen(m);
08938                         }
08939                         uc_free(m);
08940                         len *= sizeof (SQLWCHAR);
08941                     } else {
08942                         len = 0;
08943                     }
08944                 }
08945                 if (len <= 0) {
08946                     len = 0;
08947                     if (buflen > 0) {
08948                         ((SQLWCHAR *) info)[0] = 0;
08949                     }
08950                 }
08951             }
08952         } else {
08953             switch (id) {
08954             case SQL_DIAG_CLASS_ORIGIN:
08955             case SQL_DIAG_SUBCLASS_ORIGIN:
08956             case SQL_DIAG_CONNECTION_NAME:
08957             case SQL_DIAG_SERVER_NAME:
08958             case SQL_DIAG_SQLSTATE:
08959             case SQL_DIAG_MESSAGE_TEXT:
08960             case SQL_DIAG_DYNAMIC_FUNCTION:
08961                 len *= sizeof (SQLWCHAR);
08962                 break;
08963             }
08964         }
08965         if (stringlen) {
08966             *stringlen = len;
08967         }
08968     }
08969     return ret;
08970 }
08971 #endif
08972 
08983 static SQLRETURN
08984 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
08985                SQLINTEGER bufmax, SQLINTEGER *buflen)
08986 {
08987     STMT *s = (STMT *) stmt;
08988     SQLULEN *uval = (SQLULEN *) val;
08989     SQLINTEGER dummy;
08990     char dummybuf[16];
08991 
08992     if (!buflen) {
08993         buflen = &dummy;
08994     }
08995     if (!uval) {
08996         uval = (SQLPOINTER) dummybuf;
08997     }
08998     switch (attr) {
08999     case SQL_QUERY_TIMEOUT:
09000         *uval = 0;
09001         *buflen = sizeof (SQLULEN);
09002         return SQL_SUCCESS;
09003     case SQL_ATTR_CURSOR_TYPE:
09004         *uval = s->curtype;
09005         *buflen = sizeof (SQLULEN);
09006         return SQL_SUCCESS;
09007     case SQL_ATTR_CURSOR_SCROLLABLE:
09008         *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
09009             SQL_SCROLLABLE : SQL_NONSCROLLABLE;
09010         *buflen = sizeof (SQLULEN);
09011         return SQL_SUCCESS;
09012 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09013     case SQL_ATTR_CURSOR_SENSITIVITY:
09014         *uval = SQL_UNSPECIFIED;
09015         *buflen = sizeof (SQLULEN);
09016         return SQL_SUCCESS;
09017 #endif
09018     case SQL_ATTR_ROW_NUMBER:
09019         if (s->s3stmt) {
09020             *uval = (s->s3stmt_rownum < 0) ?
09021                     SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09022         } else {
09023             *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09024         }
09025         *buflen = sizeof (SQLULEN);
09026         return SQL_SUCCESS;
09027     case SQL_ATTR_ASYNC_ENABLE:
09028         *uval = SQL_ASYNC_ENABLE_OFF;
09029         *buflen = sizeof (SQLULEN);
09030         return SQL_SUCCESS;
09031     case SQL_CONCURRENCY:
09032         *uval = SQL_CONCUR_LOCK;
09033         *buflen = sizeof (SQLULEN);
09034         return SQL_SUCCESS;
09035     case SQL_ATTR_RETRIEVE_DATA:
09036         *uval = s->retr_data;
09037         *buflen = sizeof (SQLULEN);
09038         return SQL_SUCCESS;
09039     case SQL_ROWSET_SIZE:
09040     case SQL_ATTR_ROW_ARRAY_SIZE:
09041         *uval = s->rowset_size;
09042         *buflen = sizeof (SQLULEN);
09043         return SQL_SUCCESS;
09044     /* Needed for some driver managers, but dummies for now */
09045     case SQL_ATTR_IMP_ROW_DESC:
09046     case SQL_ATTR_APP_ROW_DESC:
09047     case SQL_ATTR_IMP_PARAM_DESC:
09048     case SQL_ATTR_APP_PARAM_DESC:
09049         *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
09050         *buflen = sizeof (SQLHDESC);
09051         return SQL_SUCCESS;
09052     case SQL_ATTR_ROW_STATUS_PTR:
09053         *((SQLUSMALLINT **) uval) = s->row_status;
09054         *buflen = sizeof (SQLUSMALLINT *);
09055         return SQL_SUCCESS;
09056     case SQL_ATTR_ROWS_FETCHED_PTR:
09057         *((SQLULEN **) uval) = s->row_count;
09058         *buflen = sizeof (SQLULEN *);
09059         return SQL_SUCCESS;
09060     case SQL_ATTR_USE_BOOKMARKS: {
09061         STMT *s = (STMT *) stmt;
09062 
09063         *(SQLUINTEGER *) uval = s->bkmrk;
09064         *buflen = sizeof (SQLUINTEGER);
09065         return SQL_SUCCESS;
09066     }
09067     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09068         *(SQLPOINTER *) uval = s->bkmrkptr;
09069         *buflen = sizeof (SQLPOINTER);
09070         return SQL_SUCCESS;
09071     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09072         *((SQLULEN **) uval) = s->parm_bind_offs;
09073         *buflen = sizeof (SQLULEN *);
09074         return SQL_SUCCESS;
09075     case SQL_ATTR_PARAM_BIND_TYPE:
09076         *((SQLULEN *) uval) = s->parm_bind_type;
09077         *buflen = sizeof (SQLULEN);
09078         return SQL_SUCCESS;
09079     case SQL_ATTR_PARAM_OPERATION_PTR:
09080         *((SQLUSMALLINT **) uval) = s->parm_oper;
09081         *buflen = sizeof (SQLUSMALLINT *);
09082         return SQL_SUCCESS;
09083     case SQL_ATTR_PARAM_STATUS_PTR:
09084         *((SQLUSMALLINT **) uval) = s->parm_status;
09085         *buflen = sizeof (SQLUSMALLINT *);
09086         return SQL_SUCCESS;
09087     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09088         *((SQLULEN **) uval) = s->parm_proc;
09089         *buflen = sizeof (SQLULEN *);
09090         return SQL_SUCCESS;
09091     case SQL_ATTR_PARAMSET_SIZE:
09092         *((SQLULEN *) uval) = s->paramset_size;
09093         *buflen = sizeof (SQLULEN);
09094         return SQL_SUCCESS;
09095     case SQL_ATTR_ROW_BIND_TYPE:
09096         *(SQLULEN *) uval = s->bind_type;
09097         *buflen = sizeof (SQLULEN);
09098         return SQL_SUCCESS;
09099     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09100         *((SQLULEN **) uval) = s->bind_offs;
09101         *buflen = sizeof (SQLULEN *);
09102         return SQL_SUCCESS;
09103     case SQL_ATTR_MAX_ROWS:
09104         *((SQLULEN *) uval) = s->max_rows;
09105         *buflen = sizeof (SQLULEN);
09106         return SQL_SUCCESS;
09107     case SQL_ATTR_MAX_LENGTH:
09108         *((SQLULEN *) uval) = 1000000000;
09109         *buflen = sizeof (SQLULEN);
09110         return SQL_SUCCESS;
09111 #ifdef SQL_ATTR_METADATA_ID
09112     case SQL_ATTR_METADATA_ID:
09113         *((SQLULEN *) uval) = SQL_FALSE;
09114         *buflen = sizeof (SQLULEN);
09115         return SQL_SUCCESS;
09116 #endif
09117     }
09118     return drvunimplstmt(stmt);
09119 }
09120 
09121 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09122 
09132 SQLRETURN SQL_API
09133 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09134                SQLINTEGER bufmax, SQLINTEGER *buflen)
09135 {
09136     SQLRETURN ret;
09137 
09138     HSTMT_LOCK(stmt);
09139     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09140     HSTMT_UNLOCK(stmt);
09141     return ret;
09142 }
09143 #endif
09144 
09145 #ifdef WINTERFACE
09146 
09156 SQLRETURN SQL_API
09157 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09158                 SQLINTEGER bufmax, SQLINTEGER *buflen)
09159 {
09160     SQLRETURN ret;
09161 
09162     HSTMT_LOCK(stmt);
09163     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09164     HSTMT_UNLOCK(stmt);
09165     return ret;
09166 }
09167 #endif
09168 
09178 static SQLRETURN
09179 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09180                SQLINTEGER buflen)
09181 {
09182     STMT *s = (STMT *) stmt;
09183 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
09184     SQLBIGINT uval;
09185 
09186     uval = (SQLBIGINT) val;
09187 #else
09188     SQLULEN uval;
09189 
09190     uval = (SQLULEN) val;
09191 #endif
09192     switch (attr) {
09193     case SQL_ATTR_CURSOR_TYPE:
09194         if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
09195             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09196         } else {
09197             s->curtype = SQL_CURSOR_STATIC;
09198         }
09199         if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
09200             val != (SQLPOINTER) SQL_CURSOR_STATIC) {
09201             goto e01s02;
09202         }
09203         return SQL_SUCCESS;
09204     case SQL_ATTR_CURSOR_SCROLLABLE:
09205         if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
09206             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09207         } else {
09208             s->curtype = SQL_CURSOR_STATIC;
09209         }
09210         return SQL_SUCCESS;
09211     case SQL_ATTR_ASYNC_ENABLE:
09212         if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
09213     e01s02:
09214             setstat(s, -1, "option value changed", "01S02");
09215             return SQL_SUCCESS_WITH_INFO;
09216         }
09217         return SQL_SUCCESS;
09218     case SQL_CONCURRENCY:
09219         if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
09220             goto e01s02;
09221         }
09222         return SQL_SUCCESS;
09223 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09224     case SQL_ATTR_CURSOR_SENSITIVITY:
09225         if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
09226             goto e01s02;
09227         }
09228         return SQL_SUCCESS;
09229 #endif
09230     case SQL_ATTR_QUERY_TIMEOUT:
09231         return SQL_SUCCESS;
09232     case SQL_ATTR_RETRIEVE_DATA:
09233         if (val != (SQLPOINTER) SQL_RD_ON &&
09234             val != (SQLPOINTER) SQL_RD_OFF) {
09235             goto e01s02;
09236         }
09237         s->retr_data = uval;
09238         return SQL_SUCCESS;
09239     case SQL_ROWSET_SIZE:
09240     case SQL_ATTR_ROW_ARRAY_SIZE:
09241         if (uval < 1) {
09242             setstat(s, -1, "invalid rowset size", "HY000");
09243             return SQL_ERROR;
09244         } else {
09245             SQLUSMALLINT *rst = &s->row_status1;
09246 
09247             if (uval > 1) {
09248                 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
09249                 if (!rst) {
09250                     return nomem(s);
09251                 }
09252             }
09253             if (s->row_status0 != &s->row_status1) {
09254                 freep(&s->row_status0);
09255             }
09256             s->row_status0 = rst;
09257             s->rowset_size = uval;
09258         }
09259         return SQL_SUCCESS;
09260     case SQL_ATTR_ROW_STATUS_PTR:
09261         s->row_status = (SQLUSMALLINT *) val;
09262         return SQL_SUCCESS;
09263     case SQL_ATTR_ROWS_FETCHED_PTR:
09264         s->row_count = (SQLULEN *) val;
09265         return SQL_SUCCESS;
09266     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09267         s->parm_bind_offs = (SQLULEN *) val;
09268         return SQL_SUCCESS;
09269     case SQL_ATTR_PARAM_BIND_TYPE:
09270         s->parm_bind_type = uval;
09271         return SQL_SUCCESS;
09272     case SQL_ATTR_PARAM_OPERATION_PTR:
09273         s->parm_oper = (SQLUSMALLINT *) val;
09274         return SQL_SUCCESS;
09275     case SQL_ATTR_PARAM_STATUS_PTR:
09276         s->parm_status = (SQLUSMALLINT *) val;
09277         return SQL_SUCCESS;
09278     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09279         s->parm_proc = (SQLULEN *) val;
09280         return SQL_SUCCESS;
09281     case SQL_ATTR_PARAMSET_SIZE:
09282         if (uval < 1) {
09283             goto e01s02;
09284         }
09285         s->paramset_size = uval;
09286         s->paramset_count = 0;
09287         return SQL_SUCCESS;
09288     case SQL_ATTR_ROW_BIND_TYPE:
09289         s->bind_type = uval;
09290         return SQL_SUCCESS;
09291     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09292         s->bind_offs = (SQLULEN *) val;
09293         return SQL_SUCCESS;
09294     case SQL_ATTR_USE_BOOKMARKS:
09295         if (val != (SQLPOINTER) SQL_UB_OFF &&
09296             val != (SQLPOINTER) SQL_UB_ON &&
09297             val != (SQLPOINTER) SQL_UB_VARIABLE) {
09298             goto e01s02;
09299         }
09300         if (*s->ov3 && val == (SQLPOINTER) SQL_UB_VARIABLE) {
09301             s->bkmrk = SQL_UB_VARIABLE;
09302             return SQL_SUCCESS;
09303         }
09304         if (val == (SQLPOINTER) SQL_UB_VARIABLE) {
09305             s->bkmrk = SQL_UB_ON;
09306             goto e01s02;
09307         }
09308         s->bkmrk = (val == (SQLPOINTER) SQL_UB_ON) ? SQL_UB_ON : SQL_UB_OFF;
09309         return SQL_SUCCESS;
09310     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09311         s->bkmrkptr = (SQLINTEGER *) val;
09312         return SQL_SUCCESS;
09313     case SQL_ATTR_MAX_ROWS:
09314         s->max_rows = uval;
09315         return SQL_SUCCESS;
09316     case SQL_ATTR_MAX_LENGTH:
09317         if (val != (SQLPOINTER) 1000000000) {
09318             goto e01s02;
09319         }
09320         return SQL_SUCCESS;
09321 #ifdef SQL_ATTR_METADATA_ID
09322     case SQL_ATTR_METADATA_ID:
09323         if (val != (SQLPOINTER) SQL_FALSE) {
09324             goto e01s02;
09325         }
09326         return SQL_SUCCESS;
09327 #endif
09328     }
09329     return drvunimplstmt(stmt);
09330 }
09331 
09332 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09333 
09342 SQLRETURN SQL_API
09343 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09344                SQLINTEGER buflen)
09345 {
09346     SQLRETURN ret;
09347 
09348     HSTMT_LOCK(stmt);
09349     ret = drvsetstmtattr(stmt, attr, val, buflen);
09350     HSTMT_UNLOCK(stmt);
09351     return ret;
09352 }
09353 #endif
09354 
09355 #ifdef WINTERFACE
09356 
09365 SQLRETURN SQL_API
09366 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09367                 SQLINTEGER buflen)
09368 {
09369     SQLRETURN ret;
09370 
09371     HSTMT_LOCK(stmt);
09372     ret = drvsetstmtattr(stmt, attr, val, buflen);
09373     HSTMT_UNLOCK(stmt);
09374     return ret;
09375 }
09376 #endif
09377 
09386 static SQLRETURN
09387 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09388 {
09389     STMT *s = (STMT *) stmt;
09390     SQLUINTEGER *ret = (SQLUINTEGER *) param;
09391 
09392     switch (opt) {
09393     case SQL_QUERY_TIMEOUT:
09394         *ret = 0;
09395         return SQL_SUCCESS;
09396     case SQL_CURSOR_TYPE:
09397         *ret = s->curtype;
09398         return SQL_SUCCESS;
09399     case SQL_ROW_NUMBER:
09400         if (s->s3stmt) {
09401             *ret = (s->s3stmt_rownum < 0) ?
09402                    SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09403         } else {
09404             *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09405         }
09406         return SQL_SUCCESS;
09407     case SQL_ASYNC_ENABLE:
09408         *ret = SQL_ASYNC_ENABLE_OFF;
09409         return SQL_SUCCESS;
09410     case SQL_CONCURRENCY:
09411         *ret = SQL_CONCUR_LOCK;
09412         return SQL_SUCCESS;
09413     case SQL_ATTR_RETRIEVE_DATA:
09414         *ret = s->retr_data;
09415         return SQL_SUCCESS;
09416     case SQL_ROWSET_SIZE:
09417     case SQL_ATTR_ROW_ARRAY_SIZE:
09418         *ret = s->rowset_size;
09419         return SQL_SUCCESS;
09420     case SQL_ATTR_MAX_ROWS:
09421         *ret = s->max_rows;
09422         return SQL_SUCCESS;
09423     case SQL_ATTR_MAX_LENGTH:
09424         *ret = 1000000000;
09425         return SQL_SUCCESS;
09426     }
09427     return drvunimplstmt(stmt);
09428 }
09429 
09438 SQLRETURN SQL_API
09439 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09440 {
09441     SQLRETURN ret;
09442 
09443     HSTMT_LOCK(stmt);
09444     ret = drvgetstmtoption(stmt, opt, param);
09445     HSTMT_UNLOCK(stmt);
09446     return ret;
09447 }
09448 
09449 #ifdef WINTERFACE
09450 
09458 SQLRETURN SQL_API
09459 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09460 {
09461     SQLRETURN ret;
09462 
09463     HSTMT_LOCK(stmt);
09464     ret = drvgetstmtoption(stmt, opt, param);
09465     HSTMT_UNLOCK(stmt);
09466     return ret;
09467 }
09468 #endif
09469 
09478 static SQLRETURN
09479 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
09480 {
09481     STMT *s = (STMT *) stmt;
09482 
09483     switch (opt) {
09484     case SQL_CURSOR_TYPE:
09485         if (param == SQL_CURSOR_FORWARD_ONLY) {
09486             s->curtype = param;
09487         } else {
09488             s->curtype = SQL_CURSOR_STATIC;
09489         }
09490         if (param != SQL_CURSOR_FORWARD_ONLY &&
09491             param != SQL_CURSOR_STATIC) {
09492             goto e01s02;
09493         }
09494         return SQL_SUCCESS;
09495     case SQL_ASYNC_ENABLE:
09496         if (param != SQL_ASYNC_ENABLE_OFF) {
09497             goto e01s02;
09498         }
09499         return SQL_SUCCESS;
09500     case SQL_CONCURRENCY:
09501         if (param != SQL_CONCUR_LOCK) {
09502             goto e01s02;
09503         }
09504         return SQL_SUCCESS;
09505     case SQL_QUERY_TIMEOUT:
09506         return SQL_SUCCESS;
09507     case SQL_RETRIEVE_DATA:
09508         if (param != SQL_RD_ON && param != SQL_RD_OFF) {
09509     e01s02:
09510             setstat(s, -1, "option value changed", "01S02");
09511             return SQL_SUCCESS_WITH_INFO;
09512         }
09513         s->retr_data = (int) param;
09514         return SQL_SUCCESS;
09515     case SQL_ROWSET_SIZE:
09516     case SQL_ATTR_ROW_ARRAY_SIZE:
09517         if (param < 1) {
09518             setstat(s, -1, "invalid rowset size", "HY000");
09519             return SQL_ERROR;
09520         } else {
09521             SQLUSMALLINT *rst = &s->row_status1;
09522 
09523             if (param > 1) {
09524                 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
09525                 if (!rst) {
09526                     return nomem(s);
09527                 }
09528             }
09529             if (s->row_status0 != &s->row_status1) {
09530                 freep(&s->row_status0);
09531             }
09532             s->row_status0 = rst;
09533             s->rowset_size = param;
09534         }
09535         return SQL_SUCCESS;
09536     case SQL_ATTR_MAX_ROWS:
09537         s->max_rows = param;
09538         return SQL_SUCCESS;
09539     case SQL_ATTR_MAX_LENGTH:
09540         if (param != 1000000000) {
09541             goto e01s02;
09542         }
09543         return SQL_SUCCESS;
09544     }
09545     return drvunimplstmt(stmt);
09546 }
09547 
09556 SQLRETURN SQL_API
09557 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
09558                  SETSTMTOPTION_LAST_ARG_TYPE param)
09559 {
09560     SQLRETURN ret;
09561 
09562     HSTMT_LOCK(stmt);
09563     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09564     HSTMT_UNLOCK(stmt);
09565     return ret;
09566 }
09567 
09568 #ifdef WINTERFACE
09569 
09577 SQLRETURN SQL_API
09578 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
09579                   SETSTMTOPTION_LAST_ARG_TYPE param)
09580 {
09581     SQLRETURN ret;
09582 
09583     HSTMT_LOCK(stmt);
09584     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09585     HSTMT_UNLOCK(stmt);
09586     return ret;
09587 }
09588 #endif
09589 
09596 static SQLRETURN
09597 chkunbound(STMT *s)
09598 {
09599     int i;
09600 
09601     if (!s->bindcols || s->nbindcols < s->ncols) {
09602 unbound:
09603         setstat(s, -1, "unbound columns", (*s->ov3) ? "HY000" : "S1000");
09604         return SQL_ERROR;
09605     }
09606     for (i = 0; i < s->ncols; i++) {
09607         BINDCOL *b = &s->bindcols[i];
09608 
09609         if (b->type == SQL_UNKNOWN_TYPE || !b->valp) {
09610             goto unbound;
09611         }
09612     }
09613     return SQL_SUCCESS;
09614 }
09615 
09627 static SQLRETURN
09628 setposbind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
09629 {
09630     DBC *d = (DBC *) s->dbc;
09631     SQLPOINTER dp = 0;
09632     SQLLEN *lp = 0;
09633     BINDCOL *b = &s->bindcols[i];
09634     COL *c = &s->cols[i];
09635     char strbuf[128], *cp;
09636 
09637     if (b->valp) {
09638         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09639             dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
09640         } else {
09641             dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
09642         }
09643         if (s->bind_offs) {
09644             dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
09645         }
09646     }
09647     if (b->lenp) {
09648         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09649             lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
09650         } else {
09651             lp = b->lenp + rsi;
09652         }
09653         if (s->bind_offs) {
09654             lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
09655         }
09656     }
09657     if (!dp || !lp) {
09658         setstat(s, -1, "unbound column in positional update",
09659                 (*s->ov3) ? "HY000" : "S1000");
09660         return SQL_ERROR;
09661     }
09662     if (*lp == SQL_NULL_DATA) {
09663         sqlite3_bind_null(stmt, si);
09664         if (d->trace) {
09665             fprintf(d->trace, "-- parameter %d: NULL\n", si);
09666             fflush(d->trace);
09667         }
09668         return SQL_SUCCESS;
09669     }
09670     switch (b->type) {
09671     case SQL_C_UTINYINT:
09672     case SQL_C_TINYINT:
09673     case SQL_C_STINYINT:
09674         sqlite3_bind_int(stmt, si, *(SQLCHAR *) dp);
09675         if (d->trace) {
09676             fprintf(d->trace, "-- parameter %d: %d\n", si, *(SQLCHAR *) dp);
09677             fflush(d->trace);
09678         }
09679         break;
09680 #ifdef SQL_BIT
09681     case SQL_C_BIT:
09682         sqlite3_bind_int(stmt, si, (*(SQLCHAR *) dp) ? 1 : 0);
09683         if (d->trace) {
09684             fprintf(d->trace, "-- parameter %d: %d\n", si,
09685                     (*(SQLCHAR *) dp) ? 1 : 0);
09686             fflush(d->trace);
09687         }
09688         break;
09689 #endif
09690     case SQL_C_USHORT:
09691         sqlite3_bind_int(stmt, si, *(SQLUSMALLINT *) dp);
09692         if (d->trace) {
09693             fprintf(d->trace, "-- parameter %d: %d\n", si,
09694                     *(SQLUSMALLINT *) dp);
09695             fflush(d->trace);
09696         }
09697         break;
09698     case SQL_C_SHORT:
09699     case SQL_C_SSHORT:
09700         sqlite3_bind_int(stmt, si, *(SQLSMALLINT *) dp);
09701         if (d->trace) {
09702             fprintf(d->trace, "-- parameter %d: %d\n", si,
09703                     *(SQLSMALLINT *) dp);
09704             fflush(d->trace);
09705         }
09706         break;
09707     case SQL_C_ULONG:
09708         sqlite3_bind_int(stmt, si, *(SQLUINTEGER *) dp);
09709         if (d->trace) {
09710             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09711                     (long) *(SQLUINTEGER *) dp);
09712             fflush(d->trace);
09713         }
09714         break;
09715     case SQL_C_LONG:
09716     case SQL_C_SLONG:
09717         sqlite3_bind_int(stmt, si, *(SQLINTEGER *) dp);
09718         if (d->trace) {
09719             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09720                     (long) *(SQLINTEGER *) dp);
09721             fflush(d->trace);
09722         }
09723         break;
09724 #ifdef SQL_BIGINT
09725     case SQL_C_UBIGINT:
09726     case SQL_C_SBIGINT:
09727         sqlite3_bind_int64(stmt, si, *(SQLBIGINT *) dp);
09728         if (d->trace) {
09729             fprintf(d->trace,
09730 #ifdef _WIN32
09731                     "-- parameter %d: %I64d\n",
09732 #else
09733                     "-- parameter %d: %lld\n",
09734 #endif
09735                     si, (sqlite_int64) *(SQLBIGINT *) dp);
09736             fflush(d->trace);
09737         }
09738         break;
09739 #endif
09740     case SQL_C_FLOAT:
09741         sqlite3_bind_double(stmt, si, *(float *) dp);
09742         if (d->trace) {
09743             fprintf(d->trace, "-- parameter %d: %g\n", si,
09744                     *(float *) dp);
09745             fflush(d->trace);
09746         }
09747         break;
09748     case SQL_C_DOUBLE:
09749         sqlite3_bind_double(stmt, si, *(double *) dp);
09750         if (d->trace) {
09751             fprintf(d->trace, "-- parameter %d: %g\n", si,
09752                     *(double *) dp);
09753             fflush(d->trace);
09754         }
09755         break;
09756     case SQL_C_BINARY:
09757         sqlite3_bind_blob(stmt, si, (char *) dp, *lp, SQLITE_STATIC);
09758         if (d->trace) {
09759             fprintf(d->trace, "-- parameter %d: [BLOB]\n", si);
09760             fflush(d->trace);
09761         }
09762         break;
09763 #ifdef WCHARSUPPORT
09764     case SQL_C_WCHAR:
09765         cp = uc_to_utf((SQLWCHAR *) dp, *lp);
09766         if (!cp) {
09767             return nomem(s);
09768         }
09769         sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
09770         if (d->trace) {
09771             fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
09772             fflush(d->trace);
09773         }
09774         uc_free(cp);
09775         break;
09776 #endif
09777     case SQL_C_CHAR:
09778 #if defined(_WIN32) || defined(_WIN64)
09779         if (*s->oemcp) {
09780             cp = wmb_to_utf((char *) dp, *lp);
09781             if (!cp) {
09782                 return nomem(s);
09783             }
09784             sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
09785             if (d->trace) {
09786                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
09787                 fflush(d->trace);
09788             }
09789             uc_free(cp);
09790         } else
09791 #endif
09792         {
09793             if (*lp == SQL_NTS) {
09794                 sqlite3_bind_text(stmt, si, (char *) dp, -1,
09795                                   SQLITE_STATIC);
09796                 if (d->trace) {
09797                     fprintf(d->trace, "-- parameter %d: '%s'\n", si,
09798                             (char *) dp);
09799                     fflush(d->trace);
09800                 }
09801             } else {
09802                 sqlite3_bind_text(stmt, si, (char *) dp, *lp,
09803                                   SQLITE_STATIC);
09804                 if (d->trace) {
09805                     fprintf(d->trace, "-- parameter %d: '%*s'\n", si,
09806                             (int) *lp, (char *) dp);
09807                     fflush(d->trace);
09808                 }
09809             }
09810         }
09811         break;
09812 #ifdef SQL_C_TYPE_DATE
09813     case SQL_C_TYPE_DATE:
09814 #endif
09815     case SQL_C_DATE:
09816         if (*s->jdconv) {
09817             int a, b, x1, x2, y, m, dd;
09818             double v;
09819 
09820             y = ((DATE_STRUCT *) dp)->year;
09821             m = ((DATE_STRUCT *) dp)->month;
09822             dd = ((DATE_STRUCT *) dp)->day;
09823             if (m <= 2) {
09824                 y--;
09825                 m += 12;
09826             }
09827             a = y / 100;
09828             b = 2 - a + (a / 4);
09829             x1 = 36525 * (y + 4716) / 100;
09830             x2 = 306001 * (m + 1) / 10000;
09831             v = x1 + x2 + dd + b - 1524.5;
09832             sqlite3_bind_double(stmt, si, v);
09833             if (d->trace) {
09834                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
09835                 fflush(d->trace);
09836             }
09837         } else {
09838             sprintf(strbuf, "%04d-%02d-%02d",
09839                     ((DATE_STRUCT *) dp)->year,
09840                     ((DATE_STRUCT *) dp)->month,
09841                     ((DATE_STRUCT *) dp)->day);
09842             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
09843             if (d->trace) {
09844                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
09845                 fflush(d->trace);
09846             }
09847         }
09848         break;
09849 #ifdef SQL_C_TYPE_TIME
09850     case SQL_C_TYPE_TIME:
09851 #endif
09852     case SQL_C_TIME:
09853         if (*s->jdconv) {
09854             double v;
09855 
09856             v = 2451544.5 +
09857                (((TIME_STRUCT *) dp)->hour * 3600000.0 +
09858                 ((TIME_STRUCT *) dp)->minute * 60000.0 +
09859                 ((TIME_STRUCT *) dp)->second * 1000.0) / 86400000.0;
09860             sqlite3_bind_double(stmt, si, v);
09861             if (d->trace) {
09862                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
09863                 fflush(d->trace);
09864             }
09865         } else {
09866             sprintf(strbuf, "%02d:%02d:%02d",
09867                     ((TIME_STRUCT *) dp)->hour,
09868                     ((TIME_STRUCT *) dp)->minute,
09869                     ((TIME_STRUCT *) dp)->second);
09870             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
09871             if (d->trace) {
09872                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
09873                 fflush(d->trace);
09874             }
09875         }
09876         break;
09877 #ifdef SQL_C_TYPE_TIMESTAMP
09878     case SQL_C_TYPE_TIMESTAMP:
09879 #endif
09880     case SQL_C_TIMESTAMP:
09881         if (*s->jdconv) {
09882             int a, b, x1, x2, y, m, dd;
09883             double v;
09884 
09885             y = ((TIMESTAMP_STRUCT *) dp)->year;
09886             m = ((TIMESTAMP_STRUCT *) dp)->month;
09887             dd = ((TIMESTAMP_STRUCT *) dp)->day;
09888             if (m <= 2) {
09889                 y--;
09890                 m += 12;
09891             }
09892             a = y / 100;
09893             b = 2 - a + (a / 4);
09894             x1 = 36525 * (y + 4716) / 100;
09895             x2 = 306001 * (m + 1) / 10000;
09896             v = x1 + x2 + dd + b - 1524.5 +
09897                (((TIMESTAMP_STRUCT *) dp)->hour * 3600000.0 +
09898                 ((TIMESTAMP_STRUCT *) dp)->minute * 60000.0 +
09899                 ((TIMESTAMP_STRUCT *) dp)->second * 1000.0 +
09900                 ((TIMESTAMP_STRUCT *) dp)->fraction / 1.0E6)
09901                / 86400000.0;
09902             sqlite3_bind_double(stmt, si, v);
09903             if (d->trace) {
09904                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
09905                 fflush(d->trace);
09906             }
09907         } else {
09908             int frac;
09909 
09910             frac = (int) ((TIMESTAMP_STRUCT *) dp)->fraction;
09911             frac /= 1000000;
09912             frac = frac % 1000;
09913             if (frac < 0) {
09914                 frac = 0;
09915             }
09916             if (c->prec && c->prec <= 16) {
09917                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
09918                         ((TIMESTAMP_STRUCT *) dp)->year,
09919                         ((TIMESTAMP_STRUCT *) dp)->month,
09920                         ((TIMESTAMP_STRUCT *) dp)->day,
09921                         ((TIMESTAMP_STRUCT *) dp)->hour,
09922                         ((TIMESTAMP_STRUCT *) dp)->minute);
09923             } else if (c->prec && c->prec <= 19) {
09924                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
09925                         ((TIMESTAMP_STRUCT *) dp)->year,
09926                         ((TIMESTAMP_STRUCT *) dp)->month,
09927                         ((TIMESTAMP_STRUCT *) dp)->day,
09928                         ((TIMESTAMP_STRUCT *) dp)->hour,
09929                         ((TIMESTAMP_STRUCT *) dp)->minute,
09930                         ((TIMESTAMP_STRUCT *) dp)->second);
09931             } else {
09932                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
09933                         ((TIMESTAMP_STRUCT *) dp)->year,
09934                         ((TIMESTAMP_STRUCT *) dp)->month,
09935                         ((TIMESTAMP_STRUCT *) dp)->day,
09936                         ((TIMESTAMP_STRUCT *) dp)->hour,
09937                         ((TIMESTAMP_STRUCT *) dp)->minute,
09938                         ((TIMESTAMP_STRUCT *) dp)->second,
09939                         frac);
09940             }
09941             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
09942             if (d->trace) {
09943                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
09944                 fflush(d->trace);
09945             }
09946         }
09947         break;
09948     default:
09949         setstat(s, -1, "unsupported column type in positional update",
09950                 (*s->ov3) ? "HY000" : "S1000");
09951         return SQL_ERROR;
09952     }
09953     return SQL_SUCCESS;
09954 }
09955 
09967 static SQLRETURN
09968 setposibind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
09969 {
09970     DBC *d = (DBC *) s->dbc;
09971     char **data;
09972     int pos;
09973 
09974     pos = s->rowprs;
09975     if (pos < 0) {
09976         setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
09977         return SQL_ERROR;
09978     }
09979     pos += rsi;
09980     data = s->rows + s->ncols + (pos * s->ncols) + i;
09981     if (*data == NULL) {
09982         sqlite3_bind_null(stmt, si);
09983         if (d->trace) {
09984             fprintf(d->trace, "-- parameter %d: NULL\n", si);
09985             fflush(d->trace);
09986         }
09987     } else {
09988         sqlite3_bind_text(stmt, si, *data, -1, SQLITE_STATIC);
09989         if (d->trace) {
09990             fprintf(d->trace, "-- parameter %d: '%s'\n", si, *data);
09991             fflush(d->trace);
09992         }
09993     }
09994     return SQL_SUCCESS;
09995 }
09996 
10004 static SQLRETURN
10005 setposrefr(STMT *s, int rsi)
10006 {
10007     int i, withinfo = 0;
10008     SQLRETURN ret = SQL_SUCCESS;
10009 
10010     for (i = 0; s->bindcols && i < s->ncols; i++) {
10011         BINDCOL *b = &s->bindcols[i];
10012         SQLPOINTER dp = 0;
10013         SQLLEN *lp = 0;
10014 
10015         b->offs = 0;
10016         if (b->valp) {
10017             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10018                 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
10019             } else {
10020                 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
10021             }
10022             if (s->bind_offs) {
10023                 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
10024             }
10025         }
10026         if (b->lenp) {
10027             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10028                 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
10029             } else {
10030                 lp = b->lenp + rsi;
10031             }
10032             if (s->bind_offs) {
10033                 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
10034             }
10035         }
10036         if (dp || lp) {
10037             int rowp = s->rowp;
10038 
10039             s->rowp = s->rowprs + rsi;
10040             ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp,
10041                              b->max, lp, 0);
10042             s->rowp = rowp;
10043             if (!SQL_SUCCEEDED(ret)) {
10044                 s->row_status0[rsi] = SQL_ROW_ERROR;
10045                 break;
10046             }
10047             if (ret != SQL_SUCCESS) {
10048                 withinfo = 1;
10049 #ifdef SQL_ROW_SUCCESS_WITH_INFO
10050                 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
10051 #endif
10052             }
10053         }
10054     }
10055     if (SQL_SUCCEEDED(ret)) {
10056         ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10057     }
10058     return ret;
10059 }
10060 
10070 static SQLRETURN
10071 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10072 {
10073     STMT *s = (STMT *) stmt;
10074     DBC *d = (DBC *) s->dbc;
10075     int rowp, i, k, rc, nretry = 0;
10076     dstr *sql = 0;
10077     const char *endp;
10078     sqlite3_stmt *s3stmt = NULL;
10079     SQLRETURN ret;
10080 
10081     if (lock != SQL_LOCK_NO_CHANGE) {
10082         setstat(s, -1, "unsupported locking mode",
10083                 (*s->ov3) ? "HY000" : "S1000");
10084         return SQL_ERROR;
10085     }
10086     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10087         setstat(s, -1, "incompatible statement",
10088                 (*s->ov3) ? "HY000" : "S1000");
10089         return SQL_ERROR;
10090     }
10091     if (op == SQL_ADD) {
10092         if (s->one_tbl <= 0) {
10093             setstat(s, -1, "incompatible rowset",
10094                     (*s->ov3) ? "HY000" : "S1000");
10095             return SQL_ERROR;
10096         }
10097         if (row == 0 || row > s->rowset_size + 1) {
10098             goto rowoor;
10099         }
10100         ret = chkunbound(s);
10101         if (ret != SQL_SUCCESS) {
10102             return ret;
10103         }
10104         sql = dsappend(sql, "INSERT INTO ");
10105         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10106             sql = dsappendq(sql, s->dyncols[0].db);
10107             sql = dsappend(sql, ".");
10108         }
10109         sql = dsappendq(sql, s->dyncols[0].table);
10110         for (i = 0; i < s->ncols; i++) {
10111             sql = dsappend(sql, (i > 0) ? "," : "(");
10112             sql = dsappendq(sql, s->dyncols[i].column);
10113         }
10114         sql = dsappend(sql, ") VALUES ");
10115         for (i = 0; i < s->ncols; i++) {
10116             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10117         }
10118         sql = dsappend(sql, ")");
10119         if (dserr(sql)) {
10120             dsfree(sql);
10121             return nomem(s);
10122         }
10123 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10124         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10125 #else
10126         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10127 #endif
10128         do {
10129             s3stmt = NULL;
10130 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10131             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10132                                     &s3stmt, &endp);
10133 #else
10134             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10135                                  &s3stmt, &endp);
10136 #endif
10137             if (rc != SQLITE_OK) {
10138                 if (s3stmt) {
10139                     sqlite3_finalize(s3stmt);
10140                     s3stmt = NULL;
10141                 }
10142             }
10143         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10144         dbtracerc(d, rc, NULL);
10145         dsfree(sql);
10146         if (rc != SQLITE_OK) {
10147 istmterr:
10148             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10149                     sqlite3_errmsg(d->sqlite), rc);
10150             if (s3stmt) {
10151                 dbtraceapi(d, "sqlite3_finalize", NULL);
10152                 sqlite3_finalize(s3stmt);
10153             }
10154             return SQL_ERROR;
10155         }
10156         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10157             ret = setposbind(s, s3stmt, i, k, row - 1);
10158             if (ret != SQL_SUCCESS) {
10159                 dbtraceapi(d, "sqlite3_finalize", NULL);
10160                 sqlite3_finalize(s3stmt);
10161                 return ret;
10162             }
10163             k++;
10164         }
10165         rc = sqlite3_step(s3stmt);
10166         if (rc != SQLITE_DONE) {
10167             goto istmterr;
10168         }
10169         sqlite3_finalize(s3stmt);
10170         if (sqlite3_changes(d->sqlite) > 0 && row <= s->rowset_size) {
10171             if (s->row_status0) {
10172                 s->row_status0[row - 1] = SQL_ROW_ADDED;
10173             }
10174             if (s->row_status) {
10175                 s->row_status[row - 1] = SQL_ROW_ADDED;
10176             }
10177         }
10178         return SQL_SUCCESS;
10179     } else if (op == SQL_UPDATE || op == SQL_DELETE) {
10180         if (s->one_tbl <= 0 || s->has_pk <= 0) {
10181             setstat(s, -1, "incompatible rowset",
10182                     (*s->ov3) ? "HY000" : "S1000");
10183             return SQL_ERROR;
10184         }
10185         if (row == 0) {
10186             ret = SQL_SUCCESS;
10187             for (i = 1; i <= s->rowset_size; i++) {
10188                 ret = drvsetpos(stmt, i, op, lock);
10189                 if (!SQL_SUCCEEDED(ret)) {
10190                     break;
10191                 }
10192             }
10193             return ret;
10194         }
10195         if (row > s->rowset_size) {
10196             goto rowoor;
10197         }
10198     }
10199     if (op != SQL_POSITION && op != SQL_REFRESH &&
10200         op != SQL_DELETE && op != SQL_UPDATE) {
10201         return drvunimplstmt(stmt);
10202     }
10203     if (op == SQL_POSITION) {
10204         rowp = s->rowp + row - 1;
10205         if (!s->rows || row == 0 || rowp < -1 || rowp >= s->nrows) {
10206 rowoor:
10207             setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10208             return SQL_ERROR;
10209         }
10210         s->rowp = rowp;
10211     } else if (op == SQL_REFRESH) {
10212         if (row > s->rowset_size) {
10213             goto rowoor;
10214         }
10215         if (row == 0) {
10216             ret = SQL_SUCCESS;
10217             for (i = 0; i < s->rowset_size; i++) {
10218                 ret = setposrefr(s, i);
10219                 if (!SQL_SUCCEEDED(ret)) {
10220                     break;
10221                 }
10222             }
10223             return ret;
10224         }
10225         return setposrefr(s, row - 1);
10226     } else if (op == SQL_DELETE) {
10227         sql = dsappend(sql, "DELETE FROM ");
10228         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10229             sql = dsappendq(sql, s->dyncols[0].db);
10230             sql = dsappend(sql, ".");
10231         }
10232         sql = dsappendq(sql, s->dyncols[0].table);
10233         for (i = k = 0; i < s->ncols; i++) {
10234             if (s->dyncols[i].ispk <= 0) {
10235                 continue;
10236             }
10237             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10238             sql = dsappendq(sql, s->dyncols[i].column);
10239             sql = dsappend(sql, " = ?");
10240             k++;
10241         }
10242         if (dserr(sql)) {
10243             dsfree(sql);
10244             return nomem(s);
10245         }
10246 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10247         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10248 #else
10249         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10250 #endif
10251         do {
10252             s3stmt = NULL;
10253 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10254             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10255                                     &s3stmt, &endp);
10256 #else
10257             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10258                                  &s3stmt, &endp);
10259 #endif
10260             if (rc != SQLITE_OK) {
10261                 if (s3stmt) {
10262                     sqlite3_finalize(s3stmt);
10263                     s3stmt = NULL;
10264                 }
10265             }
10266         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10267         dbtracerc(d, rc, NULL);
10268         dsfree(sql);
10269         if (rc != SQLITE_OK) {
10270 dstmterr:
10271             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10272                     sqlite3_errmsg(d->sqlite), rc);
10273             if (s3stmt) {
10274                 dbtraceapi(d, "sqlite3_finalize", NULL);
10275                 sqlite3_finalize(s3stmt);
10276             }
10277             return SQL_ERROR;
10278         }
10279         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10280             if (s->dyncols[i].ispk <= 0) {
10281                 continue;
10282             }
10283             ret = setposibind(s, s3stmt, i, k, row - 1);
10284             if (ret != SQL_SUCCESS) {
10285                 dbtraceapi(d, "sqlite3_finalize", NULL);
10286                 sqlite3_finalize(s3stmt);
10287                 return ret;
10288             }
10289             k++;
10290         }
10291         rc = sqlite3_step(s3stmt);
10292         if (rc != SQLITE_DONE) {
10293             goto dstmterr;
10294         }
10295         sqlite3_finalize(s3stmt);
10296         if (sqlite3_changes(d->sqlite) > 0) {
10297             if (s->row_status0) {
10298                 s->row_status0[row - 1] = SQL_ROW_DELETED;
10299             }
10300             if (s->row_status) {
10301                 s->row_status[row - 1] = SQL_ROW_DELETED;
10302             }
10303         }
10304         return SQL_SUCCESS;
10305     } else if (op == SQL_UPDATE) {
10306         ret = chkunbound(s);
10307         if (ret != SQL_SUCCESS) {
10308             return ret;
10309         }
10310         sql = dsappend(sql, "UPDATE ");
10311         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10312             sql = dsappendq(sql, s->dyncols[0].db);
10313             sql = dsappend(sql, ".");
10314         }
10315         sql = dsappendq(sql, s->dyncols[0].table);
10316         for (i = 0; i < s->ncols; i++) {
10317             sql = dsappend(sql, (i > 0) ? ", " : " SET ");
10318             sql = dsappendq(sql, s->dyncols[i].column);
10319             sql = dsappend(sql, " = ?");
10320         }
10321         for (i = k = 0; i < s->ncols; i++) {
10322             if (s->dyncols[i].ispk <= 0) {
10323                 continue;
10324             }
10325             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10326             sql = dsappendq(sql, s->dyncols[i].column);
10327             sql = dsappend(sql, " = ?");
10328             k++;
10329         }
10330         if (dserr(sql)) {
10331             dsfree(sql);
10332             return nomem(s);
10333         }
10334 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10335         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10336 #else
10337         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10338 #endif
10339         do {
10340             s3stmt = NULL;
10341 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10342             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10343                                     &s3stmt, &endp);
10344 #else
10345             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10346                                  &s3stmt, &endp);
10347 #endif
10348             if (rc != SQLITE_OK) {
10349                 if (s3stmt) {
10350                     sqlite3_finalize(s3stmt);
10351                     s3stmt = NULL;
10352                 }
10353             }
10354         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10355         dbtracerc(d, rc, NULL);
10356         dsfree(sql);
10357         if (rc != SQLITE_OK) {
10358 ustmterr:
10359             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10360                     sqlite3_errmsg(d->sqlite), rc);
10361             if (s3stmt) {
10362                 dbtraceapi(d, "sqlite3_finalize", NULL);
10363                 sqlite3_finalize(s3stmt);
10364             }
10365             return SQL_ERROR;
10366         }
10367         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10368             ret = setposbind(s, s3stmt, i, k, row - 1);
10369             if (ret != SQL_SUCCESS) {
10370                 dbtraceapi(d, "sqlite3_finalize", NULL);
10371                 sqlite3_finalize(s3stmt);
10372                 return ret;
10373             }
10374             k++;
10375         }
10376         for (i = 0; s->bindcols && i < s->ncols; i++) {
10377             if (s->dyncols[i].ispk <= 0) {
10378                 continue;
10379             }
10380             ret = setposibind(s, s3stmt, i, k, row - 1);
10381             if (ret != SQL_SUCCESS) {
10382                 dbtraceapi(d, "sqlite3_finalize", NULL);
10383                 sqlite3_finalize(s3stmt);
10384                 return ret;
10385             }
10386             k++;
10387         }
10388         rc = sqlite3_step(s3stmt);
10389         if (rc != SQLITE_DONE) {
10390             goto ustmterr;
10391         }
10392         sqlite3_finalize(s3stmt);
10393         if (sqlite3_changes(d->sqlite) > 0) {
10394             if (s->row_status0) {
10395                 s->row_status0[row - 1] = SQL_ROW_UPDATED;
10396             }
10397             if (s->row_status) {
10398                 s->row_status[row - 1] = SQL_ROW_UPDATED;
10399             }
10400         }
10401         return SQL_SUCCESS;
10402     }
10403     return SQL_SUCCESS;
10404 }
10405 
10415 SQLRETURN SQL_API
10416 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10417 {
10418     SQLRETURN ret;
10419 
10420     HSTMT_LOCK(stmt);
10421     ret = drvsetpos(stmt, row, op, lock);
10422     HSTMT_UNLOCK(stmt);
10423     return ret;
10424 }
10425 
10433 static SQLRETURN
10434 drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
10435 {
10436     STMT *s = (STMT *) stmt;
10437     DBC *d = (DBC *) s->dbc;
10438     int row, i, k, rc, nretry = 0;
10439     dstr *sql = 0;
10440     const char *endp;
10441     sqlite3_stmt *s3stmt = NULL;
10442     SQLRETURN ret;
10443 
10444     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10445         setstat(s, -1, "incompatible statement",
10446                 (*s->ov3) ? "HY000" : "S1000");
10447         return SQL_ERROR;
10448     }
10449     if (op == SQL_ADD) {
10450         if (s->one_tbl <= 0) {
10451             setstat(s, -1, "incompatible rowset",
10452                     (*s->ov3) ? "HY000" : "S1000");
10453             return SQL_ERROR;
10454         }
10455         ret = chkunbound(s);
10456         if (ret != SQL_SUCCESS) {
10457             return ret;
10458         }
10459         sql = dsappend(sql, "INSERT INTO ");
10460         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10461             sql = dsappendq(sql, s->dyncols[0].db);
10462             sql = dsappend(sql, ".");
10463         }
10464         sql = dsappendq(sql, s->dyncols[0].table);
10465         for (i = 0; i < s->ncols; i++) {
10466             sql = dsappend(sql, (i > 0) ? "," : "(");
10467             sql = dsappendq(sql, s->dyncols[i].column);
10468         }
10469         sql = dsappend(sql, ") VALUES ");
10470         for (i = 0; i < s->ncols; i++) {
10471             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10472         }
10473         sql = dsappend(sql, ")");
10474         if (dserr(sql)) {
10475             dsfree(sql);
10476             return nomem(s);
10477         }
10478 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10479         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10480 #else
10481         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10482 #endif
10483         do {
10484             s3stmt = NULL;
10485 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10486             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10487                                     &s3stmt, &endp);
10488 #else
10489             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10490                                  &s3stmt, &endp);
10491 #endif
10492             if (rc != SQLITE_OK) {
10493                 if (s3stmt) {
10494                     sqlite3_finalize(s3stmt);
10495                     s3stmt = NULL;
10496                 }
10497             }
10498         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10499         dbtracerc(d, rc, NULL);
10500         dsfree(sql);
10501         if (rc != SQLITE_OK) {
10502             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10503                     sqlite3_errmsg(d->sqlite), rc);
10504             if (s3stmt) {
10505                 dbtraceapi(d, "sqlite3_finalize", NULL);
10506                 sqlite3_finalize(s3stmt);
10507             }
10508             return SQL_ERROR;
10509         }
10510         for (row = 0; row < s->rowset_size; row++) {
10511             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10512                 ret = setposbind(s, s3stmt, i, k, row);
10513                 if (ret != SQL_SUCCESS) {
10514 istmterr:
10515                     if (s->row_status0) {
10516                         s->row_status0[row] = SQL_ROW_ERROR;
10517                     }
10518                     if (s->row_status) {
10519                         s->row_status[row] = SQL_ROW_ERROR;
10520                     }
10521                     dbtraceapi(d, "sqlite3_finalize", NULL);
10522                     sqlite3_finalize(s3stmt);
10523                     return ret;
10524                 }
10525                 k++;
10526             }
10527             rc = sqlite3_step(s3stmt);
10528             if (rc != SQLITE_DONE) {
10529                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10530                         sqlite3_errmsg(d->sqlite), rc);
10531                 ret = SQL_ERROR;
10532                 goto istmterr;
10533             }
10534             if (sqlite3_changes(d->sqlite) > 0) {
10535                 if (s->row_status0) {
10536                     s->row_status0[row] = SQL_ROW_ADDED;
10537                 }
10538                 if (s->row_status) {
10539                     s->row_status[row] = SQL_ROW_ADDED;
10540                 }
10541             }
10542             if (s->bkmrk == SQL_UB_VARIABLE &&
10543                 s->bkmrkcol.type == SQL_C_VARBOOKMARK &&
10544                 s->bkmrkcol.valp) {
10545                 SQLPOINTER *val;
10546 
10547                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10548                     val = (SQLPOINTER)
10549                         ((char *) s->bkmrkcol.valp + s->bind_type * row);
10550                 } else {
10551                     val = (SQLPOINTER)
10552                         ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10553                 }
10554                 if (s->bind_offs) {
10555                     val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10556                 }
10557                 *(sqlite_int64 *) val = sqlite3_last_insert_rowid(d->sqlite);
10558                 if (s->bkmrkcol.lenp) {
10559                     SQLLEN *ival;
10560 
10561                     if (s->bind_type != SQL_BIND_BY_COLUMN) {
10562                         ival = (SQLLEN *)
10563                             ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10564                     } else {
10565                         ival = &s->bkmrkcol.lenp[row];
10566                     }
10567                     if (s->bind_offs) {
10568                         ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10569                     }
10570                     *ival = sizeof (sqlite_int64);
10571                 }
10572             }
10573             dbtraceapi(d, "sqlite3_reset", NULL);
10574             sqlite3_reset(s3stmt);
10575         }
10576         dbtraceapi(d, "sqlite3_finalize", NULL);
10577         sqlite3_finalize(s3stmt);
10578         return SQL_SUCCESS;
10579     } else if (op == SQL_DELETE_BY_BOOKMARK) {
10580         if (s->has_rowid < 0 ||
10581             s->bkmrk != SQL_UB_VARIABLE ||
10582             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10583             !s->bkmrkcol.valp) {
10584             setstat(s, -1, "incompatible rowset",
10585                     (*s->ov3) ? "HY000" : "S1000");
10586             return SQL_ERROR;
10587         }
10588         sql = dsappend(sql, "DELETE FROM ");
10589         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10590             sql = dsappendq(sql, s->dyncols[0].db);
10591             sql = dsappend(sql, ".");
10592         }
10593         sql = dsappendq(sql, s->dyncols[0].table);
10594         sql = dsappend(sql, " WHERE ");
10595         sql = dsappendq(sql, s->dyncols[0].column);
10596         sql = dsappend(sql, " = ?");
10597         if (dserr(sql)) {
10598             dsfree(sql);
10599             return nomem(s);
10600         }
10601 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10602         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10603 #else
10604         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10605 #endif
10606         do {
10607             s3stmt = NULL;
10608 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10609             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10610                                     &s3stmt, &endp);
10611 #else
10612             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10613                                  &s3stmt, &endp);
10614 #endif
10615             if (rc != SQLITE_OK) {
10616                 if (s3stmt) {
10617                     sqlite3_finalize(s3stmt);
10618                     s3stmt = NULL;
10619                 }
10620             }
10621         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10622         dbtracerc(d, rc, NULL);
10623         dsfree(sql);
10624         if (rc != SQLITE_OK) {
10625             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10626                     sqlite3_errmsg(d->sqlite), rc);
10627             if (s3stmt) {
10628                 dbtraceapi(d, "sqlite3_finalize", NULL);
10629                 sqlite3_finalize(s3stmt);
10630             }
10631             return SQL_ERROR;
10632         }
10633         for (row = 0; row < s->rowset_size; row++) {
10634             SQLPOINTER *val;
10635             sqlite_int64 rowid;
10636 
10637             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10638                 val = (SQLPOINTER)
10639                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
10640             } else {
10641                 val = (SQLPOINTER)
10642                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10643             }
10644             if (s->bind_offs) {
10645                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10646             }
10647             if (s->bkmrkcol.lenp) {
10648                 SQLLEN *ival;
10649 
10650                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10651                     ival = (SQLLEN *)
10652                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10653                 } else {
10654                     ival = &s->bkmrkcol.lenp[row];
10655                 }
10656                 if (s->bind_offs) {
10657                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10658                 }
10659                 if (*ival != sizeof (sqlite_int64)) {
10660                     continue;
10661                 }
10662             }
10663             rowid = *(sqlite_int64 *) val;
10664             sqlite3_bind_int64(s3stmt, 1, rowid);
10665             if (d->trace) {
10666                 fprintf(d->trace,
10667 #ifdef _WIN32
10668                         "-- parameter 1: %I64d\n",
10669 #else
10670                         "-- parameter 1: %lld\n",
10671 #endif
10672                         rowid);
10673                 fflush(d->trace);
10674             }
10675             rc = sqlite3_step(s3stmt);
10676             if (rc != SQLITE_DONE) {
10677                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10678                         sqlite3_errmsg(d->sqlite), rc);
10679                 if (s->row_status0) {
10680                     s->row_status0[row] = SQL_ROW_ERROR;
10681                 }
10682                 if (s->row_status) {
10683                     s->row_status[row] = SQL_ROW_ERROR;
10684                 }
10685                 dbtraceapi(d, "sqlite3_finalize", NULL);
10686                 sqlite3_finalize(s3stmt);
10687                 return SQL_ERROR;
10688             }
10689             if (sqlite3_changes(d->sqlite) > 0) {
10690                 if (s->row_status0) {
10691                     s->row_status0[row] = SQL_ROW_DELETED;
10692                 }
10693                 if (s->row_status) {
10694                     s->row_status[row] = SQL_ROW_DELETED;
10695                 }
10696             }
10697             dbtraceapi(d, "sqlite3_reset", NULL);
10698             sqlite3_reset(s3stmt);
10699         }
10700         dbtraceapi(d, "sqlite3_finalize", NULL);
10701         sqlite3_finalize(s3stmt);
10702         return SQL_SUCCESS;
10703     } else if (op == SQL_UPDATE_BY_BOOKMARK) {
10704         if (s->has_rowid < 0 ||
10705             s->bkmrk != SQL_UB_VARIABLE ||
10706             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10707             !s->bkmrkcol.valp) {
10708             setstat(s, -1, "incompatible rowset",
10709                     (*s->ov3) ? "HY000" : "S1000");
10710             return SQL_ERROR;
10711         }
10712         ret = chkunbound(s);
10713         if (ret != SQL_SUCCESS) {
10714             return ret;
10715         }
10716         sql = dsappend(sql, "UPDATE ");
10717         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10718             sql = dsappendq(sql, s->dyncols[0].db);
10719             sql = dsappend(sql, ".");
10720         }
10721         sql = dsappendq(sql, s->dyncols[0].table);
10722         for (i = 0, k = 0; i < s->ncols; i++) {
10723             if (i == s->has_rowid) {
10724                 continue;
10725             }
10726             sql = dsappend(sql, (k > 0) ? ", " : " SET ");
10727             sql = dsappendq(sql, s->dyncols[i].column);
10728             sql = dsappend(sql, " = ?");
10729             k++;
10730         }
10731         sql = dsappend(sql, " WHERE ");
10732         sql = dsappendq(sql, s->dyncols[s->has_rowid].column);
10733         sql = dsappend(sql, " = ?");
10734         if (dserr(sql)) {
10735             dsfree(sql);
10736             return nomem(s);
10737         }
10738 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10739         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10740 #else
10741         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10742 #endif
10743         do {
10744             s3stmt = NULL;
10745 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10746             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10747                                     &s3stmt, &endp);
10748 #else
10749             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10750                                  &s3stmt, &endp);
10751 #endif
10752             if (rc != SQLITE_OK) {
10753                 if (s3stmt) {
10754                     sqlite3_finalize(s3stmt);
10755                     s3stmt = NULL;
10756                 }
10757             }
10758         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10759         dbtracerc(d, rc, NULL);
10760         dsfree(sql);
10761         if (rc != SQLITE_OK) {
10762             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10763                     sqlite3_errmsg(d->sqlite), rc);
10764             if (s3stmt) {
10765                 dbtraceapi(d, "sqlite3_finalize", NULL);
10766                 sqlite3_finalize(s3stmt);
10767             }
10768             return SQL_ERROR;
10769         }
10770         for (row = 0; row < s->rowset_size; row++) {
10771             SQLPOINTER *val;
10772             sqlite_int64 rowid;
10773 
10774             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10775                 val = (SQLPOINTER)
10776                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
10777             } else {
10778                 val = (SQLPOINTER)
10779                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10780             }
10781             if (s->bind_offs) {
10782                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10783             }
10784             if (s->bkmrkcol.lenp) {
10785                 SQLLEN *ival;
10786 
10787                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10788                     ival = (SQLLEN *)
10789                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10790                 } else {
10791                     ival = &s->bkmrkcol.lenp[row];
10792                 }
10793                 if (s->bind_offs) {
10794                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10795                 }
10796                 if (*ival != sizeof (sqlite_int64)) {
10797                     continue;
10798                 }
10799             }
10800             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10801                 if (i == s->has_rowid) {
10802                     continue;
10803                 }
10804                 ret = setposbind(s, s3stmt, i, k, row);
10805                 if (ret != SQL_SUCCESS) {
10806 ustmterr:
10807                     if (s->row_status0) {
10808                         s->row_status0[row] = SQL_ROW_ERROR;
10809                     }
10810                     if (s->row_status) {
10811                         s->row_status[row] = SQL_ROW_ERROR;
10812                     }
10813                     dbtraceapi(d, "sqlite3_finalize", NULL);
10814                     sqlite3_finalize(s3stmt);
10815                     return ret;
10816                 }
10817                 k++;
10818             }
10819             rowid = *(sqlite_int64 *) val;
10820             sqlite3_bind_int64(s3stmt, k, rowid);
10821             if (d->trace) {
10822                 fprintf(d->trace,
10823 #ifdef _WIN32
10824                         "-- parameter %d: %I64d\n",
10825 #else
10826                         "-- parameter %d: %lld\n",
10827 #endif
10828                         k, rowid);
10829                 fflush(d->trace);
10830             }
10831             rc = sqlite3_step(s3stmt);
10832             if (rc != SQLITE_DONE) {
10833                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10834                         sqlite3_errmsg(d->sqlite), rc);
10835                 ret = SQL_ERROR;
10836                 goto ustmterr;
10837             }
10838             if (sqlite3_changes(d->sqlite) > 0) {
10839                 if (s->row_status0) {
10840                     s->row_status0[row] = SQL_ROW_UPDATED;
10841                 }
10842                 if (s->row_status) {
10843                     s->row_status[row] = SQL_ROW_UPDATED;
10844                 }
10845             }
10846             dbtraceapi(d, "sqlite3_reset", NULL);
10847             sqlite3_reset(s3stmt);
10848         }
10849         dbtraceapi(d, "sqlite3_finalize", NULL);
10850         sqlite3_finalize(s3stmt);
10851         return SQL_SUCCESS;
10852     }
10853     setstat(s, -1, "unsupported operation", (*s->ov3) ? "HY000" : "S1000");
10854     return SQL_ERROR;
10855 }
10856 
10864 SQLRETURN SQL_API
10865 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
10866 {
10867     SQLRETURN ret;
10868 
10869     HSTMT_LOCK(stmt);
10870     ret = drvbulkoperations(stmt, oper);
10871     HSTMT_UNLOCK(stmt);
10872     return ret;
10873 }
10874 
10875 
10880 SQLRETURN SQL_API
10881 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
10882                     SQLUSMALLINT rowset)
10883 {
10884     SQLRETURN ret;
10885 
10886     HSTMT_LOCK(stmt);
10887     ret = drvunimplstmt(stmt);
10888     HSTMT_UNLOCK(stmt);
10889     return ret;
10890 }
10891 
10892 #define strmak(dst, src, max, lenp) { \
10893     int len = strlen(src); \
10894     int cnt = min(len + 1, max); \
10895     strncpy(dst, src, cnt); \
10896     *lenp = (cnt > len) ? len : cnt; \
10897 }
10898 
10909 static SQLRETURN
10910 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
10911            SQLSMALLINT *valLen)
10912 {
10913     DBC *d;
10914     char dummyc[16];
10915     SQLSMALLINT dummy;
10916 #if defined(_WIN32) || defined(_WIN64)
10917     char pathbuf[301], *drvname;
10918 #else
10919     static char drvname[] = "sqlite3odbc.so";
10920 #endif
10921 
10922     if (dbc == SQL_NULL_HDBC) {
10923         return SQL_INVALID_HANDLE;
10924     }
10925     d = (DBC *) dbc;
10926     if (valMax) {
10927         valMax--;
10928     }
10929     if (!valLen) {
10930         valLen = &dummy;
10931     }
10932     if (!val) {
10933         val = dummyc;
10934         valMax = sizeof (dummyc) - 1;
10935     }
10936     switch (type) {
10937     case SQL_MAX_USER_NAME_LEN:
10938         *((SQLSMALLINT *) val) = 16;
10939         *valLen = sizeof (SQLSMALLINT);
10940         break;
10941     case SQL_USER_NAME:
10942         strmak(val, "", valMax, valLen);
10943         break;
10944     case SQL_DRIVER_ODBC_VER:
10945 #if 0
10946         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
10947 #else
10948         strmak(val, "03.00", valMax, valLen);
10949 #endif
10950         break;
10951     case SQL_ACTIVE_CONNECTIONS:
10952     case SQL_ACTIVE_STATEMENTS:
10953         *((SQLSMALLINT *) val) = 0;
10954         *valLen = sizeof (SQLSMALLINT);
10955         break;
10956 #ifdef SQL_ASYNC_MODE
10957     case SQL_ASYNC_MODE:
10958         *((SQLUINTEGER *) val) = SQL_AM_NONE;
10959         *valLen = sizeof (SQLUINTEGER);
10960         break;
10961 #endif
10962 #ifdef SQL_CREATE_TABLE
10963     case SQL_CREATE_TABLE:
10964         *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
10965                                  SQL_CT_COLUMN_DEFAULT |
10966                                  SQL_CT_COLUMN_CONSTRAINT |
10967                                  SQL_CT_CONSTRAINT_NON_DEFERRABLE;
10968         *valLen = sizeof (SQLUINTEGER);
10969         break;
10970 #endif
10971 #ifdef SQL_CREATE_VIEW
10972     case SQL_CREATE_VIEW:
10973         *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
10974         *valLen = sizeof (SQLUINTEGER);
10975         break;
10976 #endif
10977 #ifdef SQL_DDL_INDEX
10978     case SQL_DDL_INDEX:
10979         *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
10980         *valLen = sizeof (SQLUINTEGER);
10981         break;
10982 #endif
10983 #ifdef SQL_DROP_TABLE
10984     case SQL_DROP_TABLE:
10985         *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
10986         *valLen = sizeof (SQLUINTEGER);
10987         break;
10988 #endif
10989 #ifdef SQL_DROP_VIEW
10990     case SQL_DROP_VIEW:
10991         *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
10992         *valLen = sizeof (SQLUINTEGER);
10993         break;
10994 #endif
10995 #ifdef SQL_INDEX_KEYWORDS
10996     case SQL_INDEX_KEYWORDS:
10997         *((SQLUINTEGER *) val) = SQL_IK_ALL;
10998         *valLen = sizeof (SQLUINTEGER);
10999         break;
11000 #endif
11001     case SQL_DATA_SOURCE_NAME:
11002         strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
11003         break;
11004     case SQL_DRIVER_NAME:
11005 #if defined(_WIN32) || defined(_WIN64)
11006         GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
11007         drvname = strrchr(pathbuf, '\\');
11008         if (drvname == NULL) {
11009             drvname = strrchr(pathbuf, '/');
11010         }
11011         if (drvname == NULL) {
11012             drvname = pathbuf;
11013         } else {
11014             drvname++;
11015         }
11016 #endif
11017         strmak(val, drvname, valMax, valLen);
11018         break;
11019     case SQL_DRIVER_VER:
11020         strmak(val, DRIVER_VER_INFO, valMax, valLen);
11021         break;
11022     case SQL_FETCH_DIRECTION:
11023         *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
11024             SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
11025         *valLen = sizeof (SQLUINTEGER);
11026         break;
11027     case SQL_ODBC_VER:
11028         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11029         break;
11030     case SQL_ODBC_SAG_CLI_CONFORMANCE:
11031         *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
11032         *valLen = sizeof (SQLSMALLINT);
11033         break;
11034     case SQL_STANDARD_CLI_CONFORMANCE:
11035         *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
11036         *valLen = sizeof (SQLUINTEGER);
11037         break;
11038     case SQL_SQL_CONFORMANCE:
11039         *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
11040         *valLen = sizeof (SQLUINTEGER);
11041         break;
11042     case SQL_SERVER_NAME:
11043     case SQL_DATABASE_NAME:
11044         strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
11045         break;
11046     case SQL_SEARCH_PATTERN_ESCAPE:
11047         strmak(val, "\\", valMax, valLen);
11048         break;
11049     case SQL_ODBC_SQL_CONFORMANCE:
11050         *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
11051         *valLen = sizeof (SQLSMALLINT);
11052         break;
11053     case SQL_ODBC_API_CONFORMANCE:
11054         *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
11055         *valLen = sizeof (SQLSMALLINT);
11056         break;
11057     case SQL_DBMS_NAME:
11058         strmak(val, "SQLite", valMax, valLen);
11059         break;
11060     case SQL_DBMS_VER:
11061         strmak(val, SQLITE_VERSION, valMax, valLen);
11062         break;
11063     case SQL_COLUMN_ALIAS:
11064     case SQL_NEED_LONG_DATA_LEN:
11065         strmak(val, "Y", valMax, valLen);
11066         break;
11067     case SQL_ROW_UPDATES:
11068     case SQL_ACCESSIBLE_PROCEDURES:
11069     case SQL_PROCEDURES:
11070     case SQL_EXPRESSIONS_IN_ORDERBY:
11071     case SQL_ODBC_SQL_OPT_IEF:
11072     case SQL_LIKE_ESCAPE_CLAUSE:
11073     case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11074     case SQL_OUTER_JOINS:
11075     case SQL_ACCESSIBLE_TABLES:
11076     case SQL_MULT_RESULT_SETS:
11077     case SQL_MULTIPLE_ACTIVE_TXN:
11078     case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11079         strmak(val, "N", valMax, valLen);
11080         break;
11081 #ifdef SQL_CATALOG_NAME
11082     case SQL_CATALOG_NAME:
11083 #if defined(_WIN32) || defined(_WIN64)
11084         strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
11085 #else
11086         strmak(val, "N", valMax, valLen);
11087 #endif
11088         break;
11089 #endif
11090     case SQL_DATA_SOURCE_READ_ONLY:
11091         strmak(val, "N", valMax, valLen);
11092         break;
11093 #ifdef SQL_OJ_CAPABILITIES
11094     case SQL_OJ_CAPABILITIES:
11095         *((SQLUINTEGER *) val) = 0;
11096         *valLen = sizeof (SQLUINTEGER);
11097         break;
11098 #endif
11099 #ifdef SQL_MAX_IDENTIFIER_LEN
11100     case SQL_MAX_IDENTIFIER_LEN:
11101         *((SQLUSMALLINT *) val) = 255;
11102         *valLen = sizeof (SQLUSMALLINT);
11103         break;
11104 #endif
11105     case SQL_CONCAT_NULL_BEHAVIOR:
11106         *((SQLSMALLINT *) val) = SQL_CB_NULL;
11107         *valLen = sizeof (SQLSMALLINT);
11108         break;
11109     case SQL_CURSOR_COMMIT_BEHAVIOR:
11110     case SQL_CURSOR_ROLLBACK_BEHAVIOR:
11111         *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
11112         *valLen = sizeof (SQLSMALLINT);
11113         break;
11114 #ifdef SQL_CURSOR_SENSITIVITY
11115     case SQL_CURSOR_SENSITIVITY:
11116         *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
11117         *valLen = sizeof (SQLUINTEGER);
11118         break;
11119 #endif
11120     case SQL_DEFAULT_TXN_ISOLATION:
11121         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11122         *valLen = sizeof (SQLUINTEGER);
11123         break;
11124 #ifdef SQL_DESCRIBE_PARAMETER
11125     case SQL_DESCRIBE_PARAMETER:
11126         strmak(val, "Y", valMax, valLen);
11127         break;
11128 #endif
11129     case SQL_TXN_ISOLATION_OPTION:
11130         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11131         *valLen = sizeof (SQLUINTEGER);
11132         break;
11133     case SQL_IDENTIFIER_CASE:
11134         *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
11135         *valLen = sizeof (SQLSMALLINT);
11136         break;
11137     case SQL_IDENTIFIER_QUOTE_CHAR:
11138         strmak(val, "\"", valMax, valLen);
11139         break;
11140     case SQL_MAX_TABLE_NAME_LEN:
11141     case SQL_MAX_COLUMN_NAME_LEN:
11142         *((SQLSMALLINT *) val) = 255;
11143         *valLen = sizeof (SQLSMALLINT);
11144         break;
11145     case SQL_MAX_CURSOR_NAME_LEN:
11146         *((SQLSMALLINT *) val) = 255;
11147         *valLen = sizeof (SQLSMALLINT);
11148         break;
11149     case SQL_MAX_PROCEDURE_NAME_LEN:
11150         *((SQLSMALLINT *) val) = 0;
11151         break;
11152     case SQL_MAX_QUALIFIER_NAME_LEN:
11153     case SQL_MAX_OWNER_NAME_LEN:
11154         *((SQLSMALLINT *) val) = 255;
11155         break;
11156     case SQL_OWNER_TERM:
11157         strmak(val, "", valMax, valLen);
11158         break;
11159     case SQL_PROCEDURE_TERM:
11160         strmak(val, "PROCEDURE", valMax, valLen);
11161         break;
11162     case SQL_QUALIFIER_NAME_SEPARATOR:
11163         strmak(val, ".", valMax, valLen);
11164         break;
11165     case SQL_QUALIFIER_TERM:
11166 #if defined(_WIN32) || defined(_WIN64)
11167         strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
11168 #else
11169         strmak(val, "", valMax, valLen);
11170 #endif
11171         break;
11172     case SQL_QUALIFIER_USAGE:
11173 #if defined(_WIN32) || defined(_WIN64)
11174         *((SQLUINTEGER *) val) = d->xcelqrx ?
11175             (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
11176              SQL_CU_TABLE_DEFINITION) : 0;
11177 #else
11178         *((SQLUINTEGER *) val) = 0;
11179 #endif
11180         *valLen = sizeof (SQLUINTEGER);
11181         break;
11182     case SQL_SCROLL_CONCURRENCY:
11183         *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
11184         *valLen = sizeof (SQLUINTEGER);
11185         break;
11186     case SQL_SCROLL_OPTIONS:
11187         *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
11188         *valLen = sizeof (SQLUINTEGER);
11189         break;
11190     case SQL_TABLE_TERM:
11191         strmak(val, "TABLE", valMax, valLen);
11192         break;
11193     case SQL_TXN_CAPABLE:
11194         *((SQLSMALLINT *) val) = SQL_TC_ALL;
11195         *valLen = sizeof (SQLSMALLINT);
11196         break;
11197     case SQL_CONVERT_FUNCTIONS:
11198         *((SQLUINTEGER *) val) = 0;
11199         *valLen = sizeof (SQLUINTEGER);
11200        break;
11201     case SQL_SYSTEM_FUNCTIONS:
11202     case SQL_NUMERIC_FUNCTIONS:
11203     case SQL_STRING_FUNCTIONS:
11204     case SQL_TIMEDATE_FUNCTIONS:
11205         *((SQLUINTEGER *) val) = 0;
11206         *valLen = sizeof (SQLUINTEGER);
11207         break;
11208     case SQL_CONVERT_BIGINT:
11209     case SQL_CONVERT_BIT:
11210     case SQL_CONVERT_CHAR:
11211     case SQL_CONVERT_DATE:
11212     case SQL_CONVERT_DECIMAL:
11213     case SQL_CONVERT_DOUBLE:
11214     case SQL_CONVERT_FLOAT:
11215     case SQL_CONVERT_INTEGER:
11216     case SQL_CONVERT_LONGVARCHAR:
11217     case SQL_CONVERT_NUMERIC:
11218     case SQL_CONVERT_REAL:
11219     case SQL_CONVERT_SMALLINT:
11220     case SQL_CONVERT_TIME:
11221     case SQL_CONVERT_TIMESTAMP:
11222     case SQL_CONVERT_TINYINT:
11223     case SQL_CONVERT_VARCHAR:
11224         *((SQLUINTEGER *) val) =
11225             SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
11226             SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
11227             SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
11228             SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
11229             SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
11230         *valLen = sizeof (SQLUINTEGER);
11231         break;
11232     case SQL_CONVERT_BINARY:
11233     case SQL_CONVERT_VARBINARY:
11234     case SQL_CONVERT_LONGVARBINARY:
11235         *((SQLUINTEGER *) val) = 0;
11236         *valLen = sizeof (SQLUINTEGER);
11237         break;
11238     case SQL_POSITIONED_STATEMENTS:
11239         *((SQLUINTEGER *) val) = 0;
11240         *valLen = sizeof (SQLUINTEGER);
11241         break;
11242     case SQL_LOCK_TYPES:
11243         *((SQLUINTEGER *) val) = SQL_LCK_NO_CHANGE;
11244         *valLen = sizeof (SQLUINTEGER);
11245         break;
11246     case SQL_BOOKMARK_PERSISTENCE:
11247         *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
11248         *valLen = sizeof (SQLUINTEGER);
11249         break;
11250     case SQL_UNION:
11251         *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
11252         *valLen = sizeof (SQLUINTEGER);
11253         break;
11254     case SQL_OWNER_USAGE:
11255     case SQL_SUBQUERIES:
11256     case SQL_TIMEDATE_ADD_INTERVALS:
11257     case SQL_TIMEDATE_DIFF_INTERVALS:
11258         *((SQLUINTEGER *) val) = 0;
11259         *valLen = sizeof (SQLUINTEGER);
11260         break;
11261     case SQL_QUOTED_IDENTIFIER_CASE:
11262         *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
11263         *valLen = sizeof (SQLUSMALLINT);
11264         break;
11265     case SQL_POS_OPERATIONS:
11266         *((SQLUINTEGER *) val) = SQL_POS_POSITION | SQL_POS_UPDATE |
11267             SQL_POS_DELETE | SQL_POS_ADD | SQL_POS_REFRESH;
11268         *valLen = sizeof (SQLUINTEGER);
11269         break;
11270     case SQL_ALTER_TABLE:
11271         *((SQLUINTEGER *) val) = 0;
11272         *valLen = sizeof (SQLUINTEGER);
11273         break;
11274     case SQL_CORRELATION_NAME:
11275         *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
11276         *valLen = sizeof (SQLSMALLINT);
11277         break;
11278     case SQL_NON_NULLABLE_COLUMNS:
11279         *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
11280         *valLen = sizeof (SQLSMALLINT);
11281         break;
11282     case SQL_NULL_COLLATION:
11283         *((SQLSMALLINT *) val) = SQL_NC_START;
11284         *valLen = sizeof (SQLSMALLINT);
11285         break;
11286     case SQL_MAX_COLUMNS_IN_GROUP_BY:
11287     case SQL_MAX_COLUMNS_IN_ORDER_BY:
11288     case SQL_MAX_COLUMNS_IN_SELECT:
11289     case SQL_MAX_COLUMNS_IN_TABLE:
11290     case SQL_MAX_ROW_SIZE:
11291     case SQL_MAX_TABLES_IN_SELECT:
11292         *((SQLSMALLINT *) val) = 0;
11293         *valLen = sizeof (SQLSMALLINT);
11294         break;
11295     case SQL_MAX_BINARY_LITERAL_LEN:
11296     case SQL_MAX_CHAR_LITERAL_LEN:
11297         *((SQLUINTEGER *) val) = 0;
11298         *valLen = sizeof (SQLUINTEGER);
11299         break;
11300     case SQL_MAX_COLUMNS_IN_INDEX:
11301         *((SQLSMALLINT *) val) = 0;
11302         *valLen = sizeof (SQLSMALLINT);
11303         break;
11304     case SQL_MAX_INDEX_SIZE:
11305         *((SQLUINTEGER *) val) = 0;
11306         *valLen = sizeof (SQLUINTEGER);
11307         break;
11308 #ifdef SQL_MAX_IDENTIFIER_LENGTH
11309     case SQL_MAX_IDENTIFIER_LENGTH:
11310         *((SQLUINTEGER *) val) = 255;
11311         *valLen = sizeof (SQLUINTEGER);
11312         break;
11313 #endif
11314     case SQL_MAX_STATEMENT_LEN:
11315         *((SQLUINTEGER *) val) = 16384;
11316         *valLen = sizeof (SQLUINTEGER);
11317         break;
11318     case SQL_QUALIFIER_LOCATION:
11319         *((SQLSMALLINT *) val) = SQL_QL_START;
11320         *valLen = sizeof (SQLSMALLINT);
11321         break;
11322     case SQL_GETDATA_EXTENSIONS:
11323         *((SQLUINTEGER *) val) =
11324             SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
11325         *valLen = sizeof (SQLUINTEGER);
11326         break;
11327     case SQL_STATIC_SENSITIVITY:
11328         *((SQLUINTEGER *) val) = 0;
11329         *valLen = sizeof (SQLUINTEGER);
11330         break;
11331     case SQL_FILE_USAGE:
11332 #if defined(_WIN32) || defined(_WIN64)
11333         *((SQLSMALLINT *) val) =
11334             d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
11335 #else
11336         *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
11337 #endif
11338         *valLen = sizeof (SQLSMALLINT);
11339         break;
11340     case SQL_GROUP_BY:
11341         *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
11342         *valLen = sizeof (SQLSMALLINT);
11343         break;
11344     case SQL_KEYWORDS:
11345         strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
11346                "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
11347                valMax, valLen);
11348         break;
11349     case SQL_SPECIAL_CHARACTERS:
11350 #ifdef SQL_COLLATION_SEQ
11351     case SQL_COLLATION_SEQ:
11352 #endif
11353         strmak(val, "", valMax, valLen);
11354         break;
11355     case SQL_BATCH_SUPPORT:
11356     case SQL_BATCH_ROW_COUNT:
11357     case SQL_PARAM_ARRAY_ROW_COUNTS:
11358         *((SQLUINTEGER *) val) = 0;
11359         *valLen = sizeof (SQLUINTEGER);
11360         break;
11361     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
11362         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
11363         *valLen = sizeof (SQLUINTEGER);
11364         break;
11365     case SQL_STATIC_CURSOR_ATTRIBUTES1:
11366         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
11367             SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_POS_POSITION |
11368             SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_REFRESH |
11369             SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_BULK_ADD |
11370             SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK;
11371         *valLen = sizeof (SQLUINTEGER);
11372         break;
11373     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
11374     case SQL_STATIC_CURSOR_ATTRIBUTES2:
11375         *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
11376             SQL_CA2_LOCK_CONCURRENCY;
11377         *valLen = sizeof (SQLUINTEGER);
11378         break;
11379     case SQL_KEYSET_CURSOR_ATTRIBUTES1:
11380     case SQL_KEYSET_CURSOR_ATTRIBUTES2:
11381     case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
11382     case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
11383         *((SQLUINTEGER *) val) = 0;
11384         *valLen = sizeof (SQLUINTEGER);
11385         break;
11386     case SQL_ODBC_INTERFACE_CONFORMANCE:
11387         *((SQLUINTEGER *) val) = SQL_OIC_CORE;
11388         *valLen = sizeof (SQLUINTEGER);
11389         break;
11390     default:
11391         setstatd(d, -1, "unsupported info option %d",
11392                  (*d->ov3) ? "HYC00" : "S1C00", type);
11393         return SQL_ERROR;
11394     }
11395     return SQL_SUCCESS;
11396 }
11397 
11398 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
11399 
11409 SQLRETURN SQL_API
11410 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11411            SQLSMALLINT *valLen)
11412 {
11413     SQLRETURN ret;
11414 
11415     HDBC_LOCK(dbc);
11416     ret = drvgetinfo(dbc, type, val, valMax, valLen);
11417     HDBC_UNLOCK(dbc);
11418     return ret;
11419 }
11420 #endif
11421 
11422 #ifdef WINTERFACE
11423 
11433 SQLRETURN SQL_API
11434 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11435             SQLSMALLINT *valLen)
11436 {
11437     SQLRETURN ret;
11438     SQLSMALLINT len = 0;
11439 
11440     HDBC_LOCK(dbc);
11441     ret = drvgetinfo(dbc, type, val, valMax, &len);
11442     HDBC_UNLOCK(dbc);
11443     if (ret == SQL_SUCCESS) {
11444         SQLWCHAR *v = NULL;
11445 
11446         switch (type) {
11447         case SQL_USER_NAME:
11448         case SQL_DRIVER_ODBC_VER:
11449         case SQL_DATA_SOURCE_NAME:
11450         case SQL_DRIVER_NAME:
11451         case SQL_DRIVER_VER:
11452         case SQL_ODBC_VER:
11453         case SQL_SERVER_NAME:
11454         case SQL_DATABASE_NAME:
11455         case SQL_SEARCH_PATTERN_ESCAPE:
11456         case SQL_DBMS_NAME:
11457         case SQL_DBMS_VER:
11458         case SQL_NEED_LONG_DATA_LEN:
11459         case SQL_ROW_UPDATES:
11460         case SQL_ACCESSIBLE_PROCEDURES:
11461         case SQL_PROCEDURES:
11462         case SQL_EXPRESSIONS_IN_ORDERBY:
11463         case SQL_ODBC_SQL_OPT_IEF:
11464         case SQL_LIKE_ESCAPE_CLAUSE:
11465         case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11466         case SQL_OUTER_JOINS:
11467         case SQL_COLUMN_ALIAS:
11468         case SQL_ACCESSIBLE_TABLES:
11469         case SQL_MULT_RESULT_SETS:
11470         case SQL_MULTIPLE_ACTIVE_TXN:
11471         case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11472         case SQL_DATA_SOURCE_READ_ONLY:
11473 #ifdef SQL_DESCRIBE_PARAMETER
11474         case SQL_DESCRIBE_PARAMETER:
11475 #endif
11476         case SQL_IDENTIFIER_QUOTE_CHAR:
11477         case SQL_OWNER_TERM:
11478         case SQL_PROCEDURE_TERM:
11479         case SQL_QUALIFIER_NAME_SEPARATOR:
11480         case SQL_QUALIFIER_TERM:
11481         case SQL_TABLE_TERM:
11482         case SQL_KEYWORDS:
11483         case SQL_SPECIAL_CHARACTERS:
11484 #ifdef SQL_CATALOG_NAME
11485         case SQL_CATALOG_NAME:
11486 #endif
11487 #ifdef SQL_COLLATION_SEQ
11488         case SQL_COLLATION_SEQ:
11489 #endif
11490             if (val) {
11491                 if (len > 0) {
11492                     v = uc_from_utf((SQLCHAR *) val, len);
11493                     if (v) {
11494                         int vmax = valMax / sizeof (SQLWCHAR);
11495 
11496                         uc_strncpy(val, v, vmax);
11497                         if (len < vmax) {
11498                             len = min(vmax, uc_strlen(v));
11499                             v[len] = 0;
11500                         } else {
11501                             len = vmax;
11502                         }
11503                         uc_free(v);
11504                         len *= sizeof (SQLWCHAR);
11505                     } else {
11506                         len = 0;
11507                     }
11508                 }
11509                 if (len <= 0) {
11510                     len = 0;
11511                     if (valMax >= sizeof (SQLWCHAR)) {
11512                         *((SQLWCHAR *)val) = 0;
11513                     }
11514                 }
11515             } else {
11516                 len *= sizeof (SQLWCHAR);
11517             }
11518             break;
11519         }
11520         if (valLen) {
11521             *valLen = len;
11522         }
11523     }
11524     return ret;
11525 }
11526 #endif
11527 
11536 SQLRETURN SQL_API
11537 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
11538                 SQLUSMALLINT *flags)
11539 {
11540     int i;
11541     SQLUSMALLINT exists[100];
11542 
11543     if (dbc == SQL_NULL_HDBC) {
11544         return SQL_INVALID_HANDLE;
11545     }
11546     for (i = 0; i < array_size(exists); i++) {
11547         exists[i] = SQL_FALSE;
11548     }
11549     exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
11550     exists[SQL_API_SQLFETCH] = SQL_TRUE;
11551     exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
11552     exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
11553     exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
11554     exists[SQL_API_SQLFREEENV] = SQL_TRUE;
11555     exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
11556     exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
11557     exists[SQL_API_SQLCANCEL] = SQL_TRUE;
11558     exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
11559     exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
11560     exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
11561     exists[SQL_API_SQLCONNECT] = SQL_TRUE;
11562     exists[SQL_API_SQLPREPARE] = SQL_TRUE;
11563     exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
11564     exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
11565     exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
11566     exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
11567     exists[SQL_API_SQLERROR] = SQL_TRUE;
11568     exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
11569     exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
11570     exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
11571     exists[SQL_API_SQLBULKOPERATIONS] = SQL_TRUE;
11572     exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
11573     exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
11574     exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
11575     exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
11576     exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
11577     exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
11578     exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
11579     exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
11580     exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
11581     exists[SQL_API_SQLGETDATA] = SQL_TRUE;
11582     exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
11583     exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
11584     exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
11585     exists[SQL_API_SQLGETINFO] = SQL_TRUE;
11586     exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
11587     exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
11588     exists[SQL_API_SQLTABLES] = SQL_TRUE;
11589     exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
11590     exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
11591     exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
11592     exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
11593     exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
11594     exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
11595     exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
11596     exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
11597     exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
11598     exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
11599     exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
11600     exists[SQL_API_SQLSETPOS] = SQL_TRUE;
11601     exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
11602     exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
11603     exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
11604     exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
11605     exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
11606     if (func == SQL_API_ALL_FUNCTIONS) {
11607         memcpy(flags, exists, sizeof (exists));
11608     } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
11609         int i;
11610 #define SET_EXISTS(x) \
11611         flags[(x) >> 4] |= (1 << ((x) & 0xF))
11612 #define CLR_EXISTS(x) \
11613         flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
11614 
11615         memset(flags, 0,
11616                sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
11617         for (i = 0; i < array_size(exists); i++) {
11618             if (exists[i]) {
11619                 flags[i >> 4] |= (1 << (i & 0xF));
11620             }
11621         }
11622         SET_EXISTS(SQL_API_SQLALLOCHANDLE);
11623         SET_EXISTS(SQL_API_SQLFREEHANDLE);
11624         SET_EXISTS(SQL_API_SQLGETSTMTATTR);
11625         SET_EXISTS(SQL_API_SQLSETSTMTATTR);
11626         SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
11627         SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
11628         SET_EXISTS(SQL_API_SQLGETENVATTR);
11629         SET_EXISTS(SQL_API_SQLSETENVATTR);
11630         SET_EXISTS(SQL_API_SQLCLOSECURSOR);
11631         SET_EXISTS(SQL_API_SQLBINDPARAM);
11632 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11633         /*
11634          * Some unixODBC versions have problems with
11635          * SQLError() vs. SQLGetDiagRec() with loss
11636          * of error/warning messages.
11637          */
11638         SET_EXISTS(SQL_API_SQLGETDIAGREC);
11639 #endif
11640         SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
11641         SET_EXISTS(SQL_API_SQLFETCHSCROLL);
11642         SET_EXISTS(SQL_API_SQLENDTRAN);
11643     } else {
11644         if (func < array_size(exists)) {
11645             *flags = exists[func];
11646         } else {
11647             switch (func) {
11648             case SQL_API_SQLALLOCHANDLE:
11649             case SQL_API_SQLFREEHANDLE:
11650             case SQL_API_SQLGETSTMTATTR:
11651             case SQL_API_SQLSETSTMTATTR:
11652             case SQL_API_SQLGETCONNECTATTR:
11653             case SQL_API_SQLSETCONNECTATTR:
11654             case SQL_API_SQLGETENVATTR:
11655             case SQL_API_SQLSETENVATTR:
11656             case SQL_API_SQLCLOSECURSOR:
11657             case SQL_API_SQLBINDPARAM:
11658 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11659             /*
11660              * Some unixODBC versions have problems with
11661              * SQLError() vs. SQLGetDiagRec() with loss
11662              * of error/warning messages.
11663              */
11664             case SQL_API_SQLGETDIAGREC:
11665 #endif
11666             case SQL_API_SQLGETDIAGFIELD:
11667             case SQL_API_SQLFETCHSCROLL:
11668             case SQL_API_SQLENDTRAN:
11669                 *flags = SQL_TRUE;
11670                 break;
11671             default:
11672                 *flags = SQL_FALSE;
11673             }
11674         }
11675     }
11676     return SQL_SUCCESS;
11677 }
11678 
11685 static SQLRETURN
11686 drvallocenv(SQLHENV *env)
11687 {
11688     ENV *e;
11689 
11690     if (env == NULL) {
11691         return SQL_INVALID_HANDLE;
11692     }
11693     e = (ENV *) xmalloc(sizeof (ENV));
11694     if (e == NULL) {
11695         *env = SQL_NULL_HENV;
11696         return SQL_ERROR;
11697     }
11698     e->magic = ENV_MAGIC;
11699     e->ov3 = 0;
11700     e->pool = 0;
11701 #if defined(_WIN32) || defined(_WIN64)
11702     InitializeCriticalSection(&e->cs);
11703 #else
11704 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
11705     nvfs_init();
11706 #endif
11707 #endif
11708     e->dbcs = NULL;
11709     *env = (SQLHENV) e;
11710     return SQL_SUCCESS;
11711 }
11712 
11719 SQLRETURN SQL_API
11720 SQLAllocEnv(SQLHENV *env)
11721 {
11722     return drvallocenv(env);
11723 }
11724 
11731 static SQLRETURN
11732 drvfreeenv(SQLHENV env)
11733 {
11734     ENV *e;
11735 
11736     if (env == SQL_NULL_HENV) {
11737         return SQL_INVALID_HANDLE;
11738     }
11739     e = (ENV *) env;
11740     if (e->magic != ENV_MAGIC) {
11741         return SQL_SUCCESS;
11742     }
11743 #if defined(_WIN32) || defined(_WIN64)
11744     EnterCriticalSection(&e->cs);
11745 #endif
11746     if (e->dbcs) {
11747 #if defined(_WIN32) || defined(_WIN64)
11748         LeaveCriticalSection(&e->cs);
11749 #endif
11750         return SQL_ERROR;
11751     }
11752     e->magic = DEAD_MAGIC;
11753 #if defined(_WIN32) || defined(_WIN64)
11754     LeaveCriticalSection(&e->cs);
11755     DeleteCriticalSection(&e->cs);
11756 #endif
11757     xfree(e);
11758     return SQL_SUCCESS;
11759 }
11760 
11767 SQLRETURN SQL_API
11768 SQLFreeEnv(SQLHENV env)
11769 {
11770     return drvfreeenv(env);
11771 }
11772 
11780 static SQLRETURN
11781 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
11782 {
11783     DBC *d;
11784     ENV *e;
11785     const char *verstr;
11786     int maj = 0, min = 0, lev = 0;
11787 
11788     if (dbc == NULL) {
11789         return SQL_ERROR;
11790     }
11791     d = (DBC *) xmalloc(sizeof (DBC));
11792     if (d == NULL) {
11793         *dbc = SQL_NULL_HDBC;
11794         return SQL_ERROR;
11795     }
11796     memset(d, 0, sizeof (DBC));
11797     d->curtype = SQL_CURSOR_STATIC;
11798     d->ov3 = &d->ov3val;
11799     verstr = sqlite3_libversion();
11800     sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
11801     d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
11802     e = (ENV *) env;
11803 #if defined(_WIN32) || defined(_WIN64)
11804     if (e->magic == ENV_MAGIC) {
11805         EnterCriticalSection(&e->cs);
11806     }
11807 #endif
11808     if (e->magic == ENV_MAGIC) {
11809         DBC *n, *p;
11810 
11811         d->env = e;
11812         d->ov3 = &e->ov3;
11813         p = NULL;
11814         n = e->dbcs;
11815         while (n) {
11816             p = n;
11817             n = n->next;
11818         }
11819         if (p) {
11820             p->next = d;
11821         } else {
11822             e->dbcs = d;
11823         }
11824     }
11825 #if defined(_WIN32) || defined(_WIN64)
11826     InitializeCriticalSection(&d->cs);
11827     d->owner = 0;
11828     if (e->magic == ENV_MAGIC) {
11829         LeaveCriticalSection(&e->cs);
11830     }
11831     d->oemcp = 1;
11832 #endif
11833     d->autocommit = 1;
11834     d->magic = DBC_MAGIC;
11835     *dbc = (SQLHDBC) d;
11836     drvgetgpps(d);
11837     return SQL_SUCCESS;
11838 }
11839 
11847 SQLRETURN SQL_API
11848 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
11849 {
11850     return drvallocconnect(env, dbc);
11851 }
11852 
11859 static SQLRETURN
11860 drvfreeconnect(SQLHDBC dbc)
11861 {
11862     DBC *d;
11863     ENV *e;
11864     SQLRETURN ret = SQL_ERROR;
11865 
11866     if (dbc == SQL_NULL_HDBC) {
11867         return SQL_INVALID_HANDLE;
11868     }
11869     d = (DBC *) dbc;
11870     if (d->magic != DBC_MAGIC) {
11871         return SQL_INVALID_HANDLE;
11872     }
11873     e = d->env;
11874     if (e && e->magic == ENV_MAGIC) {
11875 #if defined(_WIN32) || defined(_WIN64)
11876         EnterCriticalSection(&e->cs);
11877 #endif
11878     } else {
11879         e = NULL;
11880     }
11881     HDBC_LOCK(dbc);
11882     if (d->sqlite) {
11883         setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
11884         HDBC_UNLOCK(dbc);
11885         goto done;
11886     }
11887     while (d->stmt) {
11888         freestmt((HSTMT) d->stmt);
11889     }
11890     if (e && e->magic == ENV_MAGIC) {
11891         DBC *n, *p;
11892 
11893         p = NULL;
11894         n = e->dbcs;
11895         while (n) {
11896             if (n == d) {
11897                 break;
11898             }
11899             p = n;
11900             n = n->next;
11901         }
11902         if (n) {
11903             if (p) {
11904                 p->next = d->next;
11905             } else {
11906                 e->dbcs = d->next;
11907             }
11908         }
11909     }
11910     drvrelgpps(d);
11911     d->magic = DEAD_MAGIC;
11912     if (d->trace) {
11913         fclose(d->trace);
11914     }
11915 #if defined(_WIN32) || defined(_WIN64)
11916     d->owner = 0;
11917     LeaveCriticalSection(&d->cs);
11918     DeleteCriticalSection(&d->cs);
11919 #endif
11920     xfree(d);
11921     ret = SQL_SUCCESS;
11922 done:
11923 #if defined(_WIN32) || defined(_WIN64)
11924     if (e) {
11925         LeaveCriticalSection(&e->cs);
11926     }
11927 #endif
11928     return ret;
11929 }
11930 
11937 SQLRETURN SQL_API
11938 SQLFreeConnect(SQLHDBC dbc)
11939 {
11940     return drvfreeconnect(dbc);
11941 }
11942 
11953 static SQLRETURN
11954 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11955                   SQLINTEGER bufmax, SQLINTEGER *buflen)
11956 {
11957     DBC *d;
11958     SQLINTEGER dummy;
11959 
11960     if (dbc == SQL_NULL_HDBC) {
11961         return SQL_INVALID_HANDLE;
11962     }
11963     d = (DBC *) dbc;
11964     if (!val) {
11965         val = (SQLPOINTER) &dummy;
11966     }
11967     if (!buflen) {
11968         buflen = &dummy;
11969     }
11970     switch (attr) {
11971     case SQL_ATTR_CONNECTION_DEAD:
11972         *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
11973         *buflen = sizeof (SQLINTEGER);
11974         break;
11975     case SQL_ATTR_ACCESS_MODE:
11976         *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
11977         *buflen = sizeof (SQLINTEGER);
11978         break;
11979     case SQL_ATTR_AUTOCOMMIT:
11980         *((SQLINTEGER *) val) =
11981             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
11982         *buflen = sizeof (SQLINTEGER);
11983         break;
11984     case SQL_ATTR_LOGIN_TIMEOUT:
11985         *((SQLINTEGER *) val) = 100;
11986         *buflen = sizeof (SQLINTEGER);
11987         break;
11988     case SQL_ATTR_ODBC_CURSORS:
11989         *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
11990         *buflen = sizeof (SQLINTEGER);
11991         break;
11992     case SQL_ATTR_PACKET_SIZE:
11993         *((SQLINTEGER *) val) = 16384;
11994         *buflen = sizeof (SQLINTEGER);
11995         break;
11996     case SQL_ATTR_TXN_ISOLATION:
11997         *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11998         *buflen = sizeof (SQLINTEGER);
11999         break;
12000     case SQL_ATTR_TRACEFILE:
12001     case SQL_ATTR_TRANSLATE_LIB:
12002         *((SQLCHAR *) val) = 0;
12003         *buflen = 0;
12004         break;
12005     case SQL_ATTR_CURRENT_CATALOG:
12006 #if defined(_WIN32) || defined(_WIN64)
12007         if (d->xcelqrx) {
12008             if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
12009                 strcpy((char *) val, "main");
12010                 *buflen = 4;
12011                 break;
12012             }
12013         }
12014 #endif
12015         *((SQLCHAR *) val) = 0;
12016         *buflen = 0;
12017         break;
12018     case SQL_ATTR_TRACE:
12019     case SQL_ATTR_QUIET_MODE:
12020     case SQL_ATTR_TRANSLATE_OPTION:
12021     case SQL_ATTR_KEYSET_SIZE:
12022     case SQL_ATTR_QUERY_TIMEOUT:
12023         *((SQLINTEGER *) val) = 0;
12024         *buflen = sizeof (SQLINTEGER);
12025         break;
12026     case SQL_ATTR_PARAM_BIND_TYPE:
12027         *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
12028         *buflen = sizeof (SQLUINTEGER);
12029         break;
12030     case SQL_ATTR_ROW_BIND_TYPE:
12031         *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
12032         *buflen = sizeof (SQLULEN);
12033         break;
12034     case SQL_ATTR_USE_BOOKMARKS:
12035         *((SQLINTEGER *) val) = SQL_UB_OFF;
12036         *buflen = sizeof (SQLINTEGER);
12037         break;
12038     case SQL_ATTR_ASYNC_ENABLE:
12039         *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
12040         *buflen = sizeof (SQLINTEGER);
12041         break;
12042     case SQL_ATTR_NOSCAN:
12043         *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
12044         *buflen = sizeof (SQLINTEGER);
12045         break;
12046     case SQL_ATTR_CONCURRENCY:
12047         *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
12048         *buflen = sizeof (SQLINTEGER);
12049         break;
12050 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
12051     case SQL_ATTR_CURSOR_SENSITIVITY:
12052         *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
12053         *buflen = sizeof (SQLINTEGER);
12054         break;
12055 #endif
12056     case SQL_ATTR_SIMULATE_CURSOR:
12057         *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
12058         *buflen = sizeof (SQLINTEGER);
12059         break;
12060     case SQL_ATTR_MAX_ROWS:
12061         *((SQLINTEGER *) val) = 0;
12062         *buflen = sizeof (SQLINTEGER);
12063     case SQL_ATTR_MAX_LENGTH:
12064         *((SQLINTEGER *) val) = 1000000000;
12065         *buflen = sizeof (SQLINTEGER);
12066         break;
12067     case SQL_ATTR_CURSOR_TYPE:
12068         *((SQLINTEGER *) val) = d->curtype;
12069         *buflen = sizeof (SQLINTEGER);
12070         break;
12071     case SQL_ATTR_RETRIEVE_DATA:
12072         *((SQLINTEGER *) val) = SQL_RD_ON;
12073         *buflen = sizeof (SQLINTEGER);
12074         break;
12075 #ifdef SQL_ATTR_METADATA_ID
12076     case SQL_ATTR_METADATA_ID:
12077         *((SQLULEN *) val) = SQL_FALSE;
12078         return SQL_SUCCESS;
12079 #endif
12080     default:
12081         *((SQLINTEGER *) val) = 0;
12082         *buflen = sizeof (SQLINTEGER);
12083         setstatd(d, -1, "unsupported connect attribute %d",
12084                  (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
12085         return SQL_ERROR;
12086     }
12087     return SQL_SUCCESS;
12088 }
12089 
12090 #ifndef WINTERFACE
12091 
12101 SQLRETURN SQL_API
12102 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12103                   SQLINTEGER bufmax, SQLINTEGER *buflen)
12104 {
12105     SQLRETURN ret;
12106 
12107     HDBC_LOCK(dbc);
12108     ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
12109     HDBC_UNLOCK(dbc);
12110     return ret;
12111 }
12112 #endif
12113 
12114 #ifdef WINTERFACE
12115 
12125 SQLRETURN SQL_API
12126 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12127                    SQLINTEGER bufmax, SQLINTEGER *buflen)
12128 {
12129     SQLRETURN ret;
12130     SQLINTEGER len = 0;
12131 
12132     HDBC_LOCK(dbc);
12133     ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
12134     if (ret == SQL_SUCCESS) {
12135         SQLWCHAR *v = NULL;
12136 
12137         switch (attr) {
12138         case SQL_ATTR_TRACEFILE:
12139         case SQL_ATTR_CURRENT_CATALOG:
12140         case SQL_ATTR_TRANSLATE_LIB:
12141             if (val) {
12142                 if (len > 0) {
12143                     v = uc_from_utf((SQLCHAR *) val, len);
12144                     if (v) {
12145                         int vmax = bufmax / sizeof (SQLWCHAR);
12146 
12147                         uc_strncpy(val, v, vmax);
12148                         if (len < vmax) {
12149                             len = min(vmax, uc_strlen(v));
12150                             v[len] = 0;
12151                         } else {
12152                             len = vmax;
12153                         }
12154                         uc_free(v);
12155                         len *= sizeof (SQLWCHAR);
12156                     } else {
12157                         len = 0;
12158                     }
12159                 }
12160                 if (len <= 0) {
12161                     len = 0;
12162                     if (bufmax >= sizeof (SQLWCHAR)) {
12163                         *((SQLWCHAR *)val) = 0;
12164                     }
12165                 }
12166             } else {
12167                 len *= sizeof (SQLWCHAR);
12168             }
12169             break;
12170         }
12171         if (buflen) {
12172             *buflen = len;
12173         }
12174     }
12175     HDBC_UNLOCK(dbc);
12176     return ret;
12177 }
12178 #endif
12179 
12189 static SQLRETURN
12190 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12191                   SQLINTEGER len)
12192 {
12193     DBC *d;
12194 
12195     if (dbc == SQL_NULL_HDBC) {
12196         return SQL_INVALID_HANDLE;
12197     }
12198     d = (DBC *) dbc;
12199     switch (attr) {
12200     case SQL_AUTOCOMMIT:
12201         d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
12202         if (d->autocommit && d->intrans) {
12203             return endtran(d, SQL_COMMIT, 1);
12204         } else if (!d->autocommit) {
12205             s3stmt_end(d->cur_s3stmt);
12206         }
12207         break;
12208         return SQL_SUCCESS;
12209 #ifdef SQL_ATTR_METADATA_ID
12210     case SQL_ATTR_METADATA_ID:
12211         if (val == (SQLPOINTER) SQL_FALSE) {
12212             break;
12213         }
12214         /* fall through */
12215 #endif
12216     default:
12217         setstatd(d, -1, "option value changed", "01S02");
12218         return SQL_SUCCESS_WITH_INFO;
12219     }
12220     return SQL_SUCCESS;
12221 }
12222 
12223 #ifndef WINTERFACE
12224 
12233 SQLRETURN SQL_API
12234 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12235                   SQLINTEGER len)
12236 {
12237     SQLRETURN ret;
12238 
12239     HDBC_LOCK(dbc);
12240     ret = drvsetconnectattr(dbc, attr, val, len);
12241     HDBC_UNLOCK(dbc);
12242     return ret;
12243 }
12244 #endif
12245 
12246 #ifdef WINTERFACE
12247 
12256 SQLRETURN SQL_API
12257 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12258                    SQLINTEGER len)
12259 {
12260     SQLRETURN ret;
12261 
12262     HDBC_LOCK(dbc);
12263     ret = drvsetconnectattr(dbc, attr, val, len);
12264     HDBC_UNLOCK(dbc);
12265     return ret;
12266 }
12267 #endif
12268 
12277 static SQLRETURN
12278 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12279 {
12280     DBC *d;
12281     SQLINTEGER dummy;
12282 
12283     if (dbc == SQL_NULL_HDBC) {
12284         return SQL_INVALID_HANDLE;
12285     }
12286     d = (DBC *) dbc;
12287     if (!param) {
12288         param = (SQLPOINTER) &dummy;
12289     }
12290     switch (opt) {
12291     case SQL_ACCESS_MODE:
12292         *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
12293         break;
12294     case SQL_AUTOCOMMIT:
12295         *((SQLINTEGER *) param) =
12296             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12297         break;
12298     case SQL_LOGIN_TIMEOUT:
12299         *((SQLINTEGER *) param) = 100;
12300         break;
12301     case SQL_ODBC_CURSORS:
12302         *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
12303         break;
12304     case SQL_PACKET_SIZE:
12305         *((SQLINTEGER *) param) = 16384;
12306         break;
12307     case SQL_TXN_ISOLATION:
12308         *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
12309         break;
12310     case SQL_OPT_TRACE:
12311     case SQL_OPT_TRACEFILE:
12312     case SQL_QUIET_MODE:
12313     case SQL_TRANSLATE_DLL:
12314     case SQL_TRANSLATE_OPTION:
12315     case SQL_KEYSET_SIZE:
12316     case SQL_QUERY_TIMEOUT:
12317     case SQL_BIND_TYPE:
12318     case SQL_CURRENT_QUALIFIER:
12319         *((SQLINTEGER *) param) = 0;
12320         break;
12321     case SQL_USE_BOOKMARKS:
12322         *((SQLINTEGER *) param) = SQL_UB_OFF;
12323         break;
12324     case SQL_ASYNC_ENABLE:
12325         *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
12326         break;
12327     case SQL_NOSCAN:
12328         *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
12329         break;
12330     case SQL_CONCURRENCY:
12331         *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
12332         break;
12333     case SQL_SIMULATE_CURSOR:
12334         *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
12335         break;
12336     case SQL_MAX_ROWS:
12337         *((SQLINTEGER *) param) = 0;
12338         break;
12339     case SQL_ROWSET_SIZE:
12340     case SQL_MAX_LENGTH:
12341         *((SQLINTEGER *) param) = 1000000000;
12342         break;
12343     case SQL_CURSOR_TYPE:
12344         *((SQLINTEGER *) param) = d->curtype;
12345         break;
12346     case SQL_RETRIEVE_DATA:
12347         *((SQLINTEGER *) param) = SQL_RD_ON;
12348         break;
12349     default:
12350         *((SQLINTEGER *) param) = 0;
12351         setstatd(d, -1, "unsupported connect option %d",
12352                  (*d->ov3) ? "HYC00" : "S1C00", opt);
12353         return SQL_ERROR;
12354     }
12355     return SQL_SUCCESS;
12356 }
12357 
12358 #ifndef WINTERFACE
12359 
12367 SQLRETURN SQL_API
12368 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12369 {
12370     SQLRETURN ret;
12371 
12372     HDBC_LOCK(dbc);
12373     ret = drvgetconnectoption(dbc, opt, param);
12374     HDBC_UNLOCK(dbc);
12375     return ret;
12376 }
12377 #endif
12378 
12379 #ifdef WINTERFACE
12380 
12388 SQLRETURN SQL_API
12389 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12390 {
12391     SQLRETURN ret;
12392 
12393     HDBC_LOCK(dbc);
12394     ret = drvgetconnectoption(dbc, opt, param);
12395     if (SQL_SUCCEEDED(ret)) {
12396         switch (opt) {
12397         case SQL_OPT_TRACEFILE:
12398         case SQL_CURRENT_QUALIFIER:
12399         case SQL_TRANSLATE_DLL:
12400             if (param) {
12401                 *(SQLWCHAR *) param = 0;
12402             }
12403             break;
12404         }
12405     }
12406     HDBC_UNLOCK(dbc);
12407     return ret;
12408 }
12409 #endif
12410 
12419 static SQLRETURN
12420 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
12421 {
12422     DBC *d;
12423 
12424     if (dbc == SQL_NULL_HDBC) {
12425         return SQL_INVALID_HANDLE;
12426     }
12427     d = (DBC *) dbc;
12428     switch (opt) {
12429     case SQL_AUTOCOMMIT:
12430         d->autocommit = param == SQL_AUTOCOMMIT_ON;
12431         if (d->autocommit && d->intrans) {
12432             return endtran(d, SQL_COMMIT, 1);
12433         } else if (!d->autocommit) {
12434             s3stmt_end(d->cur_s3stmt);
12435         }
12436         break;
12437     default:
12438         setstatd(d, -1, "option value changed", "01S02");
12439         return SQL_SUCCESS_WITH_INFO;
12440     }
12441     return SQL_SUCCESS;
12442 }
12443 
12444 #ifndef WINTERFACE
12445 
12453 SQLRETURN SQL_API
12454 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12455 {
12456     SQLRETURN ret;
12457 
12458     HDBC_LOCK(dbc);
12459     ret = drvsetconnectoption(dbc, opt, param);
12460     HDBC_UNLOCK(dbc);
12461     return ret;
12462 }
12463 #endif
12464 
12465 #ifdef WINTERFACE
12466 
12474 SQLRETURN SQL_API
12475 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12476 {
12477     SQLRETURN ret;
12478 
12479     HDBC_LOCK(dbc);
12480     ret = drvsetconnectoption(dbc, opt, param);
12481     HDBC_UNLOCK(dbc);
12482     return ret;
12483 }
12484 #endif
12485 
12486 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12487 
12498 static int
12499 getdsnattr(char *dsn, char *attr, char *out, int outLen)
12500 {
12501     char *str = dsn, *start;
12502     int len = strlen(attr);
12503 
12504     while (*str) {
12505         while (*str && *str == ';') {
12506             ++str;
12507         }
12508         start = str;
12509         if ((str = strchr(str, '=')) == NULL) {
12510             return 0;
12511         }
12512         if (str - start == len && strncasecmp(start, attr, len) == 0) {
12513             start = ++str;
12514             while (*str && *str != ';') {
12515                 ++str;
12516             }
12517             len = min(outLen - 1, str - start);
12518             strncpy(out, start, len);
12519             out[len] = '\0';
12520             return 1;
12521         }
12522         while (*str && *str != ';') {
12523             ++str;
12524         }
12525     }
12526     return 0;
12527 }
12528 #endif
12529 
12541 static SQLRETURN
12542 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
12543            int pwdLen, int isu)
12544 {
12545     DBC *d;
12546     int len;
12547     SQLRETURN ret;
12548     char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12549     char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
12550     char loadext[SQL_MAX_MESSAGE_LENGTH];
12551     char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
12552     char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
12553     char jdflag[32];
12554 #if defined(_WIN32) || defined(_WIN64)
12555     char oemcp[32];
12556 #endif
12557 
12558     if (dbc == SQL_NULL_HDBC) {
12559         return SQL_INVALID_HANDLE;
12560     }
12561     d = (DBC *) dbc;
12562     if (d->magic != DBC_MAGIC) {
12563         return SQL_INVALID_HANDLE;
12564     }
12565     if (d->sqlite != NULL) {
12566         setstatd(d, -1, "connection already established", "08002");
12567         return SQL_ERROR;
12568     }
12569     buf[0] = '\0';
12570     if (dsnLen == SQL_NTS) {
12571         len = sizeof (buf) - 1;
12572     } else {
12573         len = min(sizeof (buf) - 1, dsnLen);
12574     }
12575     if (dsn != NULL) {
12576         strncpy(buf, (char *) dsn, len);
12577     }
12578     buf[len] = '\0';
12579     if (buf[0] == '\0') {
12580         setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
12581         return SQL_ERROR;
12582     }
12583 #if defined(_WIN32) || defined(_WIN64)
12584     /*
12585      * When DSN is in UTF it must be converted to ANSI
12586      * here for ANSI SQLGetPrivateProfileString()
12587      */
12588     if (isu) {
12589         char *cdsn = utf_to_wmb(buf, len);
12590 
12591         if (!cdsn) {
12592             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12593             return SQL_ERROR;
12594         }
12595         strcpy(buf, cdsn);
12596         uc_free(cdsn);
12597     }
12598 #endif
12599     busy[0] = '\0';
12600     dbname[0] = '\0';
12601 #ifdef WITHOUT_DRIVERMGR
12602     getdsnattr(buf, "database", dbname, sizeof (dbname));
12603     if (dbname[0] == '\0') {
12604         strncpy(dbname, buf, sizeof (dbname));
12605         dbname[sizeof (dbname) - 1] = '\0';
12606     }
12607     getdsnattr(buf, "timeout", busy, sizeof (busy));
12608     sflag[0] = '\0';
12609     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12610     spflag[0] = '\0';
12611     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12612     ntflag[0] = '\0';
12613     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12614     nwflag[0] = '\0';
12615     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12616     snflag[0] = '\0';
12617     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12618     lnflag[0] = '\0';
12619     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12620     ncflag[0] = '\0';
12621     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12622     fkflag[0] = '\0';
12623     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12624     loadext[0] = '\0';
12625     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12626     jmode[0] = '\0';
12627     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12628     jdflag[0] = '\0';
12629     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
12630 #if defined(_WIN32) || defined(_WIN64)
12631     oemcp[0] = '\0';
12632     getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
12633 #endif
12634     biflag[0] = '\0';
12635     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12636 #else
12637     SQLGetPrivateProfileString(buf, "timeout", "100000",
12638                                busy, sizeof (busy), ODBC_INI);
12639     SQLGetPrivateProfileString(buf, "database", "",
12640                                dbname, sizeof (dbname), ODBC_INI);
12641 #if defined(_WIN32) || defined(_WIN64)
12642     /* database name read from registry is not UTF8 !!! */
12643     isu = 0;
12644 #endif
12645     SQLGetPrivateProfileString(buf, "stepapi", "",
12646                                sflag, sizeof (sflag), ODBC_INI);
12647     SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
12648                                spflag, sizeof (spflag), ODBC_INI);
12649     SQLGetPrivateProfileString(buf, "notxn", "",
12650                                ntflag, sizeof (ntflag), ODBC_INI);
12651     SQLGetPrivateProfileString(buf, "nowchar", "",
12652                                nwflag, sizeof (nwflag), ODBC_INI);
12653     SQLGetPrivateProfileString(buf, "shortnames", "",
12654                                snflag, sizeof (snflag), ODBC_INI);
12655     SQLGetPrivateProfileString(buf, "longnames", "",
12656                                lnflag, sizeof (lnflag), ODBC_INI);
12657     SQLGetPrivateProfileString(buf, "nocreat", "",
12658                                ncflag, sizeof (ncflag), ODBC_INI);
12659     SQLGetPrivateProfileString(buf, "fksupport", "",
12660                                fkflag, sizeof (fkflag), ODBC_INI);
12661     SQLGetPrivateProfileString(buf, "loadext", "",
12662                                loadext, sizeof (loadext), ODBC_INI);
12663     SQLGetPrivateProfileString(buf, "journalmode", "",
12664                                jmode, sizeof (jmode), ODBC_INI);
12665     SQLGetPrivateProfileString(buf, "jdconv", "",
12666                                jdflag, sizeof (jdflag), ODBC_INI);
12667 #if defined(_WIN32) || defined(_WIN64)
12668     SQLGetPrivateProfileString(buf, "oemcp", "1",
12669                                oemcp, sizeof (oemcp), ODBC_INI);
12670 #endif
12671     SQLGetPrivateProfileString(buf, "bigint", "",
12672                                biflag, sizeof (biflag), ODBC_INI);
12673 #endif
12674     tracef[0] = '\0';
12675 #ifdef WITHOUT_DRIVERMGR
12676     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12677 #else
12678     SQLGetPrivateProfileString(buf, "tracefile", "",
12679                                tracef, sizeof (tracef), ODBC_INI);
12680 #endif
12681     if (tracef[0] != '\0') {
12682         d->trace = fopen(tracef, "a");
12683     }
12684     d->nowchar = getbool(nwflag);
12685     d->shortnames = getbool(snflag);
12686     d->longnames = getbool(lnflag);
12687     d->nocreat = getbool(ncflag);
12688     d->fksupport = getbool(fkflag);
12689     d->jdconv = getbool(jdflag);
12690 #if defined(_WIN32) || defined(_WIN64)
12691     d->oemcp = getbool(oemcp);
12692 #else
12693     d->oemcp = 0;
12694 #endif
12695     d->dobigint = getbool(biflag);
12696     d->pwd = pwd;
12697     d->pwdLen = 0;
12698     if (d->pwd) {
12699         d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
12700     }
12701     ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
12702                   jmode, busy);
12703     if (ret == SQL_SUCCESS) {
12704         dbloadext(d, loadext);
12705     }
12706     return ret;
12707 }
12708 
12709 #ifndef WINTERFACE
12710 
12722 SQLRETURN SQL_API
12723 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
12724            SQLCHAR *uid, SQLSMALLINT uidLen,
12725            SQLCHAR *pwd, SQLSMALLINT pwdLen)
12726 {
12727     SQLRETURN ret;
12728 
12729     HDBC_LOCK(dbc);
12730     ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
12731     HDBC_UNLOCK(dbc);
12732     return ret;
12733 }
12734 #endif
12735 
12736 #ifdef WINTERFACE
12737 
12749 SQLRETURN SQL_API
12750 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
12751             SQLWCHAR *uid, SQLSMALLINT uidLen,
12752             SQLWCHAR *pwd, SQLSMALLINT pwdLen)
12753 {
12754     char *dsna = NULL;
12755     char *pwda = NULL;
12756     SQLRETURN ret;
12757 
12758     HDBC_LOCK(dbc);
12759     if (dsn) {
12760         dsna = uc_to_utf_c(dsn, dsnLen);
12761         if (!dsna) {
12762             DBC *d = (DBC *) dbc;
12763 
12764             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12765             ret = SQL_ERROR;
12766             goto done;
12767         }
12768     }
12769     if (pwd) {
12770         pwda = uc_to_utf_c(pwd, pwdLen);
12771         if (!pwda) {
12772             DBC *d = (DBC *) dbc;
12773 
12774             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12775             ret = SQL_ERROR;
12776             goto done;
12777         }
12778     }
12779     ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
12780 done:
12781     HDBC_UNLOCK(dbc);
12782     uc_free(dsna);
12783     uc_free(pwda);
12784     return ret;
12785 }
12786 #endif
12787 
12794 static SQLRETURN
12795 drvdisconnect(SQLHDBC dbc)
12796 {
12797     DBC *d;
12798     int rc;
12799 
12800     if (dbc == SQL_NULL_HDBC) {
12801         return SQL_INVALID_HANDLE;
12802     }
12803     d = (DBC *) dbc;
12804     if (d->magic != DBC_MAGIC) {
12805         return SQL_INVALID_HANDLE;
12806     }
12807     if (d->intrans) {
12808         setstatd(d, -1, "incomplete transaction", "25000");
12809         return SQL_ERROR;
12810     }
12811     if (d->cur_s3stmt) {
12812         s3stmt_end(d->cur_s3stmt);
12813     }
12814     if (d->sqlite) {
12815         if (d->trace) {
12816             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
12817                     d->dbname);
12818             fflush(d->trace);
12819         }
12820         rc = sqlite3_close(d->sqlite);
12821         if (rc == SQLITE_BUSY) {
12822             setstatd(d, -1, "unfinished statements", "25000");
12823             return SQL_ERROR;
12824         }
12825         d->sqlite = NULL;
12826     }
12827     freep(&d->dbname);
12828     freep(&d->dsn);
12829     return SQL_SUCCESS;
12830 }
12831 
12838 SQLRETURN SQL_API
12839 SQLDisconnect(SQLHDBC dbc)
12840 {
12841     SQLRETURN ret;
12842 
12843     HDBC_LOCK(dbc);
12844     ret = drvdisconnect(dbc);
12845     HDBC_UNLOCK(dbc);
12846     return ret;
12847 }
12848 
12849 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12850 
12864 static SQLRETURN
12865 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
12866                  SQLCHAR *connIn, SQLSMALLINT connInLen,
12867                  SQLCHAR *connOut, SQLSMALLINT connOutMax,
12868                  SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
12869 {
12870     DBC *d;
12871     int len;
12872     SQLRETURN ret;
12873     char buf[SQL_MAX_MESSAGE_LENGTH * 8], dbname[SQL_MAX_MESSAGE_LENGTH];
12874     char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
12875     char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
12876     char pwd[SQL_MAX_MESSAGE_LENGTH];
12877     char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
12878     char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
12879     char jdflag[32];
12880 
12881     if (dbc == SQL_NULL_HDBC) {
12882         return SQL_INVALID_HANDLE;
12883     }
12884     if (drvcompl != SQL_DRIVER_COMPLETE &&
12885         drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
12886         drvcompl != SQL_DRIVER_PROMPT &&
12887         drvcompl != SQL_DRIVER_NOPROMPT) {
12888         return SQL_NO_DATA;
12889     }
12890     d = (DBC *) dbc;
12891     if (d->sqlite) {
12892         setstatd(d, -1, "connection already established", "08002");
12893         return SQL_ERROR;
12894     }
12895     buf[0] = '\0';
12896     if (connInLen == SQL_NTS) {
12897         len = sizeof (buf) - 1;
12898     } else {
12899         len = min(connInLen, sizeof (buf) - 1);
12900     }
12901     if (connIn != NULL) {
12902         strncpy(buf, (char *) connIn, len);
12903     }
12904     buf[len] = '\0';
12905     if (!buf[0]) {
12906         setstatd(d, -1, "invalid connect attributes",
12907                  (*d->ov3) ? "HY090" : "S1090");
12908         return SQL_ERROR;
12909     }
12910     dsn[0] = '\0';
12911     getdsnattr(buf, "DSN", dsn, sizeof (dsn));
12912 
12913     /* special case: connIn is sole DSN value without keywords */
12914     if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
12915         strncpy(dsn, buf, sizeof (dsn) - 1);
12916         dsn[sizeof (dsn) - 1] = '\0';
12917     }
12918 
12919     busy[0] = '\0';
12920     getdsnattr(buf, "timeout", busy, sizeof (busy));
12921 #ifndef WITHOUT_DRIVERMGR
12922     if (dsn[0] && !busy[0]) {
12923         SQLGetPrivateProfileString(dsn, "timeout", "100000",
12924                                    busy, sizeof (busy), ODBC_INI);
12925     }
12926 #endif
12927     dbname[0] = '\0';
12928     getdsnattr(buf, "database", dbname, sizeof (dbname));
12929 #ifndef WITHOUT_DRIVERMGR
12930     if (dsn[0] && !dbname[0]) {
12931         SQLGetPrivateProfileString(dsn, "database", "",
12932                                    dbname, sizeof (dbname), ODBC_INI);
12933     }
12934 #endif
12935     sflag[0] = '\0';
12936     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12937 #ifndef WITHOUT_DRIVERMGR
12938     if (dsn[0] && !sflag[0]) {
12939         SQLGetPrivateProfileString(dsn, "stepapi", "",
12940                                    sflag, sizeof (sflag), ODBC_INI);
12941     }
12942 #endif
12943     spflag[0] = '\0';
12944     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12945 #ifndef WITHOUT_DRIVERMGR
12946     if (dsn[0] && !spflag[0]) {
12947         SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
12948                                    spflag, sizeof (spflag), ODBC_INI);
12949     }
12950 #endif
12951     ntflag[0] = '\0';
12952     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12953 #ifndef WITHOUT_DRIVERMGR
12954     if (dsn[0] && !ntflag[0]) {
12955         SQLGetPrivateProfileString(dsn, "notxn", "",
12956                                    ntflag, sizeof (ntflag), ODBC_INI);
12957     }
12958 #endif
12959     snflag[0] = '\0';
12960     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12961 #ifndef WITHOUT_DRIVERMGR
12962     if (dsn[0] && !snflag[0]) {
12963         SQLGetPrivateProfileString(dsn, "shortnames", "",
12964                                    snflag, sizeof (snflag), ODBC_INI);
12965     }
12966 #endif
12967     lnflag[0] = '\0';
12968     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12969 #ifndef WITHOUT_DRIVERMGR
12970     if (dsn[0] && !lnflag[0]) {
12971         SQLGetPrivateProfileString(dsn, "longnames", "",
12972                                    lnflag, sizeof (lnflag), ODBC_INI);
12973     }
12974 #endif
12975     ncflag[0] = '\0';
12976     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12977 #ifndef WITHOUT_DRIVERMGR
12978     if (dsn[0] && !ncflag[0]) {
12979         SQLGetPrivateProfileString(dsn, "nocreat", "",
12980                                    ncflag, sizeof (ncflag), ODBC_INI);
12981     }
12982 #endif
12983     nwflag[0] = '\0';
12984     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12985 #ifndef WITHOUT_DRIVERMGR
12986     if (dsn[0] && !nwflag[0]) {
12987         SQLGetPrivateProfileString(dsn, "nowchar", "",
12988                                    nwflag, sizeof (nwflag), ODBC_INI);
12989     }
12990 #endif
12991     fkflag[0] = '\0';
12992     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12993 #ifndef WITHOUT_DRIVERMGR
12994     if (dsn[0] && !fkflag[0]) {
12995         SQLGetPrivateProfileString(dsn, "fksupport", "",
12996                                    fkflag, sizeof (fkflag), ODBC_INI);
12997     }
12998 #endif
12999     loadext[0] = '\0';
13000     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
13001 #ifndef WITHOUT_DRIVERMGR
13002     if (dsn[0] && !loadext[0]) {
13003         SQLGetPrivateProfileString(dsn, "loadext", "",
13004                                    loadext, sizeof (loadext), ODBC_INI);
13005     }
13006 #endif
13007     jmode[0] = '\0';
13008     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
13009 #ifndef WITHOUT_DRIVERMGR
13010     if (dsn[0] && !jmode[0]) {
13011         SQLGetPrivateProfileString(dsn, "journalmode", "",
13012                                    jmode, sizeof (jmode), ODBC_INI);
13013     }
13014 #endif
13015     biflag[0] = '\0';
13016     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
13017 #ifndef WITHOUT_DRIVERMGR
13018     if (dsn[0] && !biflag[0]) {
13019         SQLGetPrivateProfileString(dsn, "bigint", "",
13020                                    biflag, sizeof (biflag), ODBC_INI);
13021     }
13022 #endif
13023     jdflag[0] = '\0';
13024     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
13025 #ifndef WITHOUT_DRIVERMGR
13026     if (dsn[0] && !jdflag[0]) {
13027         SQLGetPrivateProfileString(dsn, "jdconv", "",
13028                                    jdflag, sizeof (jdflag), ODBC_INI);
13029     }
13030 #endif
13031     pwd[0] = '\0';
13032     getdsnattr(buf, "pwd", pwd, sizeof (pwd));
13033 #ifndef WITHOUT_DRIVERMGR
13034     if (dsn[0] && !pwd[0]) {
13035         SQLGetPrivateProfileString(dsn, "pwd", "",
13036                                    pwd, sizeof (pwd), ODBC_INI);
13037     }
13038 #endif
13039 
13040     if (!dbname[0] && !dsn[0]) {
13041         strcpy(dsn, "SQLite");
13042         strncpy(dbname, buf, sizeof (dbname));
13043         dbname[sizeof (dbname) - 1] = '\0';
13044     }
13045     tracef[0] = '\0';
13046     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
13047 #ifndef WITHOUT_DRIVERMGR
13048     if (dsn[0] && !tracef[0]) {
13049         SQLGetPrivateProfileString(dsn, "tracefile", "",
13050                                    tracef, sizeof (tracef), ODBC_INI);
13051     }
13052 #endif
13053     if (connOut || connOutLen) {
13054         int count;
13055 
13056         buf[0] = '\0';
13057         count = snprintf(buf, sizeof (buf),
13058                          "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
13059                          "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
13060                          "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
13061                          "JournalMode=%s;LoadExt=%s;BigInt=%s;JDConv=%s;"
13062                          "PWD=%s",
13063                          dsn, dbname, sflag, busy, spflag, ntflag,
13064                          snflag, lnflag, ncflag, nwflag, fkflag, tracef,
13065                          jmode, loadext, biflag, jdflag, pwd);
13066         if (count < 0) {
13067             buf[sizeof (buf) - 1] = '\0';
13068         }
13069         len = min(connOutMax - 1, strlen(buf));
13070         if (connOut) {
13071             strncpy((char *) connOut, buf, len);
13072             connOut[len] = '\0';
13073         }
13074         if (connOutLen) {
13075             *connOutLen = len;
13076         }
13077     }
13078     if (tracef[0] != '\0') {
13079         d->trace = fopen(tracef, "a");
13080     }
13081     d->shortnames = getbool(snflag);
13082     d->longnames = getbool(lnflag);
13083     d->nocreat = getbool(ncflag);
13084     d->nowchar = getbool(nwflag);
13085     d->fksupport = getbool(fkflag);
13086     d->dobigint = getbool(biflag);
13087     d->jdconv = getbool(jdflag);
13088     d->oemcp = 0;
13089     d->pwdLen = strlen(pwd);
13090     d->pwd = (d->pwdLen > 0) ? pwd : NULL;
13091     ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
13092     memset(pwd, 0, sizeof (pwd));
13093     if (ret == SQL_SUCCESS) {
13094         dbloadext(d, loadext);
13095     }
13096     return ret;
13097 }
13098 #endif
13099 
13106 static SQLRETURN
13107 freestmt(SQLHSTMT stmt)
13108 {
13109     STMT *s;
13110     DBC *d;
13111 
13112     if (stmt == SQL_NULL_HSTMT) {
13113         return SQL_INVALID_HANDLE;
13114     }
13115     s = (STMT *) stmt;
13116     s3stmt_drop(s);
13117     freeresult(s, 1);
13118     freep(&s->query);
13119     d = (DBC *) s->dbc;
13120     if (d && d->magic == DBC_MAGIC) {
13121         STMT *p, *n;
13122 
13123         p = NULL;
13124         n = d->stmt;
13125         while (n) {
13126             if (n == s) {
13127                 break;
13128             }
13129             p = n;
13130             n = n->next;
13131         }
13132         if (n) {
13133             if (p) {
13134                 p->next = s->next;
13135             } else {
13136                 d->stmt = s->next;
13137             }
13138         }
13139     }
13140     freeparams(s);
13141     freep(&s->bindparms);
13142     if (s->row_status0 != &s->row_status1) {
13143         freep(&s->row_status0);
13144         s->rowset_size = 1;
13145         s->row_status0 = &s->row_status1;
13146     }
13147     xfree(s);
13148     return SQL_SUCCESS;
13149 }
13150 
13158 static SQLRETURN
13159 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
13160 {
13161     DBC *d;
13162     STMT *s, *sl, *pl;
13163 
13164     if (dbc == SQL_NULL_HDBC) {
13165         return SQL_INVALID_HANDLE;
13166     }
13167     d = (DBC *) dbc;
13168     if (d->magic != DBC_MAGIC || stmt == NULL) {
13169         return SQL_INVALID_HANDLE;
13170     }
13171     s = (STMT *) xmalloc(sizeof (STMT));
13172     if (s == NULL) {
13173         *stmt = SQL_NULL_HSTMT;
13174         return SQL_ERROR;
13175     }
13176     *stmt = (SQLHSTMT) s;
13177     memset(s, 0, sizeof (STMT));
13178     s->dbc = dbc;
13179     s->ov3 = d->ov3;
13180     s->bkmrk = SQL_UB_OFF;
13181     s->bkmrkptr = 0;
13182     s->oemcp = &d->oemcp;
13183     s->jdconv = &d->jdconv;
13184     s->nowchar[0] = d->nowchar;
13185     s->nowchar[1] = 0;
13186     s->dobigint = d->dobigint;
13187     s->curtype = d->curtype;
13188     s->row_status0 = &s->row_status1;
13189     s->rowset_size = 1;
13190     s->longnames = d->longnames;
13191     s->retr_data = SQL_RD_ON;
13192     s->max_rows = 0;
13193     s->bind_type = SQL_BIND_BY_COLUMN;
13194     s->bind_offs = NULL;
13195     s->paramset_size = 1;
13196     s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
13197     s->one_tbl = -1;
13198     s->has_pk = -1;
13199     s->has_rowid = -1;
13200 #ifdef _WIN64
13201     sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
13202 #else
13203     sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
13204 #endif
13205     sl = d->stmt;
13206     pl = NULL;
13207     while (sl) {
13208         pl = sl;
13209         sl = sl->next;
13210     }
13211     if (pl) {
13212         pl->next = s;
13213     } else {
13214         d->stmt = s;
13215     }
13216     return SQL_SUCCESS;
13217 }
13218 
13226 SQLRETURN SQL_API
13227 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
13228 {
13229     SQLRETURN ret;
13230 
13231     HDBC_LOCK(dbc);
13232     ret = drvallocstmt(dbc, stmt);
13233     HDBC_UNLOCK(dbc);
13234     return ret;
13235 }
13236 
13244 static SQLRETURN
13245 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13246 {
13247     STMT *s;
13248     SQLRETURN ret = SQL_SUCCESS;
13249     SQLHDBC dbc;
13250 
13251     if (stmt == SQL_NULL_HSTMT) {
13252         return SQL_INVALID_HANDLE;
13253     }
13254     HSTMT_LOCK(stmt);
13255     s = (STMT *) stmt;
13256     dbc = s->dbc;
13257     switch (opt) {
13258     case SQL_RESET_PARAMS:
13259         freeparams(s);
13260         break;
13261     case SQL_UNBIND:
13262         unbindcols(s);
13263         break;
13264     case SQL_CLOSE:
13265         s3stmt_end_if(s);
13266         freeresult(s, 0);
13267         break;
13268     case SQL_DROP:
13269         s3stmt_end_if(s);
13270         ret = freestmt(stmt);
13271         break;
13272     default:
13273         setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
13274         ret = SQL_ERROR;
13275         break;
13276     }
13277     HDBC_UNLOCK(dbc);
13278     return ret;
13279 }
13280 
13288 SQLRETURN SQL_API
13289 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13290 {
13291     return drvfreestmt(stmt, opt);
13292 }
13293 
13300 SQLRETURN SQL_API
13301 SQLCancel(SQLHSTMT stmt)
13302 {
13303     if (stmt != SQL_NULL_HSTMT) {
13304         DBC *d = (DBC *) ((STMT *) stmt)->dbc;
13305 #if defined(_WIN32) || defined(_WIN64)
13306         /* interrupt when other thread owns critical section */
13307         if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
13308             d->owner != 0) {
13309             d->busyint = 1;
13310             sqlite3_interrupt(d->sqlite);
13311             return SQL_SUCCESS;
13312         }
13313 #else
13314         if (d->magic == DBC_MAGIC) {
13315             d->busyint = 1;
13316             sqlite3_interrupt(d->sqlite);
13317         }
13318 #endif
13319     }
13320     return drvfreestmt(stmt, SQL_CLOSE);
13321 }
13322 
13332 static SQLRETURN
13333 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13334                  SQLSMALLINT *lenp)
13335 {
13336     STMT *s;
13337 
13338     if (stmt == SQL_NULL_HSTMT) {
13339         return SQL_INVALID_HANDLE;
13340     }
13341     s = (STMT *) stmt;
13342     if (lenp && !cursor) {
13343         *lenp = strlen((char *) s->cursorname);
13344         return SQL_SUCCESS;
13345     }
13346     if (cursor) {
13347         if (buflen > 0) {
13348             strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
13349             cursor[buflen - 1] = '\0';
13350         }
13351         if (lenp) {
13352             *lenp = min(strlen((char *) s->cursorname), buflen - 1);
13353         }
13354     }
13355     return SQL_SUCCESS;
13356 }
13357 
13358 #ifndef WINTERFACE
13359 
13368 SQLRETURN SQL_API
13369 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13370                  SQLSMALLINT *lenp)
13371 {
13372     SQLRETURN ret;
13373 #if defined(_WIN32) || defined(_WIN64)
13374     SQLSMALLINT len = 0;
13375 #endif
13376 
13377     HSTMT_LOCK(stmt);
13378 #if defined(_WIN32) || defined(_WIN64)
13379     if (!((STMT *) stmt)->oemcp[0]) {
13380         ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13381         goto done;
13382     }
13383     ret = drvgetcursorname(stmt, cursor, buflen, &len);
13384     if (ret == SQL_SUCCESS) {
13385         char *c = NULL;
13386 
13387         if (cursor) {
13388             c = utf_to_wmb((char *) cursor, len);
13389             if (!c) {
13390                 ret = nomem((STMT *) stmt);
13391                 goto done;
13392             }
13393             c[len] = 0;
13394             len = strlen(c);
13395             if (buflen > 0) {
13396                 strncpy((char *) cursor, c, buflen - 1);
13397                 cursor[buflen - 1] = 0;
13398             }
13399             uc_free(c);
13400         }
13401         if (lenp) {
13402             *lenp = min(len, buflen - 1);
13403         }
13404     }
13405 done:
13406     ;
13407 #else
13408     ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13409 #endif
13410     HSTMT_UNLOCK(stmt);
13411     return ret;
13412 }
13413 #endif
13414 
13415 #ifdef WINTERFACE
13416 
13425 SQLRETURN SQL_API
13426 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
13427                   SQLSMALLINT *lenp)
13428 {
13429     SQLRETURN ret;
13430     SQLSMALLINT len = 0;
13431 
13432     HSTMT_LOCK(stmt);
13433     ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
13434     if (ret == SQL_SUCCESS) {
13435         SQLWCHAR *c = NULL;
13436 
13437         if (cursor) {
13438             c = uc_from_utf((SQLCHAR *) cursor, len);
13439             if (!c) {
13440                 ret = nomem((STMT *) stmt);
13441                 goto done;
13442             }
13443             c[len] = 0;
13444             len = uc_strlen(c);
13445             if (buflen > 0) {
13446                 uc_strncpy(cursor, c, buflen - 1);
13447                 cursor[buflen - 1] = 0;
13448             }
13449             uc_free(c);
13450         }
13451         if (lenp) {
13452             *lenp = min(len, buflen - 1);
13453         }
13454     }
13455 done:
13456     HSTMT_UNLOCK(stmt);
13457     return ret;
13458 }
13459 #endif
13460 
13469 static SQLRETURN
13470 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13471 {
13472     STMT *s;
13473 
13474     if (stmt == SQL_NULL_HSTMT) {
13475         return SQL_INVALID_HANDLE;
13476     }
13477     s = (STMT *) stmt;
13478     if (!cursor ||
13479         !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
13480           (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
13481         setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
13482         return SQL_ERROR;
13483     }
13484     if (len == SQL_NTS) {
13485         len = sizeof (s->cursorname) - 1;
13486     } else {
13487         len = min(sizeof (s->cursorname) - 1, len);
13488     }
13489     strncpy((char *) s->cursorname, (char *) cursor, len);
13490     s->cursorname[len] = '\0';
13491     return SQL_SUCCESS;
13492 }
13493 
13494 #ifndef WINTERFACE
13495 
13503 SQLRETURN SQL_API
13504 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13505 {
13506 #if defined(_WIN32) || defined(_WIN64)
13507     char *c = NULL;
13508 #endif
13509     SQLRETURN ret;
13510 
13511     HSTMT_LOCK(stmt);
13512 #if defined(_WIN32) || defined(_WIN64)
13513     if (!((STMT *) stmt)->oemcp[0]) {
13514         ret = drvsetcursorname(stmt, cursor, len);
13515         goto done2;
13516     }
13517     if (cursor) {
13518         c = wmb_to_utf_c((char *) cursor, len);
13519         if (!c) {
13520             ret = nomem((STMT *) stmt);
13521             goto done;
13522         }
13523     }
13524     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13525 #else
13526     ret = drvsetcursorname(stmt, cursor, len);
13527 #endif
13528 #if defined(_WIN32) || defined(_WIN64)
13529 done:
13530     uc_free(c);
13531 done2:
13532     ;
13533 #endif
13534     HSTMT_UNLOCK(stmt);
13535     return ret;
13536 }
13537 #endif
13538 
13539 #ifdef WINTERFACE
13540 
13548 SQLRETURN SQL_API
13549 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
13550 {
13551     char *c = NULL;
13552     SQLRETURN ret;
13553 
13554     HSTMT_LOCK(stmt);
13555     if (cursor) {
13556         c = uc_to_utf_c(cursor, len);
13557         if (!c) {
13558             ret = nomem((STMT *) stmt);
13559             goto done;
13560         }
13561     }
13562     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13563 done:
13564     uc_free(c);
13565     HSTMT_UNLOCK(stmt);
13566     return ret;
13567 }
13568 #endif
13569 
13576 SQLRETURN SQL_API
13577 SQLCloseCursor(SQLHSTMT stmt)
13578 {
13579     return drvfreestmt(stmt, SQL_CLOSE);
13580 }
13581 
13590 SQLRETURN SQL_API
13591 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
13592 {
13593     SQLRETURN ret;
13594 
13595     switch (type) {
13596     case SQL_HANDLE_ENV:
13597         ret = drvallocenv((SQLHENV *) output);
13598         if (ret == SQL_SUCCESS) {
13599             ENV *e = (ENV *) *output;
13600 
13601             if (e && e->magic == ENV_MAGIC) {
13602                 e->ov3 = 1;
13603             }
13604         }
13605         return ret;
13606     case SQL_HANDLE_DBC:
13607         return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
13608     case SQL_HANDLE_STMT:
13609         HDBC_LOCK((SQLHDBC) input);
13610         ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
13611         HDBC_UNLOCK((SQLHDBC) input);
13612         return ret;
13613     }
13614     return SQL_ERROR;
13615 }
13616 
13624 SQLRETURN SQL_API
13625 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
13626 {
13627     switch (type) {
13628     case SQL_HANDLE_ENV:
13629         return drvfreeenv((SQLHENV) h);
13630     case SQL_HANDLE_DBC:
13631         return drvfreeconnect((SQLHDBC) h);
13632     case SQL_HANDLE_STMT:
13633         return drvfreestmt((SQLHSTMT) h, SQL_DROP);
13634     }
13635     return SQL_ERROR;
13636 }
13637 
13643 static void
13644 freedyncols(STMT *s)
13645 {
13646     if (s->dyncols) {
13647         int i;
13648 
13649         for (i = 0; i < s->dcols; i++) {
13650             freep(&s->dyncols[i].typename);
13651         }
13652         if (s->cols == s->dyncols) {
13653             s->cols = NULL;
13654             s->ncols = 0;
13655         }
13656         freep(&s->dyncols);
13657     }
13658     s->dcols = 0;
13659 }
13660 
13672 static void
13673 freeresult(STMT *s, int clrcols)
13674 {
13675     freep(&s->bincache);
13676     s->bincell = NULL;
13677     s->binlen = 0;
13678     if (s->rows) {
13679         if (s->rowfree) {
13680             s->rowfree(s->rows);
13681             s->rowfree = NULL;
13682         }
13683         s->rows = NULL;
13684     }
13685     s->nrows = -1;
13686     if (clrcols > 0) {
13687         freep(&s->bindcols);
13688         s->nbindcols = 0;
13689     }
13690     if (clrcols) {
13691         freedyncols(s);
13692         s->cols = NULL;
13693         s->ncols = 0;
13694         s->nowchar[1] = 0;
13695         s->one_tbl = -1;
13696         s->has_pk = -1;
13697         s->has_rowid = -1;
13698     }
13699 }
13700 
13706 static void
13707 unbindcols(STMT *s)
13708 {
13709     int i;
13710 
13711     for (i = 0; s->bindcols && i < s->nbindcols; i++) {
13712         s->bindcols[i].type = SQL_UNKNOWN_TYPE;
13713         s->bindcols[i].max = 0;
13714         s->bindcols[i].lenp = NULL;
13715         s->bindcols[i].valp = NULL;
13716         s->bindcols[i].index = i;
13717         s->bindcols[i].offs = 0;
13718     }
13719 }
13720 
13728 static SQLRETURN
13729 mkbindcols(STMT *s, int ncols)
13730 {
13731     if (s->bindcols) {
13732         if (s->nbindcols < ncols) {
13733             int i;
13734             BINDCOL *bindcols =
13735                 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
13736 
13737             if (!bindcols) {
13738                 return nomem(s);
13739             }
13740             for (i = s->nbindcols; i < ncols; i++) {
13741                 bindcols[i].type = SQL_UNKNOWN_TYPE;
13742                 bindcols[i].max = 0;
13743                 bindcols[i].lenp = NULL;
13744                 bindcols[i].valp = NULL;
13745                 bindcols[i].index = i;
13746                 bindcols[i].offs = 0;
13747             }
13748             s->bindcols = bindcols;
13749             s->nbindcols = ncols;
13750         }
13751     } else if (ncols > 0) {
13752         s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
13753         if (!s->bindcols) {
13754             return nomem(s);
13755         }
13756         s->nbindcols = ncols;
13757         unbindcols(s);
13758     }
13759     return SQL_SUCCESS;
13760 }
13761 
13775 static SQLRETURN
13776 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
13777            SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
13778 {
13779     char **data, valdummy[16];
13780     SQLLEN dummy;
13781     SQLINTEGER *ilenp = NULL;
13782     int valnull = 0;
13783     int type = otype;
13784     SQLRETURN sret = SQL_NO_DATA;
13785 
13786     if (!lenp) {
13787         lenp = &dummy;
13788     }
13789     /* workaround for JDK 1.7.0 on x86_64 */
13790     if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
13791         ilenp = (SQLINTEGER *) lenp;
13792         lenp = &dummy;
13793     }
13794     if (col >= s->ncols) {
13795         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13796         return SQL_ERROR;
13797     }
13798     if (s->retr_data != SQL_RD_ON) {
13799         return SQL_SUCCESS;
13800     }
13801     if (!s->rows) {
13802         *lenp = SQL_NULL_DATA;
13803         goto done;
13804     }
13805     if (s->rowp < 0 || s->rowp >= s->nrows) {
13806         *lenp = SQL_NULL_DATA;
13807         goto done;
13808     }
13809     type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
13810                       s->nowchar[0]);
13811 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
13812     /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
13813     if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
13814         type = SQL_C_CHAR;
13815     }
13816 #endif
13817     data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
13818     if (!val) {
13819         valnull = 1;
13820         val = (SQLPOINTER) valdummy;
13821     }
13822     if (*data == NULL) {
13823         *lenp = SQL_NULL_DATA;
13824         switch (type) {
13825         case SQL_C_UTINYINT:
13826         case SQL_C_TINYINT:
13827         case SQL_C_STINYINT:
13828 #ifdef SQL_BIT
13829         case SQL_C_BIT:
13830 #endif
13831             *((SQLCHAR *) val) = 0;
13832             break;
13833         case SQL_C_USHORT:
13834         case SQL_C_SHORT:
13835         case SQL_C_SSHORT:
13836             *((SQLSMALLINT *) val) = 0;
13837             break;
13838         case SQL_C_ULONG:
13839         case SQL_C_LONG:
13840         case SQL_C_SLONG:
13841             *((SQLINTEGER *) val) = 0;
13842             break;
13843 #ifdef SQL_BIGINT
13844         case SQL_C_SBIGINT:
13845         case SQL_C_UBIGINT:
13846             *((SQLBIGINT *) val) = 0;
13847             break;
13848 #endif
13849         case SQL_C_FLOAT:
13850             *((float *) val) = 0;
13851             break;
13852         case SQL_C_DOUBLE:
13853             *((double *) val) = 0;
13854             break;
13855         case SQL_C_BINARY:
13856         case SQL_C_CHAR:
13857             if (len > 0) {
13858                 *((SQLCHAR *) val) = '\0';
13859             }
13860             break;
13861 #ifdef WCHARSUPPORT
13862         case SQL_C_WCHAR:
13863             if (len > 0) {
13864                 *((SQLWCHAR *) val) = '\0';
13865             }
13866             break;
13867 #endif
13868 #ifdef SQL_C_TYPE_DATE
13869         case SQL_C_TYPE_DATE:
13870 #endif
13871         case SQL_C_DATE:
13872             memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
13873             break;
13874 #ifdef SQL_C_TYPE_TIME
13875         case SQL_C_TYPE_TIME:
13876 #endif
13877         case SQL_C_TIME:
13878             memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
13879             break;
13880 #ifdef SQL_C_TYPE_TIMESTAMP
13881         case SQL_C_TYPE_TIMESTAMP:
13882 #endif
13883         case SQL_C_TIMESTAMP:
13884             memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
13885             break;
13886         default:
13887             return SQL_ERROR;
13888         }
13889     } else {
13890         char *endp = NULL;
13891 #if defined(_WIN32) || defined(_WIN64)
13892 #ifdef SQL_BIGINT
13893         char endc;
13894 #endif
13895 #endif
13896 
13897         switch (type) {
13898         case SQL_C_UTINYINT:
13899         case SQL_C_TINYINT:
13900         case SQL_C_STINYINT:
13901             *((SQLCHAR *) val) = strtol(*data, &endp, 0);
13902             if (endp && endp == *data) {
13903                 *lenp = SQL_NULL_DATA;
13904             } else {
13905                 *lenp = sizeof (SQLCHAR);
13906             }
13907             break;
13908 #ifdef SQL_BIT
13909         case SQL_C_BIT:
13910             *((SQLCHAR *) val) = getbool(*data);
13911             *lenp = sizeof (SQLCHAR);
13912             break;
13913 #endif
13914         case SQL_C_USHORT:
13915         case SQL_C_SHORT:
13916         case SQL_C_SSHORT:
13917             *((SQLSMALLINT *) val) = strtol(*data, &endp, 0);
13918             if (endp && endp == *data) {
13919                 *lenp = SQL_NULL_DATA;
13920             } else {
13921                 *lenp = sizeof (SQLSMALLINT);
13922             }
13923             break;
13924         case SQL_C_ULONG:
13925         case SQL_C_LONG:
13926         case SQL_C_SLONG:
13927             *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
13928             if (endp && endp == *data) {
13929                 *lenp = SQL_NULL_DATA;
13930             } else {
13931                 *lenp = sizeof (SQLINTEGER);
13932             }
13933             break;
13934 #ifdef SQL_BIGINT
13935         case SQL_C_UBIGINT:
13936 #if defined(_WIN32) || defined(_WIN64)
13937             if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
13938                 *lenp = SQL_NULL_DATA;
13939             } else {
13940                 *lenp = sizeof (SQLUBIGINT);
13941             }
13942 #else
13943 #ifdef __osf__
13944             *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
13945 #else
13946             *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
13947 #endif
13948             if (endp && endp == *data) {
13949                 *lenp = SQL_NULL_DATA;
13950             } else {
13951                 *lenp = sizeof (SQLUBIGINT);
13952             }
13953 #endif
13954             break;
13955         case SQL_C_SBIGINT:
13956 #if defined(_WIN32) || defined(_WIN64)
13957             if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
13958                 *lenp = SQL_NULL_DATA;
13959             } else {
13960                 *lenp = sizeof (SQLBIGINT);
13961             }
13962 #else
13963 #ifdef __osf__
13964             *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
13965 #else
13966             *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
13967 #endif
13968             if (endp && endp == *data) {
13969                 *lenp = SQL_NULL_DATA;
13970             } else {
13971                 *lenp = sizeof (SQLBIGINT);
13972             }
13973 #endif
13974             break;
13975 #endif
13976         case SQL_C_FLOAT:
13977             *((float *) val) = ln_strtod(*data, &endp);
13978             if (endp && endp == *data) {
13979                 *lenp = SQL_NULL_DATA;
13980             } else {
13981                 *lenp = sizeof (float);
13982             }
13983             break;
13984         case SQL_C_DOUBLE:
13985             *((double *) val) = ln_strtod(*data, &endp);
13986             if (endp && endp == *data) {
13987                 *lenp = SQL_NULL_DATA;
13988             } else {
13989                 *lenp = sizeof (double);
13990             }
13991             break;
13992         case SQL_C_BINARY: {
13993             int dlen, offs = 0;
13994             char *bin;
13995 
13996             if (valnull) {
13997                 freep(&s->bincache);
13998                 s->binlen = 0;
13999                 goto doCHAR;
14000             }
14001             if (*data == s->bincell) {
14002                 if (s->bincache) {
14003                     bin = s->bincache;
14004                     dlen = s->binlen;
14005                 } else {
14006                     goto doCHAR;
14007                 }
14008             } else {
14009                 char *dp;
14010                 int i;
14011 
14012                 freep(&s->bincache);
14013                 dp = *data;
14014                 dlen = strlen(dp);
14015                 s->bincell = dp;
14016                 s->binlen = 0;
14017                 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
14018                     dp[dlen - 1] != '\'') {
14019                     goto doCHAR;
14020                 }
14021                 dlen -= 2;
14022                 dp += 2;
14023                 dlen = dlen / 2;
14024                 s->bincache = bin = xmalloc(dlen + 1);
14025                 if (!bin) {
14026                     return nomem(s);
14027                 }
14028                 s->binlen = dlen;
14029                 memset(bin, 0, dlen);
14030                 bin[dlen] = '\0';       /* terminator, just in case */
14031                 for (i = 0; i < dlen; i++) {
14032                     char *x;
14033                     int v;
14034 
14035                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14036                         goto converr;
14037                     }
14038                     v = x - xdigits;
14039                     bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
14040                     ++dp;
14041                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14042 converr:
14043                         freep(&s->bincache);
14044                         s->binlen = 0;
14045                         setstat(s, -1, "conversion error",
14046                                 (*s->ov3) ? "HY000" : "S1000");
14047                         return SQL_ERROR;
14048                     }
14049                     v = x - xdigits;
14050                     bin[i] |= (v >= 16) ? (v - 6) : v;
14051                     ++dp;
14052                 }
14053                 bin = s->bincache;
14054             }
14055             if (partial && len && s->bindcols) {
14056                 if (s->bindcols[col].offs >= dlen) {
14057                     *lenp = 0;
14058                     if (!dlen && s->bindcols[col].offs == dlen) {
14059                         s->bindcols[col].offs = 1;
14060                         sret = SQL_SUCCESS;
14061                         goto done;
14062                     }
14063                     s->bindcols[col].offs = 0;
14064                     sret = SQL_NO_DATA;
14065                     goto done;
14066                 }
14067                 offs = s->bindcols[col].offs;
14068                 dlen -= offs;
14069             }
14070             if (val && len) {
14071                 memcpy(val, bin + offs, min(len, dlen));
14072             }
14073             if (len < 1) {
14074                 *lenp = dlen;
14075             } else {
14076                 *lenp = min(len, dlen);
14077                 if (*lenp == len && *lenp != dlen) {
14078                     *lenp = SQL_NO_TOTAL;
14079                 }
14080             }
14081             if (partial && len && s->bindcols) {
14082                 if (*lenp == SQL_NO_TOTAL) {
14083                     *lenp = dlen;
14084                     s->bindcols[col].offs += len;
14085                     setstat(s, -1, "data right truncated", "01004");
14086                     if (s->bindcols[col].lenp) {
14087                         *s->bindcols[col].lenp = dlen;
14088                     }
14089                     sret = SQL_SUCCESS_WITH_INFO;
14090                     goto done;
14091                 }
14092                 s->bindcols[col].offs += *lenp;
14093             }
14094             if (*lenp == SQL_NO_TOTAL) {
14095                 *lenp = dlen;
14096                 setstat(s, -1, "data right truncated", "01004");
14097                 sret = SQL_SUCCESS_WITH_INFO;
14098                 goto done;
14099             }
14100             break;
14101         }
14102         doCHAR:
14103 #ifdef WCHARSUPPORT
14104         case SQL_C_WCHAR:
14105 #endif
14106         case SQL_C_CHAR: {
14107             int doz, zlen = len - 1;
14108             int dlen = strlen(*data);
14109             int offs = 0;
14110 #ifdef WCHARSUPPORT
14111             SQLWCHAR *ucdata = NULL;
14112             SQLCHAR *cdata = (SQLCHAR *) *data;
14113 #endif
14114 
14115 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14116             /* MS Access hack part 2 (reserved error -7748) */
14117             if (!valnull &&
14118                 (s->cols == statSpec2P || s->cols == statSpec3P) &&
14119                 type == SQL_C_WCHAR) {
14120                 if (len > 0 && len <= sizeof (SQLWCHAR)) {
14121                     ((char *) val)[0] = data[0][0];
14122                     memset((char *) val + 1, 0, len - 1);
14123                     *lenp = 1;
14124                     sret = SQL_SUCCESS;
14125                     goto done;
14126                 }
14127             }
14128 #endif
14129 
14130 #ifdef WCHARSUPPORT
14131             switch (type) {
14132             case SQL_C_CHAR:
14133                 doz = 1;
14134                 break;
14135             case SQL_C_WCHAR:
14136                 doz = sizeof (SQLWCHAR);
14137                 break;
14138             default:
14139                 doz = 0;
14140                 break;
14141             }
14142             if (type == SQL_C_WCHAR) {
14143                 ucdata = uc_from_utf(cdata, dlen);
14144                 if (!ucdata) {
14145                     return nomem(s);
14146                 }
14147                 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
14148             }
14149 #if defined(_WIN32) || defined(_WIN64)
14150             else if (*s->oemcp && type == SQL_C_CHAR) {
14151                 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
14152                 if (!ucdata) {
14153                     return nomem(s);
14154                 }
14155                 cdata = (SQLCHAR *) ucdata;
14156                 dlen = strlen((char *) cdata);
14157             }
14158 #endif
14159 #else
14160             doz = (type == SQL_C_CHAR) ? 1 : 0;
14161 #endif
14162             if (partial && len && s->bindcols) {
14163                 if (s->bindcols[col].offs >= dlen) {
14164 #ifdef WCHARSUPPORT
14165                     uc_free(ucdata);
14166 #endif
14167                     *lenp = 0;
14168                     if (doz && val) {
14169 #ifdef WCHARSUPPORT
14170                         if (type == SQL_C_WCHAR) {
14171                             ((SQLWCHAR *) val)[0] = 0;
14172                         } else {
14173                             ((char *) val)[0] = '\0';
14174                         }
14175 #else
14176                         ((char *) val)[0] = '\0';
14177 #endif
14178                     }
14179                     if (!dlen && s->bindcols[col].offs == dlen) {
14180                         s->bindcols[col].offs = 1;
14181                         sret = SQL_SUCCESS;
14182                         goto done;
14183                     }
14184                     s->bindcols[col].offs = 0;
14185                     sret = SQL_NO_DATA;
14186                     goto done;
14187                 }
14188                 offs = s->bindcols[col].offs;
14189                 dlen -= offs;
14190             }
14191             if (val && !valnull && len) {
14192 #ifdef WCHARSUPPORT
14193                 if (type == SQL_C_WCHAR) {
14194                     uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
14195                                (len - doz) / sizeof (SQLWCHAR));
14196                 } else {
14197                     strncpy(val, (char *) cdata + offs, len - doz);
14198                 }
14199 #else
14200                 strncpy(val, *data + offs, len - doz);
14201 #endif
14202             }
14203             if (valnull || len < 1) {
14204                 *lenp = dlen;
14205             } else {
14206                 *lenp = min(len - doz, dlen);
14207                 if (*lenp == len - doz && *lenp != dlen) {
14208                     *lenp = SQL_NO_TOTAL;
14209                 } else if (*lenp < zlen) {
14210                     zlen = *lenp;
14211                 }
14212             }
14213             if (len && !valnull && doz) {
14214 #ifdef WCHARSUPPORT
14215                 if (type == SQL_C_WCHAR) {
14216                     ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
14217                 } else {
14218                     ((char *) val)[zlen] = '\0';
14219                 }
14220 #else
14221                 ((char *) val)[zlen] = '\0';
14222 #endif
14223             }
14224 #ifdef WCHARSUPPORT
14225             uc_free(ucdata);
14226 #endif
14227             if (partial && len && s->bindcols) {
14228                 if (*lenp == SQL_NO_TOTAL) {
14229                     *lenp = dlen;
14230                     s->bindcols[col].offs += len - doz;
14231                     setstat(s, -1, "data right truncated", "01004");
14232                     if (s->bindcols[col].lenp) {
14233                         *s->bindcols[col].lenp = dlen;
14234                     }
14235                     sret = SQL_SUCCESS_WITH_INFO;
14236                     goto done;
14237                 }
14238                 s->bindcols[col].offs += *lenp;
14239             }
14240             if (*lenp == SQL_NO_TOTAL) {
14241                 *lenp = dlen;
14242                 setstat(s, -1, "data right truncated", "01004");
14243                 sret = SQL_SUCCESS_WITH_INFO;
14244                 goto done;
14245             }
14246             break;
14247         }
14248 #ifdef SQL_C_TYPE_DATE
14249         case SQL_C_TYPE_DATE:
14250 #endif
14251         case SQL_C_DATE:
14252             if (str2date(*s->jdconv, *data, (DATE_STRUCT *) val) < 0) {
14253                 *lenp = SQL_NULL_DATA;
14254             } else {
14255                 *lenp = sizeof (DATE_STRUCT);
14256             }
14257             break;
14258 #ifdef SQL_C_TYPE_TIME
14259         case SQL_C_TYPE_TIME:
14260 #endif
14261         case SQL_C_TIME:
14262             if (str2time(*s->jdconv, *data, (TIME_STRUCT *) val) < 0) {
14263                 *lenp = SQL_NULL_DATA;
14264             } else {
14265                 *lenp = sizeof (TIME_STRUCT);
14266             }
14267             break;
14268 #ifdef SQL_C_TYPE_TIMESTAMP
14269         case SQL_C_TYPE_TIMESTAMP:
14270 #endif
14271         case SQL_C_TIMESTAMP:
14272             if (str2timestamp(*s->jdconv, *data,
14273                               (TIMESTAMP_STRUCT *) val) < 0) {
14274                 *lenp = SQL_NULL_DATA;
14275             } else {
14276                 *lenp = sizeof (TIMESTAMP_STRUCT);
14277             }
14278             switch (s->cols[col].prec) {
14279             case 0:
14280                 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
14281                 break;
14282             case 1:
14283                 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
14284                 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
14285                 break;
14286             case 2:
14287                 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
14288                 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
14289                 break;
14290             }
14291             break;
14292         default:
14293             return SQL_ERROR;
14294         }
14295     }
14296     sret = SQL_SUCCESS;
14297 done:
14298     if (ilenp) {
14299         *ilenp = *lenp;
14300     }
14301     return sret;
14302 }
14303 
14315 static SQLRETURN
14316 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14317            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14318 {
14319     STMT *s;
14320     int sz = 0;
14321 
14322     if (stmt == SQL_NULL_HSTMT) {
14323         return SQL_INVALID_HANDLE;
14324     }
14325     s = (STMT *) stmt;
14326     if (col < 1) {
14327         if (col == 0 && s->bkmrk == SQL_UB_ON &&
14328             type == SQL_C_BOOKMARK) {
14329             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14330             s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
14331             s->bkmrkcol.lenp = val ? lenp : 0;
14332             s->bkmrkcol.valp = val;
14333             s->bkmrkcol.offs = 0;
14334             if (val && lenp) {
14335                 *lenp = 0;
14336             }
14337             return SQL_SUCCESS;
14338         } else if (col == 0 && s->bkmrk == SQL_UB_VARIABLE &&
14339                    type == SQL_C_VARBOOKMARK &&
14340                    max >= sizeof (sqlite_int64)) {
14341             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14342             s->bkmrkcol.max = val ? max : 0;
14343             s->bkmrkcol.lenp = val ? lenp : 0;
14344             s->bkmrkcol.valp = val;
14345             s->bkmrkcol.offs = 0;
14346             if (val && lenp) {
14347                 *lenp = 0;
14348             }
14349             return SQL_SUCCESS;
14350         }
14351         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14352         return SQL_ERROR;
14353     }
14354     if (mkbindcols(s, col) != SQL_SUCCESS) {
14355         return SQL_ERROR;
14356     }
14357     --col;
14358     if (type == SQL_C_DEFAULT) {
14359         type = mapdeftype(type, s->cols[col].type, 0,
14360                           s->nowchar[0] || s->nowchar[1]);
14361     }
14362     switch (type) {
14363     case SQL_C_LONG:
14364     case SQL_C_ULONG:
14365     case SQL_C_SLONG:
14366         sz = sizeof (SQLINTEGER);
14367         break;
14368     case SQL_C_TINYINT:
14369     case SQL_C_UTINYINT:
14370     case SQL_C_STINYINT:
14371         sz = sizeof (SQLCHAR);
14372         break;
14373     case SQL_C_SHORT:
14374     case SQL_C_USHORT:
14375     case SQL_C_SSHORT:
14376         sz = sizeof (SQLSMALLINT);
14377         break;
14378     case SQL_C_FLOAT:
14379         sz = sizeof (SQLFLOAT);
14380         break;
14381     case SQL_C_DOUBLE:
14382         sz = sizeof (SQLDOUBLE);
14383         break;
14384     case SQL_C_TIMESTAMP:
14385         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14386         break;
14387     case SQL_C_TIME:
14388         sz = sizeof (SQL_TIME_STRUCT);
14389         break;
14390     case SQL_C_DATE:
14391         sz = sizeof (SQL_DATE_STRUCT);
14392         break;
14393     case SQL_C_CHAR:
14394         break;
14395 #ifdef WCHARSUPPORT
14396     case SQL_C_WCHAR:
14397         break;
14398 #endif
14399 #ifdef SQL_C_TYPE_DATE
14400     case SQL_C_TYPE_DATE:
14401         sz = sizeof (SQL_DATE_STRUCT);
14402         break;
14403 #endif
14404 #ifdef SQL_C_TYPE_TIME
14405     case SQL_C_TYPE_TIME:
14406         sz = sizeof (SQL_TIME_STRUCT);
14407         break;
14408 #endif
14409 #ifdef SQL_C_TYPE_TIMESTAMP
14410     case SQL_C_TYPE_TIMESTAMP:
14411         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14412         break;
14413 #endif
14414 #ifdef SQL_BIT
14415     case SQL_C_BIT:
14416         sz = sizeof (SQLCHAR);
14417         break;
14418 #endif
14419     case SQL_C_BINARY:
14420         break;
14421 #ifdef SQL_BIGINT
14422     case SQL_C_SBIGINT:
14423     case SQL_C_UBIGINT:
14424         sz = sizeof (SQLBIGINT);
14425         break;
14426 #endif
14427     default:
14428         if (val == NULL) {
14429             /* fall through, unbinding column */
14430             break;
14431         }
14432         setstat(s, -1, "invalid type %d", "HY003", type);
14433         return SQL_ERROR;
14434     }
14435     if (val == NULL) {
14436         /* unbind column */
14437         s->bindcols[col].type = SQL_UNKNOWN_TYPE;
14438         s->bindcols[col].max = 0;
14439         s->bindcols[col].lenp = NULL;
14440         s->bindcols[col].valp = NULL;
14441         s->bindcols[col].offs = 0;
14442     } else {
14443         if (sz == 0 && max < 0) {
14444             setstat(s, -1, "invalid length", "HY090");
14445             return SQL_ERROR;
14446         }
14447         s->bindcols[col].type = type;
14448         s->bindcols[col].max = (sz == 0) ? max : sz;
14449         s->bindcols[col].lenp = lenp;
14450         s->bindcols[col].valp = val;
14451         s->bindcols[col].offs = 0;
14452         if (lenp) {
14453             *lenp = 0;
14454         }
14455     }
14456     return SQL_SUCCESS;
14457 }
14458 
14470 SQLRETURN SQL_API
14471 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14472            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14473 {
14474     SQLRETURN ret;
14475 
14476     HSTMT_LOCK(stmt);
14477     ret = drvbindcol(stmt, col, type, val, max, lenp);
14478     HSTMT_UNLOCK(stmt);
14479     return ret;
14480 }
14481 
14486 static COL tableSpec2[] = {
14487     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14488     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14489     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14490     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14491     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14492 };
14493 
14494 static COL tableSpec3[] = {
14495     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14496     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14497     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14498     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14499     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14500 };
14501 
14516 static SQLRETURN
14517 drvtables(SQLHSTMT stmt,
14518           SQLCHAR *cat, SQLSMALLINT catLen,
14519           SQLCHAR *schema, SQLSMALLINT schemaLen,
14520           SQLCHAR *table, SQLSMALLINT tableLen,
14521           SQLCHAR *type, SQLSMALLINT typeLen)
14522 {
14523     SQLRETURN ret;
14524     STMT *s;
14525     DBC *d;
14526     int ncols, asize, rc, size, npatt;
14527     char *errp = NULL, *sql, tname[512];
14528     char *where = "(type = 'table' or type = 'view')";
14529 
14530     ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
14531                       tableSpec3, array_size(tableSpec3), &asize);
14532     if (ret != SQL_SUCCESS) {
14533         return ret;
14534     }
14535     s = (STMT *) stmt;
14536     d = (DBC *) s->dbc;
14537     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
14538         int size = 3 * asize;
14539 
14540         s->rows = xmalloc(size * sizeof (char *));
14541         if (!s->rows) {
14542             s->nrows = 0;
14543             return nomem(s);
14544         }
14545         memset(s->rows, 0, sizeof (char *) * size);
14546         s->ncols = asize;
14547         s->rows[s->ncols + 0] = "";
14548         s->rows[s->ncols + 1] = "";
14549         s->rows[s->ncols + 2] = "";
14550         s->rows[s->ncols + 3] = "TABLE";
14551         s->rows[s->ncols + 5] = "";
14552         s->rows[s->ncols + 6] = "";
14553         s->rows[s->ncols + 7] = "";
14554         s->rows[s->ncols + 8] = "VIEW";
14555 #ifdef MEMORY_DEBUG
14556         s->rowfree = xfree__;
14557 #else
14558         s->rowfree = sqlite3_free;
14559 #endif
14560         s->nrows = 2;
14561         s->rowp = s->rowprs = -1;
14562         return SQL_SUCCESS;
14563     }
14564     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
14565         table = NULL;
14566         goto doit;
14567     }
14568     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
14569         schema[0] == '%') {
14570         if ((!cat || catLen == 0 || !cat[0]) &&
14571             (!table || tableLen == 0 || !table[0])) {
14572             table = NULL;
14573             goto doit;
14574         }
14575     }
14576     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
14577         char tmp[256], *t;
14578         int with_view = 0, with_table = 0;
14579 
14580         if (typeLen == SQL_NTS) {
14581             strncpy(tmp, (char *) type, sizeof (tmp));
14582             tmp[sizeof (tmp) - 1] = '\0';
14583         } else {
14584             int len = min(sizeof (tmp) - 1, typeLen);
14585 
14586             strncpy(tmp, (char *) type, len);
14587             tmp[len] = '\0';
14588         }
14589         t = tmp;
14590         while (*t) {
14591             *t = TOLOWER(*t);
14592             t++;
14593         }
14594         t = tmp;
14595         unescpat(t);
14596         while (t) {
14597             if (t[0] == '\'') {
14598                 ++t;
14599             }
14600             if (strncmp(t, "table", 5) == 0) {
14601                 with_table++;
14602             } else if (strncmp(t, "view", 4) == 0) {
14603                 with_view++;
14604             }
14605             t = strchr(t, ',');
14606             if (t) {
14607                 ++t;
14608             }
14609         }
14610         if (with_view && with_table) {
14611             /* where is already preset */
14612         } else if (with_view && !with_table) {
14613             where = "type = 'view'";
14614         } else if (!with_view && with_table) {
14615             where = "type = 'table'";
14616         } else {
14617             return SQL_SUCCESS;
14618         }
14619     }
14620 doit:
14621     if (!table) {
14622         size = 1;
14623         tname[0] = '%';
14624     } else {
14625         if (tableLen == SQL_NTS) {
14626             size = sizeof (tname) - 1;
14627         } else {
14628             size = min(sizeof (tname) - 1, tableLen);
14629         }
14630         strncpy(tname, (char *) table, size);
14631     }
14632     tname[size] = '\0';
14633     npatt = unescpat(tname);
14634 #if defined(_WIN32) || defined(_WIN64)
14635     sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14636                           "%s as 'TABLE_SCHEM', "
14637                           "tbl_name as 'TABLE_NAME', "
14638                           "upper(type) as 'TABLE_TYPE', "
14639                           "NULL as 'REMARKS' "
14640                           "from sqlite_master where %s "
14641                           "and tbl_name %s %Q",
14642                           d->xcelqrx ? "'main'" : "NULL",
14643                           d->xcelqrx ? "''" : "NULL",
14644                           where,
14645                           npatt ? "like" : "=", tname);
14646 #else
14647     sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14648                           "NULL as 'TABLE_OWNER', "
14649                           "tbl_name as 'TABLE_NAME', "
14650                           "upper(type) as 'TABLE_TYPE', "
14651                           "NULL as 'REMARKS' "
14652                           "from sqlite_master where %s "
14653                           "and tbl_name %s %Q", where,
14654                           npatt ? "like" : "=", tname);
14655 #endif
14656     if (!sql) {
14657         return nomem(s);
14658     }
14659     ret = starttran(s);
14660     if (ret != SQL_SUCCESS) {
14661         sqlite3_free(sql);
14662         return ret;
14663     }
14664     dbtraceapi(d, "sqlite3_get_table", sql);
14665     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
14666     sqlite3_free(sql);
14667     if (rc == SQLITE_OK) {
14668         if (ncols != s->ncols) {
14669             freeresult(s, 0);
14670             s->nrows = 0;
14671         } else {
14672             s->rowfree = sqlite3_free_table;
14673         }
14674     } else {
14675         s->nrows = 0;
14676         s->rows = NULL;
14677         s->rowfree = NULL;
14678     }
14679     if (errp) {
14680         sqlite3_free(errp);
14681         errp = NULL;
14682     }
14683     s->rowp = s->rowprs = -1;
14684     return SQL_SUCCESS;
14685 }
14686 
14687 #ifndef WINTERFACE
14688 
14702 SQLRETURN SQL_API
14703 SQLTables(SQLHSTMT stmt,
14704           SQLCHAR *cat, SQLSMALLINT catLen,
14705           SQLCHAR *schema, SQLSMALLINT schemaLen,
14706           SQLCHAR *table, SQLSMALLINT tableLen,
14707           SQLCHAR *type, SQLSMALLINT typeLen)
14708 {
14709 #if defined(_WIN32) || defined(_WIN64)
14710     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14711 #endif
14712     SQLRETURN ret;
14713 
14714     HSTMT_LOCK(stmt);
14715 #if defined(_WIN32) || defined(_WIN64)
14716     if (!((STMT *) stmt)->oemcp[0]) {
14717         ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14718                         table, tableLen, type, typeLen);
14719         goto done2;
14720     }
14721     if (cat) {
14722         c = wmb_to_utf_c((char *) cat, catLen);
14723         if (!c) {
14724             ret = nomem((STMT *) stmt);
14725             goto done;
14726         }
14727     }
14728     if (schema) {
14729         s = wmb_to_utf_c((char *) schema, schemaLen);
14730         if (!s) {
14731             ret = nomem((STMT *) stmt);
14732             goto done;
14733         }
14734     }
14735     if (table) {
14736         t = wmb_to_utf_c((char *) table, tableLen);
14737         if (!t) {
14738             ret = nomem((STMT *) stmt);
14739             goto done;
14740         }
14741     }
14742     if (type) {
14743         y = wmb_to_utf_c((char *) type, typeLen);
14744         if (!y) {
14745             ret = nomem((STMT *) stmt);
14746             goto done;
14747         }
14748     }
14749     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14750                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14751 #else
14752     ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14753                     table, tableLen, type, typeLen);
14754 #endif
14755 #if defined(_WIN32) || defined(_WIN64)
14756 done:
14757     uc_free(y);
14758     uc_free(t);
14759     uc_free(s);
14760     uc_free(c);
14761 done2:
14762     ;
14763 #endif
14764     HSTMT_UNLOCK(stmt);
14765     return ret;
14766 }
14767 #endif
14768 
14769 #ifdef WINTERFACE
14770 
14784 SQLRETURN SQL_API
14785 SQLTablesW(SQLHSTMT stmt,
14786            SQLWCHAR *cat, SQLSMALLINT catLen,
14787            SQLWCHAR *schema, SQLSMALLINT schemaLen,
14788            SQLWCHAR *table, SQLSMALLINT tableLen,
14789            SQLWCHAR *type, SQLSMALLINT typeLen)
14790 {
14791     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14792     SQLRETURN ret;
14793 
14794     HSTMT_LOCK(stmt);
14795     if (cat) {
14796         c = uc_to_utf_c(cat, catLen);
14797         if (!c) {
14798             ret = nomem((STMT *) stmt);
14799             goto done;
14800         }
14801     }
14802     if (schema) {
14803         s = uc_to_utf_c(schema, schemaLen);
14804         if (!s) {
14805             ret = nomem((STMT *) stmt);
14806             goto done;
14807         }
14808     }
14809     if (table) {
14810         t = uc_to_utf_c(table, tableLen);
14811         if (!t) {
14812             ret = nomem((STMT *) stmt);
14813             goto done;
14814         }
14815     }
14816     if (type) {
14817         y = uc_to_utf_c(type, typeLen);
14818         if (!y) {
14819             ret = nomem((STMT *) stmt);
14820             goto done;
14821         }
14822     }
14823     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14824                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14825 done:
14826     uc_free(y);
14827     uc_free(t);
14828     uc_free(s);
14829     uc_free(c);
14830     HSTMT_UNLOCK(stmt);
14831     return ret;
14832 }
14833 #endif
14834 
14839 static COL colSpec2[] = {
14840     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14841     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14842     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14843     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
14844     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
14845     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
14846     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
14847     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
14848     { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
14849     { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
14850     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
14851     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
14852     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
14853     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
14854     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
14855     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
14856     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
14857     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
14858 };
14859 
14860 static COL colSpec3[] = {
14861     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14862     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14863     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14864     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
14865     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
14866     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
14867     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
14868     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
14869     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
14870     { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
14871     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
14872     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
14873     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
14874     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
14875     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
14876     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
14877     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
14878     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
14879 };
14880 
14895 static SQLRETURN
14896 drvcolumns(SQLHSTMT stmt,
14897            SQLCHAR *cat, SQLSMALLINT catLen,
14898            SQLCHAR *schema, SQLSMALLINT schemaLen,
14899            SQLCHAR *table, SQLSMALLINT tableLen,
14900            SQLCHAR *col, SQLSMALLINT colLen)
14901 {
14902     SQLRETURN sret;
14903     STMT *s;
14904     DBC *d;
14905     int ret, nrows, ncols, asize, i, k, roffs, namec;
14906     int tnrows, tncols, npatt;
14907     PTRDIFF_T size;
14908     char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
14909 
14910     sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
14911                        colSpec3, array_size(colSpec3), &asize);
14912     if (sret != SQL_SUCCESS) {
14913         return sret;
14914     }
14915     s = (STMT *) stmt;
14916     d = (DBC *) s->dbc;
14917     if (!table) {
14918         size = 1;
14919         tname[0] = '%';
14920     } else {
14921         if (tableLen == SQL_NTS) {
14922             size = sizeof (tname) - 1;
14923         } else {
14924             size = min(sizeof (tname) - 1, tableLen);
14925         }
14926         strncpy(tname, (char *) table, size);
14927     }
14928     tname[size] = '\0';
14929     npatt = unescpat(tname);
14930     size = 0;
14931     if (col) {
14932         if (colLen == SQL_NTS) {
14933             size = sizeof (cname) - 1;
14934         } else {
14935             size = min(sizeof (cname) - 1, colLen);
14936         }
14937         strncpy(cname, (char *) col, size);
14938     }
14939     cname[size] = '\0';
14940     if (!strcmp(cname, "%")) {
14941         cname[0] = '\0';
14942     }
14943     sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
14944                           "(type = 'table' or type = 'view') "
14945                           "and tbl_name %s %Q", npatt ? "like" : "=", tname);
14946     if (!sql) {
14947         return nomem(s);
14948     }
14949     sret = starttran(s);
14950     if (sret != SQL_SUCCESS) {
14951         sqlite3_free(sql);
14952         return sret;
14953     }
14954     dbtraceapi(d, "sqlite3_get_table", sql);
14955     ret = sqlite3_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
14956     sqlite3_free(sql);
14957     if (ret != SQLITE_OK) {
14958         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14959                 errp ? errp : "unknown error", ret);
14960         if (errp) {
14961             sqlite3_free(errp);
14962             errp = NULL;
14963         }
14964         return SQL_ERROR;
14965     }
14966     if (errp) {
14967         sqlite3_free(errp);
14968         errp = NULL;
14969     }
14970     /* pass 1: compute number of rows of result set */
14971     if (tncols * tnrows <= 0) {
14972         sqlite3_free_table(trows);
14973         return SQL_SUCCESS;
14974     }
14975     size = 0;
14976     for (i = 1; i <= tnrows; i++) {
14977         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
14978         if (!sql) {
14979             sqlite3_free_table(trows);
14980             return nomem(s);
14981         }
14982         dbtraceapi(d, "sqlite3_get_table", sql);
14983         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
14984         sqlite3_free(sql);
14985         if (ret != SQLITE_OK) {
14986             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14987                     errp ? errp : "unknown error", ret);
14988             if (errp) {
14989                 sqlite3_free(errp);
14990                 errp = NULL;
14991             }
14992             sqlite3_free_table(trows);
14993             return SQL_ERROR;
14994         }
14995         if (errp) {
14996             sqlite3_free(errp);
14997             errp = NULL;
14998         }
14999         if (ncols * nrows > 0) {
15000             namec = -1;
15001             for (k = 0; k < ncols; k++) {
15002                 if (strcmp(rowp[k], "name") == 0) {
15003                     namec = k;
15004                     break;
15005                 }
15006             }
15007             if (cname[0]) {
15008                 if (namec >= 0) {
15009                     for (k = 1; k <= nrows; k++) {
15010                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15011                             size++;
15012                         }
15013                     }
15014                 }
15015             } else {
15016                 size += nrows;
15017             }
15018         }
15019         sqlite3_free_table(rowp);
15020     }
15021     /* pass 2: fill result set */
15022     if (size <= 0) {
15023         sqlite3_free_table(trows);
15024         return SQL_SUCCESS;
15025     }
15026     s->nrows = size;
15027     size = (size + 1) * asize;
15028     s->rows = xmalloc((size + 1) * sizeof (char *));
15029     if (!s->rows) {
15030         s->nrows = 0;
15031         sqlite3_free_table(trows);
15032         return nomem(s);
15033     }
15034     s->rows[0] = (char *) size;
15035     s->rows += 1;
15036     memset(s->rows, 0, sizeof (char *) * size);
15037     s->rowfree = freerows;
15038     roffs = 1;
15039     for (i = 1; i <= tnrows; i++) {
15040         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15041         if (!sql) {
15042             sqlite3_free_table(trows);
15043             return nomem(s);
15044         }
15045         dbtraceapi(d, "sqlite3_get_table", sql);
15046         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15047         sqlite3_free(sql);
15048         if (ret != SQLITE_OK) {
15049             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15050                     errp ? errp : "unknown error", ret);
15051             if (errp) {
15052                 sqlite3_free(errp);
15053                 errp = NULL;
15054             }
15055             sqlite3_free_table(trows);
15056             return SQL_ERROR;
15057         }
15058         if (errp) {
15059             sqlite3_free(errp);
15060             errp = NULL;
15061         }
15062         if (ncols * nrows > 0) {
15063             int m, mr, nr = nrows;
15064 
15065             namec = -1;
15066             for (k = 0; k < ncols; k++) {
15067                 if (strcmp(rowp[k], "name") == 0) {
15068                     namec = k;
15069                     break;
15070                 }
15071             }
15072             if (cname[0]) {
15073                 nr = 0;
15074                 if (namec >= 0) {
15075                     for (k = 1; k <= nrows; k++) {
15076                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15077                             nr++;
15078                         }
15079                     }
15080                 }
15081             }
15082             for (k = 0; k < nr; k++) {
15083                 m = asize * (roffs + k);
15084 #if defined(_WIN32) || defined(_WIN64)
15085                 s->rows[m + 0] = xstrdup(d->xcelqrx ? "main" : "");
15086                 s->rows[m + 1] = xstrdup("");
15087 #else
15088                 s->rows[m + 0] = xstrdup("");
15089                 s->rows[m + 1] = xstrdup("");
15090 #endif
15091                 s->rows[m + 2] = xstrdup(trows[i]);
15092                 s->rows[m + 8] = xstrdup("10");
15093                 s->rows[m + 9] = xstrdup("0");
15094                 s->rows[m + 15] = xstrdup("16384");
15095             }
15096             for (k = 0; nr && k < ncols; k++) {
15097                 if (strcmp(rowp[k], "cid") == 0) {
15098                     for (mr = 0, m = 1; m <= nrows; m++) {
15099                         char buf[256];
15100                         int ir, coln = k;
15101 
15102                         if (cname[0] &&
15103                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15104                             continue;
15105                         }
15106                         ir = asize * (roffs + mr);
15107                         sscanf(rowp[m * ncols + k], "%d", &coln);
15108                         sprintf(buf, "%d", coln + 1);
15109                         s->rows[ir + 16] = xstrdup(buf);
15110                         ++mr;
15111                     }
15112                 } else if (k == namec) {
15113                     for (mr = 0, m = 1; m <= nrows; m++) {
15114                         int ir;
15115 
15116                         if (cname[0] &&
15117                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15118                             continue;
15119                         }
15120                         ir = asize * (roffs + mr);
15121                         s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
15122                         ++mr;
15123                     }
15124                 } else if (strcmp(rowp[k], "notnull") == 0) {
15125                     for (mr = 0, m = 1; m <= nrows; m++) {
15126                         int ir;
15127 
15128                         if (cname[0] &&
15129                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15130                             continue;
15131                         }
15132                         ir = asize * (roffs + mr);
15133                         if (*rowp[m * ncols + k] != '0') {
15134                             s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
15135                         } else {
15136                             s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
15137                         }
15138                         s->rows[ir + 17] =
15139                             xstrdup((*rowp[m * ncols + k] != '0') ?
15140                                     "NO" : "YES");
15141                         ++mr;
15142                     }
15143                 } else if (strcmp(rowp[k], "dflt_value") == 0) {
15144                     for (mr = 0, m = 1; m <= nrows; m++) {
15145                         char *dflt = unquote(rowp[m * ncols + k]);
15146                         int ir;
15147 
15148                         if (cname[0] &&
15149                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15150                             continue;
15151                         }
15152                         ir = asize * (roffs + mr);
15153                         s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
15154                         ++mr;
15155                     }
15156                 } else if (strcmp(rowp[k], "type") == 0) {
15157                     for (mr = 0, m = 1; m <= nrows; m++) {
15158                         char *typename = rowp[m * ncols + k];
15159                         int sqltype, mm, dd, ir;
15160                         char buf[256];
15161 
15162                         if (cname[0] &&
15163                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15164                             continue;
15165                         }
15166                         ir = asize * (roffs + mr);
15167                         s->rows[ir + 5] = xstrdup(typename);
15168                         sqltype = mapsqltype(typename, NULL, *s->ov3,
15169                                              s->nowchar[0], s->dobigint);
15170                         getmd(typename, sqltype, &mm, &dd);
15171 #ifdef SQL_LONGVARCHAR
15172                         if (sqltype == SQL_VARCHAR && mm > 255) {
15173                             sqltype = SQL_LONGVARCHAR;
15174                         }
15175 #endif
15176 #ifdef WINTERFACE
15177 #ifdef SQL_WLONGVARCHAR
15178                         if (sqltype == SQL_WVARCHAR && mm > 255) {
15179                             sqltype = SQL_WLONGVARCHAR;
15180                         }
15181 #endif
15182 #endif
15183                         if (sqltype == SQL_VARBINARY && mm > 255) {
15184                             sqltype = SQL_LONGVARBINARY;
15185                         }
15186                         sprintf(buf, "%d", sqltype);
15187                         s->rows[ir + 4] = xstrdup(buf);
15188                         s->rows[ir + 13] = xstrdup(buf);
15189                         sprintf(buf, "%d", mm);
15190                         s->rows[ir + 7] = xstrdup(buf);
15191                         sprintf(buf, "%d", dd);
15192                         s->rows[ir + 6] = xstrdup(buf);
15193                         ++mr;
15194                     }
15195                 }
15196             }
15197             roffs += nr;
15198         }
15199         sqlite3_free_table(rowp);
15200     }
15201     sqlite3_free_table(trows);
15202     return SQL_SUCCESS;
15203 }
15204 
15205 #ifndef WINTERFACE
15206 
15220 SQLRETURN SQL_API
15221 SQLColumns(SQLHSTMT stmt,
15222            SQLCHAR *cat, SQLSMALLINT catLen,
15223            SQLCHAR *schema, SQLSMALLINT schemaLen,
15224            SQLCHAR *table, SQLSMALLINT tableLen,
15225            SQLCHAR *col, SQLSMALLINT colLen)
15226 {
15227 #if defined(_WIN32) || defined(_WIN64)
15228     char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15229 #endif
15230     SQLRETURN ret;
15231 
15232     HSTMT_LOCK(stmt);
15233 #if defined(_WIN32) || defined(_WIN64)
15234     if (!((STMT *) stmt)->oemcp[0]) {
15235         ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15236                          table, tableLen, col, colLen);
15237         goto done2;
15238     }
15239     if (cat) {
15240         c = wmb_to_utf_c((char *) cat, catLen);
15241         if (!c) {
15242             ret = nomem((STMT *) stmt);
15243             goto done;
15244         }
15245     }
15246     if (schema) {
15247         s = wmb_to_utf_c((char *) schema, schemaLen);
15248         if (!s) {
15249             ret = nomem((STMT *) stmt);
15250             goto done;
15251         }
15252     }
15253     if (table) {
15254         t = wmb_to_utf_c((char *) table, tableLen);
15255         if (!t) {
15256             ret = nomem((STMT *) stmt);
15257             goto done;
15258         }
15259     }
15260     if (col) {
15261         k = wmb_to_utf_c((char *) col, colLen);
15262         if (!k) {
15263             ret = nomem((STMT *) stmt);
15264             goto done;
15265         }
15266     }
15267     ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15268                      (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
15269 #else
15270     ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15271                      table, tableLen, col, colLen);
15272 #endif
15273 #if defined(_WIN32) || defined(_WIN64)
15274 done:
15275     uc_free(k);
15276     uc_free(t);
15277     uc_free(s);
15278     uc_free(c);
15279 done2:
15280     ;
15281 #endif
15282     HSTMT_UNLOCK(stmt);
15283     return ret;
15284 }
15285 #endif
15286 
15287 #ifdef WINTERFACE
15288 
15302 SQLRETURN