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 if (c < 0xfc) {
00914                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00915                     (str[3] & 0xc0) == 0x80 && (str[4] & 0xc0) == 0x80) {
00916                     unsigned long t = ((c & 0x01) << 24) |
00917                         ((str[1] & 0x3f) << 18) | ((str[2] & 0x3f) << 12) |
00918                         ((str[3] & 0x3f) << 6) | (str[4] & 0x3f);
00919 
00920                     if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00921                         t >= 0x10000) {
00922                         t -= 0x10000;
00923                         uc[i++] = 0xd800 | ((t >> 10) & 0x3ff);
00924                         if (i >= ucLen) {
00925                             break;
00926                         }
00927                         t = 0xdc00 | (t & 0x3ff);
00928                     }
00929                     uc[i++] = t;
00930                     str += 5;
00931                 } else {
00932                     uc[i++] = c;
00933                     ++str;
00934                 }
00935             } else {
00936                 /* ignore */
00937                 ++str;
00938             }
00939         }
00940         if (i < ucLen) {
00941             uc[i] = 0;
00942         }
00943     }
00944 }
00945 
00953 static SQLWCHAR *
00954 uc_from_utf(unsigned char *str, int len)
00955 {
00956     SQLWCHAR *uc = NULL;
00957     int ucLen;
00958 
00959     if (str) {
00960         if (len == SQL_NTS) {
00961             len = strlen((char *) str);
00962         }
00963         ucLen = sizeof (SQLWCHAR) * (len + 1);
00964         uc = xmalloc(ucLen);
00965         if (uc) {
00966             uc_from_utf_buf(str, len, uc, ucLen);
00967         }
00968     }
00969     return uc;
00970 }
00971 
00979 static char *
00980 uc_to_utf(SQLWCHAR *str, int len)
00981 {
00982     int i;
00983     char *cp, *ret = NULL;
00984 
00985     if (!str) {
00986         return ret;
00987     }
00988     if (len == SQL_NTS) {
00989         len = uc_strlen(str);
00990     } else {
00991         len = len / sizeof (SQLWCHAR);
00992     }
00993     cp = xmalloc(len * 6 + 1);
00994     if (!cp) {
00995         return ret;
00996     }
00997     ret = cp;
00998     for (i = 0; i < len; i++) {
00999         unsigned long c = str[i];
01000 
01001         if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
01002             c &= 0xffff;
01003         }
01004         if (c < 0x80) {
01005             *cp++ = c;
01006         } else if (c < 0x800) {
01007             *cp++ = 0xc0 | ((c >> 6) & 0x1f);
01008             *cp++ = 0x80 | (c & 0x3f);
01009         } else if (c < 0x10000) {
01010             if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
01011                 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
01012                 unsigned long c2 = str[i + 1] & 0xffff;
01013 
01014                 if (c2 >= 0xdc00 && c2 <= 0xdfff) {
01015                     c = (((c & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
01016                     *cp++ = 0xf0 | ((c >> 18) & 0x07);
01017                     *cp++ = 0x80 | ((c >> 12) & 0x3f);
01018                     *cp++ = 0x80 | ((c >> 6) & 0x3f);
01019                     *cp++ = 0x80 | (c & 0x3f);
01020                     ++i;
01021                     continue;
01022                 }
01023             }
01024             *cp++ = 0xe0 | ((c >> 12) & 0x0f);
01025             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01026             *cp++ = 0x80 | (c & 0x3f);
01027         } else if (c < 0x200000) {
01028             *cp++ = 0xf0 | ((c >> 18) & 0x07);
01029             *cp++ = 0x80 | ((c >> 12) & 0x3f);
01030             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01031             *cp++ = 0x80 | (c & 0x3f);
01032         } else if (c < 0x4000000) {
01033             *cp++ = 0xf8 | ((c >> 24) & 0x03);
01034             *cp++ = 0x80 | ((c >> 18) & 0x3f);
01035             *cp++ = 0x80 | ((c >> 12) & 0x3f);
01036             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01037             *cp++ = 0x80 | (c & 0x3f);
01038         } else if (c < 0x80000000) {
01039             *cp++ = 0xfc | ((c >> 31) & 0x01);
01040             *cp++ = 0x80 | ((c >> 24) & 0x3f);
01041             *cp++ = 0x80 | ((c >> 18) & 0x3f);
01042             *cp++ = 0x80 | ((c >> 12) & 0x3f);
01043             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01044             *cp++ = 0x80 | (c & 0x3f);
01045         }
01046     }
01047     *cp = '\0';
01048     return ret;
01049 }
01050 
01051 #endif
01052 
01053 #ifdef WINTERFACE
01054 
01062 static char *
01063 uc_to_utf_c(SQLWCHAR *str, int len)
01064 {
01065     if (len != SQL_NTS) {
01066         len = len * sizeof (SQLWCHAR);
01067     }
01068     return uc_to_utf(str, len);
01069 }
01070 
01071 #endif
01072 
01073 #if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
01074 
01080 static void
01081 uc_free(void *str)
01082 {
01083     if (str) {
01084         xfree(str);
01085     }
01086 }
01087 
01088 #endif
01089 
01090 #if defined(_WIN32) || defined(_WIN64)
01091 
01099 static char *
01100 wmb_to_utf(char *str, int len)
01101 {
01102     WCHAR *wstr;
01103     OSVERSIONINFO ovi;
01104     int nchar, is2k, cp = CP_OEMCP;
01105 
01106     ovi.dwOSVersionInfoSize = sizeof (ovi);
01107     GetVersionEx(&ovi);
01108     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01109     if (AreFileApisANSI()) {
01110         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01111     }
01112     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01113     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01114     if (!wstr) {
01115         return NULL;
01116     }
01117     wstr[0] = 0;
01118     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01119     wstr[nchar] = 0;
01120     str = xmalloc((nchar + 1) * 7);
01121     if (!str) {
01122         xfree(wstr);
01123         return NULL;
01124     }
01125     str[0] = '\0';
01126     nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
01127     str[nchar] = '\0';
01128     xfree(wstr);
01129     return str;
01130 }
01131 
01132 #ifndef WINTERFACE
01133 
01141 static char *
01142 wmb_to_utf_c(char *str, int len)
01143 {
01144     if (len == SQL_NTS) {
01145         len = strlen(str);
01146     }
01147     return wmb_to_utf(str, len);
01148 }
01149 
01150 #endif
01151 
01159 static char *
01160 utf_to_wmb(char *str, int len)
01161 {
01162     WCHAR *wstr;
01163     OSVERSIONINFO ovi;
01164     int nchar, is2k, cp = CP_OEMCP;
01165 
01166     ovi.dwOSVersionInfoSize = sizeof (ovi);
01167     GetVersionEx(&ovi);
01168     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01169     if (AreFileApisANSI()) {
01170         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01171     }
01172     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
01173     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01174     if (!wstr) {
01175         return NULL;
01176     }
01177     wstr[0] = 0;
01178     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
01179     wstr[nchar] = 0;
01180     str = xmalloc((nchar + 1) * 7);
01181     if (!str) {
01182         xfree(wstr);
01183         return NULL;
01184     }
01185     str[0] = '\0';
01186     nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
01187     str[nchar] = '\0';
01188     xfree(wstr);
01189     return str;
01190 }
01191 
01192 #ifdef WINTERFACE
01193 
01201 static WCHAR *
01202 wmb_to_uc(char *str, int len)
01203 {
01204     WCHAR *wstr;
01205     OSVERSIONINFO ovi;
01206     int nchar, is2k, cp = CP_OEMCP;
01207 
01208     ovi.dwOSVersionInfoSize = sizeof (ovi);
01209     GetVersionEx(&ovi);
01210     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01211     if (AreFileApisANSI()) {
01212         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01213     }
01214     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01215     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01216     if (!wstr) {
01217         return NULL;
01218     }
01219     wstr[0] = 0;
01220     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01221     wstr[nchar] = 0;
01222     return wstr;
01223 }
01224 
01232 static char *
01233 uc_to_wmb(WCHAR *wstr, int len)
01234 {
01235     char *str;
01236     OSVERSIONINFO ovi;
01237     int nchar, is2k, cp = CP_OEMCP;
01238 
01239     ovi.dwOSVersionInfoSize = sizeof (ovi);
01240     GetVersionEx(&ovi);
01241     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01242     if (AreFileApisANSI()) {
01243         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01244     }
01245     nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
01246     str = xmalloc((nchar + 1) * 2);
01247     if (!str) {
01248         return NULL;
01249     }
01250     str[0] = '\0';
01251     nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
01252     str[nchar] = '\0';
01253     return str;
01254 }
01255 
01256 #endif /* WINTERFACE */
01257 
01258 #endif /* _WIN32 || _WIN64 */
01259 
01260 
01261 #ifdef USE_DLOPEN_FOR_GPPS
01262 
01263 #include <dlfcn.h>
01264 
01265 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
01266 
01267 /*
01268  * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
01269  * dlopen(), in theory this makes the driver independent from the
01270  * driver manager, i.e. the same driver binary can run with iODBC
01271  * and unixODBC.
01272  */
01273 
01274 static void
01275 drvgetgpps(DBC *d)
01276 {
01277     void *lib;
01278     int (*gpps)();
01279 
01280     lib = dlopen("libodbcinst.so.2", RTLD_LAZY);
01281     if (!lib) {
01282         lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
01283     }
01284     if (!lib) {
01285         lib = dlopen("libodbcinst.so", RTLD_LAZY);
01286     }
01287     if (!lib) {
01288         lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
01289     }
01290     if (!lib) {
01291         lib = dlopen("libiodbcinst.so", RTLD_LAZY);
01292     }
01293     if (lib) {
01294         gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
01295         if (!gpps) {
01296             dlclose(lib);
01297             return;
01298         }
01299         d->instlib = lib;
01300         d->gpps = gpps;
01301     }
01302 }
01303 
01304 static void
01305 drvrelgpps(DBC *d)
01306 {
01307     if (d->instlib) {
01308         dlclose(d->instlib);
01309         d->instlib = 0;
01310     }
01311 }
01312 
01313 static int
01314 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
01315         int bufsiz, char *fname)
01316 {
01317     if (d->gpps) {
01318         return d->gpps(sect, ent, def, buf, bufsiz, fname);
01319     }
01320     strncpy(buf, def, bufsiz);
01321     buf[bufsiz - 1] = '\0';
01322     return 1;
01323 }
01324 #else
01325 #include <odbcinst.h>
01326 #define drvgetgpps(d)
01327 #define drvrelgpps(d)
01328 #endif
01329 
01330 /*
01331  * Internal function to bind SQLite3 parameters.
01332  */
01333 
01334 static void
01335 s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
01336 {
01337     int i;
01338 
01339     if (stmt && p && nparams > 0) {
01340         for (i = 0; i < nparams; i++, p++) {
01341             switch (p->s3type) {
01342             default:
01343             case SQLITE_NULL:
01344                 sqlite3_bind_null(stmt, i + 1);
01345                 if (d->trace) {
01346                     fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
01347                     fflush(d->trace);
01348                 }
01349                 break;
01350             case SQLITE_TEXT:
01351                 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
01352                                   SQLITE_STATIC);
01353                 if (d->trace) {
01354                     fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
01355                             p->s3size, (char *) p->s3val);
01356                     fflush(d->trace);
01357                 }
01358                 break;
01359             case SQLITE_BLOB:
01360                 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
01361                                   SQLITE_STATIC);
01362                 if (d->trace) {
01363                     fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
01364                     fflush(d->trace);
01365                 }
01366                 break;
01367             case SQLITE_FLOAT:
01368                 sqlite3_bind_double(stmt, i + 1, p->s3dval);
01369                 if (d->trace) {
01370                     fprintf(d->trace, "-- parameter %d: %g\n",
01371                             i + 1, p->s3dval);
01372                     fflush(d->trace);
01373                 }
01374                 break;
01375             case SQLITE_INTEGER:
01376                 if (p->s3size > sizeof (int)) {
01377                     sqlite3_bind_int64(stmt, i + 1, p->s3lival);
01378                     if (d->trace) {
01379                         fprintf(d->trace,
01380 #ifdef _WIN32
01381                                 "-- parameter %d: %I64d\n",
01382 #else
01383                                 "-- parameter %d: %lld\n",
01384 #endif
01385                                 i + 1, p->s3lival);
01386                         fflush(d->trace);
01387                     }
01388                 } else {
01389                     sqlite3_bind_int(stmt, i + 1, p->s3ival);
01390                     if (d->trace) {
01391                         fprintf(d->trace, "-- parameter %d: %d\n",
01392                                 i + 1, p->s3ival);
01393                         fflush(d->trace);
01394                     }
01395                 }
01396                 break;
01397             }
01398         }
01399     }
01400 }
01401 
01409 typedef struct tblres {
01410     char **resarr;      
01411     char *errmsg;       
01412     sqlite3_stmt *stmt; 
01413     STMT *s;            
01414     int nalloc;         
01415     int nrow;           
01416     int ncol;           
01417     PTRDIFF_T ndata;    
01418     int rc;             
01419 } TBLRES;
01420 
01421 /*
01422  * Driver's version of sqlite3_get_table() and friends which are
01423  * capable of dealing with blobs.
01424  */
01425 
01426 static int
01427 drvgettable_row(TBLRES *t, int ncol, int rc)
01428 {
01429     int need;
01430     int i;
01431     char *p;
01432 
01433     if (t->nrow == 0 && rc == SQLITE_ROW) {
01434         need = ncol * 2;
01435     } else {
01436         need = ncol;
01437     }
01438     if (t->ndata + need >= t->nalloc) {
01439         char **resnew;
01440         int nalloc = t->nalloc * 2 + need + 1;
01441 
01442         resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
01443         if (!resnew) {
01444 nomem:
01445             t->rc = SQLITE_NOMEM;
01446             return 1;
01447         }
01448         t->nalloc = nalloc;
01449         t->resarr = resnew;
01450     }
01451     /* column names when first row */
01452     if (t->nrow == 0) {
01453         t->ncol = ncol;
01454         for (i = 0; i < ncol; i++) {
01455             p = (char *) sqlite3_column_name(t->stmt, i);
01456             if (p) {
01457                 char *q = xmalloc(strlen(p) + 1);
01458 
01459                 if (!q) {
01460                     goto nomem;
01461                 }
01462                 strcpy(q, p);
01463                 p = q;
01464             }
01465             t->resarr[t->ndata++] = p;
01466         }
01467         if (t->s && t->s->guessed_types) {
01468             int ncol2 = ncol;
01469 
01470             setupdyncols(t->s, t->stmt, &ncol2);
01471             t->s->guessed_types = 0;
01472             t->s->ncols = ncol;
01473         }
01474     } else if (t->ncol != ncol) {
01475         t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
01476                                     " more incompatible queries");
01477         t->rc = SQLITE_ERROR;
01478         return 1;
01479     }
01480     /* copy row data */
01481     if (rc == SQLITE_ROW) {
01482         for (i = 0; i < ncol; i++) {
01483             int coltype = sqlite3_column_type(t->stmt, i);
01484 
01485             p = NULL;
01486             if (coltype == SQLITE_BLOB) {
01487                 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
01488                 char *qp;
01489                 unsigned const char *bp;
01490 
01491                 bp = sqlite3_column_blob(t->stmt, i);
01492                 qp = xmalloc(nbytes * 2 + 4);
01493                 if (!qp) {
01494                     goto nomem;
01495                 }
01496                 p = qp;
01497                 *qp++ = 'X';
01498                 *qp++ = '\'';
01499                 for (k = 0; k < nbytes; k++) {
01500                     *qp++ = xdigits[(bp[k] >> 4)];
01501                     *qp++ = xdigits[(bp[k] & 0xF)];
01502                 }
01503                 *qp++ = '\'';
01504                 *qp = '\0';
01505 #ifdef _MSC_VER
01506             } else if (coltype == SQLITE_FLOAT) {
01507                 struct lconv *lc = 0;
01508                 double val = sqlite3_column_double(t->stmt, i);
01509                 char buffer[128];
01510 
01511                 /*
01512                  * This avoids floating point rounding
01513                  * and formatting problems of some SQLite
01514                  * versions in conjunction with MSVC 2010.
01515                  */
01516                 snprintf(buffer, sizeof (buffer), "%.15g", val);
01517                 lc = localeconv();
01518                 if (lc && lc->decimal_point && lc->decimal_point[0] &&
01519                     lc->decimal_point[0] != '.') {
01520                     p = strchr(buffer, lc->decimal_point[0]);
01521                     if (p) {
01522                         *p = '.';
01523                     }
01524                 }
01525                 p = xstrdup(buffer);
01526                 if (!p) {
01527                     goto nomem;
01528                 }
01529 #endif
01530             } else if (coltype != SQLITE_NULL) {
01531                 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
01532                 if (!p) {
01533                     goto nomem;
01534                 }
01535             }
01536             t->resarr[t->ndata++] = p;
01537         }
01538         t->nrow++;
01539     }
01540     return 0;
01541 }
01542 
01543 static int
01544 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
01545             int *ncolp, char **errp, int nparam, BINDPARM *p)
01546 {
01547     DBC *d = (DBC *) s->dbc;
01548     int rc = SQLITE_OK, keep = sql == NULL;
01549     TBLRES tres;
01550     const char *sqlleft = 0;
01551     int nretry = 0, haveerr = 0;
01552 
01553     if (!resp) {
01554         return SQLITE_ERROR;
01555     }
01556     *resp = NULL;
01557     if (nrowp) {
01558         *nrowp = 0;
01559     }
01560     if (ncolp) {
01561         *ncolp = 0;
01562     }
01563     tres.errmsg = NULL;
01564     tres.nrow = 0;
01565     tres.ncol = 0;
01566     tres.ndata = 1;
01567     tres.nalloc = 20;
01568     tres.rc = SQLITE_OK;
01569     tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
01570     tres.stmt = NULL;
01571     tres.s = s;
01572     if (!tres.resarr) {
01573         return SQLITE_NOMEM;
01574     }
01575     tres.resarr[0] = 0;
01576     if (sql == NULL) {
01577         tres.stmt = s->s3stmt;
01578         if (tres.stmt == NULL) {
01579             return SQLITE_NOMEM;
01580         }
01581         goto retrieve;
01582     }
01583     while (sql && *sql && (rc == SQLITE_OK ||
01584                            (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
01585         int ncol;
01586 
01587         tres.stmt = NULL;
01588 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
01589         dbtraceapi(d, "sqlite3_prepare_v2", sql);
01590         rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01591 #else
01592         dbtraceapi(d, "sqlite3_prepare", sql);
01593         rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01594 #endif
01595         if (rc != SQLITE_OK) {
01596             if (tres.stmt) {
01597                 dbtraceapi(d, "sqlite3_finalize", 0);
01598                 sqlite3_finalize(tres.stmt);
01599                 tres.stmt = NULL;
01600             }
01601             continue;
01602         }
01603         if (!tres.stmt) {
01604             /* this happens for a comment or white-space */
01605             sql = sqlleft;
01606             continue;
01607         }
01608 retrieve:
01609         if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
01610             if (errp) {
01611                 *errp =
01612                     sqlite3_mprintf("%s", "parameter marker count incorrect");
01613             }
01614             haveerr = 1;
01615             rc = SQLITE_ERROR;
01616             goto tbldone;
01617         }
01618         s3bind(d, tres.stmt, nparam, p);
01619         ncol = sqlite3_column_count(tres.stmt);
01620         while (1) {
01621             if (s->max_rows && tres.nrow >= s->max_rows) {
01622                 rc = SQLITE_OK;
01623                 break;
01624             }
01625             rc = sqlite3_step(tres.stmt);
01626             if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
01627                 if (drvgettable_row(&tres, ncol, rc)) {
01628                     rc = SQLITE_ABORT;
01629                     goto tbldone;
01630                 }
01631             }
01632             if (rc != SQLITE_ROW) {
01633                 if (keep) {
01634                     dbtraceapi(d, "sqlite3_reset", 0);
01635                     rc = sqlite3_reset(tres.stmt);
01636                     s->s3stmt_noreset = 1;
01637                 } else {
01638                     dbtraceapi(d, "sqlite3_finalize", 0);
01639                     rc = sqlite3_finalize(tres.stmt);
01640                 }
01641                 tres.stmt = 0;
01642                 if (rc != SQLITE_SCHEMA) {
01643                     nretry = 0;
01644                     sql = sqlleft;
01645                     while (sql && ISSPACE(*sql)) {
01646                         sql++;
01647                     }
01648                 }
01649                 if (rc == SQLITE_DONE) {
01650                     rc = SQLITE_OK;
01651                 }
01652                 break;
01653             }
01654         }
01655     }
01656 tbldone:
01657     if (tres.stmt) {
01658         if (keep) {
01659             if (!s->s3stmt_noreset) {
01660                 dbtraceapi(d, "sqlite3_reset", 0);
01661                 sqlite3_reset(tres.stmt);
01662                 s->s3stmt_noreset = 1;
01663             }
01664         } else {
01665             dbtraceapi(d, "sqlite3_finalize", 0);
01666             sqlite3_finalize(tres.stmt);
01667         }
01668     }
01669     if (haveerr) {
01670         /* message already in *errp if any */
01671     } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
01672         *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
01673     } else if (errp) {
01674         *errp = NULL;
01675     }
01676     if (tres.resarr) {
01677         tres.resarr[0] = (char *) (tres.ndata - 1);
01678     }
01679     if (rc == SQLITE_ABORT) {
01680         freerows(&tres.resarr[1]);
01681         if (tres.errmsg) {
01682             if (errp) {
01683                 if (*errp) {
01684                     sqlite3_free(*errp);
01685                 }
01686                 *errp = tres.errmsg;
01687             } else {
01688                 sqlite3_free(tres.errmsg);
01689             }
01690         }
01691         return tres.rc;
01692     }
01693     sqlite3_free(tres.errmsg);
01694     if (rc != SQLITE_OK) {
01695         freerows(&tres.resarr[1]);
01696         return rc;
01697     }
01698     *resp = &tres.resarr[1];
01699     if (ncolp) {
01700         *ncolp = tres.ncol;
01701     }
01702     if (nrowp) {
01703         *nrowp = tres.nrow;
01704     }
01705     return rc;
01706 }
01707 
01716 #if defined(__GNUC__) && (__GNUC__ >= 2)
01717 static void setstatd(DBC *, int, char *, char *, ...)
01718     __attribute__((format (printf, 3, 5)));
01719 #endif
01720 
01721 static void
01722 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
01723 {
01724     va_list ap;
01725 
01726     if (!d) {
01727         return;
01728     }
01729     d->naterr = naterr;
01730     d->logmsg[0] = '\0';
01731     if (msg) {
01732         int count;
01733 
01734         va_start(ap, st);
01735         count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
01736         va_end(ap);
01737         if (count < 0) {
01738             d->logmsg[sizeof (d->logmsg) - 1] = '\0';
01739         }
01740     }
01741     if (!st) {
01742         st = "?????";
01743     }
01744     strncpy(d->sqlstate, st, 5);
01745     d->sqlstate[5] = '\0';
01746 }
01747 
01756 #if defined(__GNUC__) && (__GNUC__ >= 2)
01757 static void setstat(STMT *, int, char *, char *, ...)
01758     __attribute__((format (printf, 3, 5)));
01759 #endif
01760 
01761 static void
01762 setstat(STMT *s, int naterr, char *msg, char *st, ...)
01763 {
01764     va_list ap;
01765 
01766     if (!s) {
01767         return;
01768     }
01769     s->naterr = naterr;
01770     s->logmsg[0] = '\0';
01771     if (msg) {
01772         int count;
01773 
01774         va_start(ap, st);
01775         count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
01776         va_end(ap);
01777         if (count < 0) {
01778             s->logmsg[sizeof (s->logmsg) - 1] = '\0';
01779         }
01780     }
01781     if (!st) {
01782         st = "?????";
01783     }
01784     strncpy(s->sqlstate, st, 5);
01785     s->sqlstate[5] = '\0';
01786 }
01787 
01794 static SQLRETURN
01795 drvunimpldbc(HDBC dbc)
01796 {
01797     DBC *d;
01798 
01799     if (dbc == SQL_NULL_HDBC) {
01800         return SQL_INVALID_HANDLE;
01801     }
01802     d = (DBC *) dbc;
01803     setstatd(d, -1, "not supported", "IM001");
01804     return SQL_ERROR;
01805 }
01806 
01813 static SQLRETURN
01814 drvunimplstmt(HSTMT stmt)
01815 {
01816     STMT *s;
01817 
01818     if (stmt == SQL_NULL_HSTMT) {
01819         return SQL_INVALID_HANDLE;
01820     }
01821     s = (STMT *) stmt;
01822     setstat(s, -1, "not supported", "IM001");
01823     return SQL_ERROR;
01824 }
01825 
01831 static void
01832 freep(void *x)
01833 {
01834     if (x && ((char **) x)[0]) {
01835         xfree(((char **) x)[0]);
01836         ((char **) x)[0] = NULL;
01837     }
01838 }
01839 
01846 static SQLRETURN
01847 nomem(STMT *s)
01848 {
01849     setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
01850     return SQL_ERROR;
01851 }
01852 
01859 static SQLRETURN
01860 noconn(STMT *s)
01861 {
01862     setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
01863     return SQL_ERROR;
01864 }
01865 
01873 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
01874 
01875 static double
01876 ln_strtod(const char *data, char **endp)
01877 {
01878     struct lconv *lc = 0;
01879     char buf[128], *p, *end;
01880     double value;
01881 
01882     lc = localeconv();
01883     if (lc && lc->decimal_point && lc->decimal_point[0] &&
01884         lc->decimal_point[0] != '.') {
01885         strncpy(buf, data, sizeof (buf) - 1);
01886         buf[sizeof (buf) - 1] = '\0';
01887         p = strchr(buf, '.');
01888         if (p) {
01889             *p = lc->decimal_point[0];
01890         }
01891         p = buf;
01892     } else {
01893         p = (char *) data;
01894     }
01895     value = strtod(p, &end);
01896     end = (char *) data + (end - p);
01897     if (endp) {
01898         *endp = end;
01899     }
01900     return value;
01901 }
01902 
01903 #else
01904 
01905 #define ln_strtod(A,B) strtod(A,B)
01906 
01907 #endif
01908 
01914 static char *
01915 unquote(char *str)
01916 {
01917     if (str) {
01918         int len = strlen(str);
01919 
01920         if (len > 1) {
01921             int end = len - 1;
01922 
01923             if ((str[0] == '\'' && str[end] == '\'') ||
01924                 (str[0] == '"' && str[end] == '"') ||
01925                 (str[0] == '[' && str[end] == ']')) {
01926                 memmove(str, str + 1, end - 1);
01927                 str[end - 1] = '\0';
01928             }
01929         }
01930     }
01931     return str;
01932 }
01933 
01941 static int
01942 unescpat(char *str)
01943 {
01944     char *p, *q;
01945     int count = 0;
01946 
01947     p = str;
01948     while ((q = strchr(p, '_')) != NULL) {
01949         if (q == str || q[-1] != '\\') {
01950             count++;
01951         }
01952         p = q + 1;
01953     }
01954     p = str;
01955     while ((q = strchr(p, '%')) != NULL) {
01956         if (q == str || q[-1] != '\\') {
01957             count++;
01958         }
01959         p = q + 1;
01960     }
01961     p = str;
01962     while ((q = strchr(p, '\\')) != NULL) {
01963         if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
01964             memmove(q, q + 1, strlen(q));
01965         }
01966         p = q + 1;
01967     }
01968     return count;
01969 }
01970 
01979 static int
01980 namematch(char *str, char *pat, int esc)
01981 {
01982     int cp, ch;
01983 
01984     while (1) {
01985         cp = TOLOWER(*pat);
01986         if (cp == '\0') {
01987             if (*str != '\0') {
01988                 goto nomatch;
01989             }
01990             break;
01991         }
01992         if (*str == '\0' && cp != '%') {
01993             goto nomatch;
01994         }
01995         if (cp == '%') {
01996             while (*pat == '%') {
01997                 ++pat;
01998             }
01999             cp = TOLOWER(*pat);
02000             if (cp == '\0') {
02001                 break;
02002             }
02003             while (1) {
02004                 if (cp != '_' && cp != '\\') {
02005                     while (*str) {
02006                         ch = TOLOWER(*str);
02007                         if (ch == cp) {
02008                             break;
02009                         }
02010                         ++str;
02011                     }
02012                 }
02013                 if (namematch(str, pat, esc)) {
02014                     goto match;
02015                 }
02016                 if (*str == '\0') {
02017                     goto nomatch;
02018                 }
02019                 ch = TOLOWER(*str);
02020                 ++str;
02021             }
02022         }
02023         if (cp == '_') {
02024             pat++;
02025             str++;
02026             continue;
02027         }
02028         if (esc && cp == '\\' &&
02029             (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
02030             ++pat;
02031             cp = TOLOWER(*pat);
02032         }
02033         ch = TOLOWER(*str++);
02034         ++pat;
02035         if (ch != cp) {
02036             goto nomatch;
02037         }
02038     }
02039 match:
02040     return 1;
02041 nomatch:
02042     return 0;
02043 }
02044 
02052 static int
02053 busy_handler(void *udata, int count)
02054 {
02055     DBC *d = (DBC *) udata;
02056     long t1;
02057     int ret = 0;
02058 #if !defined(_WIN32) && !defined(_WIN64)
02059     struct timeval tv;
02060 #ifdef HAVE_NANOSLEEP
02061     struct timespec ts;
02062 #endif
02063 #endif
02064 
02065     if (d->busyint) {
02066         d->busyint = 0;
02067         return ret;
02068     }
02069     if (d->timeout <= 0) {
02070         return ret;
02071     }
02072     if (count <= 1) {
02073 #if defined(_WIN32) || defined(_WIN64)
02074         d->t0 = GetTickCount();
02075 #else
02076         gettimeofday(&tv, NULL);
02077         d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02078 #endif
02079     }
02080 #if defined(_WIN32) || defined(_WIN64)
02081     t1 = GetTickCount();
02082 #else
02083     gettimeofday(&tv, NULL);
02084     t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02085 #endif
02086     if (t1 - d->t0 > d->timeout) {
02087         goto done;
02088     }
02089 #if defined(_WIN32) || defined(_WIN64)
02090     Sleep(10);
02091 #else
02092 #ifdef HAVE_NANOSLEEP
02093     ts.tv_sec = 0;
02094     ts.tv_nsec = 10000000;
02095     do {
02096         ret = nanosleep(&ts, &ts);
02097         if (ret < 0 && errno != EINTR) {
02098             ret = 0;
02099         }
02100     } while (ret);
02101 #else
02102 #ifdef HAVE_USLEEP
02103     usleep(10000);
02104 #else
02105     tv.tv_sec = 0;
02106     tv.tv_usec = 10000;
02107     select(0, NULL, NULL, NULL, &tv);
02108 #endif
02109 #endif
02110 #endif
02111     ret = 1;
02112 done:
02113     return ret;
02114 }
02115 
02127 static int
02128 setsqliteopts(sqlite3 *x, DBC *d)
02129 {
02130     int count = 0, step = 0, max, rc = SQLITE_ERROR;
02131 
02132 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
02133     max = d->longnames ? 3 : 1;
02134 #else
02135     max = 3;
02136 #endif
02137     if (d->shortnames) {
02138         max = 3;
02139     }
02140     while (step < max) {
02141         if (step < 1) {
02142             rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
02143                               NULL, NULL, NULL);
02144             if (rc == SQLITE_OK) {
02145                 rc = sqlite3_exec(x, d->fksupport ?
02146                                   "PRAGMA foreign_keys = on;" :
02147                                   "PRAGMA foreign_keys = off;",
02148                                   NULL, NULL, NULL);
02149             }
02150         } else if (step < 2) {
02151             rc = sqlite3_exec(x, d->shortnames ?
02152                               "PRAGMA full_column_names = off;" :
02153                               "PRAGMA full_column_names = on;",
02154                               NULL, NULL, NULL);
02155         } else if (step < 3) {
02156             rc = sqlite3_exec(x, d->shortnames ?
02157                               "PRAGMA short_column_names = on;" :
02158                               "PRAGMA short_column_names = off;",
02159                               NULL, NULL, NULL);
02160         }
02161         if (rc != SQLITE_OK) {
02162             if (rc != SQLITE_BUSY ||
02163                 !busy_handler((void *) d, ++count)) {
02164                 return rc;
02165             }
02166             continue;
02167         }
02168         count = 0;
02169         ++step;
02170     }
02171     sqlite3_busy_handler(x, busy_handler, (void *) d);
02172     return SQLITE_OK;
02173 }
02174 
02184 static void
02185 freerows(char **rowp)
02186 {
02187     PTRDIFF_T size, i;
02188 
02189     if (!rowp) {
02190         return;
02191     }
02192     --rowp;
02193     size = (PTRDIFF_T) rowp[0];
02194     for (i = 1; i <= size; i++) {
02195         freep(&rowp[i]);
02196     }
02197     freep(&rowp);
02198 }
02199 
02210 static int
02211 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
02212            int dobigint)
02213 {
02214     char *p, *q;
02215     int testsign = 0, result;
02216 
02217 #ifdef WINTERFACE
02218     result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
02219 #else
02220     result = SQL_VARCHAR;
02221 #endif
02222     if (!typename) {
02223         return result;
02224     }
02225     q = p = xmalloc(strlen(typename) + 1);
02226     if (!p) {
02227         return result;
02228     }
02229     strcpy(p, typename);
02230     while (*q) {
02231         *q = TOLOWER(*q);
02232         ++q;
02233     }
02234     if (strncmp(p, "inter", 5) == 0) {
02235     } else if (strncmp(p, "int", 3) == 0 ||
02236         strncmp(p, "mediumint", 9) == 0) {
02237         testsign = 1;
02238         result = SQL_INTEGER;
02239     } else if (strncmp(p, "numeric", 7) == 0) {
02240         result = SQL_DOUBLE;
02241     } else if (strncmp(p, "tinyint", 7) == 0) {
02242         testsign = 1;
02243         result = SQL_TINYINT;
02244     } else if (strncmp(p, "smallint", 8) == 0) {
02245         testsign = 1;
02246         result = SQL_SMALLINT;
02247     } else if (strncmp(p, "float", 5) == 0) {
02248         result = SQL_DOUBLE;
02249     } else if (strncmp(p, "double", 6) == 0 ||
02250         strncmp(p, "real", 4) == 0) {
02251         result = SQL_DOUBLE;
02252     } else if (strncmp(p, "timestamp", 9) == 0) {
02253 #ifdef SQL_TYPE_TIMESTAMP
02254         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02255 #else
02256         result = SQL_TIMESTAMP;
02257 #endif
02258     } else if (strncmp(p, "datetime", 8) == 0) {
02259 #ifdef SQL_TYPE_TIMESTAMP
02260         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02261 #else
02262         result = SQL_TIMESTAMP;
02263 #endif
02264     } else if (strncmp(p, "time", 4) == 0) {
02265 #ifdef SQL_TYPE_TIME
02266         result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
02267 #else
02268         result = SQL_TIME;
02269 #endif
02270     } else if (strncmp(p, "date", 4) == 0) {
02271 #ifdef SQL_TYPE_DATE
02272         result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
02273 #else
02274         result = SQL_DATE;
02275 #endif
02276 #ifdef SQL_LONGVARCHAR
02277     } else if (strncmp(p, "text", 4) == 0 ||
02278                strncmp(p, "memo", 4) == 0 ||
02279                strncmp(p, "longvarchar", 11) == 0) {
02280 #ifdef WINTERFACE
02281         result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
02282 #else
02283         result = SQL_LONGVARCHAR;
02284 #endif
02285 #ifdef WINTERFACE
02286     } else if (strncmp(p, "wtext", 5) == 0 ||
02287                strncmp(p, "wvarchar", 8) == 0 ||
02288                strncmp(p, "longwvarchar", 12) == 0) {
02289         result = SQL_WLONGVARCHAR;
02290 #endif
02291 #endif
02292 #ifdef SQL_BIT
02293     } else if (strncmp(p, "bool", 4) == 0 ||
02294                strncmp(p, "bit", 3) == 0) {
02295         result = SQL_BIT;
02296 #endif
02297 #ifdef SQL_BIGINT
02298     } else if (strncmp(p, "bigint", 6) == 0) {
02299         testsign = 1;
02300         result = SQL_BIGINT;
02301 #endif
02302     } else if (strncmp(p, "blob", 4) == 0) {
02303         result = SQL_BINARY;
02304     } else if (strncmp(p, "varbinary", 9) == 0) {
02305         result = SQL_VARBINARY;
02306     } else if (strncmp(p, "longvarbinary", 13) == 0) {
02307         result = SQL_LONGVARBINARY;
02308     }
02309     if (nosign) {
02310         if (testsign) {
02311             *nosign = strstr(p, "unsigned") != NULL;
02312         } else {
02313             *nosign = 1;
02314         }
02315     }
02316 #ifdef SQL_BIGINT
02317     if (dobigint && result == SQL_INTEGER) {
02318         result = SQL_BIGINT;
02319     }
02320 #endif
02321     xfree(p);
02322     return result;
02323 }
02324 
02334 static void
02335 getmd(const char *typename, int sqltype, int *mp, int *dp)
02336 {
02337     int m = 0, d = 0;
02338 
02339     switch (sqltype) {
02340     case SQL_INTEGER:       m = 10; d = 9; break;
02341     case SQL_TINYINT:       m = 4; d = 3; break;
02342     case SQL_SMALLINT:      m = 6; d = 5; break;
02343     case SQL_FLOAT:         m = 25; d = 24; break;
02344     case SQL_DOUBLE:        m = 54; d = 53; break;
02345     case SQL_VARCHAR:       m = 255; d = 0; break;
02346 #ifdef WINTERFACE
02347 #ifdef SQL_WVARCHAR
02348     case SQL_WVARCHAR:      m = 255; d = 0; break;
02349 #endif
02350 #endif
02351 #ifdef SQL_TYPE_DATE
02352     case SQL_TYPE_DATE:
02353 #endif
02354     case SQL_DATE:          m = 10; d = 0; break;
02355 #ifdef SQL_TYPE_TIME
02356     case SQL_TYPE_TIME:
02357 #endif
02358     case SQL_TIME:          m = 8; d = 0; break;
02359 #ifdef SQL_TYPE_TIMESTAMP
02360     case SQL_TYPE_TIMESTAMP:
02361 #endif
02362     case SQL_TIMESTAMP:     m = 32; d = 3; break;
02363 #ifdef SQL_LONGVARCHAR
02364     case SQL_LONGVARCHAR :  m = 65536; d = 0; break;
02365 #endif
02366 #ifdef WINTERFACE
02367 #ifdef SQL_WLONGVARCHAR
02368     case SQL_WLONGVARCHAR:  m = 65536; d = 0; break;
02369 #endif
02370 #endif
02371     case SQL_BINARY:
02372     case SQL_VARBINARY:     m = 255; d = 0; break;
02373     case SQL_LONGVARBINARY: m = 65536; d = 0; break;
02374 #ifdef SQL_BIGINT
02375     case SQL_BIGINT:        m = 20; d = 19; break;
02376 #endif
02377 #ifdef SQL_BIT
02378     case SQL_BIT:           m = 1; d = 1; break;
02379 #endif
02380     }
02381     if (m && typename) {
02382         int mm, dd;
02383         char clbr[4];
02384 
02385         if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
02386             m = mm;
02387             d = dd;
02388         } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
02389             if (sqltype == SQL_TIMESTAMP) {
02390                 d = mm;
02391             }
02392 #ifdef SQL_TYPE_TIMESTAMP
02393             else if (sqltype == SQL_TYPE_TIMESTAMP) {
02394                 d = mm;
02395             }
02396 #endif
02397             else {
02398                 m = d = mm;
02399             }
02400         }
02401     }
02402     if (mp) {
02403         *mp = m;
02404     }
02405     if (dp) {
02406         *dp = d;
02407     }
02408 }
02409 
02419 static int
02420 mapdeftype(int type, int stype, int nosign, int nowchar)
02421 {
02422     if (type == SQL_C_DEFAULT) {
02423         switch (stype) {
02424         case SQL_INTEGER:
02425             type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
02426             break;
02427         case SQL_TINYINT:
02428             type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
02429             break;
02430         case SQL_SMALLINT:
02431             type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
02432             break;
02433         case SQL_FLOAT:
02434             type = SQL_C_FLOAT;
02435             break;
02436         case SQL_DOUBLE:
02437             type = SQL_C_DOUBLE;
02438             break;
02439         case SQL_TIMESTAMP:
02440             type = SQL_C_TIMESTAMP;
02441             break;
02442         case SQL_TIME:
02443             type = SQL_C_TIME;
02444             break;
02445         case SQL_DATE:
02446             type = SQL_C_DATE;
02447             break;
02448 #ifdef SQL_C_TYPE_TIMESTAMP
02449         case SQL_TYPE_TIMESTAMP:
02450             type = SQL_C_TYPE_TIMESTAMP;
02451             break;
02452 #endif
02453 #ifdef SQL_C_TYPE_TIME
02454         case SQL_TYPE_TIME:
02455             type = SQL_C_TYPE_TIME;
02456             break;
02457 #endif
02458 #ifdef SQL_C_TYPE_DATE
02459         case SQL_TYPE_DATE:
02460             type = SQL_C_TYPE_DATE;
02461             break;
02462 #endif
02463 #ifdef WINTERFACE
02464         case SQL_WVARCHAR:
02465         case SQL_WCHAR:
02466 #ifdef SQL_WLONGVARCHAR
02467         case SQL_WLONGVARCHAR:
02468 #endif
02469             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02470             break;
02471 #endif
02472         case SQL_BINARY:
02473         case SQL_VARBINARY:
02474         case SQL_LONGVARBINARY:
02475             type = SQL_C_BINARY;
02476             break;
02477 #ifdef SQL_BIT
02478         case SQL_BIT:
02479             type = SQL_C_BIT;
02480             break;
02481 #endif
02482 #ifdef SQL_BIGINT
02483         case SQL_BIGINT:
02484             type = SQL_C_CHAR;
02485             break;
02486 #endif
02487         default:
02488 #ifdef WINTERFACE
02489             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02490 #else
02491             type = SQL_C_CHAR;
02492 #endif
02493             break;
02494         }
02495     }
02496     return type;
02497 }
02498 
02510 static char *
02511 fixupsql(char *sql, int sqlLen, int cte, int *nparam, int *isselect,
02512          char **errmsg)
02513 {
02514     char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
02515     int np = 0, isddl = -1, size;
02516 
02517     if (errmsg) {
02518         *errmsg = NULL;
02519     }
02520     if (sqlLen != SQL_NTS) {
02521         qz = q = xmalloc(sqlLen + 1);
02522         if (!qz) {
02523             return NULL;
02524         }
02525         memcpy(q, sql, sqlLen);
02526         q[sqlLen] = '\0';
02527         size = sqlLen * 4;
02528     } else {
02529         size = strlen(sql) * 4;
02530     }
02531     size += sizeof (char *) - 1;
02532     size &= ~(sizeof (char *) - 1);
02533     p = xmalloc(size);
02534     if (!p) {
02535 errout:
02536         freep(&qz);
02537         return NULL;
02538     }
02539     memset(p, 0, size);
02540     out = p;
02541     while (*q) {
02542         switch (*q) {
02543         case '\'':
02544         case '\"':
02545             if (q == inq) {
02546                 inq = NULL;
02547             } else if (!inq) {
02548                 inq = q + 1;
02549 
02550                 while (*inq) {
02551                     if (*inq == *q) {
02552                         if (inq[1] == *q) {
02553                             inq++;
02554                         } else {
02555                             break;
02556                         }
02557                     }
02558                     inq++;
02559                 }
02560             }
02561             *p++ = *q;
02562             break;
02563         case '?':
02564             *p++ = *q;
02565             if (!inq) {
02566                 np++;
02567             }
02568             break;
02569         case ';':
02570             if (!inq) {
02571                 if (isddl < 0) {
02572                     char *qq = out;
02573 
02574                     while (*qq && ISSPACE(*qq)) {
02575                         ++qq;
02576                     }
02577                     if (*qq && *qq != ';') {
02578                         int i;
02579                         static const struct {
02580                             int len;
02581                             const char *str;
02582                         } ddlstr[] = {
02583                             { 5, "alter" },
02584                             { 7, "analyze" },
02585                             { 6, "attach" },
02586                             { 5, "begin" },
02587                             { 6, "commit" },
02588                             { 6, "create" },
02589                             { 6, "detach" },
02590                             { 4, "drop" },
02591                             { 3, "end" },
02592                             { 7, "reindex" },
02593                             { 7, "release" },
02594                             { 8, "rollback" },
02595                             { 9, "savepoint" },
02596                             { 6, "vacuum" }
02597                         };
02598 
02599                         size = strlen(qq);
02600                         for (i = 0; i < array_size(ddlstr); i++) {
02601                             if (size >= ddlstr[i].len &&
02602                                 strncasecmp(qq, ddlstr[i].str, ddlstr[i].len)
02603                                 == 0) {
02604                                 isddl = 1;
02605                                 break;
02606                             }
02607                         }
02608                         if (isddl != 1) {
02609                             isddl = 0;
02610                         }
02611                     }
02612                 }
02613                 if (isddl == 0) {
02614                     char *qq = q;
02615 
02616                     do {
02617                         ++qq;
02618                     } while (*qq && ISSPACE(*qq));
02619                     if (*qq && *qq != ';') {
02620                         freep(&out);
02621                         if (errmsg) {
02622                             *errmsg = "only one SQL statement allowed";
02623                         }
02624                         goto errout;
02625                     }
02626                 }
02627             }
02628             *p++ = *q;
02629             break;
02630         case '{':
02631             /*
02632              * Deal with escape sequences:
02633              * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
02634              * {oj ...}, {fn ...} etc.
02635              */
02636             if (!inq) {
02637                 int ojfn = 0, brc = 0;
02638                 char *inq2 = NULL, *end = q + 1, *start;
02639 
02640                 while (*end && ISSPACE(*end)) {
02641                     ++end;
02642                 }
02643                 if (*end != 'd' && *end != 'D' &&
02644                     *end != 't' && *end != 'T') {
02645                     ojfn = 1;
02646                 }
02647                 start = end;
02648                 while (*end) {
02649                     if (inq2 && *end == *inq2) {
02650                         inq2 = NULL;
02651                     } else if (inq2 == NULL && *end == '{') {
02652                         char *nerr = 0, *nsql;
02653 
02654                         nsql = fixupsql(end, SQL_NTS, cte, 0, 0, &nerr);
02655                         if (nsql && !nerr) {
02656                             strcpy(end, nsql);
02657                         } else {
02658                             brc++;
02659                         }
02660                         freep(&nsql);
02661                     } else if (inq2 == NULL && *end == '}') {
02662                         if (brc-- <= 0) {
02663                             break;
02664                         }
02665                     } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
02666                         inq2 = end;
02667                     } else if (inq2 == NULL && *end == '?') {
02668                         np++;
02669                     }
02670                     ++end;
02671                 }
02672                 if (*end == '}') {
02673                     char *end2 = end - 1;
02674 
02675                     if (ojfn) {
02676                         while (start < end) {
02677                             if (ISSPACE(*start)) {
02678                                 break;
02679                             }
02680                             ++start;
02681                         }
02682                         while (start < end) {
02683                             *p++ = *start;
02684                             ++start;
02685                         }
02686                         q = end;
02687                         break;
02688                     } else {
02689                         while (start < end2 && *start != '\'') {
02690                             ++start;
02691                         }
02692                         while (end2 > start && *end2 != '\'') {
02693                             --end2;
02694                         }
02695                         if (*start == '\'' && *end2 == '\'') {
02696                             while (start <= end2) {
02697                                 *p++ = *start;
02698                                 ++start;
02699                             }
02700                             q = end;
02701                             break;
02702                         }
02703                     }
02704                 }
02705             }
02706             /* FALL THROUGH */
02707         default:
02708             *p++ = *q;
02709         }
02710         ++q;
02711     }
02712     freep(&qz);
02713     *p = '\0';
02714     if (nparam) {
02715         *nparam = np;
02716     }
02717     if (isselect) {
02718         if (isddl > 0) {
02719             *isselect = 2;
02720         } else {
02721             int incom = 0;
02722 
02723             p = out;
02724             while (*p) {
02725                 switch (*p) {
02726                 case '-':
02727                     if (!incom && p[1] == '-') {
02728                         incom = -1;
02729                     }
02730                     break;
02731                 case '\n':
02732                     if (incom < 0) {
02733                         incom = 0;
02734                     }
02735                     break;
02736                 case '/':
02737                     if (incom > 0 && p[-1] == '*') {
02738                         incom = 0;
02739                         p++;
02740                         continue;
02741                     } else if (!incom && p[1] == '*') {
02742                         incom = 1;
02743                     }
02744                     break;
02745                 }
02746                 if (!incom && !ISSPACE(*p)) {
02747                     break;
02748                 }
02749                 p++;
02750             }
02751             size = strlen(p);
02752             if (size >= 6 &&
02753                 (strncasecmp(p, "select", 6) == 0 ||
02754                  strncasecmp(p, "pragma", 6) == 0)) {
02755                 *isselect = 1;
02756             } else if (cte && size >= 4 && strncasecmp(p, "with", 4) == 0) {
02757                 *isselect = 1;
02758             } else if (size >= 7 && strncasecmp(p, "explain", 7) == 0) {
02759                 *isselect = 1;
02760             } else {
02761                 *isselect = 0;
02762             }
02763         }
02764     }
02765     return out;
02766 }
02767 
02776 static int
02777 findcol(char **cols, int ncols, char *name)
02778 {
02779     int i;
02780 
02781     if (cols) {
02782         for (i = 0; i < ncols; i++) {
02783             if (strcmp(cols[i], name) == 0) {
02784                 return i;
02785             }
02786         }
02787     }
02788     return -1;
02789 }
02790 
02807 static void
02808 fixupdyncols(STMT *s, DBC *d)
02809 {
02810     int i, k;
02811 #ifndef FULL_METADATA
02812     int pk, nn, t, r, nrows, ncols;
02813     char **rowp, *flagp, flags[128];
02814 #endif
02815 
02816     if (!s->dyncols) {
02817         return;
02818     }
02819     /* fixup labels */
02820     if (!s->longnames) {
02821         if (s->dcols > 1) {
02822             char *table = s->dyncols[0].table;
02823 
02824             for (i = 1; table[0] && i < s->dcols; i++) {
02825                 if (strcmp(s->dyncols[i].table, table)) {
02826                     break;
02827                 }
02828             }
02829             if (i >= s->dcols) {
02830                 for (i = 0; i < s->dcols; i++) {
02831                     s->dyncols[i].label = s->dyncols[i].column;
02832                 }
02833             }
02834         } else if (s->dcols == 1) {
02835             s->dyncols[0].label = s->dyncols[0].column;
02836         }
02837     }
02838     for (i = 0; i < s->dcols; i++) {
02839         s->dyncols[i].type =
02840             mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
02841                        s->nowchar[0] || s->nowchar[1], s->dobigint);
02842         getmd(s->dyncols[i].typename, s->dyncols[i].type,
02843               &s->dyncols[i].size, &s->dyncols[i].prec);
02844 #ifdef SQL_LONGVARCHAR
02845         if (s->dyncols[i].type == SQL_VARCHAR &&
02846             s->dyncols[i].size > 255) {
02847             s->dyncols[i].type = SQL_LONGVARCHAR;
02848         }
02849 #endif
02850 #ifdef WINTERFACE
02851 #ifdef SQL_WLONGVARCHAR
02852         if (s->dyncols[i].type == SQL_WVARCHAR &&
02853             s->dyncols[i].size > 255) {
02854             s->dyncols[i].type = SQL_WLONGVARCHAR;
02855         }
02856 #endif
02857 #endif
02858         if (s->dyncols[i].type == SQL_VARBINARY &&
02859             s->dyncols[i].size > 255) {
02860             s->dyncols[i].type = SQL_LONGVARBINARY;
02861         }
02862     }
02863 #ifndef FULL_METADATA
02864     if (s->dcols > array_size(flags)) {
02865         flagp = xmalloc(sizeof (flags[0]) * s->dcols);
02866         if (flagp == NULL) {
02867             return;
02868         }
02869     } else {
02870         flagp = flags;
02871     }
02872     memset(flagp, 0, sizeof (flags[0]) * s->dcols);
02873     for (i = 0; i < s->dcols; i++) {
02874         s->dyncols[i].autoinc = SQL_FALSE;
02875         s->dyncols[i].notnull = SQL_NULLABLE;
02876     }
02877     for (i = 0; i < s->dcols; i++) {
02878         int ret, lastpk = -1, autoinccount = 0;
02879         char *sql;
02880 
02881         if (!s->dyncols[i].table[0]) {
02882             continue;
02883         }
02884         if (flagp[i]) {
02885             continue;
02886         }
02887         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
02888         if (!sql) {
02889             continue;
02890         }
02891         dbtraceapi(d, "sqlite3_get_table", sql);
02892         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
02893         sqlite3_free(sql);
02894         if (ret != SQLITE_OK) {
02895             continue;
02896         }
02897         k = findcol(rowp, ncols, "name");
02898         t = findcol(rowp, ncols, "type");
02899         pk = findcol(rowp, ncols, "pk");
02900         nn = findcol(rowp, ncols, "notnull");
02901         if (k < 0 || t < 0) {
02902             goto freet;
02903         }
02904         for (r = 1; r <= nrows; r++) {
02905             int m;
02906 
02907             for (m = i; m < s->dcols; m++) {
02908                 char *colname = s->dyncols[m].column;
02909 
02910                 if (s->longnames) {
02911                     char *dotp = strchr(colname, '.');
02912 
02913                     if (dotp) {
02914                         colname = dotp + 1;
02915                     }
02916                 }
02917                 if (!flagp[m] &&
02918                     strcmp(colname, rowp[r * ncols + k]) == 0 &&
02919                     strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
02920                     char *typename = rowp[r * ncols + t];
02921 
02922                     flagp[m] = i + 1;
02923                     freep(&s->dyncols[m].typename);
02924                     s->dyncols[m].typename = xstrdup(typename);
02925                     s->dyncols[m].type =
02926                         mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
02927                                    s->nowchar[0] || s->nowchar[1],
02928                                    s->dobigint);
02929                     getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
02930                           &s->dyncols[m].prec);
02931 #ifdef SQL_LONGVARCHAR
02932                     if (s->dyncols[m].type == SQL_VARCHAR &&
02933                         s->dyncols[m].size > 255) {
02934                         s->dyncols[m].type = SQL_LONGVARCHAR;
02935                     }
02936 #endif
02937 #ifdef WINTERFACE
02938 #ifdef SQL_WLONGVARCHAR
02939                     if (s->dyncols[i].type == SQL_WVARCHAR &&
02940                         s->dyncols[i].size > 255) {
02941                         s->dyncols[i].type = SQL_WLONGVARCHAR;
02942                     }
02943 #endif
02944 #endif
02945                     if (s->dyncols[i].type == SQL_VARBINARY &&
02946                         s->dyncols[i].size > 255) {
02947                         s->dyncols[i].type = SQL_LONGVARBINARY;
02948                     }
02949                     if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
02950                         s->dyncols[m].ispk = 1;
02951                         if (++autoinccount > 1) {
02952                             if (lastpk >= 0) {
02953                                 s->dyncols[lastpk].autoinc = SQL_FALSE;
02954                                 lastpk = -1;
02955                             }
02956                         } else {
02957                             lastpk = m;
02958                             if (strlen(typename) == 7 &&
02959                                 strncasecmp(typename, "integer", 7) == 0) {
02960                                 s->dyncols[m].autoinc = SQL_TRUE;
02961                             }
02962                         }
02963                     } else {
02964                         s->dyncols[m].ispk = 0;
02965                     }
02966                     if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
02967                         s->dyncols[m].notnull = SQL_NO_NULLS;
02968                     }
02969                 }
02970             }
02971         }
02972 freet:
02973         sqlite3_free_table(rowp);
02974     }
02975     for (i = k = 0; i < s->dcols; i++) {
02976         if (flagp[i] == 0) {
02977             break;
02978         }
02979         if (k == 0) {
02980             k = flagp[i];
02981         } else if (flagp[i] != k) {
02982             k = 0;
02983             break;
02984         }
02985     }
02986     s->one_tbl = k ? 1 : 0;
02987     k = 0;
02988     if (s->one_tbl) {
02989         for (i = 0; i < s->dcols; i++) {
02990             if (s->dyncols[i].ispk > 0) {
02991                 ++k;
02992             }
02993         }
02994     }
02995     s->has_pk = k;
02996     if (flagp != flags) {
02997         freep(&flagp);
02998     }
02999 #else
03000     for (i = 1, k = 0; i < s->dcols; i++) {
03001         if (strcmp(s->dyncols[i].table, s->dyncols[0].table) == 0) {
03002             k++;
03003         }
03004     }
03005     s->one_tbl = (k && k + 1 == s->dcols) ? 1 : 0;
03006     k = 0;
03007     if (s->one_tbl) {
03008         for (i = 0; i < s->dcols; i++) {
03009             if (s->dyncols[i].ispk > 0) {
03010                 ++k;
03011                 if (s->has_rowid < 0 && s->dyncols[i].isrowid > 0) {
03012                     s->has_rowid = i;
03013                 }
03014             }
03015         }
03016     }
03017     s->has_pk = k;
03018 #endif
03019 }
03020 
03027 static void
03028 convJD2YMD(double jd, DATE_STRUCT *ds)
03029 {
03030     int z, a, b, c, d, e, x1;
03031     sqlite_int64 ijd;
03032 
03033     ijd = jd * 86400000.0 + 0.5;
03034     z = (int) ((ijd + 43200000) / 86400000);
03035     a = (int) ((z - 1867216.25) / 36524.25);
03036     a = z + 1 + a - (a / 4);
03037     b = a + 1524;
03038     c = (int) ((b - 122.1) / 365.25);
03039     d = (36525 * c) / 100;
03040     e = (int) ((b - d) / 30.6001);
03041     x1 = (int) (30.6001 * e);
03042     ds->day = b - d - x1;
03043     ds->month = (e < 14) ? (e - 1) : (e - 13);
03044     ds->year = (ds->month > 2) ? (c - 4716) : (c - 4715);
03045 }
03046 
03047 
03055 static void
03056 convJD2HMS(double jd, TIME_STRUCT *ts, int *fp)
03057 {
03058     int s;
03059     double ds;
03060     sqlite_int64 ijd;
03061 
03062     ijd = jd * 86400000.0 + 0.5;
03063     s = (int)((ijd + 43200000) % 86400000);
03064     ds = s / 1000.0;
03065     if (fp) {
03066         *fp = (s % 1000) * 1000000;
03067     }
03068     s = (int) ds;
03069     ds -= s;
03070     ts->hour = s / 3600;
03071     s -= ts->hour * 3600;
03072     ts->minute = s / 60;
03073     ds += s - ts->minute *60;
03074     ts->second = (int) ds;
03075 }
03076 
03084 static int
03085 getmdays(int year, int month)
03086 {
03087     static const int mdays[] = {
03088         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
03089     };
03090     int mday;
03091 
03092     if (month < 1) {
03093         return 0;
03094     }
03095     mday = mdays[(month - 1) % 12];
03096     if (mday == 28 && year % 4 == 0 &&
03097         (!(year % 100 == 0) || year % 400 == 0)) {
03098         mday++;
03099     }
03100     return mday;
03101 }
03102 
03118 static int
03119 str2date(int jdconv, char *str, DATE_STRUCT *ds)
03120 {
03121     int i, err = 0;
03122     double jd;
03123     char *p, *q, sepc = '\0';
03124 
03125     ds->year = ds->month = ds->day = 0;
03126     if (jdconv) {
03127         p = strchr(str, '.');
03128         if (p) {
03129             /* julian day format */
03130             p = 0;
03131             jd = ln_strtod(str, &p);
03132             if (p && p > str) {
03133                 convJD2YMD(jd, ds);
03134                 return 0;
03135             }
03136         }
03137     }
03138     p = str;
03139     while (*p && !ISDIGIT(*p)) {
03140         ++p;
03141     }
03142     q = p;
03143     i = 0;
03144     while (*q && !ISDIGIT(*q)) {
03145         ++i;
03146         ++q;
03147     }
03148     if (i >= 8) {
03149         char buf[8];
03150 
03151         strncpy(buf, p + 0, 4); buf[4] = '\0';
03152         ds->year = strtol(buf, NULL, 10);
03153         strncpy(buf, p + 4, 2); buf[2] = '\0';
03154         ds->month = strtol(buf, NULL, 10);
03155         strncpy(buf, p + 6, 2); buf[2] = '\0';
03156         ds->day = strtol(buf, NULL, 10);
03157         goto done;
03158     }
03159     i = 0;
03160     while (i < 3) {
03161         int n;
03162 
03163         q = NULL;
03164         n = strtol(p, &q, 10);
03165         if (!q || q == p) {
03166             if (*q == '\0') {
03167                 if (i == 0) {
03168                     err = 1;
03169                 }
03170                 goto done;
03171             }
03172         }
03173         if (!sepc) {
03174             sepc = *q;
03175         }
03176         if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
03177             switch (i) {
03178             case 0: ds->year = n; break;
03179             case 1: ds->month = n; break;
03180             case 2: ds->day = n; break;
03181             }
03182             ++i;
03183             if (*q) {
03184                 ++q;
03185             }
03186         } else {
03187             i = 0;
03188             while (*q && !ISDIGIT(*q)) {
03189                 ++q;
03190             }
03191         }
03192         p = q;
03193     }
03194 done:
03195     /* final check for overflow */
03196     if (err ||
03197         ds->month < 1 || ds->month > 12 ||
03198         ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
03199         if (sepc == '/') {
03200             /* Try MM/DD/YYYY format */
03201             int t[3];
03202 
03203             t[0] = ds->year;
03204             t[1] = ds->month;
03205             t[2] = ds->day;
03206             ds->year = t[2];
03207             ds->day = t[1];
03208             ds->month = t[0];
03209             if (ds->month >= 1 && ds->month <= 12 &&
03210                 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
03211                 return 0;
03212             }
03213         }
03214         return -1;
03215     }
03216     return 0;
03217 }
03218 
03233 static int
03234 str2time(int jdconv, char *str, TIME_STRUCT *ts)
03235 {
03236     int i, err = 0, ampm = -1;
03237     double jd;
03238     char *p, *q;
03239 
03240     ts->hour = ts->minute = ts->second = 0;
03241     if (jdconv) {
03242         p = strchr(str, '.');
03243         if (p) {
03244             /* julian day format */
03245             p = 0;
03246             jd = ln_strtod(str, &p);
03247             if (p && p > str) {
03248                 convJD2HMS(jd, ts, 0);
03249                 return 0;
03250             }
03251         }
03252     }
03253     p = str;
03254     while (*p && !ISDIGIT(*p)) {
03255         ++p;
03256     }
03257     q = p;
03258     i = 0;
03259     while (*q && ISDIGIT(*q)) {
03260         ++i;
03261         ++q;
03262     }
03263     if (i >= 6) {
03264         char buf[4];
03265 
03266         strncpy(buf, p + 0, 2); buf[2] = '\0';
03267         ts->hour = strtol(buf, NULL, 10);
03268         strncpy(buf, p + 2, 2); buf[2] = '\0';
03269         ts->minute = strtol(buf, NULL, 10);
03270         strncpy(buf, p + 4, 2); buf[2] = '\0';
03271         ts->second = strtol(buf, NULL, 10);
03272         goto done;
03273     }
03274     i = 0;
03275     while (i < 3) {
03276         int n;
03277 
03278         q = NULL;
03279         n = strtol(p, &q, 10);
03280         if (!q || q == p) {
03281             if (*q == '\0') {
03282                 if (i == 0) {
03283                     err = 1;
03284                 }
03285                 goto done;
03286             }
03287         }
03288         if (*q == ':' || *q == '\0' || i == 2) {
03289             switch (i) {
03290             case 0: ts->hour = n; break;
03291             case 1: ts->minute = n; break;
03292             case 2: ts->second = n; break;
03293             }
03294             ++i;
03295             if (*q) {
03296                 ++q;
03297             }
03298         } else {
03299             i = 0;
03300             while (*q && !ISDIGIT(*q)) {
03301                 ++q;
03302             }
03303         }
03304         p = q;
03305     }
03306     if (!err) {
03307         while (*p) {
03308             if ((p[0] == 'p' || p[0] == 'P') &&
03309                 (p[1] == 'm' || p[1] == 'M')) {
03310                 ampm = 1;
03311             } else if ((p[0] == 'a' || p[0] == 'A') &&
03312                 (p[1] == 'm' || p[1] == 'M')) {
03313                 ampm = 0;
03314             }
03315             ++p;
03316         }
03317         if (ampm > 0) {
03318             if (ts->hour < 12) {
03319                 ts->hour += 12;
03320             }
03321         } else if (ampm == 0) {
03322             if (ts->hour == 12) {
03323                 ts->hour = 0;
03324             }
03325         }
03326     }
03327 done:
03328     /* final check for overflow */
03329     if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
03330         return -1;
03331     }
03332     return 0;
03333 }
03334 
03354 static int
03355 str2timestamp(int jdconv, char *str, TIMESTAMP_STRUCT *tss)
03356 {
03357     int i, m, n, err = 0, ampm = -1;
03358     double jd;
03359     char *p, *q, in = '\0', sepc = '\0';
03360 
03361     tss->year = tss->month = tss->day = 0;
03362     tss->hour = tss->minute = tss->second = 0;
03363     tss->fraction = 0;
03364     if (jdconv) {
03365         p = strchr(str, '.');
03366         if (p) {
03367             q = strchr(str, '-');
03368             if (q == str) {
03369                 q = 0;
03370             }
03371             if (!q) {
03372                 q = strchr(str, '/');
03373                 if (!q) {
03374                     q = strchr(str, ':');
03375                 }
03376             }
03377             if (!q || q > p) {
03378                 /* julian day format */
03379                 p = 0;
03380                 jd = ln_strtod(str, &p);
03381                 if (p && p > str) {
03382                     DATE_STRUCT ds;
03383                     TIME_STRUCT ts;
03384 
03385                     convJD2YMD(jd, &ds);
03386                     convJD2HMS(jd, &ts, &n);
03387                     tss->year = ds.year;
03388                     tss->month = ds.month;
03389                     tss->day = ds.day;
03390                     tss->hour = ts.hour;
03391                     tss->minute = ts.minute;
03392                     tss->second = ts.second;
03393                     tss->fraction = n;
03394                     return 0;
03395                 }
03396             }
03397         }
03398     }
03399     p = str;
03400     while (*p && !ISDIGIT(*p)) {
03401         ++p;
03402     }
03403     q = p;
03404     i = 0;
03405     while (*q && ISDIGIT(*q)) {
03406         ++i;
03407         ++q;
03408     }
03409     if (i >= 14) {
03410         char buf[16];
03411 
03412         strncpy(buf, p + 0, 4); buf[4] = '\0';
03413         tss->year = strtol(buf, NULL, 10);
03414         strncpy(buf, p + 4, 2); buf[2] = '\0';
03415         tss->month = strtol(buf, NULL, 10);
03416         strncpy(buf, p + 6, 2); buf[2] = '\0';
03417         tss->day = strtol(buf, NULL, 10);
03418         strncpy(buf, p + 8, 2); buf[2] = '\0';
03419         tss->hour = strtol(buf, NULL, 10);
03420         strncpy(buf, p + 10, 2); buf[2] = '\0';
03421         tss->minute = strtol(buf, NULL, 10);
03422         strncpy(buf, p + 12, 2); buf[2] = '\0';
03423         tss->second = strtol(buf, NULL, 10);
03424         if (i > 14) {
03425             m = i - 14;
03426             strncpy(buf, p + 14, m);
03427             while (m < 9) {
03428                 buf[m] = '0';
03429                 ++m;
03430             }
03431             buf[m] = '\0';
03432             tss->fraction = strtol(buf, NULL, 10);
03433         }
03434         m = 7;
03435         goto done;
03436     }
03437     m = i = 0;
03438     while ((m & 7) != 7) {
03439         q = NULL;
03440         n = strtol(p, &q, 10);
03441         if (!q || q == p) {
03442             if (*q == '\0') {
03443                 if (m < 1) {
03444                     err = 1;
03445                 }
03446                 goto done;
03447             }
03448         }
03449         if (in == '\0') {
03450             switch (*q) {
03451             case '-':
03452             case '/':
03453                 if ((m & 1) == 0) {
03454                     in = *q;
03455                     i = 0;
03456                 }
03457                 break;
03458             case ':':
03459                 if ((m & 2) == 0) {
03460                     in = *q;
03461                     i = 0;
03462                 }
03463                 break;
03464             case ' ':
03465             case '.':
03466                 break;
03467             default:
03468                 in = '\0';
03469                 i = 0;
03470                 break;
03471             }
03472         }
03473         switch (in) {
03474         case '-':
03475         case '/':
03476             if (!sepc) {
03477                 sepc = in;
03478             }
03479             switch (i) {
03480             case 0: tss->year = n; break;
03481             case 1: tss->month = n; break;
03482             case 2: tss->day = n; break;
03483             }
03484             if (++i >= 3) {
03485                 i = 0;
03486                 m |= 1;
03487                 if (!(m & 2)) {
03488                     m |= 8;
03489                 }
03490                 goto skip;
03491             } else {
03492                 ++q;
03493             }
03494             break;
03495         case ':':
03496             switch (i) {
03497             case 0: tss->hour = n; break;
03498             case 1: tss->minute = n; break;
03499             case 2: tss->second = n; break;
03500             }
03501             if (++i >= 3) {
03502                 i = 0;
03503                 m |= 2;
03504                 if (*q == '.') {
03505                     in = '.';
03506                     goto skip2;
03507                 }
03508                 if (*q == ' ') {
03509                     if ((m & 1) == 0) {
03510                         char *e = NULL;
03511 
03512                         (void) strtol(q + 1, &e, 10);
03513                         if (e && *e == '-') {
03514                             goto skip;
03515                         }
03516                     }
03517                     in = '.';
03518                     goto skip2;
03519                 }
03520                 goto skip;
03521             } else {
03522                 ++q;
03523             }
03524             break;
03525         case '.':
03526             if (++i >= 1) {
03527                 int ndig = q - p;
03528 
03529                 if (p[0] == '+' || p[0] == '-') {
03530                     ndig--;
03531                 }
03532                 while (ndig < 9) {
03533                     n = n * 10;
03534                     ++ndig;
03535                 }
03536                 tss->fraction = n;
03537                 m |= 4;
03538                 i = 0;
03539             }
03540         default:
03541         skip:
03542             in = '\0';
03543         skip2:
03544             while (*q && !ISDIGIT(*q)) {
03545                 if ((q[0] == 'a' || q[0] == 'A') &&
03546                     (q[1] == 'm' || q[1] == 'M')) {
03547                     ampm = 0;
03548                     ++q;
03549                 } else if ((q[0] == 'p' || q[0] == 'P') &&
03550                            (q[1] == 'm' || q[1] == 'M')) {
03551                     ampm = 1;
03552                     ++q;
03553                 }
03554                 ++q;
03555             }
03556         }
03557         p = q;
03558     }
03559     if ((m & 7) > 1 && (m & 8)) {
03560         /* ISO8601 timezone */
03561         if (p > str && ISDIGIT(*p)) {
03562             int nn, sign;
03563 
03564             q = p - 1;
03565             if (*q != '+' && *q != '-') {
03566                 goto done;
03567             }
03568             sign = (*q == '+') ? -1 : 1;
03569             q = NULL;
03570             n = strtol(p, &q, 10);
03571             if (!q || *q++ != ':' || !ISDIGIT(*q)) {
03572                 goto done;
03573             }
03574             p = q;
03575             q = NULL;
03576             nn = strtol(p, &q, 10);
03577             tss->minute += nn * sign;
03578             if ((SQLSMALLINT) tss->minute < 0) {
03579                 tss->hour -= 1;
03580                 tss->minute += 60;
03581             } else if (tss->minute >= 60) {
03582                 tss->hour += 1;
03583                 tss->minute -= 60;
03584             }
03585             tss->hour += n * sign;
03586             if ((SQLSMALLINT) tss->hour < 0) {
03587                 tss->day -= 1;
03588                 tss->hour += 24;
03589             } else if (tss->hour >= 24) {
03590                 tss->day += 1;
03591                 tss->hour -= 24;
03592             }
03593             if ((short) tss->day < 1 || tss->day >= 28) {
03594                 int mday, pday, pmon;
03595 
03596                 mday = getmdays(tss->year, tss->month);
03597                 pmon = tss->month - 1;
03598                 if (pmon < 1) {
03599                     pmon = 12;
03600                 }
03601                 pday = getmdays(tss->year, pmon);
03602                 if ((SQLSMALLINT) tss->day < 1) {
03603                     tss->month -= 1;
03604                     tss->day = pday;
03605                 } else if (tss->day > mday) {
03606                     tss->month += 1;
03607                     tss->day = 1;
03608                 }
03609                 if ((SQLSMALLINT) tss->month < 1) {
03610                     tss->year -= 1;
03611                     tss->month = 12;
03612                 } else if (tss->month > 12) {
03613                     tss->year += 1;
03614                     tss->month = 1;
03615                 }
03616             }
03617         }
03618     }
03619 done:
03620     if ((m & 1) &&
03621         (tss->month < 1 || tss->month > 12 ||
03622          tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
03623         if (sepc == '/') {
03624             /* Try MM/DD/YYYY format */
03625             int t[3];
03626 
03627             t[0] = tss->year;
03628             t[1] = tss->month;
03629             t[2] = tss->day;
03630             tss->year = t[2];
03631             tss->day = t[1];
03632             tss->month = t[0];
03633         }
03634     }
03635     /* Replace missing year/month/day with current date */
03636     if (!err && (m & 1) == 0) {
03637 #ifdef _WIN32
03638         SYSTEMTIME t;
03639 
03640         GetLocalTime(&t);
03641         tss->year = t.wYear;
03642         tss->month = t.wMonth;
03643         tss->day = t.wDay;
03644 #else
03645         struct timeval tv;
03646         struct tm tm;
03647 
03648         gettimeofday(&tv, NULL);
03649         tm = *localtime(&tv.tv_sec);
03650         tss->year = tm.tm_year + 1900;
03651         tss->month = tm.tm_mon + 1;
03652         tss->day = tm.tm_mday;
03653 #endif
03654     }
03655     /* Normalize fraction */
03656     if (tss->fraction < 0) {
03657         tss->fraction = 0;
03658     }
03659     /* Final check for overflow */
03660     if (err ||
03661         tss->month < 1 || tss->month > 12 ||
03662         tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
03663         tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
03664         return -1;
03665     }
03666     if ((m & 7) > 1) {
03667         if (ampm > 0) {
03668             if (tss->hour < 12) {
03669                 tss->hour += 12;
03670             }
03671         } else if (ampm == 0) {
03672             if (tss->hour == 12) {
03673                 tss->hour = 0;
03674             }
03675         }
03676     }
03677     return ((m & 7) < 1) ? -1 : 0;
03678 }
03679 
03686 static int
03687 getbool(char *string)
03688 {
03689     if (string) {
03690         return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
03691     }
03692     return 0;
03693 }
03694 
03702 static void
03703 blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03704 {
03705 #if 0
03706     DBC *d = (DBC *) sqlite3_user_data(ctx);
03707 #endif
03708     char *filename = 0;
03709 
03710     if (nargs > 0) {
03711         if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
03712             filename = (char *) sqlite3_value_text(args[0]);
03713         }
03714     }
03715     if (filename) {
03716 #ifdef _WIN32
03717         char *wname = utf_to_wmb(filename, -1);
03718         FILE *f;
03719 #else
03720         FILE *f = fopen(filename, "r");
03721 #endif
03722         char *p;
03723         long n, nn;
03724 
03725 #ifdef _WIN32
03726         if (wname) {
03727             f = fopen(wname, "rb");
03728         } else {
03729             sqlite3_result_error(ctx, "out of memory", -1);
03730             return;
03731         }
03732         uc_free(wname);
03733 #endif
03734         if (f) {
03735             if (fseek(f, 0, SEEK_END) == 0) {
03736                 n = ftell(f);
03737                 if (fseek(f, 0, SEEK_SET) == 0) {
03738                     p = sqlite3_malloc(n);
03739                     if (p) {
03740                         nn = fread(p, 1, n, f);
03741                         if (nn != n) {
03742                             sqlite3_result_error(ctx, "read error", -1);
03743                             sqlite3_free(p);
03744                         } else {
03745                             sqlite3_result_blob(ctx, p, n, sqlite3_free);
03746                         }
03747                     } else {
03748                         sqlite3_result_error(ctx, "out of memory", -1);
03749                     }
03750                 } else {
03751                     sqlite3_result_error(ctx, "seek error", -1);
03752                 }
03753             } else {
03754                 sqlite3_result_error(ctx, "seek error", -1);
03755             }
03756             fclose(f);
03757         } else {
03758             sqlite3_result_error(ctx, "cannot open file", -1);
03759         }
03760     } else {
03761         sqlite3_result_error(ctx, "no filename given", -1);
03762     }
03763 }
03764 
03772 static void
03773 blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03774 {
03775 #if 0
03776     DBC *d = (DBC *) sqlite3_user_data(ctx);
03777 #endif
03778     char *filename = 0;
03779     char *p = 0;
03780     int n = 0;
03781 
03782     if (nargs > 0) {
03783         p = (char *) sqlite3_value_blob(args[0]);
03784         n = sqlite3_value_bytes(args[0]);
03785     }
03786     if (nargs > 1) {
03787         if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
03788             filename = (char *) sqlite3_value_text(args[1]);
03789         }
03790     }
03791     if (p) {
03792         if (filename) {
03793 #ifdef _WIN32
03794             char *wname = utf_to_wmb(filename, -1);
03795             FILE *f;
03796 #else
03797             FILE *f = fopen(filename, "w");
03798 #endif
03799             int nn;
03800 
03801 #ifdef _WIN32
03802             if (wname) {
03803                 f = fopen(wname, "wb");
03804             } else {
03805                 sqlite3_result_error(ctx, "out of memory", -1);
03806                 return;
03807             }
03808             uc_free(wname);
03809 #endif
03810             if (f) {
03811                 nn = fwrite(p, 1, n, f);
03812                 fclose(f);
03813                 if (nn != n) {
03814                     sqlite3_result_error(ctx, "write error", -1);
03815                 } else {
03816                     sqlite3_result_int(ctx, nn);
03817                 }
03818             } else {
03819                 sqlite3_result_error(ctx, "cannot open file", -1);
03820             }
03821         } else {
03822             sqlite3_result_error(ctx, "no filename given", -1);
03823         }
03824     } else {
03825         sqlite3_result_null(ctx);
03826     }
03827 }
03828 
03836 static void
03837 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03838 dbtrace(void *arg, const char *msg, sqlite_uint64 et)
03839 #else
03840 dbtrace(void *arg, const char *msg)
03841 #endif
03842 {
03843     DBC *d = (DBC *) arg;
03844 
03845     if (msg && d->trace) {
03846         int len = strlen(msg);
03847 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03848         unsigned long s, f;
03849 #endif
03850 
03851         if (len > 0) {
03852             char *end = "\n";
03853 
03854             if (msg[len - 1] != ';') {
03855                 end = ";\n";
03856             }
03857             fprintf(d->trace, "%s%s", msg, end);
03858 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03859             s = et / 1000000000LL;
03860             f = et % 1000000000LL;
03861             fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
03862 #endif
03863             fflush(d->trace);
03864         }
03865     }
03866 }
03867 
03875 static void
03876 dbtraceapi(DBC *d, char *fn, const char *sql)
03877 {
03878     if (fn && d->trace) {
03879         if (sql) {
03880             fprintf(d->trace, "-- %s: %s\n", fn, sql);
03881         } else {
03882             fprintf(d->trace, "-- %s\n", fn);
03883         }
03884         fflush(d->trace);
03885     }
03886 }
03887 
03895 static void
03896 dbtracerc(DBC *d, int rc, char *err)
03897 {
03898     if (rc != SQLITE_OK && d->trace) {
03899         fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
03900         fprintf(d->trace, err ? ": %s\n" : "\n", err);
03901         fflush(d->trace);
03902     }
03903 }
03904 
03919 static SQLRETURN
03920 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
03921        char *spflag, char *ntflag, char *jmode, char *busy)
03922 {
03923     char *endp = NULL;
03924     int rc, tmp, busyto = 100000;
03925 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03926     int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
03927     char *uname = name;
03928     const char *vfs_name = NULL;
03929 #endif
03930 
03931     if (d->sqlite) {
03932         if (d->trace) {
03933             fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
03934                     d->dbname);
03935             fflush(d->trace);
03936         }
03937 #if defined(HAVE_SQLITE3CLOSEV2) && (HAVE_SQLITE3CLOSEV2)
03938         sqlite3_close_v2(d->sqlite);
03939 #else
03940         sqlite3_close(d->sqlite);
03941 #endif
03942         d->sqlite = NULL;
03943     }
03944 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03945     if (d->nocreat) {
03946         flags &= ~ SQLITE_OPEN_CREATE;
03947     }
03948 #if defined(_WIN32) || defined(_WIN64)
03949     if (!isu) {
03950         char expname[SQL_MAX_MESSAGE_LENGTH * 2];
03951 
03952         expname[0] = '\0';
03953         rc = ExpandEnvironmentStrings(name, expname, sizeof (expname));
03954         if (rc <= sizeof (expname)) {
03955             uname = wmb_to_utf(expname, rc - 1);
03956         } else {
03957             uname = wmb_to_utf(name, -1);
03958         }
03959         if (!uname) {
03960             rc = SQLITE_NOMEM;
03961             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
03962             return SQL_ERROR;
03963         }
03964     }
03965 #endif
03966 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
03967     vfs_name = nvfs_makevfs(uname);
03968 #endif
03969 #ifdef SQLITE_OPEN_URI
03970     flags |= SQLITE_OPEN_URI;
03971 #endif
03972     rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
03973 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
03974     if (uname != name) {
03975         uc_free(uname);
03976     }
03977 #endif
03978 #else
03979 #if defined(_WIN32) || defined(_WIN64)
03980     if (d->nocreat) {
03981         char *cname = NULL;
03982 
03983         if (isu) {
03984             cname = utf_to_wmb(name, -1);
03985         }
03986         if (GetFileAttributesA(cname ? cname : name) ==
03987             INVALID_FILE_ATTRIBUTES) {
03988             uc_free(cname);
03989             rc = SQLITE_CANTOPEN;
03990             setstatd(d, rc, "cannot open database",
03991                      (*d->ov3) ? "HY000" : "S1000");
03992             return SQL_ERROR;
03993         }
03994         uc_free(cname);
03995     }
03996 #else
03997     if (d->nocreat && access(name, 004) < 0) {
03998         rc = SQLITE_CANTOPEN;
03999         setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
04000         return SQL_ERROR;
04001     }
04002 #endif
04003 #if defined(_WIN32) || defined(_WIN64)
04004     if (!isu) {
04005         WCHAR *wname = wmb_to_uc(name, -1);
04006 
04007         if (!wname) {
04008             rc = SQLITE_NOMEM;
04009             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
04010             return SQL_ERROR;
04011         }
04012         rc = sqlite3_open16(wname, &d->sqlite);
04013         uc_free(wname);
04014     } else
04015 #endif
04016     rc = sqlite3_open(name, &d->sqlite);
04017 #endif /* !HAVE_SQLITE3VFS */
04018     if (rc != SQLITE_OK) {
04019 connfail:
04020         setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
04021         if (d->sqlite) {
04022             sqlite3_close(d->sqlite);
04023             d->sqlite = NULL;
04024         }
04025         return SQL_ERROR;
04026     }
04027 #if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
04028     if (d->pwd) {
04029         sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
04030     }
04031 #endif
04032     d->pwd = NULL;
04033     d->pwdLen = 0;
04034     if (d->trace) {
04035 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
04036         sqlite3_profile(d->sqlite, dbtrace, d);
04037 #else
04038         sqlite3_trace(d->sqlite, dbtrace, d);
04039 #endif
04040     }
04041     d->step_enable = getbool(sflag);
04042     d->trans_disable = getbool(ntflag);
04043     d->curtype = d->step_enable ?
04044         SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
04045     tmp = strtol(busy, &endp, 0);
04046     if (endp && *endp == '\0' && endp != busy) {
04047         busyto = tmp;
04048     }
04049     if (busyto < 1 || busyto > 1000000) {
04050         busyto = 1000000;
04051     }
04052     d->timeout = busyto;
04053     freep(&d->dbname);
04054     d->dbname = xstrdup(name);
04055     freep(&d->dsn);
04056     d->dsn = xstrdup(dsn);
04057     if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
04058         if (d->trace) {
04059             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
04060                     d->dbname);
04061             fflush(d->trace);
04062         }
04063         sqlite3_close(d->sqlite);
04064         d->sqlite = NULL;
04065         goto connfail;
04066     }
04067     if (!spflag || spflag[0] == '\0') {
04068         spflag = "NORMAL";
04069     }
04070     if (spflag[0] != '\0') {
04071         char syncp[128];
04072 
04073         sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
04074         sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
04075     }
04076     if (jmode[0] != '\0') {
04077         char jourp[128];
04078 
04079         sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
04080         sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
04081     }
04082     if (d->trace) {
04083         fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
04084         fflush(d->trace);
04085     }
04086 #if defined(_WIN32) || defined(_WIN64)
04087     {
04088         char pname[MAX_PATH];
04089         HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
04090                                FALSE, GetCurrentProcessId());
04091 
04092         pname[0] = '\0';
04093         if (h) {
04094             HMODULE m = NULL, l = LoadLibrary("psapi.dll");
04095             DWORD need;
04096             typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
04097             typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
04098             epmfunc epm;
04099             gmbfunc gmb;
04100 
04101             if (l) {
04102                 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
04103                 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
04104                 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
04105                     gmb(h, m, pname, sizeof (pname));
04106                 }
04107                 FreeLibrary(l);
04108             }
04109             CloseHandle(h);
04110         }
04111         d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
04112                      strncasecmp(pname, "MSQRY", 5) == 0;
04113         if (d->trace && d->xcelqrx) {
04114 
04115             fprintf(d->trace, "-- enabled EXCEL quirks\n");
04116             fflush(d->trace);
04117         }
04118     }
04119 #endif
04120     sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
04121                             d, blob_import, 0, 0);
04122     sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
04123                             d, blob_export, 0, 0);
04124     return SQL_SUCCESS;
04125 }
04126 
04133 static void
04134 dbloadext(DBC *d, char *exts)
04135 {
04136 #if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
04137     char *p;
04138     char path[SQL_MAX_MESSAGE_LENGTH];
04139     int plen = 0;
04140 
04141     if (!d->sqlite) {
04142         return;
04143     }
04144     sqlite3_enable_load_extension(d->sqlite, 1);
04145 #if defined(_WIN32) || defined(_WIN64)
04146     GetModuleFileName(hModule, path, sizeof (path));
04147     p = strrchr(path, '\\');
04148     plen = p ? ((p + 1) - path) : 0;
04149 #endif
04150     do {
04151         p = strchr(exts, ',');
04152         if (p) {
04153             strncpy(path + plen, exts, p - exts);
04154             path[plen + (p - exts)] = '\0';
04155         } else {
04156             strcpy(path + plen, exts);
04157         }
04158         if (exts[0]) {
04159             char *errmsg = NULL;
04160             int rc;
04161 #if defined(_WIN32) || defined(_WIN64)
04162             int i;
04163             char *q;
04164 
04165             q = path + plen;
04166             if (!(q[0] &&
04167                   ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
04168                    q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
04169                 q = path;
04170             }
04171             /* sqlite3_load_extension() dislikes backslashes */
04172             for (i = 0; q[i] != '\0'; i++) {
04173                 if (q[i] == '\\') {
04174                     q[i] = '/';
04175                 }
04176             }
04177             rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
04178 #else
04179             rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
04180 #endif
04181             if (rc != SQLITE_OK) {
04182 #if defined(_WIN32) || defined(_WIN64)
04183                 char buf[512], msg[512];
04184 
04185                 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
04186                 wsprintf(msg, buf, q, errmsg ?
04187                          errmsg : "no error info available");
04188                 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
04189                 MessageBox(NULL, msg, buf,
04190                            MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
04191                            MB_SETFOREGROUND);
04192 #else
04193                 fprintf(stderr, "extension '%s' did not load%s%s\n",
04194                         path, errmsg ? ": " : "", errmsg ? errmsg : "");
04195 #endif
04196             }
04197         }
04198         if (p) {
04199             exts = p + 1;
04200         }
04201     } while (p);
04202 #endif /* HAVE_SQLITE3LOADEXTENSION */
04203 }
04204 
04214 static char *
04215 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
04216 {
04217     char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
04218     char guess[64];
04219 
04220     guess[0] = '\0';
04221     if (!typename) {
04222         int coltype = sqlite3_column_type(s3stmt, col);
04223 
04224         if (guessed_types) {
04225             guessed_types[0]++;
04226         }
04227         if (d->trace) {
04228             sprintf(guess, " (guessed from %d)", coltype);
04229         }
04230         switch (coltype) {
04231         case SQLITE_INTEGER: typename = "integer"; break;
04232         case SQLITE_FLOAT:   typename = "double";  break;
04233         default:
04234         case SQLITE_TEXT:    typename = "varchar"; break;
04235         case SQLITE_BLOB:    typename = "blob";    break;
04236 #if 0
04237         case SQLITE_NULL:    typename = "null";    break;
04238 #endif
04239         }
04240     }
04241     if (d->trace) {
04242         fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
04243                 guess, typename);
04244         fflush(d->trace);
04245     }
04246     return typename;
04247 }
04248 
04249 #ifdef FULL_METADATA
04250 
04259 static void
04260 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
04261 {
04262     int nn = 0, pk = 0, ai = 0;
04263     const char *dn = NULL, *tn = NULL, *cn = NULL, *dummy[4];
04264 
04265     dn = sqlite3_column_database_name(s3stmt, col);
04266     tn = sqlite3_column_table_name(s3stmt, col);
04267     cn = sqlite3_column_origin_name(s3stmt, col);
04268     dummy[0] = dummy[1] = 0;
04269     if (tn && cn) {
04270         sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
04271                                       dummy, dummy + 1,
04272                                       &nn, &pk, &ai);
04273     }
04274     ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
04275     ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
04276     ci->ispk = pk ? 1 : 0;
04277     if (d->trace) {
04278         fprintf(d->trace, "-- column %d %s\n",
04279                 col + 1, nn ? "notnull" : "nullable");
04280         if (ai) {
04281             fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
04282         }
04283         fflush(d->trace);
04284     }
04285     ci->isrowid = 0;
04286     if (ci->ispk && tn) {
04287         nn = pk = ai = 0;
04288         dummy[2] = dummy[3] = 0;
04289 
04290         sqlite3_table_column_metadata(d->sqlite, dn, tn, "rowid",
04291                                       dummy + 2, dummy + 3,
04292                                       &nn, &pk, &ai);
04293         if (pk && dummy[0] && dummy[0] == dummy[2]) {
04294             ci->isrowid = 1;
04295         }
04296     }
04297 }
04298 
04299 #endif
04300 
04307 static int
04308 s3stmt_step(STMT *s)
04309 {
04310     DBC *d = (DBC *) s->dbc;
04311     char **rowd = NULL;
04312     const char *errp = NULL;
04313     int i, ncols, rc;
04314 
04315     if (s != d->cur_s3stmt || !s->s3stmt) {
04316         setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
04317         return SQL_ERROR;
04318     }
04319     rc = sqlite3_step(s->s3stmt);
04320     if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
04321         ++s->s3stmt_rownum;
04322         ncols = sqlite3_column_count(s->s3stmt);
04323         if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
04324             PTRDIFF_T size;
04325             char *p;
04326             COL *dyncols;
04327             const char *colname, *typename;
04328 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04329             char *tblname;
04330 #endif
04331 
04332             for (i = size = 0; i < ncols; i++) {
04333                 colname = sqlite3_column_name(s->s3stmt, i);
04334                 size += 3 + 3 * strlen(colname);
04335             }
04336 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04337             tblname = (char *) size;
04338             for (i = 0; i < ncols; i++) {
04339                 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
04340                 size += 2 + (p ? strlen(p) : 0);
04341             }
04342 #endif
04343             dyncols = xmalloc(ncols * sizeof (COL) + size);
04344             if (!dyncols) {
04345                 freedyncols(s);
04346                 s->ncols = 0;
04347                 dbtraceapi(d, "sqlite3_finalize", 0);
04348                 sqlite3_finalize(s->s3stmt);
04349                 s->s3stmt = NULL;
04350                 d->cur_s3stmt = NULL;
04351                 return nomem(s);
04352             }
04353             p = (char *) (dyncols + ncols);
04354 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04355             tblname = p + (PTRDIFF_T) tblname;
04356 #endif
04357             for (i = 0; i < ncols; i++) {
04358                 char *q;
04359 
04360                 colname = sqlite3_column_name(s->s3stmt, i);
04361                 if (d->trace) {
04362                     fprintf(d->trace, "-- column %d name: '%s'\n",
04363                             i + 1, colname);
04364                     fflush(d->trace);
04365                 }
04366 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04367                 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
04368                 strcpy(tblname, q ? q : "");
04369                 if (d->trace) {
04370                     fprintf(d->trace, "-- table %d name: '%s'\n",
04371                             i + 1, tblname);
04372                     fflush(d->trace);
04373                 }
04374                 dyncols[i].table = tblname;
04375                 tblname += strlen(tblname) + 1;
04376 #endif
04377                 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
04378                 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
04379                 strcpy(p, colname);
04380                 dyncols[i].label = p;
04381                 p += strlen(p) + 1;
04382                 q = strchr(colname, '.');
04383                 if (q) {
04384                     char *q2 = strchr(q + 1, '.');
04385 
04386                     /* SQLite 3.3.4 produces view.table.column sometimes */
04387                     if (q2) {
04388                         q = q2;
04389                     }
04390                 }
04391                 if (q) {
04392 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04393                     dyncols[i].table = p;
04394 #endif
04395                     strncpy(p, colname, q - colname);
04396                     p[q - colname] = '\0';
04397                     p += strlen(p) + 1;
04398                     strcpy(p, q + 1);
04399                     dyncols[i].column = p;
04400                     p += strlen(p) + 1;
04401                 } else {
04402 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04403                     dyncols[i].table = "";
04404 #endif
04405                     strcpy(p, colname);
04406                     dyncols[i].column = p;
04407                     p += strlen(p) + 1;
04408                 }
04409                 if (s->longnames) {
04410                     dyncols[i].column = dyncols[i].label;
04411                 }
04412 #ifdef SQL_LONGVARCHAR
04413                 dyncols[i].type = SQL_LONGVARCHAR;
04414                 dyncols[i].size = 65535;
04415 #else
04416                 dyncols[i].type = SQL_VARCHAR;
04417                 dyncols[i].size = 255;
04418 #endif
04419                 dyncols[i].index = i;
04420                 dyncols[i].scale = 0;
04421                 dyncols[i].prec = 0;
04422                 dyncols[i].nosign = 1;
04423                 dyncols[i].autoinc = SQL_FALSE;
04424                 dyncols[i].notnull = SQL_NULLABLE;
04425                 dyncols[i].ispk = -1;
04426                 dyncols[i].isrowid = -1;
04427 #ifdef FULL_METADATA
04428                 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
04429 #endif
04430                 dyncols[i].typename = xstrdup(typename);
04431             }
04432             freedyncols(s);
04433             s->ncols = s->dcols = ncols;
04434             s->dyncols = s->cols = dyncols;
04435             fixupdyncols(s, d);
04436             mkbindcols(s, s->ncols);
04437             d->s3stmt_needmeta = 0;
04438         }
04439         if (ncols <= 0) {
04440             goto killstmt;
04441         }
04442         if (rc == SQLITE_DONE) {
04443             freeresult(s, 0);
04444             s->nrows = 0;
04445             dbtraceapi(d, "sqlite3_finalize", 0);
04446             sqlite3_finalize(s->s3stmt);
04447             s->s3stmt = NULL;
04448             d->cur_s3stmt = NULL;
04449             return SQL_SUCCESS;
04450         }
04451         rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
04452         if (rowd) {
04453             const unsigned char *value;
04454 
04455             rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
04456             ++rowd;
04457             for (i = 0; i < ncols; i++) {
04458                 int coltype = sqlite3_column_type(s->s3stmt, i);
04459 
04460                 rowd[i] = rowd[i + ncols] = NULL;
04461                 if (coltype == SQLITE_BLOB) {
04462                     int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
04463                     char *qp;
04464                     unsigned const char *bp;
04465 
04466                     bp = sqlite3_column_blob(s->s3stmt, i);
04467                     qp = xmalloc(nbytes * 2 + 4);
04468                     if (qp) {
04469                         rowd[i + ncols] = qp;
04470                         *qp++ = 'X';
04471                         *qp++ = '\'';
04472                         for (k = 0; k < nbytes; k++) {
04473                             *qp++ = xdigits[(bp[k] >> 4)];
04474                             *qp++ = xdigits[(bp[k] & 0xF)];
04475                         }
04476                         *qp++ = '\'';
04477                         *qp = '\0';
04478                     }
04479 #ifdef _MSC_VER
04480                 } else if (coltype == SQLITE_FLOAT) {
04481                     struct lconv *lc = 0;
04482                     double d = sqlite3_column_double(s->s3stmt, i);
04483                     char *p, buffer[128];
04484 
04485                     /*
04486                      * This avoids floating point rounding
04487                      * and formatting problems of some SQLite
04488                      * versions in conjunction with MSVC 2010.
04489                      */
04490                     snprintf(buffer, sizeof (buffer), "%.15g", d);
04491                     lc = localeconv();
04492                     if (lc && lc->decimal_point && lc->decimal_point[0] &&
04493                         lc->decimal_point[0] != '.') {
04494                         p = strchr(buffer, lc->decimal_point[0]);
04495                         if (p) {
04496                             *p = '.';
04497                         }
04498                     }
04499                     rowd[i + ncols] = xstrdup(buffer);
04500 #endif
04501                 } else if (coltype != SQLITE_NULL) {
04502                     value = sqlite3_column_text(s->s3stmt, i);
04503                     rowd[i + ncols] = xstrdup((char *) value);
04504                 }
04505             }
04506             for (i = 0; i < ncols; i++) {
04507                 int coltype = sqlite3_column_type(s->s3stmt, i);
04508 
04509                 value = NULL;
04510                 if (coltype == SQLITE_BLOB) {
04511                     value = sqlite3_column_blob(s->s3stmt, i);
04512                 } else if (coltype != SQLITE_NULL) {
04513                     value = sqlite3_column_text(s->s3stmt, i);
04514                 }
04515                 if (value && !rowd[i + ncols]) {
04516                     freerows(rowd);
04517                     rowd = 0;
04518                     break;
04519                 }
04520             }
04521         }
04522         if (rowd) {
04523             freeresult(s, 0);
04524             s->nrows = 1;
04525             s->rows = rowd;
04526             s->rowfree = freerows;
04527             if (rc == SQLITE_DONE) {
04528                 dbtraceapi(d, "sqlite3_finalize", 0);
04529                 sqlite3_finalize(s->s3stmt);
04530                 s->s3stmt = NULL;
04531                 d->cur_s3stmt = NULL;
04532             }
04533             return SQL_SUCCESS;
04534         }
04535     }
04536 killstmt:
04537     dbtraceapi(d, "sqlite3_reset", 0);
04538     rc = sqlite3_reset(s->s3stmt);
04539     s->s3stmt_noreset = 1;
04540     errp = sqlite3_errmsg(d->sqlite);
04541     if (d->cur_s3stmt == s) {
04542         d->cur_s3stmt = NULL;
04543     }
04544     setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04545             errp ? errp : "unknown error", rc);
04546     return SQL_ERROR;
04547 }
04548 
04554 static void
04555 s3stmt_end(STMT *s)
04556 {
04557     DBC *d;
04558 
04559     if (!s || !s->s3stmt) {
04560         return;
04561     }
04562     d = (DBC *) s->dbc;
04563     if (d) {
04564         d->busyint = 0;
04565     }
04566     if (!s->s3stmt_noreset) {
04567         dbtraceapi(d, "sqlite3_reset", 0);
04568         sqlite3_reset(s->s3stmt);
04569         s->s3stmt_noreset = 1;
04570         s->s3stmt_rownum = -1;
04571     }
04572     if (d->cur_s3stmt == s) {
04573         d->cur_s3stmt = NULL;
04574     }
04575 }
04576 
04582 static void
04583 s3stmt_end_if(STMT *s)
04584 {
04585     DBC *d = (DBC *) s->dbc;
04586 
04587     if (d) {
04588         d->busyint = 0;
04589     }
04590     if (d && d->cur_s3stmt == s) {
04591         s3stmt_end(s);
04592     }
04593 }
04594 
04600 static void
04601 s3stmt_drop(STMT *s)
04602 {
04603     if (s->s3stmt) {
04604         DBC *d = (DBC *) s->dbc;
04605 
04606         if (d) {
04607             dbtraceapi(d, "sqlite3_finalize", 0);
04608         }
04609         sqlite3_finalize(s->s3stmt);
04610         s->s3stmt = NULL;
04611         s->s3stmt_rownum = 0;
04612     }
04613 }
04614 
04621 static SQLRETURN
04622 s3stmt_start(STMT *s)
04623 {
04624     DBC *d = (DBC *) s->dbc;
04625     const char *endp;
04626     sqlite3_stmt *s3stmt = NULL;
04627     int rc, nretry = 0;
04628 
04629     d->s3stmt_needmeta = 0;
04630     if (!s->s3stmt) {
04631 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04632         dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
04633 #else
04634         dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
04635 #endif
04636         do {
04637             s3stmt = NULL;
04638 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04639             rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
04640                                     &s3stmt, &endp);
04641 #else
04642             rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
04643                                  &s3stmt, &endp);
04644 #endif
04645             if (rc != SQLITE_OK) {
04646                 if (s3stmt) {
04647                     sqlite3_finalize(s3stmt);
04648                     s3stmt = NULL;
04649                 }
04650             }
04651         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
04652         dbtracerc(d, rc, NULL);
04653         if (rc != SQLITE_OK) {
04654             if (s3stmt) {
04655                 dbtraceapi(d, "sqlite3_finalize", NULL);
04656                 sqlite3_finalize(s3stmt);
04657             }
04658             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04659                     sqlite3_errmsg(d->sqlite), rc);
04660             return SQL_ERROR;
04661         }
04662         if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
04663             dbtraceapi(d, "sqlite3_finalize", 0);
04664             sqlite3_finalize(s3stmt);
04665             setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
04666                     (*s->ov3) ? "HY000" : "S1000");
04667             return SQL_ERROR;
04668         }
04669         s->s3stmt = s3stmt;
04670         s->s3stmt_noreset = 1;
04671         d->s3stmt_needmeta = 1;
04672     }
04673     d->cur_s3stmt = s;
04674     s->s3stmt_rownum = -1;
04675     s3bind(d, s->s3stmt, s->nparams, s->bindparms);
04676     return SQL_SUCCESS;
04677 }
04678 
04679 #ifndef WINTERFACE
04680 
04684 SQLRETURN SQL_API
04685 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
04686                SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04687                SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04688 {
04689     if (env == SQL_NULL_HENV) {
04690         return SQL_INVALID_HANDLE;
04691     }
04692     return SQL_ERROR;
04693 }
04694 #endif
04695 
04696 #ifdef WINTERFACE
04697 
04701 SQLRETURN SQL_API
04702 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
04703                 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04704                 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04705 {
04706     if (env == SQL_NULL_HENV) {
04707         return SQL_INVALID_HANDLE;
04708     }
04709     return SQL_ERROR;
04710 }
04711 #endif
04712 
04713 #ifndef WINTERFACE
04714 
04718 SQLRETURN SQL_API
04719 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
04720            SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04721            SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04722 {
04723     if (env == SQL_NULL_HENV) {
04724         return SQL_INVALID_HANDLE;
04725     }
04726     return SQL_ERROR;
04727 }
04728 #endif
04729 
04730 #ifdef WINTERFACE
04731 
04735 SQLRETURN SQL_API
04736 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
04737             SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04738             SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04739 {
04740     if (env == SQL_NULL_HENV) {
04741         return SQL_INVALID_HANDLE;
04742     }
04743     return SQL_ERROR;
04744 }
04745 #endif
04746 
04747 #ifndef WINTERFACE
04748 
04752 SQLRETURN SQL_API
04753 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
04754                  SQLCHAR *connout, SQLSMALLINT connoutMax,
04755                  SQLSMALLINT *connoutLen)
04756 {
04757     SQLRETURN ret;
04758 
04759     HDBC_LOCK(dbc);
04760     ret = drvunimpldbc(dbc);
04761     HDBC_UNLOCK(dbc);
04762     return ret;
04763 }
04764 #endif
04765 
04766 #ifdef WINTERFACE
04767 
04771 SQLRETURN SQL_API
04772 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
04773                   SQLWCHAR *connout, SQLSMALLINT connoutMax,
04774                   SQLSMALLINT *connoutLen)
04775 {
04776     SQLRETURN ret;
04777 
04778     HDBC_LOCK(dbc);
04779     ret = drvunimpldbc(dbc);
04780     HDBC_UNLOCK(dbc);
04781     return ret;
04782 }
04783 #endif
04784 
04793 static SQLRETURN
04794 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
04795 {
04796     STMT *s;
04797     int i, dlen, done = 0;
04798     BINDPARM *p;
04799 
04800     if (stmt == SQL_NULL_HSTMT) {
04801         return SQL_INVALID_HANDLE;
04802     }
04803     s = (STMT *) stmt;
04804     if (!s->query || s->nparams <= 0) {
04805 seqerr:
04806         setstat(s, -1, "sequence error", "HY010");
04807         return SQL_ERROR;
04808     }
04809     for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
04810         p = &s->bindparms[i];
04811         if (p->need > 0) {
04812             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
04813 
04814             if (len == SQL_NULL_DATA) {
04815                 freep(&p->parbuf);
04816                 p->param = NULL;
04817                 p->len = SQL_NULL_DATA;
04818                 p->need = -1;
04819             } else if (type != SQL_C_CHAR
04820 #ifdef WCHARSUPPORT
04821                        && type != SQL_C_WCHAR
04822 #endif
04823                        && type != SQL_C_BINARY) {
04824                 int size = 0;
04825 
04826                 switch (type) {
04827                 case SQL_C_TINYINT:
04828                 case SQL_C_UTINYINT:
04829                 case SQL_C_STINYINT:
04830 #ifdef SQL_BIT
04831                 case SQL_C_BIT:
04832 #endif
04833                     size = sizeof (SQLCHAR);
04834                     break;
04835                 case SQL_C_SHORT:
04836                 case SQL_C_USHORT:
04837                 case SQL_C_SSHORT:
04838                     size = sizeof (SQLSMALLINT);
04839                     break;
04840                 case SQL_C_LONG:
04841                 case SQL_C_ULONG:
04842                 case SQL_C_SLONG:
04843                     size = sizeof (SQLINTEGER);
04844                     break;
04845 #ifdef SQL_BIGINT
04846                 case SQL_C_UBIGINT:
04847                 case SQL_C_SBIGINT:
04848                     size = sizeof (SQLBIGINT);
04849                     break;
04850 #endif
04851                 case SQL_C_FLOAT:
04852                     size = sizeof (float);
04853                     break;
04854                 case SQL_C_DOUBLE:
04855                     size = sizeof (double);
04856                     break;
04857 #ifdef SQL_C_TYPE_DATE
04858                 case SQL_C_TYPE_DATE:
04859 #endif
04860                 case SQL_C_DATE:
04861                     size = sizeof (DATE_STRUCT);
04862                     break;
04863 #ifdef SQL_C_TYPE_DATE
04864                 case SQL_C_TYPE_TIME:
04865 #endif
04866                 case SQL_C_TIME:
04867                     size = sizeof (TIME_STRUCT);
04868                     break;
04869 #ifdef SQL_C_TYPE_DATE
04870                 case SQL_C_TYPE_TIMESTAMP:
04871 #endif
04872                 case SQL_C_TIMESTAMP:
04873                     size = sizeof (TIMESTAMP_STRUCT);
04874                     break;
04875                 }
04876                 freep(&p->parbuf);
04877                 p->parbuf = xmalloc(size);
04878                 if (!p->parbuf) {
04879                     return nomem(s);
04880                 }
04881                 p->param = p->parbuf;
04882                 memcpy(p->param, data, size);
04883                 p->len = size;
04884                 p->need = -1;
04885             } else if (len == SQL_NTS && (
04886                        type == SQL_C_CHAR
04887 #ifdef WCHARSUPPORT
04888                        || type == SQL_C_WCHAR
04889 #endif
04890                       )) {
04891                 char *dp = data;
04892 
04893 #ifdef WCHARSUPPORT
04894                 if (type == SQL_C_WCHAR) {
04895                     dp = uc_to_utf(data, len);
04896                     if (!dp) {
04897                         return nomem(s);
04898                     }
04899                 }
04900 #endif
04901 #if defined(_WIN32) || defined(_WIN64)
04902                 if (*s->oemcp) {
04903                     dp = wmb_to_utf(data, strlen (data));
04904                     if (!dp) {
04905                         return nomem(s);
04906                     }
04907                 }
04908 #endif
04909                 dlen = strlen(dp);
04910                 freep(&p->parbuf);
04911                 p->parbuf = xmalloc(dlen + 1);
04912                 if (!p->parbuf) {
04913                     if (dp != data) {
04914                         uc_free(dp);
04915                     }
04916                     return nomem(s);
04917                 }
04918                 p->param = p->parbuf;
04919                 strcpy(p->param, dp);
04920                 if (dp != data) {
04921                     uc_free(dp);
04922                 }
04923                 p->len = dlen;
04924                 p->need = -1;
04925             } else if (len < 0) {
04926                 setstat(s, -1, "invalid length", "HY090");
04927                 return SQL_ERROR;
04928             } else {
04929                 dlen = min(p->len - p->offs, len);
04930                 if (!p->param) {
04931                     setstat(s, -1, "no memory for parameter", "HY013");
04932                     return SQL_ERROR;
04933                 }
04934                 memcpy((char *) p->param + p->offs, data, dlen);
04935                 p->offs += dlen;
04936                 if (p->offs >= p->len) {
04937 #ifdef WCHARSUPPORT
04938                     if (type == SQL_C_WCHAR) {
04939                         char *dp = uc_to_utf(p->param, p->len);
04940                         char *np;
04941                         int nlen;
04942 
04943                         if (!dp) {
04944                             return nomem(s);
04945                         }
04946                         nlen = strlen(dp);
04947                         np = xmalloc(nlen + 1);
04948                         if (!np) {
04949                             uc_free(dp);
04950                             return nomem(s);
04951                         }
04952                         strcpy(np, dp);
04953                         uc_free(dp);
04954                         if (p->param == p->parbuf) {
04955                             freep(&p->parbuf);
04956                         }
04957                         p->parbuf = p->param = np;
04958                         p->len = nlen;
04959                     } else {
04960                         *((char *) p->param + p->len) = '\0';
04961                     }
04962                     p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
04963                             ? -1 : 0;
04964 #else
04965                     *((char *) p->param + p->len) = '\0';
04966                     p->need = (type == SQL_C_CHAR) ? -1 : 0;
04967 #endif
04968 #if defined(_WIN32) || defined(_WIN64)
04969                     if (type == SQL_C_CHAR && *s->oemcp &&
04970                         !(p->stype == SQL_BINARY ||
04971                           p->stype == SQL_VARBINARY ||
04972                           p->stype == SQL_LONGVARBINARY)) {
04973                         char *dp = wmb_to_utf(p->param, p->len);
04974 
04975                         if (!dp) {
04976                             return nomem(s);
04977                         }
04978                         if (p->param == p->parbuf) {
04979                             freep(&p->parbuf);
04980                         }
04981                         p->parbuf = p->param = dp;
04982                         p->len = strlen(dp);
04983                     }
04984                     if (p->type == SQL_C_WCHAR &&
04985                         (p->stype == SQL_VARCHAR ||
04986                          p->stype == SQL_LONGVARCHAR) &&
04987                          p->len == p->coldef * sizeof (SQLWCHAR)) {
04988                         /* fix for MS-Access */
04989                         p->len = p->coldef;
04990                     }
04991 #endif
04992                 }
04993             }
04994             done = 1;
04995             break;
04996         }
04997     }
04998     if (!done) {
04999         goto seqerr;
05000     }
05001     return SQL_SUCCESS;
05002 }
05003 
05012 SQLRETURN SQL_API
05013 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
05014 {
05015     SQLRETURN ret;
05016 
05017     HSTMT_LOCK(stmt);
05018     ret = drvputdata(stmt, data, len);
05019     HSTMT_UNLOCK(stmt);
05020     return ret;
05021 }
05022 
05028 static SQLRETURN
05029 freeparams(STMT *s)
05030 {
05031     if (s->bindparms) {
05032         int n;
05033 
05034         for (n = 0; n < s->nbindparms; n++) {
05035             freep(&s->bindparms[n].parbuf);
05036             memset(&s->bindparms[n], 0, sizeof (BINDPARM));
05037         }
05038     }
05039     return SQL_SUCCESS;
05040 }
05041 
05053 static SQLRETURN
05054 setupparam(STMT *s, char *sql, int pnum)
05055 {
05056     int type, len = 0, needalloc = 0;
05057     BINDPARM *p;
05058 
05059     if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
05060         goto error;
05061     }
05062     p = &s->bindparms[pnum];
05063     type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05064 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
05065     /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
05066     if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
05067         type = SQL_C_CHAR;
05068     }
05069 #endif
05070     if (p->need > 0) {
05071         return setupparbuf(s, p);
05072     }
05073     p->strbuf[0] = '\0';
05074     if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
05075         p->s3type = SQLITE_NULL;
05076         p->s3size = 0;
05077         return SQL_SUCCESS;
05078     }
05079     if (type == SQL_C_CHAR &&
05080         (p->stype == SQL_BINARY ||
05081          p->stype == SQL_VARBINARY ||
05082          p->stype == SQL_LONGVARBINARY)) {
05083         type = SQL_C_BINARY;
05084     }
05085     switch (type) {
05086     case SQL_C_BINARY:
05087         p->s3type = SQLITE_BLOB;
05088         p->s3size = p->len;
05089         p->s3val = p->param;
05090         if (p->need < 0) {
05091             break;
05092         }
05093         if (!p->lenp) {
05094             len = p->len;
05095         } else if (*p->lenp == SQL_DATA_AT_EXEC) {
05096             len = p->len;
05097         } else {
05098             len = *p->lenp;
05099             if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
05100                 len = SQL_LEN_DATA_AT_EXEC(len);
05101             }
05102         }
05103         if (len < 0) {
05104             setstat(s, -1, "invalid length", "HY009");
05105             return SQL_ERROR;
05106         }
05107         p->len = len;
05108         p->max = p->len;
05109         p->need = -1;
05110         p->s3size = len;
05111         break;
05112 #ifdef WCHARSUPPORT
05113     case SQL_C_WCHAR:
05114 #endif
05115     case SQL_C_CHAR:
05116         p->s3type = SQLITE_TEXT;
05117         p->s3size = -1;
05118         p->s3val = p->param;
05119         if (!p->parbuf) {
05120 #ifdef WCHARSUPPORT
05121             if (type == SQL_C_WCHAR) {
05122                 if (!p->lenp || *p->lenp == SQL_NTS) {
05123                     p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
05124                 } else if (*p->lenp >= 0) {
05125                     p->max = *p->lenp;
05126                 }
05127             } else
05128 #endif
05129             if (type == SQL_C_CHAR) {
05130                 if (!p->lenp || *p->lenp == SQL_NTS) {
05131                     p->len = p->max = strlen(p->param);
05132 #if defined(_WIN32) || defined(_WIN64)
05133                     needalloc = 1;
05134 #endif
05135                 } else if (*p->lenp >= 0) {
05136                     p->len = p->max = *p->lenp;
05137                     needalloc = 1;
05138                 }
05139             }
05140         }
05141         if (p->need < 0 && p->parbuf == p->param) {
05142             break;
05143         }
05144 #ifdef WCHARSUPPORT
05145         if (type == SQL_C_WCHAR) {
05146             char *dp = uc_to_utf(p->param, p->max);
05147 
05148             if (!dp) {
05149                 return nomem(s);
05150             }
05151             if (p->param == p->parbuf) {
05152                 freep(&p->parbuf);
05153             }
05154             p->parbuf = p->param = dp;
05155             p->need = -1;
05156             p->len = strlen(p->param);
05157             p->s3val = p->param;
05158             p->s3size = p->len;
05159         } else
05160 #endif
05161         if (type == SQL_C_CHAR) {
05162             p->s3val = p->param;
05163             if (needalloc) {
05164                 char *dp;
05165 
05166 #if defined(_WIN32) || defined(_WIN64)
05167                 if (*s->oemcp) {
05168                     dp = wmb_to_utf(p->param, p->len);
05169                 } else {
05170                     dp = xmalloc(p->len + 1);
05171                 }
05172 #else
05173                 dp = xmalloc(p->len + 1);
05174 #endif
05175                 if (!dp) {
05176                     return nomem(s);
05177                 }
05178 #if defined(_WIN32) || defined(_WIN64)
05179                 if (*s->oemcp) {
05180                     p->len = strlen(dp);
05181                 } else {
05182                     memcpy(dp, p->param, p->len);
05183                     dp[p->len] = '\0';
05184                 }
05185 #else
05186                 memcpy(dp, p->param, p->len);
05187                 dp[p->len] = '\0';
05188 #endif
05189                 if (p->param == p->parbuf) {
05190                     freep(&p->parbuf);
05191                 }
05192                 p->parbuf = p->param = dp;
05193                 p->need = -1;
05194                 p->s3val = p->param;
05195                 p->s3size = p->len;
05196             }
05197         }
05198         break;
05199     case SQL_C_UTINYINT:
05200     case SQL_C_TINYINT:
05201     case SQL_C_STINYINT:
05202         p->s3type = SQLITE_INTEGER;
05203         p->s3size = sizeof (int);
05204         p->s3ival = *((SQLCHAR *) p->param);
05205         break;
05206     case SQL_C_USHORT:
05207         p->s3type = SQLITE_INTEGER;
05208         p->s3size = sizeof (int);
05209         p->s3ival = *((SQLUSMALLINT *) p->param);
05210         break;
05211     case SQL_C_SHORT:
05212     case SQL_C_SSHORT:
05213         p->s3type = SQLITE_INTEGER;
05214         p->s3size = sizeof (int);
05215         p->s3ival = *((SQLSMALLINT *) p->param);
05216         break;
05217     case SQL_C_ULONG:
05218         p->s3type = SQLITE_INTEGER;
05219         p->s3size = sizeof (int);
05220         p->s3ival = *((SQLUINTEGER *) p->param);
05221         break;
05222     case SQL_C_LONG:
05223     case SQL_C_SLONG:
05224         p->s3type = SQLITE_INTEGER;
05225         p->s3size = sizeof (int);
05226         p->s3ival = *((SQLINTEGER *) p->param);
05227         break;
05228 #ifdef SQL_BIT
05229     case SQL_C_BIT:
05230         p->s3type = SQLITE_INTEGER;
05231         p->s3size = sizeof (int);
05232         p->s3ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
05233         break;
05234 #endif
05235 #ifdef SQL_BIGINT
05236     case SQL_C_SBIGINT:
05237         p->s3type = SQLITE_INTEGER;
05238         p->s3size = sizeof (sqlite_int64);
05239         p->s3lival = *((sqlite_int64 *) p->param);
05240         break;
05241     case SQL_C_UBIGINT:
05242         p->s3type = SQLITE_INTEGER;
05243         p->s3size = sizeof (sqlite_int64);
05244         p->s3lival = *((sqlite_uint64 *) p->param);
05245         break;
05246 #endif
05247     case SQL_C_FLOAT:
05248         p->s3type = SQLITE_FLOAT;
05249         p->s3size = sizeof (double);
05250         p->s3dval = *((float *) p->param);
05251         break;
05252     case SQL_C_DOUBLE:
05253         p->s3type = SQLITE_FLOAT;
05254         p->s3size = sizeof (double);
05255         p->s3dval = *((double *) p->param);
05256         break;
05257 #ifdef SQL_C_TYPE_DATE
05258     case SQL_C_TYPE_DATE:
05259 #endif
05260     case SQL_C_DATE:
05261         if (*s->jdconv) {
05262             int a, b, x1, x2, y, m, d;
05263 
05264             p->s3type = SQLITE_FLOAT;
05265             p->s3size = sizeof (double);
05266             y = ((DATE_STRUCT *) p->param)->year;
05267             m = ((DATE_STRUCT *) p->param)->month;
05268             d = ((DATE_STRUCT *) p->param)->day;
05269             if (m <= 2) {
05270                 y--;
05271                 m += 12;
05272             }
05273             a = y / 100;
05274             b = 2 - a + (a / 4);
05275             x1 = 36525 * (y + 4716) / 100;
05276             x2 = 306001 * (m + 1) / 10000;
05277             p->s3dval = x1 + x2 + d + b - 1524.5;
05278             break;
05279         }
05280         sprintf(p->strbuf, "%04d-%02d-%02d",
05281                 ((DATE_STRUCT *) p->param)->year,
05282                 ((DATE_STRUCT *) p->param)->month,
05283                 ((DATE_STRUCT *) p->param)->day);
05284         p->s3type = SQLITE_TEXT;
05285         p->s3size = -1;
05286         p->s3val = p->strbuf;
05287         break;
05288 #ifdef SQL_C_TYPE_TIME
05289     case SQL_C_TYPE_TIME:
05290 #endif
05291     case SQL_C_TIME:
05292         if (*s->jdconv) {
05293             p->s3type = SQLITE_FLOAT;
05294             p->s3size = sizeof (double);
05295             p->s3dval = 2451544.5 +
05296                (((TIME_STRUCT *) p->param)->hour * 3600000.0 +
05297                 ((TIME_STRUCT *) p->param)->minute * 60000.0 +
05298                 ((TIME_STRUCT *) p->param)->second * 1000.0) / 86400000.0;
05299             break;
05300         }
05301         sprintf(p->strbuf, "%02d:%02d:%02d",
05302                 ((TIME_STRUCT *) p->param)->hour,
05303                 ((TIME_STRUCT *) p->param)->minute,
05304                 ((TIME_STRUCT *) p->param)->second);
05305         p->s3type = SQLITE_TEXT;
05306         p->s3size = -1;
05307         p->s3val = p->strbuf;
05308         break;
05309 #ifdef SQL_C_TYPE_TIMESTAMP
05310     case SQL_C_TYPE_TIMESTAMP:
05311 #endif
05312     case SQL_C_TIMESTAMP:
05313         if (*s->jdconv) {
05314             int a, b, x1, x2, y, m, d;
05315 
05316             p->s3type = SQLITE_FLOAT;
05317             p->s3size = sizeof (double);
05318             y = ((TIMESTAMP_STRUCT *) p->param)->year;
05319             m = ((TIMESTAMP_STRUCT *) p->param)->month;
05320             d = ((TIMESTAMP_STRUCT *) p->param)->day;
05321             if (m <= 2) {
05322                 y--;
05323                 m += 12;
05324             }
05325             a = y / 100;
05326             b = 2 - a + (a / 4);
05327             x1 = 36525 * (y + 4716) / 100;
05328             x2 = 306001 * (m + 1) / 10000;
05329             p->s3dval = x1 + x2 + d + b - 1524.5 +
05330                (((TIMESTAMP_STRUCT *) p->param)->hour * 3600000.0 +
05331                 ((TIMESTAMP_STRUCT *) p->param)->minute * 60000.0 +
05332                 ((TIMESTAMP_STRUCT *) p->param)->second * 1000.0 +
05333                 ((TIMESTAMP_STRUCT *) p->param)->fraction / 1.0E6)
05334                / 86400000.0;
05335             break;
05336         }
05337         len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
05338         len /= 1000000;
05339         len = len % 1000;
05340         if (len < 0) {
05341             len = 0;
05342         }
05343         if (p->coldef && p->coldef <= 16) {
05344             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
05345                     ((TIMESTAMP_STRUCT *) p->param)->year,
05346                     ((TIMESTAMP_STRUCT *) p->param)->month,
05347                     ((TIMESTAMP_STRUCT *) p->param)->day,
05348                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05349                     ((TIMESTAMP_STRUCT *) p->param)->minute);
05350         } else if (p->coldef && p->coldef <= 19) {
05351             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
05352                     ((TIMESTAMP_STRUCT *) p->param)->year,
05353                     ((TIMESTAMP_STRUCT *) p->param)->month,
05354                     ((TIMESTAMP_STRUCT *) p->param)->day,
05355                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05356                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05357                     ((TIMESTAMP_STRUCT *) p->param)->second);
05358         } else {
05359             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
05360                     ((TIMESTAMP_STRUCT *) p->param)->year,
05361                     ((TIMESTAMP_STRUCT *) p->param)->month,
05362                     ((TIMESTAMP_STRUCT *) p->param)->day,
05363                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05364                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05365                     ((TIMESTAMP_STRUCT *) p->param)->second,
05366                     len);
05367         }
05368         p->s3type = SQLITE_TEXT;
05369         p->s3size = -1;
05370         p->s3val = p->strbuf;
05371         break;
05372     default:
05373     error:
05374         setstat(s, -1, "unsupported parameter type",
05375                 (*s->ov3) ? "07009" : "S1093");
05376         return SQL_ERROR;
05377     }
05378     return SQL_SUCCESS;
05379 }
05380 
05396 static SQLRETURN
05397 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05398              SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
05399              SQLSMALLINT scale,
05400              SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
05401 {
05402     STMT *s;
05403     BINDPARM *p;
05404 
05405     if (stmt == SQL_NULL_HSTMT) {
05406         return SQL_INVALID_HANDLE;
05407     }
05408     s = (STMT *) stmt;
05409     if (pnum == 0) {
05410         setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
05411         return SQL_ERROR;
05412     }
05413     if (!data && !len) {
05414         setstat(s, -1, "invalid buffer", "HY003");
05415         return SQL_ERROR;
05416     }
05417     --pnum;
05418     if (s->bindparms) {
05419         if (pnum >= s->nbindparms) {
05420             BINDPARM *newparms;
05421 
05422             newparms = xrealloc(s->bindparms,
05423                                 (pnum + 1) * sizeof (BINDPARM));
05424             if (!newparms) {
05425 outofmem:
05426                 return nomem(s);
05427             }
05428             s->bindparms = newparms;
05429             memset(&s->bindparms[s->nbindparms], 0,
05430                    (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
05431             s->nbindparms = pnum + 1;
05432         }
05433     } else {
05434         int npar = max(10, pnum + 1);
05435 
05436         s->bindparms = xmalloc(npar * sizeof (BINDPARM));
05437         if (!s->bindparms) {
05438             goto outofmem;
05439         }
05440         memset(s->bindparms, 0, npar * sizeof (BINDPARM));
05441         s->nbindparms = npar;
05442     }
05443     switch (buftype) {
05444     case SQL_C_STINYINT:
05445     case SQL_C_UTINYINT:
05446     case SQL_C_TINYINT:
05447 #ifdef SQL_C_BIT
05448     case SQL_C_BIT:
05449 #endif
05450         buflen = sizeof (SQLCHAR);
05451         break;
05452     case SQL_C_SHORT:
05453     case SQL_C_USHORT:
05454     case SQL_C_SSHORT:
05455         buflen = sizeof (SQLSMALLINT);
05456         break;
05457     case SQL_C_SLONG:
05458     case SQL_C_ULONG:
05459     case SQL_C_LONG:
05460         buflen = sizeof (SQLINTEGER);
05461         break;
05462     case SQL_C_FLOAT:
05463         buflen = sizeof (float);
05464         break;
05465     case SQL_C_DOUBLE:
05466         buflen = sizeof (double);
05467         break;
05468     case SQL_C_TIMESTAMP:
05469 #ifdef SQL_C_TYPE_TIMESTAMP
05470     case SQL_C_TYPE_TIMESTAMP:
05471 #endif
05472         buflen = sizeof (TIMESTAMP_STRUCT);
05473         break;
05474     case SQL_C_TIME:
05475 #ifdef SQL_C_TYPE_TIME
05476     case SQL_C_TYPE_TIME:
05477 #endif
05478         buflen = sizeof (TIME_STRUCT);
05479         break;
05480     case SQL_C_DATE:
05481 #ifdef SQL_C_TYPE_DATE
05482     case SQL_C_TYPE_DATE:
05483 #endif
05484         buflen = sizeof (DATE_STRUCT);
05485         break;
05486 #ifdef SQL_C_UBIGINT
05487     case SQL_C_UBIGINT:
05488         buflen = sizeof (SQLBIGINT);
05489         break;
05490 #endif
05491 #ifdef SQL_C_SBIGINT
05492     case SQL_C_SBIGINT:
05493         buflen = sizeof (SQLBIGINT);
05494         break;
05495 #endif
05496 #ifdef SQL_C_BIGINT
05497     case SQL_C_BIGINT:
05498         buflen = sizeof (SQLBIGINT);
05499         break;
05500 #endif
05501     }
05502     p = &s->bindparms[pnum];
05503     p->type = buftype;
05504     p->stype = ptype;
05505     p->coldef = coldef;
05506     p->scale = scale;
05507     p->max = buflen;
05508     p->inc = buflen;
05509     p->lenp = p->lenp0 = len;
05510     p->offs = 0;
05511     p->len = 0;
05512     p->param0 = data;
05513     freep(&p->parbuf);
05514     p->param = p->param0;
05515     p->bound = 1;
05516     p->need = 0;
05517     return SQL_SUCCESS;
05518 }
05519 
05535 SQLRETURN SQL_API
05536 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05537                  SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
05538                  SQLSMALLINT scale,
05539                  SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
05540 {
05541     SQLRETURN ret;
05542 
05543     HSTMT_LOCK(stmt);
05544     ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
05545                        scale, data, buflen, len);
05546     HSTMT_UNLOCK(stmt);
05547     return ret;
05548 }
05549 
05550 #ifndef HAVE_IODBC
05551 
05564 SQLRETURN SQL_API
05565 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
05566              SQLSMALLINT ptype, SQLULEN lenprec,
05567              SQLSMALLINT scale, SQLPOINTER val,
05568              SQLLEN *lenp)
05569 {
05570     SQLRETURN ret;
05571 
05572     HSTMT_LOCK(stmt);
05573     ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
05574                        lenprec, scale, val, 0, lenp);
05575     HSTMT_UNLOCK(stmt);
05576     return ret;
05577 }
05578 #endif
05579 
05587 SQLRETURN SQL_API
05588 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
05589 {
05590     STMT *s;
05591     SQLSMALLINT dummy;
05592 
05593     HSTMT_LOCK(stmt);
05594     if (stmt == SQL_NULL_HSTMT) {
05595         return SQL_INVALID_HANDLE;
05596     }
05597     s = (STMT *) stmt;
05598     if (!nparam) {
05599         nparam = &dummy;
05600     }
05601     *nparam = s->nparams;
05602     HSTMT_UNLOCK(stmt);
05603     return SQL_SUCCESS;
05604 }
05605 
05613 static SQLRETURN
05614 setupparbuf(STMT *s, BINDPARM *p)
05615 {
05616     if (!p->parbuf) {
05617         if (*p->lenp == SQL_DATA_AT_EXEC) {
05618             p->len = p->max;
05619         } else {
05620             p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
05621         }
05622         if (p->len < 0 && p->len != SQL_NTS &&
05623             p->len != SQL_NULL_DATA) {
05624             setstat(s, -1, "invalid length", "HY009");
05625             return SQL_ERROR;
05626         }
05627         if (p->len >= 0) {
05628             p->parbuf = xmalloc(p->len + 2);
05629             if (!p->parbuf) {
05630                 return nomem(s);
05631             }
05632             p->param = p->parbuf;
05633         } else {
05634             p->param = NULL;
05635         }
05636     }
05637     return SQL_NEED_DATA;
05638 }
05639 
05647 SQLRETURN SQL_API
05648 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
05649 {
05650     STMT *s;
05651     int i;
05652     SQLPOINTER dummy;
05653     SQLRETURN ret;
05654     BINDPARM *p;
05655 
05656     HSTMT_LOCK(stmt);
05657     if (stmt == SQL_NULL_HSTMT) {
05658         return SQL_INVALID_HANDLE;
05659     }
05660     s = (STMT *) stmt;
05661     if (!pind) {
05662         pind = &dummy;
05663     }
05664     if (s->pdcount < s->nparams) {
05665         s->pdcount++;
05666     }
05667     for (i = 0; i < s->pdcount; i++) {
05668         p = &s->bindparms[i];
05669         if (p->need > 0) {
05670             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05671 
05672             p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? -1 : 0;
05673         }
05674     }
05675     for (; i < s->nparams; i++) {
05676         p = &s->bindparms[i];
05677         if (p->need > 0) {
05678             *pind = (SQLPOINTER) p->param0;
05679             ret = setupparbuf(s, p);
05680             s->pdcount = i;
05681             goto done;
05682         }
05683     }
05684     ret = drvexecute(stmt, 0);
05685 done:
05686     HSTMT_UNLOCK(stmt);
05687     return ret;
05688 }
05689 
05701 SQLRETURN SQL_API
05702 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
05703                  SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
05704 {
05705     STMT *s;
05706     SQLRETURN ret = SQL_ERROR;
05707 
05708     HSTMT_LOCK(stmt);
05709     if (stmt == SQL_NULL_HSTMT) {
05710         return SQL_INVALID_HANDLE;
05711     }
05712     s = (STMT *) stmt;
05713     --pnum;
05714     if (pnum >= s->nparams) {
05715         setstat(s, -1, "invalid parameter index",
05716                 (*s->ov3) ? "HY000" : "S1000");
05717         goto done;
05718     }
05719     if (dtype) {
05720 #ifdef SQL_LONGVARCHAR
05721 #ifdef WINTERFACE
05722         *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
05723 #else
05724         *dtype = SQL_LONGVARCHAR;
05725 #endif
05726 #else
05727 #ifdef WINTERFACE
05728         *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
05729 #else
05730         *dtype = SQL_VARCHAR;
05731 #endif
05732 #endif
05733     }
05734     if (size) {
05735 #ifdef SQL_LONGVARCHAR
05736         *size = 65536;
05737 #else
05738         *size = 255;
05739 #endif
05740     }
05741     if (decdigits) {
05742         *decdigits = 0;
05743     }
05744     if (nullable) {
05745         *nullable = SQL_NULLABLE;
05746     }
05747     ret = SQL_SUCCESS;
05748 done:
05749     HSTMT_UNLOCK(stmt);
05750     return ret;
05751 }
05752 
05766 SQLRETURN SQL_API
05767 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
05768             SQLSMALLINT sqltype, SQLULEN coldef,
05769             SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
05770 {
05771     SQLRETURN ret;
05772 
05773     HSTMT_LOCK(stmt);
05774     ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
05775                        type, sqltype, coldef, scale, val,
05776                        SQL_SETPARAM_VALUE_MAX, nval);
05777     HSTMT_UNLOCK(stmt);
05778     return ret;
05779 }
05780 
05785 SQLRETURN SQL_API
05786 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
05787 {
05788     SQLRETURN ret;
05789 
05790     HSTMT_LOCK(stmt);
05791     ret = drvunimplstmt(stmt);
05792     HSTMT_UNLOCK(stmt);
05793     return ret;
05794 }
05795 
05796 #ifndef WINTERFACE
05797 
05801 SQLRETURN SQL_API
05802 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
05803                 SQLSMALLINT fieldid, SQLPOINTER value,
05804                 SQLINTEGER buflen, SQLINTEGER *strlen)
05805 {
05806     return SQL_ERROR;
05807 }
05808 #endif
05809 
05810 #ifdef WINTERFACE
05811 
05815 SQLRETURN SQL_API
05816 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05817                  SQLSMALLINT fieldid, SQLPOINTER value,
05818                  SQLINTEGER buflen, SQLINTEGER *strlen)
05819 {
05820     return SQL_ERROR;
05821 }
05822 #endif
05823 
05824 #ifndef WINTERFACE
05825 
05829 SQLRETURN SQL_API
05830 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
05831                 SQLSMALLINT fieldid, SQLPOINTER value,
05832                 SQLINTEGER buflen)
05833 {
05834     return SQL_ERROR;
05835 }
05836 #endif
05837 
05838 #ifdef WINTERFACE
05839 
05843 SQLRETURN SQL_API
05844 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05845                  SQLSMALLINT fieldid, SQLPOINTER value,
05846                  SQLINTEGER buflen)
05847 {
05848     return SQL_ERROR;
05849 }
05850 #endif
05851 
05852 #ifndef WINTERFACE
05853 
05857 SQLRETURN SQL_API
05858 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05859               SQLCHAR *name, SQLSMALLINT buflen,
05860               SQLSMALLINT *strlen, SQLSMALLINT *type,
05861               SQLSMALLINT *subtype, SQLLEN *len,
05862               SQLSMALLINT *prec, SQLSMALLINT *scale,
05863               SQLSMALLINT *nullable)
05864 {
05865     return SQL_ERROR;
05866 }
05867 #endif
05868 
05869 #ifdef WINTERFACE
05870 
05874 SQLRETURN SQL_API
05875 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
05876                SQLWCHAR *name, SQLSMALLINT buflen,
05877                SQLSMALLINT *strlen, SQLSMALLINT *type,
05878                SQLSMALLINT *subtype, SQLLEN *len,
05879                SQLSMALLINT *prec, SQLSMALLINT *scale,
05880                SQLSMALLINT *nullable)
05881 {
05882     return SQL_ERROR;
05883 }
05884 #endif
05885 
05890 SQLRETURN SQL_API
05891 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05892               SQLSMALLINT type, SQLSMALLINT subtype,
05893               SQLLEN len, SQLSMALLINT prec,
05894               SQLSMALLINT scale, SQLPOINTER data,
05895               SQLLEN *strlen, SQLLEN *indicator)
05896 {
05897     return SQL_ERROR;
05898 }
05899 
05911 static SQLRETURN
05912 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
05913             int ncols3, int *nret)
05914 {
05915     STMT *s;
05916     DBC *d;
05917 
05918     if (stmt == SQL_NULL_HSTMT) {
05919         return SQL_INVALID_HANDLE;
05920     }
05921     s = (STMT *) stmt;
05922     if (s->dbc == SQL_NULL_HDBC) {
05923 noconn:
05924         return noconn(s);
05925     }
05926     d = (DBC *) s->dbc;
05927     if (!d->sqlite) {
05928         goto noconn;
05929     }
05930     s3stmt_end_if(s);
05931     freeresult(s, 0);
05932     if (colspec3 && *s->ov3) {
05933         s->ncols = ncols3;
05934         s->cols = colspec3;
05935     } else {
05936         s->ncols = ncols;
05937         s->cols = colspec;
05938     }
05939     mkbindcols(s, s->ncols);
05940     s->nowchar[1] = 1;
05941     s->nrows = 0;
05942     s->rowp = s->rowprs = -1;
05943     s->isselect = -1;
05944     if (nret) {
05945         *nret = s->ncols;
05946     }
05947     return SQL_SUCCESS;
05948 }
05949 
05954 static COL tablePrivSpec2[] = {
05955     { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05956     { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
05957     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05958     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05959     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05960     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05961     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05962 };
05963 
05964 static COL tablePrivSpec3[] = {
05965     { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
05966     { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
05967     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05968     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05969     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05970     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05971     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05972 };
05973 
05986 static SQLRETURN
05987 drvtableprivileges(SQLHSTMT stmt,
05988                    SQLCHAR *cat, SQLSMALLINT catLen,
05989                    SQLCHAR *schema, SQLSMALLINT schemaLen,
05990                    SQLCHAR *table, SQLSMALLINT tableLen)
05991 {
05992     SQLRETURN ret;
05993     STMT *s;
05994     DBC *d;
05995     int ncols, rc, size, npatt;
05996     char *errp = NULL, *sql, tname[512];
05997 
05998     ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
05999                       tablePrivSpec3, array_size(tablePrivSpec3), NULL);
06000     if (ret != SQL_SUCCESS) {
06001         return ret;
06002     }
06003     s = (STMT *) stmt;
06004     d = (DBC *) s->dbc;
06005     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
06006         table = NULL;
06007         goto doit;
06008     }
06009     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
06010         schema[0] == '%') {
06011         if ((!cat || catLen == 0 || !cat[0]) &&
06012             (!table || tableLen == 0 || !table[0])) {
06013             table = NULL;
06014             goto doit;
06015         }
06016     }
06017 doit:
06018     if (!table) {
06019         size = 1;
06020         tname[0] = '%';
06021     } else {
06022         if (tableLen == SQL_NTS) {
06023             size = sizeof (tname) - 1;
06024         } else {
06025             size = min(sizeof (tname) - 1, tableLen);
06026         }
06027         strncpy(tname, (char *) table, size);
06028     }
06029     tname[size] = '\0';
06030     npatt = unescpat(tname);
06031 #if defined(_WIN32) || defined(_WIN64)
06032     sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
06033                           "%s as 'TABLE_OWNER', "
06034                           "tbl_name as 'TABLE_NAME', "
06035                           "'' as 'GRANTOR', "
06036                           "'' as 'GRANTEE', "
06037                           "'SELECT' AS 'PRIVILEGE', "
06038                           "NULL as 'IS_GRANTABLE' "
06039                           "from sqlite_master where "
06040                           "(type = 'table' or type = 'view') "
06041                           "and tbl_name %s %Q "
06042                           "UNION "
06043                           "select %s as 'TABLE_QUALIFIER', "
06044                           "%s as 'TABLE_OWNER', "
06045                           "tbl_name as 'TABLE_NAME', "
06046                           "'' as 'GRANTOR', "
06047                           "'' as 'GRANTEE', "
06048                           "'UPDATE' AS 'PRIVILEGE', "
06049                           "NULL as 'IS_GRANTABLE' "
06050                           "from sqlite_master where "
06051                           "(type = 'table' or type = 'view') "
06052                           "and tbl_name %s %Q "
06053                           "UNION "
06054                           "select %s as 'TABLE_QUALIFIER', "
06055                           "%s as 'TABLE_OWNER', "
06056                           "tbl_name as 'TABLE_NAME', "
06057                           "'' as 'GRANTOR', "
06058                           "'' as 'GRANTEE', "
06059                           "'DELETE' AS 'PRIVILEGE', "
06060                           "NULL as 'IS_GRANTABLE' "
06061                           "from sqlite_master where "
06062                           "(type = 'table' or type = 'view') "
06063                           "and tbl_name %s %Q "
06064                           "UNION "
06065                           "select %s as 'TABLE_QUALIFIER', "
06066                           "%s as 'TABLE_OWNER', "
06067                           "tbl_name as 'TABLE_NAME', "
06068                           "'' as 'GRANTOR', "
06069                           "'' as 'GRANTEE', "
06070                           "'INSERT' AS 'PRIVILEGE', "
06071                           "NULL as 'IS_GRANTABLE' "
06072                           "from sqlite_master where "
06073                           "(type = 'table' or type = 'view') "
06074                           "and tbl_name %s %Q "
06075                           "UNION "
06076                           "select %s as 'TABLE_QUALIFIER', "
06077                           "%s as 'TABLE_OWNER', "
06078                           "tbl_name as 'TABLE_NAME', "
06079                           "'' as 'GRANTOR', "
06080                           "'' as 'GRANTEE', "
06081                           "'REFERENCES' AS 'PRIVILEGE', "
06082                           "NULL as 'IS_GRANTABLE' "
06083                           "from sqlite_master where "
06084                           "(type = 'table' or type = 'view') "
06085                           "and tbl_name %s %Q",
06086                           d->xcelqrx ? "'main'" : "NULL",
06087                           d->xcelqrx ? "''" : "NULL",
06088                           npatt ? "like" : "=", tname,
06089                           d->xcelqrx ? "'main'" : "NULL",
06090                           d->xcelqrx ? "''" : "NULL",
06091                           npatt ? "like" : "=", tname,
06092                           d->xcelqrx ? "'main'" : "NULL",
06093                           d->xcelqrx ? "''" : "NULL",
06094                           npatt ? "like" : "=", tname,
06095                           d->xcelqrx ? "'main'" : "NULL",
06096                           d->xcelqrx ? "''" : "NULL",
06097                           npatt ? "like" : "=", tname,
06098                           d->xcelqrx ? "'main'" : "NULL",
06099                           d->xcelqrx ? "''" : "NULL",
06100                           npatt ? "like" : "=", tname);
06101 #else
06102     sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
06103                           "NULL as 'TABLE_OWNER', "
06104                           "tbl_name as 'TABLE_NAME', "
06105                           "'' as 'GRANTOR', "
06106                           "'' as 'GRANTEE', "
06107                           "'SELECT' AS 'PRIVILEGE', "
06108                           "NULL as 'IS_GRANTABLE' "
06109                           "from sqlite_master where "
06110                           "(type = 'table' or type = 'view') "
06111                           "and tbl_name %s %Q "
06112                           "UNION "
06113                           "select NULL as 'TABLE_QUALIFIER', "
06114                           "NULL as 'TABLE_OWNER', "
06115                           "tbl_name as 'TABLE_NAME', "
06116                           "'' as 'GRANTOR', "
06117                           "'' as 'GRANTEE', "
06118                           "'UPDATE' AS 'PRIVILEGE', "
06119                           "NULL as 'IS_GRANTABLE' "
06120                           "from sqlite_master where "
06121                           "(type = 'table' or type = 'view') "
06122                           "and tbl_name %s %Q "
06123                           "UNION "
06124                           "select NULL as 'TABLE_QUALIFIER', "
06125                           "NULL as 'TABLE_OWNER', "
06126                           "tbl_name as 'TABLE_NAME', "
06127                           "'' as 'GRANTOR', "
06128                           "'' as 'GRANTEE', "
06129                           "'DELETE' AS 'PRIVILEGE', "
06130                           "NULL as 'IS_GRANTABLE' "
06131                           "from sqlite_master where "
06132                           "(type = 'table' or type = 'view') "
06133                           "and tbl_name %s %Q "
06134                           "UNION "
06135                           "select NULL as 'TABLE_QUALIFIER', "
06136                           "NULL as 'TABLE_OWNER', "
06137                           "tbl_name as 'TABLE_NAME', "
06138                           "'' as 'GRANTOR', "
06139                           "'' as 'GRANTEE', "
06140                           "'INSERT' AS 'PRIVILEGE', "
06141                           "NULL as 'IS_GRANTABLE' "
06142                           "from sqlite_master where "
06143                           "(type = 'table' or type = 'view') "
06144                           "and tbl_name %s %Q "
06145                           "UNION "
06146                           "select NULL as 'TABLE_QUALIFIER', "
06147                           "NULL as 'TABLE_OWNER', "
06148                           "tbl_name as 'TABLE_NAME', "
06149                           "'' as 'GRANTOR', "
06150                           "'' as 'GRANTEE', "
06151                           "'REFERENCES' AS 'PRIVILEGE', "
06152                           "NULL as 'IS_GRANTABLE' "
06153                           "from sqlite_master where "
06154                           "(type = 'table' or type = 'view') "
06155                           "and tbl_name %s %Q",
06156                           npatt ? "like" : "=", tname,
06157                           npatt ? "like" : "=", tname,
06158                           npatt ? "like" : "=", tname,
06159                           npatt ? "like" : "=", tname,
06160                           npatt ? "like" : "=", tname);
06161 #endif
06162     if (!sql) {
06163         return nomem(s);
06164     }
06165     ret = starttran(s);
06166     if (ret != SQL_SUCCESS) {
06167         sqlite3_free(sql);
06168         return ret;
06169     }
06170     dbtraceapi(d, "sqlite3_get_table", sql);
06171     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
06172     sqlite3_free(sql);
06173     if (rc == SQLITE_OK) {
06174         if (ncols != s->ncols) {
06175             freeresult(s, 0);
06176             s->nrows = 0;
06177         } else {
06178             s->rowfree = sqlite3_free_table;
06179         }
06180     } else {
06181         s->nrows = 0;
06182         s->rows = NULL;
06183         s->rowfree = NULL;
06184     }
06185     if (errp) {
06186         sqlite3_free(errp);
06187         errp = NULL;
06188     }
06189     s->rowp = s->rowprs = -1;
06190     return SQL_SUCCESS;
06191 }
06192 
06193 
06194 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06195 
06207 SQLRETURN SQL_API
06208 SQLTablePrivileges(SQLHSTMT stmt,
06209                    SQLCHAR *catalog, SQLSMALLINT catalogLen,
06210                    SQLCHAR *schema, SQLSMALLINT schemaLen,
06211                    SQLCHAR *table, SQLSMALLINT tableLen)
06212 {
06213 #if defined(_WIN32) || defined(_WIN64)
06214     char *c = NULL, *s = NULL, *t = NULL;
06215 #endif
06216     SQLRETURN ret;
06217 
06218     HSTMT_LOCK(stmt);
06219 #if defined(_WIN32) || defined(_WIN64)
06220     if (!((STMT *) stmt)->oemcp[0]) {
06221         ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06222                                  table, tableLen);
06223         goto done2;
06224     }
06225     if (catalog) {
06226         c = wmb_to_utf_c((char *) catalog, catalogLen);
06227         if (!c) {
06228             ret = nomem((STMT *) stmt);
06229             goto done;
06230         }
06231     }
06232     if (schema) {
06233         s = wmb_to_utf_c((char *) schema, schemaLen);
06234         if (!s) {
06235             ret = nomem((STMT *) stmt);
06236             goto done;
06237         }
06238     }
06239     if (table) {
06240         t = wmb_to_utf_c((char *) table, tableLen);
06241         if (!t) {
06242             ret = nomem((STMT *) stmt);
06243             goto done;
06244         }
06245     }
06246     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06247                              (SQLCHAR *) s, SQL_NTS,
06248                              (SQLCHAR *) t, SQL_NTS);
06249 #else
06250     ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06251                              table, tableLen);
06252 #endif
06253 #if defined(_WIN32) || defined(_WIN64)
06254 done:
06255     uc_free(t);
06256     uc_free(s);
06257     uc_free(c);
06258 done2:
06259     ;
06260 #endif
06261     HSTMT_UNLOCK(stmt);
06262     return ret;
06263 }
06264 #endif
06265 
06266 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06267 #ifdef WINTERFACE
06268 
06280 SQLRETURN SQL_API
06281 SQLTablePrivilegesW(SQLHSTMT stmt,
06282                     SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06283                     SQLWCHAR *schema, SQLSMALLINT schemaLen,
06284                     SQLWCHAR *table, SQLSMALLINT tableLen)
06285 {
06286     char *c = NULL, *s = NULL, *t = NULL;
06287     SQLRETURN ret;
06288 
06289     HSTMT_LOCK(stmt);
06290     if (catalog) {
06291         c = uc_to_utf_c(catalog, catalogLen);
06292         if (!c) {
06293             ret = nomem((STMT *) stmt);
06294             goto done;
06295         }
06296     }
06297     if (schema) {
06298         s = uc_to_utf_c(schema, schemaLen);
06299         if (!s) {
06300             ret = nomem((STMT *) stmt);
06301             goto done;
06302         }
06303     }
06304     if (table) {
06305         t = uc_to_utf_c(table, tableLen);
06306         if (!t) {
06307             ret = nomem((STMT *) stmt);
06308             goto done;
06309         }
06310     }
06311     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06312                              (SQLCHAR *) s, SQL_NTS,
06313                              (SQLCHAR *) t, SQL_NTS);
06314 done:
06315     uc_free(t);
06316     uc_free(s);
06317     uc_free(c);
06318     HSTMT_UNLOCK(stmt);
06319     return ret;
06320 }
06321 #endif
06322 #endif
06323 
06328 static COL colPrivSpec2[] = {
06329     { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06330     { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06331     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06332     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06333     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06334     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06335     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06336 };
06337 
06338 static COL colPrivSpec3[] = {
06339     { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
06340     { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06341     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06342     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06343     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06344     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06345     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06346 };
06347 
06348 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06349 
06363 SQLRETURN SQL_API
06364 SQLColumnPrivileges(SQLHSTMT stmt,
06365                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
06366                     SQLCHAR *schema, SQLSMALLINT schemaLen,
06367                     SQLCHAR *table, SQLSMALLINT tableLen,
06368                     SQLCHAR *column, SQLSMALLINT columnLen)
06369 {
06370     SQLRETURN ret;
06371 
06372     HSTMT_LOCK(stmt);
06373     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06374                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06375     HSTMT_UNLOCK(stmt);
06376     return ret;
06377 }
06378 #endif
06379 
06380 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06381 #ifdef WINTERFACE
06382 
06396 SQLRETURN SQL_API
06397 SQLColumnPrivilegesW(SQLHSTMT stmt,
06398                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06399                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
06400                      SQLWCHAR *table, SQLSMALLINT tableLen,
06401                      SQLWCHAR *column, SQLSMALLINT columnLen)
06402 {
06403     SQLRETURN ret;
06404 
06405     HSTMT_LOCK(stmt);
06406     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06407                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06408     HSTMT_UNLOCK(stmt);
06409     return ret;
06410 }
06411 #endif
06412 #endif
06413 
06418 static COL pkeySpec2[] = {
06419     { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06420     { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06421     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06422     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06423     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06424     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06425 };
06426 
06427 static COL pkeySpec3[] = {
06428     { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
06429     { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06430     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06431     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06432     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06433     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06434 };
06435 
06448 static SQLRETURN
06449 drvprimarykeys(SQLHSTMT stmt,
06450                SQLCHAR *cat, SQLSMALLINT catLen,
06451                SQLCHAR *schema, SQLSMALLINT schemaLen,
06452                SQLCHAR *table, SQLSMALLINT tableLen)
06453 {
06454     STMT *s;
06455     DBC *d;
06456     SQLRETURN sret;
06457     int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
06458     int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
06459     PTRDIFF_T size;
06460     char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
06461 
06462     sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
06463                        pkeySpec3, array_size(pkeySpec3), &asize);
06464     if (sret != SQL_SUCCESS) {
06465         return sret;
06466     }
06467     s = (STMT *) stmt;
06468     d = (DBC *) s->dbc;
06469     if (!table || table[0] == '\0' || table[0] == '%') {
06470         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06471         return SQL_ERROR;
06472     }
06473     if (tableLen == SQL_NTS) {
06474         size = sizeof (tname) - 1;
06475     } else {
06476         size = min(sizeof (tname) - 1, tableLen);
06477     }
06478     strncpy(tname, (char *) table, size);
06479     tname[size] = '\0';
06480     unescpat(tname);
06481     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
06482     if (!sql) {
06483         return nomem(s);
06484     }
06485     sret = starttran(s);
06486     if (sret != SQL_SUCCESS) {
06487         sqlite3_free(sql);
06488         return sret;
06489     }
06490     dbtraceapi(d, "sqlite3_get_table", sql);
06491     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06492     sqlite3_free(sql);
06493     if (ret != SQLITE_OK) {
06494         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06495                 errp ? errp : "unknown error", ret);
06496         if (errp) {
06497             sqlite3_free(errp);
06498             errp = NULL;
06499         }
06500         return SQL_ERROR;
06501     }
06502     if (errp) {
06503         sqlite3_free(errp);
06504         errp = NULL;
06505     }
06506     size = 0;
06507     if (ncols * nrows > 0) {
06508         int typec;
06509 
06510         namec = findcol(rowp, ncols, "name");
06511         uniquec = findcol(rowp, ncols, "pk");
06512         typec = findcol(rowp, ncols, "type");
06513         if (namec >= 0 && uniquec >= 0 && typec >= 0) {
06514             for (i = 1; i <= nrows; i++) {
06515                 if (*rowp[i * ncols + uniquec] != '0') {
06516                     size++;
06517                 }
06518             }
06519         }
06520     }
06521     if (size == 0) {
06522         sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
06523         if (!sql) {
06524             sqlite3_free_table(rowp);
06525             return nomem(s);
06526         }
06527         dbtraceapi(d, "sqlite3_get_table", sql);
06528         ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
06529                                 &errp);
06530         sqlite3_free(sql);
06531         if (ret != SQLITE_OK) {
06532             sqlite3_free_table(rowp);
06533             sqlite3_free_table(rowp2);
06534             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06535                     errp ? errp : "unknown error", ret);
06536             if (errp) {
06537                 sqlite3_free(errp);
06538                 errp = NULL;
06539             }
06540             return SQL_ERROR;
06541         }
06542         if (errp) {
06543             sqlite3_free(errp);
06544             errp = NULL;
06545         }
06546     }
06547     if (ncols2 * nrows2 > 0) {
06548         namec2 = findcol(rowp2, ncols2, "name");
06549         uniquec2 = findcol(rowp2, ncols2, "unique");
06550         if (namec2 >= 0 && uniquec2 >=  0) {
06551             for (i = 1; i <= nrows2; i++) {
06552                 int nnrows, nncols, nlen = 0;
06553                 char **rowpp;
06554 
06555                 if (rowp2[i * ncols2 + namec2]) {
06556                     nlen = strlen(rowp2[i * ncols2 + namec2]);
06557                 }
06558                 if (nlen < 17 ||
06559                     strncmp(rowp2[i * ncols2 + namec2],
06560                             "sqlite_autoindex_", 17)) {
06561                     continue;
06562                 }
06563                 if (*rowp2[i * ncols2 + uniquec2] != '0') {
06564                     ret = SQLITE_ERROR;
06565                     sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06566                                           rowp2[i * ncols2 + namec2]);
06567                     if (sql) {
06568                         dbtraceapi(d, "sqlite3_get_table", sql);
06569                         ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06570                                                 &nnrows, &nncols, NULL);
06571                         sqlite3_free(sql);
06572                     }
06573                     if (ret == SQLITE_OK) {
06574                         size += nnrows;
06575                         sqlite3_free_table(rowpp);
06576                     }
06577                 }
06578             }
06579         }
06580     }
06581     if (size == 0) {
06582         sqlite3_free_table(rowp);
06583         sqlite3_free_table(rowp2);
06584         return SQL_SUCCESS;
06585     }
06586     s->nrows = size;
06587     size = (size + 1) * asize;
06588     s->rows = xmalloc((size + 1) * sizeof (char *));
06589     if (!s->rows) {
06590         s->nrows = 0;
06591         sqlite3_free_table(rowp);
06592         sqlite3_free_table(rowp2);
06593         return nomem(s);
06594     }
06595     s->rows[0] = (char *) size;
06596     s->rows += 1;
06597     memset(s->rows, 0, sizeof (char *) * size);
06598     s->rowfree = freerows;
06599     offs = s->ncols;
06600     if (rowp) {
06601         for (i = 1; i <= nrows; i++) {
06602             if (*rowp[i * ncols + uniquec] != '0') {
06603                 char buf[32];
06604 
06605 #if defined(_WIN32) || defined(_WIN64)
06606                 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
06607                 s->rows[offs + 1] = xstrdup("");
06608 #else
06609                 s->rows[offs + 0] = xstrdup("");
06610                 s->rows[offs + 1] = xstrdup("");
06611 #endif
06612                 s->rows[offs + 2] = xstrdup(tname);
06613                 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
06614                 sprintf(buf, "%d", seq++);
06615                 s->rows[offs + 4] = xstrdup(buf);
06616                 offs += s->ncols;
06617             }
06618         }
06619     }
06620     if (rowp2) {
06621         for (i = 1; i <= nrows2; i++) {
06622             int nnrows, nncols, nlen = 0;
06623             char **rowpp;
06624 
06625             if (rowp2[i * ncols2 + namec2]) {
06626                 nlen = strlen(rowp2[i * ncols2 + namec2]);
06627             }
06628             if (nlen < 17 ||
06629                 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
06630                 continue;
06631             }
06632             if (*rowp2[i * ncols2 + uniquec2] != '0') {
06633                 int k;
06634 
06635                 ret = SQLITE_ERROR;
06636                 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06637                                       rowp2[i * ncols2 + namec2]);
06638                 if (sql) {
06639                     dbtraceapi(d, "sqlite3_get_table", sql);
06640                     ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06641                                             &nnrows, &nncols, NULL);
06642                     sqlite3_free(sql);
06643                 }
06644                 if (ret != SQLITE_OK) {
06645                     continue;
06646                 }
06647                 for (k = 0; nnrows && k < nncols; k++) {
06648                     if (strcmp(rowpp[k], "name") == 0) {
06649                         int m;
06650 
06651                         for (m = 1; m <= nnrows; m++) {
06652                             int roffs = offs + (m - 1) * s->ncols;
06653 
06654 #if defined(_WIN32) || defined(_WIN64)
06655                             s->rows[roffs + 0] =
06656                                 xstrdup(d->xcelqrx ? "main" : "");
06657                             s->rows[roffs + 1] = xstrdup("");
06658 #else
06659                             s->rows[roffs + 0] = xstrdup("");
06660                             s->rows[roffs + 1] = xstrdup("");
06661 #endif
06662                             s->rows[roffs + 2] = xstrdup(tname);
06663                             s->rows[roffs + 3] =
06664                                 xstrdup(rowpp[m * nncols + k]);
06665                             s->rows[roffs + 5] =
06666                                 xstrdup(rowp2[i * ncols2 + namec2]);
06667                         }
06668                     } else if (strcmp(rowpp[k], "seqno") == 0) {
06669                         int m;
06670 
06671                         for (m = 1; m <= nnrows; m++) {
06672                             int roffs = offs + (m - 1) * s->ncols;
06673                             int pos = m - 1;
06674                             char buf[32];
06675 
06676                             sscanf(rowpp[m * nncols + k], "%d", &pos);
06677                             sprintf(buf, "%d", pos + 1);
06678                             s->rows[roffs + 4] = xstrdup(buf);
06679                         }
06680                     }
06681                 }
06682                 offs += nnrows * s->ncols;
06683                 sqlite3_free_table(rowpp);
06684             }
06685         }
06686     }
06687     sqlite3_free_table(rowp);
06688     sqlite3_free_table(rowp2);
06689     return SQL_SUCCESS;
06690 }
06691 
06692 #ifndef WINTERFACE
06693 
06705 SQLRETURN SQL_API
06706 SQLPrimaryKeys(SQLHSTMT stmt,
06707                SQLCHAR *cat, SQLSMALLINT catLen,
06708                SQLCHAR *schema, SQLSMALLINT schemaLen,
06709                SQLCHAR *table, SQLSMALLINT tableLen)
06710 {
06711 #if defined(_WIN32) || defined(_WIN64)
06712     char *c = NULL, *s = NULL, *t = NULL;
06713 #endif
06714     SQLRETURN ret;
06715 
06716     HSTMT_LOCK(stmt);
06717 #if defined(_WIN32) || defined(_WIN64)
06718     if (!((STMT *) stmt)->oemcp[0]) {
06719         ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06720                              table, tableLen);
06721         goto done2;
06722     }
06723     if (cat) {
06724         c = wmb_to_utf_c((char *) cat, catLen);
06725         if (!c) {
06726             ret = nomem((STMT *) stmt);
06727             goto done;
06728         }
06729     }
06730     if (schema) {
06731         s = wmb_to_utf_c((char *) schema, schemaLen);
06732         if (!s) {
06733             ret = nomem((STMT *) stmt);
06734             goto done;
06735         }
06736     }
06737     if (table) {
06738         t = wmb_to_utf_c((char *) table, tableLen);
06739         if (!t) {
06740             ret = nomem((STMT *) stmt);
06741             goto done;
06742         }
06743     }
06744     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06745                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06746 #else
06747     ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06748                          table, tableLen);
06749 #endif
06750 #if defined(_WIN32) || defined(_WIN64)
06751 done:
06752     uc_free(t);
06753     uc_free(s);
06754     uc_free(c);
06755 done2:
06756     ;
06757 #endif
06758     HSTMT_UNLOCK(stmt);
06759     return ret;
06760 }
06761 #endif
06762 
06763 #ifdef WINTERFACE
06764 
06776 SQLRETURN SQL_API
06777 SQLPrimaryKeysW(SQLHSTMT stmt,
06778                 SQLWCHAR *cat, SQLSMALLINT catLen,
06779                 SQLWCHAR *schema, SQLSMALLINT schemaLen,
06780                 SQLWCHAR *table, SQLSMALLINT tableLen)
06781 {
06782     char *c = NULL, *s = NULL, *t = NULL;
06783     SQLRETURN ret;
06784 
06785     HSTMT_LOCK(stmt);
06786     if (cat) {
06787         c = uc_to_utf_c(cat, catLen);
06788         if (!c) {
06789             ret = nomem((STMT *) stmt);
06790             goto done;
06791         }
06792     }
06793     if (schema) {
06794         s = uc_to_utf_c(schema, schemaLen);
06795         if (!s) {
06796             ret = nomem((STMT *) stmt);
06797             goto done;
06798         }
06799     }
06800     if (table) {
06801         t = uc_to_utf_c(table, tableLen);
06802         if (!t) {
06803             ret = nomem((STMT *) stmt);
06804             goto done;
06805         }
06806     }
06807     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06808                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06809 done:
06810     uc_free(t);
06811     uc_free(s);
06812     uc_free(c);
06813     HSTMT_UNLOCK(stmt);
06814     return ret;
06815 }
06816 #endif
06817 
06822 static COL scolSpec2[] = {
06823     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06824     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06825     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06826     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06827     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
06828     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
06829     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06830     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06831     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06832 };
06833 
06834 static COL scolSpec3[] = {
06835     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06836     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06837     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06838     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06839     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
06840     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
06841     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06842     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06843     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06844 };
06845 
06861 static SQLRETURN
06862 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
06863                   SQLCHAR *cat, SQLSMALLINT catLen,
06864                   SQLCHAR *schema, SQLSMALLINT schemaLen,
06865                   SQLCHAR *table, SQLSMALLINT tableLen,
06866                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
06867 {
06868     STMT *s;
06869     DBC *d;
06870     SQLRETURN sret;
06871     int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
06872     PTRDIFF_T size;
06873     int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
06874     int notnullcc = -1, mkrowid = 0;
06875     char *errp = NULL, *sql, tname[512];
06876     char **rowp = NULL, **rowppp = NULL;
06877 
06878     sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
06879                        scolSpec3, array_size(scolSpec3), &asize);
06880     if (sret != SQL_SUCCESS) {
06881         return sret;
06882     }
06883     s = (STMT *) stmt;
06884     d = (DBC *) s->dbc;
06885     if (!table || table[0] == '\0' || table[0] == '%') {
06886         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06887         return SQL_ERROR;
06888     }
06889     if (tableLen == SQL_NTS) {
06890         size = sizeof (tname) - 1;
06891     } else {
06892         size = min(sizeof (tname) - 1, tableLen);
06893     }
06894     strncpy(tname, (char *) table, size);
06895     tname[size] = '\0';
06896     unescpat(tname);
06897     if (id != SQL_BEST_ROWID) {
06898         return SQL_SUCCESS;
06899     }
06900     sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
06901     if (!sql) {
06902         return nomem(s);
06903     }
06904     sret = starttran(s);
06905     if (sret != SQL_SUCCESS) {
06906         sqlite3_free(sql);
06907         return sret;
06908     }
06909     dbtraceapi(d, "sqlite3_get_table", sql);
06910     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06911     sqlite3_free(sql);
06912     if (ret != SQLITE_OK) {
06913 doerr:
06914         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06915                 errp ? errp : "unknown error", ret);
06916         if (errp) {
06917             sqlite3_free(errp);
06918             errp = NULL;
06919         }
06920         return SQL_ERROR;
06921     }
06922     if (errp) {
06923         sqlite3_free(errp);
06924         errp = NULL;
06925     }
06926     size = 0; /* number result rows */
06927     if (ncols * nrows <= 0) {
06928         goto nodata_but_rowid;
06929     }
06930     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
06931     if (!sql) {
06932         return nomem(s);
06933     }
06934     dbtraceapi(d, "sqlite3_get_table", sql);
06935     ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
06936                             &errp);
06937     sqlite3_free(sql);
06938     if (ret != SQLITE_OK) {
06939         sqlite3_free_table(rowp);
06940         goto doerr;
06941     }
06942     if (errp) {
06943         sqlite3_free(errp);
06944         errp = NULL;
06945     }
06946     namec = findcol(rowp, ncols, "name");
06947     uniquec = findcol(rowp, ncols, "unique");
06948     if (namec < 0 || uniquec < 0) {
06949         goto nodata_but_rowid;
06950     }
06951     namecc = findcol(rowppp, nnncols, "name");
06952     typecc = findcol(rowppp, nnncols, "type");
06953     notnullcc = findcol(rowppp, nnncols, "notnull");
06954     for (i = 1; i <= nrows; i++) {
06955         int nnrows, nncols;
06956         char **rowpp = NULL;
06957 
06958         if (*rowp[i * ncols + uniquec] != '0') {
06959             ret = SQLITE_ERROR;
06960             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06961                                   rowp[i * ncols + namec]);
06962             if (sql) {
06963                 dbtraceapi(d, "sqlite3_get_table", sql);
06964                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06965                                         &nnrows, &nncols, NULL);
06966                 sqlite3_free(sql);
06967             }
06968             if (ret == SQLITE_OK) {
06969                 size += nnrows;
06970                 sqlite3_free_table(rowpp);
06971             }
06972         }
06973     }
06974 nodata_but_rowid:
06975     if (size == 0) {
06976         size = 1;
06977         mkrowid = 1;
06978     }
06979     s->nrows = size;
06980     size = (size + 1) * asize;
06981     s->rows = xmalloc((size + 1) * sizeof (char *));
06982     if (!s->rows) {
06983         s->nrows = 0;
06984         sqlite3_free_table(rowp);
06985         sqlite3_free_table(rowppp);
06986         return nomem(s);
06987     }
06988     s->rows[0] = (char *) size;
06989     s->rows += 1;
06990     memset(s->rows, 0, sizeof (char *) * size);
06991     s->rowfree = freerows;
06992     if (mkrowid) {
06993         s->nrows = 0;
06994         goto mkrowid;
06995     }
06996     offs = 0;
06997     for (i = 1; i <= nrows; i++) {
06998         int nnrows, nncols;
06999         char **rowpp = NULL;
07000 
07001         if (*rowp[i * ncols + uniquec] != '0') {
07002             int k;
07003 
07004             ret = SQLITE_ERROR;
07005             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
07006                                   rowp[i * ncols + namec]);
07007             if (sql) {
07008                 dbtraceapi(d, "sqlite3_get_table", sql);
07009                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07010                                         &nnrows, &nncols, NULL);
07011                 sqlite3_free(sql);
07012             }
07013             if (ret != SQLITE_OK) {
07014                 continue;
07015             }
07016             for (k = 0; nnrows && k < nncols; k++) {
07017                 if (strcmp(rowpp[k], "name") == 0) {
07018                     int m;
07019 
07020                     for (m = 1; m <= nnrows; m++) {
07021                         int roffs = (offs + m) * s->ncols;
07022 
07023                         s->rows[roffs + 0] =
07024                             xstrdup(stringify(SQL_SCOPE_SESSION));
07025                         s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
07026                         s->rows[roffs + 4] = xstrdup("0");
07027                         s->rows[roffs + 7] =
07028                             xstrdup(stringify(SQL_PC_NOT_PSEUDO));
07029                         if (namecc >= 0 && typecc >= 0) {
07030                             int ii;
07031 
07032                             for (ii = 1; ii <= nnnrows; ii++) {
07033                                 if (strcmp(rowppp[ii * nnncols + namecc],
07034                                            rowpp[m * nncols + k]) == 0) {
07035                                     char *typen = rowppp[ii * nnncols + typecc];
07036                                     int sqltype, mm, dd, isnullable = 0;
07037                                     char buf[32];
07038 
07039                                     s->rows[roffs + 3] = xstrdup(typen);
07040                                     sqltype = mapsqltype(typen, NULL, *s->ov3,
07041                                                          s->nowchar[0],
07042                                                          s->dobigint);
07043                                     getmd(typen, sqltype, &mm, &dd);
07044 #ifdef SQL_LONGVARCHAR
07045                                     if (sqltype == SQL_VARCHAR && mm > 255) {
07046                                         sqltype = SQL_LONGVARCHAR;
07047                                     }
07048 #endif
07049 #ifdef WINTERFACE
07050 #ifdef SQL_WLONGVARCHAR
07051                                     if (sqltype == SQL_WVARCHAR && mm > 255) {
07052                                         sqltype = SQL_WLONGVARCHAR;
07053                                     }
07054 #endif
07055 #endif
07056                                     if (sqltype == SQL_VARBINARY && mm > 255) {
07057                                         sqltype = SQL_LONGVARBINARY;
07058                                     }
07059                                     sprintf(buf, "%d", sqltype);
07060                                     s->rows[roffs + 2] = xstrdup(buf);
07061                                     sprintf(buf, "%d", mm);
07062                                     s->rows[roffs + 5] = xstrdup(buf);
07063                                     sprintf(buf, "%d", dd);
07064                                     s->rows[roffs + 6] = xstrdup(buf);
07065                                     if (notnullcc >= 0) {
07066                                         char *inp =
07067                                            rowppp[ii * nnncols + notnullcc];
07068 
07069                                         isnullable = inp[0] != '0';
07070                                     }
07071                                     sprintf(buf, "%d", isnullable);
07072                                     s->rows[roffs + 8] = xstrdup(buf);
07073                                 }
07074                             }
07075                         }
07076                     }
07077                 }
07078             }
07079             offs += nnrows;
07080             sqlite3_free_table(rowpp);
07081         }
07082     }
07083     if (nullable == SQL_NO_NULLS) {
07084         for (i = 1; i < s->nrows; i++) {
07085             if (s->rows[i * s->ncols + 8][0] == '0') {
07086                 int m, i1 = i + 1;
07087 
07088                 for (m = 0; m < s->ncols; m++) {
07089                     freep(&s->rows[i * s->ncols + m]);
07090                 }
07091                 size = s->ncols * sizeof (char *) * (s->nrows - i1);
07092                 if (size > 0) {
07093                     memmove(s->rows + i * s->ncols,
07094                             s->rows + i1 * s->ncols,
07095                             size);
07096                     memset(s->rows + s->nrows * s->ncols, 0,
07097                            s->ncols * sizeof (char *));
07098                 }
07099                 s->nrows--;
07100                 --i;
07101             }
07102         }
07103     }
07104 mkrowid:
07105     sqlite3_free_table(rowp);
07106     sqlite3_free_table(rowppp);
07107     if (s->nrows == 0) {
07108         s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
07109         s->rows[s->ncols + 1] = xstrdup("_ROWID_");
07110         s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
07111         s->rows[s->ncols + 3] = xstrdup("integer");
07112         s->rows[s->ncols + 4] = xstrdup("0");
07113         s->rows[s->ncols + 5] = xstrdup("10");
07114         s->rows[s->ncols + 6] = xstrdup("9");
07115         s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
07116         s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
07117         s->nrows = 1;
07118     }
07119     return SQL_SUCCESS;
07120 }
07121 
07122 #ifndef WINTERFACE
07123 
07138 SQLRETURN SQL_API
07139 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
07140                   SQLCHAR *cat, SQLSMALLINT catLen,
07141                   SQLCHAR *schema, SQLSMALLINT schemaLen,
07142                   SQLCHAR *table, SQLSMALLINT tableLen,
07143                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
07144 {
07145 #if defined(_WIN32) || defined(_WIN64)
07146     char *c = NULL, *s = NULL, *t = NULL;
07147 #endif
07148     SQLRETURN ret;
07149 
07150     HSTMT_LOCK(stmt);
07151 #if defined(_WIN32) || defined(_WIN64)
07152     if (!((STMT *) stmt)->oemcp[0]) {
07153         ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07154                                 table, tableLen, scope, nullable);
07155         goto done2;
07156     }
07157     if (cat) {
07158         c = wmb_to_utf_c((char *) cat, catLen);
07159         if (!c) {
07160             ret = nomem((STMT *) stmt);
07161             goto done;
07162         }
07163     }
07164     if (schema) {
07165         s = wmb_to_utf_c((char *) schema, schemaLen);
07166         if (!s) {
07167             ret = nomem((STMT *) stmt);
07168             goto done;
07169         }
07170     }
07171     if (table) {
07172         t = wmb_to_utf_c((char *) table, tableLen);
07173         if (!t) {
07174             ret = nomem((STMT *) stmt);
07175             goto done;
07176         }
07177     }
07178     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07179                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07180                             scope, nullable);
07181 #else
07182     ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07183                             table, tableLen, scope, nullable);
07184 #endif
07185 #if defined(_WIN32) || defined(_WIN64)
07186 done:
07187     uc_free(t);
07188     uc_free(s);
07189     uc_free(c);
07190 done2:
07191     ;
07192 #endif
07193     HSTMT_UNLOCK(stmt);
07194     return ret;
07195 }
07196 #endif
07197 
07198 #ifdef WINTERFACE
07199 
07214 SQLRETURN SQL_API
07215 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
07216                    SQLWCHAR *cat, SQLSMALLINT catLen,
07217                    SQLWCHAR *schema, SQLSMALLINT schemaLen,
07218                    SQLWCHAR *table, SQLSMALLINT tableLen,
07219                    SQLUSMALLINT scope, SQLUSMALLINT nullable)
07220 {
07221     char *c = NULL, *s = NULL, *t = NULL;
07222     SQLRETURN ret;
07223 
07224     HSTMT_LOCK(stmt);
07225     if (cat) {
07226         c = uc_to_utf_c(cat, catLen);
07227         if (!c) {
07228             ret = nomem((STMT *) stmt);
07229             goto done;
07230         }
07231     }
07232     if (schema) {
07233         s = uc_to_utf_c(schema, schemaLen);
07234         if (!s) {
07235             ret = nomem((STMT *) stmt);
07236             goto done;
07237         }
07238     }
07239     if (table) {
07240         t = uc_to_utf_c(table, tableLen);
07241         if (!t) {
07242             ret = nomem((STMT *) stmt);
07243             goto done;
07244         }
07245     }
07246     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07247                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07248                             scope, nullable);
07249 done:
07250     uc_free(t);
07251     uc_free(s);
07252     uc_free(c);
07253     HSTMT_UNLOCK(stmt);
07254     return ret;
07255 }
07256 #endif
07257 
07262 static COL fkeySpec2[] = {
07263     { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07264     { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
07265     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07266     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07267     { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07268     { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
07269     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07270     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07271     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07272     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07273     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07274     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07275     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07276     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07277 };
07278 
07279 static COL fkeySpec3[] = {
07280     { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
07281     { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07282     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07283     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07284     { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
07285     { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07286     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07287     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07288     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07289     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07290     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07291     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07292     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07293     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07294 };
07295 
07314 static SQLRETURN SQL_API
07315 drvforeignkeys(SQLHSTMT stmt,
07316                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07317                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07318                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07319                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07320                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07321                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07322 {
07323     STMT *s;
07324     DBC *d;
07325     SQLRETURN sret;
07326     int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
07327     int onu, ond;
07328     PTRDIFF_T size;
07329     char **rowp, *errp = NULL, *sql, pname[512], fname[512];
07330 
07331     sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
07332                        fkeySpec3, array_size(fkeySpec3), &asize);
07333     if (sret != SQL_SUCCESS) {
07334         return sret;
07335     }
07336     s = (STMT *) stmt;
07337     sret = starttran(s);
07338     if (sret != SQL_SUCCESS) {
07339         return sret;
07340     }
07341     d = (DBC *) s->dbc;
07342     if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
07343         (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
07344         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
07345         return SQL_ERROR;
07346     }
07347     size = 0;
07348     if (PKtable) {
07349         if (PKtableLen == SQL_NTS) {
07350             size = sizeof (pname) - 1;
07351         } else {
07352             size = min(sizeof (pname) - 1, PKtableLen);
07353         }
07354         strncpy(pname, (char *) PKtable, size);
07355     }
07356     pname[size] = '\0';
07357     size = 0;
07358     if (FKtable) {
07359 
07360         if (FKtableLen == SQL_NTS) {
07361             size = sizeof (fname) - 1;
07362         } else {
07363             size = min(sizeof (fname) - 1, FKtableLen);
07364         }
07365         strncpy(fname, (char *) FKtable, size);
07366     }
07367     fname[size] = '\0';
07368     if (fname[0] != '\0') {
07369         int plen;
07370 
07371         ret = SQLITE_ERROR;
07372         sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
07373         if (sql) {
07374             dbtraceapi(d, "sqlite3_get_table", sql);
07375             ret = sqlite3_get_table(d->sqlite, sql, &rowp,
07376                                     &nrows, &ncols, &errp);
07377             sqlite3_free(sql);
07378         }
07379         if (ret != SQLITE_OK) {
07380             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07381                     errp ? errp : "unknown error", ret);
07382             if (errp) {
07383                 sqlite3_free(errp);
07384                 errp = NULL;
07385             }
07386             return SQL_ERROR;
07387         }
07388         if (errp) {
07389             sqlite3_free(errp);
07390             errp = NULL;
07391         }
07392         if (ncols * nrows <= 0) {
07393 nodata:
07394             sqlite3_free_table(rowp);
07395             return SQL_SUCCESS;
07396         }
07397         size = 0;
07398         namec = findcol(rowp, ncols, "table");
07399         seqc = findcol(rowp, ncols, "seq");
07400         fromc = findcol(rowp, ncols, "from");
07401         toc = findcol(rowp, ncols, "to");
07402         onu = findcol(rowp, ncols, "on_update");
07403         ond = findcol(rowp, ncols, "on_delete");
07404         if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07405             goto nodata;
07406         }
07407         plen = strlen(pname);
07408         for (i = 1; i <= nrows; i++) {
07409             char *ptab = unquote(rowp[i * ncols + namec]);
07410 
07411             if (plen && ptab) {
07412                 int len = strlen(ptab);
07413 
07414                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07415                     continue;
07416                 }
07417             }
07418             size++;
07419         }
07420         if (size == 0) {
07421             goto nodata;
07422         }
07423         s->nrows = size;
07424         size = (size + 1) * asize;
07425         s->rows = xmalloc((size + 1) * sizeof (char *));
07426         if (!s->rows) {
07427             s->nrows = 0;
07428             return nomem(s);
07429         }
07430         s->rows[0] = (char *) size;
07431         s->rows += 1;
07432         memset(s->rows, 0, sizeof (char *) * size);
07433         s->rowfree = freerows;
07434         offs = 0;
07435         for (i = 1; i <= nrows; i++) {
07436             int pos = 0, roffs = (offs + 1) * s->ncols;
07437             char *ptab = rowp[i * ncols + namec];
07438             char buf[32];
07439 
07440             if (plen && ptab) {
07441                 int len = strlen(ptab);
07442 
07443                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07444                     continue;
07445                 }
07446             }
07447 #if defined(_WIN32) || defined(_WIN64)
07448             s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07449             s->rows[roffs + 1] = xstrdup("");
07450 #else
07451             s->rows[roffs + 0] = xstrdup("");
07452             s->rows[roffs + 1] = xstrdup("");
07453 #endif
07454             s->rows[roffs + 2] = xstrdup(ptab);
07455             s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
07456             s->rows[roffs + 4] = xstrdup("");
07457             s->rows[roffs + 5] = xstrdup("");
07458             s->rows[roffs + 6] = xstrdup(fname);
07459             s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
07460             sscanf(rowp[i * ncols + seqc], "%d", &pos);
07461             sprintf(buf, "%d", pos + 1);
07462             s->rows[roffs + 8] = xstrdup(buf);
07463             if (onu < 0) {
07464                 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07465             } else {
07466                 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
07467                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07468                 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
07469                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
07470                 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
07471                     s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07472                 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
07473                     s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07474                 } else {
07475                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07476                 }
07477             }
07478             if (ond < 0) {
07479                 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07480             } else {
07481                 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
07482                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07483                 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
07484                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
07485                 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
07486                     s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07487                 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
07488                     s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07489                 } else {
07490                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07491                 }
07492             }
07493             s->rows[roffs + 11] = NULL;
07494             s->rows[roffs + 12] = NULL;
07495             s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07496             offs++;
07497         }
07498         sqlite3_free_table(rowp);
07499     } else {
07500         int nnrows, nncols, plen = strlen(pname);
07501         char **rowpp;
07502 
07503         sql = "select name from sqlite_master where type='table'";
07504         dbtraceapi(d, "sqlite3_get_table", sql);
07505         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
07506         if (ret != SQLITE_OK) {
07507             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07508                     errp ? errp : "unknown error", ret);
07509             if (errp) {
07510                 sqlite3_free(errp);
07511                 errp = NULL;
07512             }
07513             return SQL_ERROR;
07514         }
07515         if (errp) {
07516             sqlite3_free(errp);
07517             errp = NULL;
07518         }
07519         if (ncols * nrows <= 0) {
07520             goto nodata;
07521         }
07522         size = 0;
07523         for (i = 1; i <= nrows; i++) {
07524             int k;
07525 
07526             if (!rowp[i]) {
07527                 continue;
07528             }
07529             rowpp = NULL;
07530             ret = SQLITE_ERROR;
07531             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07532             if (sql) {
07533                 dbtraceapi(d, "sqlite3_get_table", sql);
07534                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07535                                       &nnrows, &nncols, NULL);
07536                 sqlite3_free(sql);
07537             }
07538             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07539                 sqlite3_free_table(rowpp);
07540                 continue;
07541             }
07542             namec = findcol(rowpp, nncols, "table");
07543             seqc = findcol(rowpp, nncols, "seq");
07544             fromc = findcol(rowpp, nncols, "from");
07545             toc = findcol(rowpp, nncols, "to");
07546             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07547                 sqlite3_free_table(rowpp);
07548                 continue;
07549             }
07550             for (k = 1; k <= nnrows; k++) {
07551                 char *ptab = unquote(rowpp[k * nncols + namec]);
07552 
07553                 if (plen && ptab) {
07554                     int len = strlen(ptab);
07555 
07556                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07557                         continue;
07558                     }
07559                 }
07560                 size++;
07561             }
07562             sqlite3_free_table(rowpp);
07563         }
07564         if (size == 0) {
07565             goto nodata;
07566         }
07567         s->nrows = size;
07568         size = (size + 1) * asize;
07569         s->rows = xmalloc((size + 1) * sizeof (char *));
07570         if (!s->rows) {
07571             s->nrows = 0;
07572             return nomem(s);
07573         }
07574         s->rows[0] = (char *) size;
07575         s->rows += 1;
07576         memset(s->rows, 0, sizeof (char *) * size);
07577         s->rowfree = freerows;
07578         offs = 0;
07579         for (i = 1; i <= nrows; i++) {
07580             int k;
07581 
07582             if (!rowp[i]) {
07583                 continue;
07584             }
07585             rowpp = NULL;
07586             ret = SQLITE_ERROR;
07587             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07588             if (sql) {
07589                 dbtraceapi(d, "sqlite3_get_table", sql);
07590                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07591                                         &nnrows, &nncols, NULL);
07592                 sqlite3_free(sql);
07593             }
07594             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07595                 sqlite3_free_table(rowpp);
07596                 continue;
07597             }
07598             namec = findcol(rowpp, nncols, "table");
07599             seqc = findcol(rowpp, nncols, "seq");
07600             fromc = findcol(rowpp, nncols, "from");
07601             toc = findcol(rowpp, nncols, "to");
07602             onu = findcol(rowpp, nncols, "on_update");
07603             ond = findcol(rowpp, nncols, "on_delete");
07604             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07605                 sqlite3_free_table(rowpp);
07606                 continue;
07607             }
07608             for (k = 1; k <= nnrows; k++) {
07609                 int pos = 0, roffs = (offs + 1) * s->ncols;
07610                 char *ptab = unquote(rowpp[k * nncols + namec]);
07611                 char buf[32];
07612 
07613                 if (plen && ptab) {
07614                     int len = strlen(ptab);
07615 
07616                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07617                         continue;
07618                     }
07619                 }
07620 #if defined(_WIN32) || defined(_WIN64)
07621                 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07622                 s->rows[roffs + 1] = xstrdup("");
07623 #else
07624                 s->rows[roffs + 0] = xstrdup("");
07625                 s->rows[roffs + 1] = xstrdup("");
07626 #endif
07627                 s->rows[roffs + 2] = xstrdup(ptab);
07628                 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
07629                 s->rows[roffs + 4] = xstrdup("");
07630                 s->rows[roffs + 5] = xstrdup("");
07631                 s->rows[roffs + 6] = xstrdup(rowp[i]);
07632                 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
07633                 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
07634                 sprintf(buf, "%d", pos + 1);
07635                 s->rows[roffs + 8] = xstrdup(buf);
07636                 if (onu < 0) {
07637                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07638                 } else {
07639                     if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
07640                         s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07641                     } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
07642                                == 0) {
07643                         s->rows[roffs + 9] =
07644                             xstrdup(stringify(SQL_SET_DEFAULT));
07645                     } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
07646                                == 0) {
07647                         s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07648                     } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
07649                                == 0) {
07650                         s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07651                     } else {
07652                         s->rows[roffs + 9] =
07653                             xstrdup(stringify(SQL_NO_ACTION));
07654                     }
07655                 }
07656                 if (ond < 0) {
07657                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07658                 } else {
07659                     if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
07660                         s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07661                     } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
07662                                == 0) {
07663                         s->rows[roffs + 10] =
07664                             xstrdup(stringify(SQL_SET_DEFAULT));
07665                     } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
07666                                == 0) {
07667                         s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07668                     } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
07669                                == 0) {
07670                         s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07671                     } else {
07672                         s->rows[roffs + 10] =
07673                             xstrdup(stringify(SQL_NO_ACTION));
07674                     }
07675                 }
07676                 s->rows[roffs + 11] = NULL;
07677                 s->rows[roffs + 12] = NULL;
07678                 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07679                 offs++;
07680             }
07681             sqlite3_free_table(rowpp);
07682         }
07683         sqlite3_free_table(rowp);
07684     }
07685     return SQL_SUCCESS;
07686 }
07687 
07688 #ifndef WINTERFACE
07689 
07707 SQLRETURN SQL_API
07708 SQLForeignKeys(SQLHSTMT stmt,
07709                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07710                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07711                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07712                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07713                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07714                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07715 {
07716 #if defined(_WIN32) || defined(_WIN64)
07717     char *pc = NULL, *ps = NULL, *pt = NULL;
07718     char *fc = NULL, *fs = NULL, *ft = NULL;
07719 #endif
07720     SQLRETURN ret;
07721 
07722     HSTMT_LOCK(stmt);
07723 #if defined(_WIN32) || defined(_WIN64)
07724     if (!((STMT *) stmt)->oemcp[0]) {
07725         ret = drvforeignkeys(stmt,
07726                              PKcatalog, PKcatalogLen,
07727                              PKschema, PKschemaLen, PKtable, PKtableLen,
07728                              FKcatalog, FKcatalogLen,
07729                              FKschema, FKschemaLen,
07730                              FKtable, FKtableLen);
07731         goto done2;
07732     }
07733     if (PKcatalog) {
07734         pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
07735         if (!pc) {
07736             ret = nomem((STMT *) stmt);
07737             goto done;
07738         }
07739     }
07740     if (PKschema) {
07741         ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
07742         if (!ps) {
07743             ret = nomem((STMT *) stmt);
07744             goto done;
07745         }
07746     }
07747     if (PKtable) {
07748         pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
07749         if (!pt) {
07750             ret = nomem((STMT *) stmt);
07751             goto done;
07752         }
07753     }
07754     if (FKcatalog) {
07755         fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
07756         if (!fc) {
07757             ret = nomem((STMT *) stmt);
07758             goto done;
07759         }
07760     }
07761     if (FKschema) {
07762         fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
07763         if (!fs) {
07764             ret = nomem((STMT *) stmt);
07765             goto done;
07766         }
07767     }
07768     if (FKtable) {
07769         ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
07770         if (!ft) {
07771             ret = nomem((STMT *) stmt);
07772             goto done;
07773         }
07774     }
07775     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
07776                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
07777                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
07778                          (SQLCHAR *) ft, SQL_NTS);
07779 #else
07780     ret = drvforeignkeys(stmt,
07781                          PKcatalog, PKcatalogLen,
07782                          PKschema, PKschemaLen, PKtable, PKtableLen,
07783                          FKcatalog, FKcatalogLen,
07784                          FKschema, FKschemaLen,
07785                          FKtable, FKtableLen);
07786 #endif
07787 #if defined(_WIN32) || defined(_WIN64)
07788 done:
07789     uc_free(ft);
07790     uc_free(fs);
07791     uc_free(fc);
07792     uc_free(pt);
07793     uc_free(ps);
07794     uc_free(pc);
07795 done2:
07796     ;
07797 #endif
07798     HSTMT_UNLOCK(stmt);
07799     return ret;
07800 }
07801 #endif
07802 
07803 #ifdef WINTERFACE
07804 
07822 SQLRETURN SQL_API
07823 SQLForeignKeysW(SQLHSTMT stmt,
07824                 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07825                 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
07826                 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
07827                 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07828                 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
07829                 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
07830 {
07831     char *pc = NULL, *ps = NULL, *pt = NULL;
07832     char *fc = NULL, *fs = NULL, *ft = NULL;
07833     SQLRETURN ret;
07834 
07835     HSTMT_LOCK(stmt);
07836     if (PKcatalog) {
07837         pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
07838         if (!pc) {
07839             ret = nomem((STMT *) stmt);
07840             goto done;
07841         }
07842     }
07843     if (PKschema) {
07844         ps = uc_to_utf_c(PKschema, PKschemaLen);
07845         if (!ps) {
07846             ret = nomem((STMT *) stmt);
07847             goto done;
07848         }
07849     }
07850     if (PKtable) {
07851         pt = uc_to_utf_c(PKtable, PKtableLen);
07852         if (!pt) {
07853             ret = nomem((STMT *) stmt);
07854             goto done;
07855         }
07856     }
07857     if (FKcatalog) {
07858         fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
07859         if (!fc) {
07860             ret = nomem((STMT *) stmt);
07861             goto done;
07862         }
07863     }
07864     if (FKschema) {
07865         fs = uc_to_utf_c(FKschema, FKschemaLen);
07866         if (!fs) {
07867             ret = nomem((STMT *) stmt);
07868             goto done;
07869         }
07870     }
07871     if (FKtable) {
07872         ft = uc_to_utf_c(FKtable, FKtableLen);
07873         if (!ft) {
07874             ret = nomem((STMT *) stmt);
07875             goto done;
07876         }
07877     }
07878     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
07879                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
07880                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
07881                          (SQLCHAR *) ft, SQL_NTS);
07882 done:
07883     uc_free(ft);
07884     uc_free(fs);
07885     uc_free(fc);
07886     uc_free(pt);
07887     uc_free(ps);
07888     uc_free(pc);
07889     HSTMT_UNLOCK(stmt);
07890     return ret;
07891 }
07892 #endif
07893 
07900 static SQLRETURN
07901 starttran(STMT *s)
07902 {
07903     int ret = SQL_SUCCESS, rc, busy_count = 0;
07904     char *errp = NULL;
07905     DBC *d = (DBC *) s->dbc;
07906 
07907     if (!d->autocommit && !d->intrans && !d->trans_disable) {
07908 begin_again:
07909         rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
07910         if (rc == SQLITE_BUSY) {
07911             if (busy_handler((void *) d, ++busy_count)) {
07912                 if (errp) {
07913                     sqlite3_free(errp);
07914                     errp = NULL;
07915                 }
07916                 goto begin_again;
07917             }
07918         }
07919         dbtracerc(d, rc, errp);
07920         if (rc != SQLITE_OK) {
07921             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07922                     errp ? errp : "unknown error", rc);
07923             ret = SQL_ERROR;
07924         } else {
07925             d->intrans = 1;
07926         }
07927         if (errp) {
07928             sqlite3_free(errp);
07929             errp = NULL;
07930         }
07931     }
07932     return ret;
07933 }
07934 
07943 static SQLRETURN
07944 endtran(DBC *d, SQLSMALLINT comptype, int force)
07945 {
07946     int ret, busy_count = 0;
07947     char *sql, *errp = NULL;
07948 
07949     if (!d->sqlite) {
07950         setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
07951         return SQL_ERROR;
07952     }
07953     if ((!force && d->autocommit) || !d->intrans) {
07954         return SQL_SUCCESS;
07955     }
07956     switch (comptype) {
07957     case SQL_COMMIT:
07958         sql = "COMMIT TRANSACTION";
07959         goto doit;
07960     case SQL_ROLLBACK:
07961         sql = "ROLLBACK TRANSACTION";
07962     doit:
07963         ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
07964         dbtracerc(d, ret, errp);
07965         if (ret == SQLITE_BUSY && busy_count < 10) {
07966             if (busy_handler((void *) d, ++busy_count)) {
07967                 if (errp) {
07968                     sqlite3_free(errp);
07969                     errp = NULL;
07970                 }
07971                 goto doit;
07972             }
07973         }
07974         if (ret != SQLITE_OK) {
07975             setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
07976                      errp ? errp : "transaction failed");
07977             if (errp) {
07978                 sqlite3_free(errp);
07979                 errp = NULL;
07980             }
07981             return SQL_ERROR;
07982         }
07983         if (errp) {
07984             sqlite3_free(errp);
07985             errp = NULL;
07986         }
07987         d->intrans = 0;
07988         return SQL_SUCCESS;
07989     }
07990     setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
07991     return SQL_ERROR;
07992 }
07993 
08002 static SQLRETURN
08003 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
08004 {
08005     DBC *dbc = NULL;
08006     int fail = 0;
08007     SQLRETURN ret;
08008 #if defined(_WIN32) || defined(_WIN64)
08009     ENV *env;
08010 #endif
08011 
08012     switch (type) {
08013     case SQL_HANDLE_DBC:
08014         HDBC_LOCK((SQLHDBC) handle);
08015         if (handle == SQL_NULL_HDBC) {
08016             return SQL_INVALID_HANDLE;
08017         }
08018         dbc = (DBC *) handle;
08019         ret = endtran(dbc, comptype, 0);
08020         HDBC_UNLOCK((SQLHDBC) handle);
08021         return ret;
08022     case SQL_HANDLE_ENV:
08023         if (handle == SQL_NULL_HENV) {
08024             return SQL_INVALID_HANDLE;
08025         }
08026 #if defined(_WIN32) || defined(_WIN64)
08027         env = (ENV *) handle;
08028         if (env->magic != ENV_MAGIC) {
08029             return SQL_INVALID_HANDLE;
08030         }
08031         EnterCriticalSection(&env->cs);
08032 #endif
08033         dbc = ((ENV *) handle)->dbcs;
08034         while (dbc) {
08035             HDBC_LOCK((SQLHDBC) dbc);
08036             ret = endtran(dbc, comptype, 0);
08037             HDBC_UNLOCK((SQLHDBC) dbc);
08038             if (ret != SQL_SUCCESS) {
08039                 fail++;
08040             }
08041             dbc = dbc->next;
08042         }
08043 #if defined(_WIN32) || defined(_WIN64)
08044         LeaveCriticalSection(&env->cs);
08045 #endif
08046         return fail ? SQL_ERROR : SQL_SUCCESS;
08047     }
08048     return SQL_INVALID_HANDLE;
08049 }
08050 
08059 SQLRETURN SQL_API
08060 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
08061 {
08062     return drvendtran(type, handle, comptype);
08063 }
08064 
08073 SQLRETURN SQL_API
08074 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
08075 {
08076     if (dbc != SQL_NULL_HDBC) {
08077         return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
08078     }
08079     return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
08080 }
08081 
08086 SQLRETURN SQL_API
08087 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
08088 {
08089     return SQL_ERROR;
08090 }
08091 
08092 #ifndef WINTERFACE
08093 
08104 SQLRETURN SQL_API
08105 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
08106              SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08107 {
08108     int outLen = 0;
08109     SQLRETURN ret = SQL_SUCCESS;
08110 
08111     HSTMT_LOCK(stmt);
08112     if (sqlinLen == SQL_NTS) {
08113         sqlinLen = strlen((char *) sqlin);
08114     }
08115     if (sql) {
08116         if (sqlMax > 0) {
08117             strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
08118             sqlin[sqlMax - 1] = '\0';
08119             outLen = min(sqlMax - 1, sqlinLen);
08120         }
08121     } else {
08122         outLen = sqlinLen;
08123     }
08124     if (sqlLen) {
08125         *sqlLen = outLen;
08126     }
08127     if (sql && outLen < sqlinLen) {
08128         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08129         ret = SQL_SUCCESS_WITH_INFO;
08130     }
08131     HSTMT_UNLOCK(stmt);
08132     return ret;
08133 }
08134 #endif
08135 
08136 #ifdef WINTERFACE
08137 
08148 SQLRETURN SQL_API
08149 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
08150               SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08151 {
08152     int outLen = 0;
08153     SQLRETURN ret = SQL_SUCCESS;
08154 
08155     HSTMT_LOCK(stmt);
08156     if (sqlinLen == SQL_NTS) {
08157         sqlinLen = uc_strlen(sqlin);
08158     }
08159     if (sql) {
08160         if (sqlMax > 0) {
08161             uc_strncpy(sql, sqlin, sqlMax - 1);
08162             sqlin[sqlMax - 1] = 0;
08163             outLen = min(sqlMax  - 1, sqlinLen);
08164         }
08165     } else {
08166         outLen = sqlinLen;
08167     }
08168     if (sqlLen) {
08169         *sqlLen = outLen;
08170     }
08171     if (sql && outLen < sqlinLen) {
08172         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08173         ret = SQL_SUCCESS_WITH_INFO;
08174     }
08175     HSTMT_UNLOCK(stmt);
08176     return ret;
08177 }
08178 #endif
08179 
08184 static COL procSpec2[] = {
08185     { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08186     { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08187     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08188     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08189     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08190     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08191     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08192     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08193 };
08194 
08195 static COL procSpec3[] = {
08196     { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08197     { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08198     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08199     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08200     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08201     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08202     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08203     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08204 };
08205 
08206 #ifndef WINTERFACE
08207 
08219 SQLRETURN SQL_API
08220 SQLProcedures(SQLHSTMT stmt,
08221               SQLCHAR *catalog, SQLSMALLINT catalogLen,
08222               SQLCHAR *schema, SQLSMALLINT schemaLen,
08223               SQLCHAR *proc, SQLSMALLINT procLen)
08224 {
08225     SQLRETURN ret;
08226 
08227     HSTMT_LOCK(stmt);
08228     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08229                       procSpec3, array_size(procSpec3), NULL);
08230     HSTMT_UNLOCK(stmt);
08231     return ret;
08232 }
08233 #endif
08234 
08235 #ifdef WINTERFACE
08236 
08248 SQLRETURN SQL_API
08249 SQLProceduresW(SQLHSTMT stmt,
08250                SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08251                SQLWCHAR *schema, SQLSMALLINT schemaLen,
08252                SQLWCHAR *proc, SQLSMALLINT procLen)
08253 {
08254     SQLRETURN ret;
08255 
08256     HSTMT_LOCK(stmt);
08257     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08258                       procSpec3, array_size(procSpec3), NULL);
08259     HSTMT_UNLOCK(stmt);
08260     return ret;
08261 }
08262 #endif
08263 
08268 static COL procColSpec2[] = {
08269     { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08270     { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08271     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08272     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08273     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08274     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08275     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08276     { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
08277     { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
08278     { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
08279     { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
08280     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08281     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08282     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08283     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08284     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08285     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08286     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08287     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08288 };
08289 
08290 static COL procColSpec3[] = {
08291     { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08292     { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08293     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08294     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08295     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08296     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08297     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08298     { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
08299     { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
08300     { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
08301     { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
08302     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08303     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08304     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08305     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08306     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08307     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08308     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08309     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08310 };
08311 
08312 #ifndef WINTERFACE
08313 
08327 SQLRETURN SQL_API
08328 SQLProcedureColumns(SQLHSTMT stmt,
08329                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
08330                     SQLCHAR *schema, SQLSMALLINT schemaLen,
08331                     SQLCHAR *proc, SQLSMALLINT procLen,
08332                     SQLCHAR *column, SQLSMALLINT columnLen)
08333 {
08334     SQLRETURN ret;
08335 
08336     HSTMT_LOCK(stmt);
08337     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08338                       procColSpec3, array_size(procColSpec3), NULL);
08339     HSTMT_UNLOCK(stmt);
08340     return ret;
08341 }
08342 #endif
08343 
08344 #ifdef WINTERFACE
08345 
08360 SQLRETURN SQL_API
08361 SQLProcedureColumnsW(SQLHSTMT stmt,
08362                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08363                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
08364                      SQLWCHAR *proc, SQLSMALLINT procLen,
08365                      SQLWCHAR *column, SQLSMALLINT columnLen)
08366 {
08367     SQLRETURN ret;
08368 
08369     HSTMT_LOCK(stmt);
08370     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08371                       procColSpec3, array_size(procColSpec3), NULL);
08372     HSTMT_UNLOCK(stmt);
08373     return ret;
08374 }
08375 #endif
08376 
08387 SQLRETURN SQL_API
08388 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
08389               SQLINTEGER len, SQLINTEGER *lenp)
08390 {
08391     ENV *e;
08392     SQLRETURN ret = SQL_ERROR;
08393 
08394     if (env == SQL_NULL_HENV) {
08395         return SQL_INVALID_HANDLE;
08396     }
08397     e = (ENV *) env;
08398     if (!e || e->magic != ENV_MAGIC) {
08399         return SQL_INVALID_HANDLE;
08400     }
08401 #if defined(_WIN32) || defined(_WIN64)
08402     EnterCriticalSection(&e->cs);
08403 #endif
08404     switch (attr) {
08405     case SQL_ATTR_CONNECTION_POOLING:
08406         ret = SQL_ERROR;
08407         break;
08408     case SQL_ATTR_CP_MATCH:
08409         ret = SQL_NO_DATA;
08410         break;
08411     case SQL_ATTR_OUTPUT_NTS:
08412         if (val) {
08413             *((SQLINTEGER *) val) = SQL_TRUE;
08414         }
08415         if (lenp) {
08416             *lenp = sizeof (SQLINTEGER);
08417         }
08418         ret = SQL_SUCCESS;
08419         break;
08420     case SQL_ATTR_ODBC_VERSION:
08421         if (val) {
08422             *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
08423         }
08424         if (lenp) {
08425             *lenp = sizeof (SQLINTEGER);
08426         }
08427         ret = SQL_SUCCESS;
08428         break;
08429     }
08430 #if defined(_WIN32) || defined(_WIN64)
08431     LeaveCriticalSection(&e->cs);
08432 #endif
08433     return ret;
08434 }
08435 
08445 SQLRETURN SQL_API
08446 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
08447 {
08448     ENV *e;
08449     SQLRETURN ret = SQL_ERROR;
08450 
08451     if (env == SQL_NULL_HENV) {
08452         return SQL_INVALID_HANDLE;
08453     }
08454     e = (ENV *) env;
08455     if (!e || e->magic != ENV_MAGIC) {
08456         return SQL_INVALID_HANDLE;
08457     }
08458 #if defined(_WIN32) || defined(_WIN64)
08459     EnterCriticalSection(&e->cs);
08460 #endif
08461     switch (attr) {
08462     case SQL_ATTR_CONNECTION_POOLING:
08463         ret = SQL_SUCCESS;
08464         break;
08465     case SQL_ATTR_CP_MATCH:
08466         ret = SQL_NO_DATA;
08467         break;
08468     case SQL_ATTR_OUTPUT_NTS:
08469         if (val == (SQLPOINTER) SQL_TRUE) {
08470             ret = SQL_SUCCESS;
08471         }
08472         break;
08473     case SQL_ATTR_ODBC_VERSION:
08474         if (!val) {
08475             break;
08476         }
08477         if (val == (SQLPOINTER) SQL_OV_ODBC2) {
08478             e->ov3 = 0;
08479             ret = SQL_SUCCESS;
08480         }
08481         if (val == (SQLPOINTER) SQL_OV_ODBC3) {
08482             e->ov3 = 1;
08483             ret = SQL_SUCCESS;
08484         }
08485         break;
08486     }
08487 #if defined(_WIN32) || defined(_WIN64)
08488     LeaveCriticalSection(&e->cs);
08489 #endif
08490     return ret;
08491 }
08492 
08506 static SQLRETURN
08507 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08508               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08509               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08510 {
08511     DBC *d = NULL;
08512     STMT *s = NULL;
08513     int len, naterr;
08514     char *logmsg, *sqlst;
08515     SQLRETURN ret = SQL_ERROR;
08516 
08517     if (handle == SQL_NULL_HANDLE) {
08518         return SQL_INVALID_HANDLE;
08519     }
08520     if (sqlstate) {
08521         sqlstate[0] = '\0';
08522     }
08523     if (msg && buflen > 0) {
08524         msg[0] = '\0';
08525     }
08526     if (msglen) {
08527         *msglen = 0;
08528     }
08529     if (nativeerr) {
08530         *nativeerr = 0;
08531     }
08532     switch (htype) {
08533     case SQL_HANDLE_ENV:
08534     case SQL_HANDLE_DESC:
08535         return SQL_NO_DATA;
08536     case SQL_HANDLE_DBC:
08537         HDBC_LOCK((SQLHDBC) handle);
08538         d = (DBC *) handle;
08539         logmsg = (char *) d->logmsg;
08540         sqlst = d->sqlstate;
08541         naterr = d->naterr;
08542         break;
08543     case SQL_HANDLE_STMT:
08544         HSTMT_LOCK((SQLHSTMT) handle);
08545         s = (STMT *) handle;
08546         logmsg = (char *) s->logmsg;
08547         sqlst = s->sqlstate;
08548         naterr = s->naterr;
08549         break;
08550     default:
08551         return SQL_INVALID_HANDLE;
08552     }
08553     if (buflen < 0) {
08554         goto done;
08555     }
08556     if (recno > 1) {
08557         ret = SQL_NO_DATA;
08558         goto done;
08559     }
08560     len = strlen(logmsg);
08561     if (len == 0) {
08562         ret = SQL_NO_DATA;
08563         goto done;
08564     }
08565     if (nativeerr) {
08566         *nativeerr = naterr;
08567     }
08568     if (sqlstate) {
08569         strcpy((char *) sqlstate, sqlst);
08570     }
08571     if (msglen) {
08572         *msglen = len;
08573     }
08574     if (len >= buflen) {
08575         if (msg && buflen > 0) {
08576             strncpy((char *) msg, logmsg, buflen);
08577             msg[buflen - 1] = '\0';
08578             logmsg[0] = '\0';
08579         }
08580     } else if (msg) {
08581         strcpy((char *) msg, logmsg);
08582         logmsg[0] = '\0';
08583     }
08584     ret = SQL_SUCCESS;
08585 done:
08586     switch (htype) {
08587     case SQL_HANDLE_DBC:
08588         HDBC_UNLOCK((SQLHDBC) handle);
08589         break;
08590     case SQL_HANDLE_STMT:
08591         HSTMT_UNLOCK((SQLHSTMT) handle);
08592         break;
08593     }
08594     return ret;
08595 }
08596 
08597 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
08598 
08611 SQLRETURN SQL_API
08612 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08613               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08614               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08615 {
08616     return drvgetdiagrec(htype, handle, recno, sqlstate,
08617                          nativeerr, msg, buflen, msglen);
08618 }
08619 #endif
08620 
08621 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
08622 #ifdef WINTERFACE
08623 
08637 SQLRETURN SQL_API
08638 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08639               SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
08640               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08641 {
08642     char state[16];
08643     SQLSMALLINT len;
08644     SQLRETURN ret;
08645 
08646     ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
08647                         nativeerr, (SQLCHAR *) msg, buflen, &len);
08648     if (ret == SQL_SUCCESS) {
08649         if (sqlstate) {
08650             uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
08651                             6 * sizeof (SQLWCHAR));
08652         }
08653         if (msg) {
08654             if (len > 0) {
08655                 SQLWCHAR *m = NULL;
08656 
08657                 m = uc_from_utf((unsigned char *) msg, len);
08658                 if (m) {
08659                     if (buflen) {
08660                         buflen /= sizeof (SQLWCHAR);
08661                         uc_strncpy(msg, m, buflen);
08662                         m[len] = 0;
08663                         len = min(buflen, uc_strlen(m));
08664                     } else {
08665                         len = uc_strlen(m);
08666                     }
08667                     uc_free(m);
08668                 } else {
08669                     len = 0;
08670                 }
08671             }
08672             if (len <= 0) {
08673                 len = 0;
08674                 if (buflen > 0) {
08675                     msg[0] = 0;
08676                 }
08677             }
08678         } else {
08679             /* estimated length !!! */
08680             len *= sizeof (SQLWCHAR);
08681         }
08682         if (msglen) {
08683             *msglen = len;
08684         }
08685     } else if (ret == SQL_NO_DATA) {
08686         if (sqlstate) {
08687             sqlstate[0] = 0;
08688         }
08689         if (msg) {
08690             if (buflen > 0) {
08691                 msg[0] = 0;
08692             }
08693         }
08694         if (msglen) {
08695             *msglen = 0;
08696         }
08697     }
08698     return ret;
08699 }
08700 #endif
08701 #endif
08702 
08715 static SQLRETURN
08716 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08717                 SQLSMALLINT id, SQLPOINTER info,
08718                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08719 {
08720     DBC *d = NULL;
08721     STMT *s = NULL;
08722     int len, naterr, strbuf = 1;
08723     char *logmsg, *sqlst, *clrmsg = NULL;
08724     SQLRETURN ret = SQL_ERROR;
08725 
08726     if (handle == SQL_NULL_HANDLE) {
08727         return SQL_INVALID_HANDLE;
08728     }
08729     if (stringlen) {
08730         *stringlen = 0;
08731     }
08732     switch (htype) {
08733     case SQL_HANDLE_ENV:
08734     case SQL_HANDLE_DESC:
08735         return SQL_NO_DATA;
08736     case SQL_HANDLE_DBC:
08737         HDBC_LOCK((SQLHDBC) handle);
08738         d = (DBC *) handle;
08739         logmsg = (char *) d->logmsg;
08740         sqlst = d->sqlstate;
08741         naterr = d->naterr;
08742         break;
08743     case SQL_HANDLE_STMT:
08744         HSTMT_LOCK((SQLHSTMT) handle);
08745         s = (STMT *) handle;
08746         d = (DBC *) s->dbc;
08747         logmsg = (char *) s->logmsg;
08748         sqlst = s->sqlstate;
08749         naterr = s->naterr;
08750         break;
08751     default:
08752         return SQL_INVALID_HANDLE;
08753     }
08754     if (buflen < 0) {
08755         switch (buflen) {
08756         case SQL_IS_POINTER:
08757         case SQL_IS_UINTEGER:
08758         case SQL_IS_INTEGER:
08759         case SQL_IS_USMALLINT:
08760         case SQL_IS_SMALLINT:
08761             strbuf = 0;
08762             break;
08763         default:
08764             ret = SQL_ERROR;
08765             goto done;
08766         }
08767     }
08768     if (recno > 1) {
08769         ret = SQL_NO_DATA;
08770         goto done;
08771     }
08772     switch (id) {
08773     case SQL_DIAG_CLASS_ORIGIN:
08774         logmsg = "ISO 9075";
08775         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
08776             logmsg = "ODBC 3.0";
08777         }
08778         break;
08779     case SQL_DIAG_SUBCLASS_ORIGIN:
08780         logmsg = "ISO 9075";
08781         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
08782             logmsg = "ODBC 3.0";
08783         } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
08784             logmsg = "ODBC 3.0";
08785         } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
08786             logmsg = "ODBC 3.0";
08787         }
08788         break;
08789     case SQL_DIAG_CONNECTION_NAME:
08790     case SQL_DIAG_SERVER_NAME:
08791         logmsg = d->dsn ? d->dsn : "No DSN";
08792         break;
08793     case SQL_DIAG_SQLSTATE:
08794         logmsg = sqlst;
08795         break;
08796     case SQL_DIAG_MESSAGE_TEXT:
08797         if (info) {
08798             clrmsg = logmsg;
08799         }
08800         break;
08801     case SQL_DIAG_NUMBER:
08802         naterr = 1;
08803         /* fall through */
08804     case SQL_DIAG_NATIVE:
08805         len = strlen(logmsg);
08806         if (len == 0) {
08807             ret = SQL_NO_DATA;
08808             goto done;
08809         }
08810         if (info) {
08811             *((SQLINTEGER *) info) = naterr;
08812         }
08813         ret = SQL_SUCCESS;
08814         goto done;
08815     case SQL_DIAG_DYNAMIC_FUNCTION:
08816         logmsg = "";
08817         break;
08818     case SQL_DIAG_CURSOR_ROW_COUNT:
08819         if (htype == SQL_HANDLE_STMT) {
08820             SQLULEN count;
08821 
08822             count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
08823             *((SQLULEN *) info) = count;
08824             ret = SQL_SUCCESS;
08825         }
08826         goto done;
08827     case SQL_DIAG_ROW_COUNT:
08828         if (htype == SQL_HANDLE_STMT) {
08829             SQLULEN count;
08830 
08831             count = s->isselect ? 0 : s->nrows;
08832             *((SQLULEN *) info) = count;
08833             ret = SQL_SUCCESS;
08834         }
08835         goto done;
08836     default:
08837         goto done;
08838     }
08839     if (info && buflen > 0) {
08840         ((char *) info)[0] = '\0';
08841     }
08842     len = strlen(logmsg);
08843     if (len == 0) {
08844         ret = SQL_NO_DATA;
08845         goto done;
08846     }
08847     if (stringlen) {
08848         *stringlen = len;
08849     }
08850     if (strbuf) {
08851         if (len >= buflen) {
08852             if (info && buflen > 0) {
08853                 if (stringlen) {
08854                     *stringlen = buflen - 1;
08855                 }
08856                 strncpy((char *) info, logmsg, buflen);
08857                 ((char *) info)[buflen - 1] = '\0';
08858             }
08859         } else if (info) {
08860             strcpy((char *) info, logmsg);
08861         }
08862     }
08863     if (clrmsg) {
08864         *clrmsg = '\0';
08865     }
08866     ret = SQL_SUCCESS;
08867 done:
08868     switch (htype) {
08869     case SQL_HANDLE_DBC:
08870         HDBC_UNLOCK((SQLHDBC) handle);
08871         break;
08872     case SQL_HANDLE_STMT:
08873         HSTMT_UNLOCK((SQLHSTMT) handle);
08874         break;
08875     }
08876     return ret;
08877 }
08878 
08879 #ifndef WINTERFACE
08880 
08892 SQLRETURN SQL_API
08893 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08894                 SQLSMALLINT id, SQLPOINTER info,
08895                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08896 {
08897     return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
08898 }
08899 #endif
08900 
08901 #ifdef WINTERFACE
08902 
08914 SQLRETURN SQL_API
08915 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08916                  SQLSMALLINT id, SQLPOINTER info,
08917                  SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08918 {
08919     SQLSMALLINT len;
08920     SQLRETURN ret;
08921 
08922     ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
08923     if (ret == SQL_SUCCESS) {
08924         if (info) {
08925             switch (id) {
08926             case SQL_DIAG_CLASS_ORIGIN:
08927             case SQL_DIAG_SUBCLASS_ORIGIN:
08928             case SQL_DIAG_CONNECTION_NAME:
08929             case SQL_DIAG_SERVER_NAME:
08930             case SQL_DIAG_SQLSTATE:
08931             case SQL_DIAG_MESSAGE_TEXT:
08932             case SQL_DIAG_DYNAMIC_FUNCTION:
08933                 if (len > 0) {
08934                     SQLWCHAR *m = NULL;
08935 
08936                     m = uc_from_utf((unsigned char *) info, len);
08937                     if (m) {
08938                         if (buflen) {
08939                             buflen /= sizeof (SQLWCHAR);
08940                             uc_strncpy(info, m, buflen);
08941                             m[len] = 0;
08942                             len = min(buflen, uc_strlen(m));
08943                         } else {
08944                             len = uc_strlen(m);
08945                         }
08946                         uc_free(m);
08947                         len *= sizeof (SQLWCHAR);
08948                     } else {
08949                         len = 0;
08950                     }
08951                 }
08952                 if (len <= 0) {
08953                     len = 0;
08954                     if (buflen > 0) {
08955                         ((SQLWCHAR *) info)[0] = 0;
08956                     }
08957                 }
08958             }
08959         } else {
08960             switch (id) {
08961             case SQL_DIAG_CLASS_ORIGIN:
08962             case SQL_DIAG_SUBCLASS_ORIGIN:
08963             case SQL_DIAG_CONNECTION_NAME:
08964             case SQL_DIAG_SERVER_NAME:
08965             case SQL_DIAG_SQLSTATE:
08966             case SQL_DIAG_MESSAGE_TEXT:
08967             case SQL_DIAG_DYNAMIC_FUNCTION:
08968                 len *= sizeof (SQLWCHAR);
08969                 break;
08970             }
08971         }
08972         if (stringlen) {
08973             *stringlen = len;
08974         }
08975     }
08976     return ret;
08977 }
08978 #endif
08979 
08990 static SQLRETURN
08991 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
08992                SQLINTEGER bufmax, SQLINTEGER *buflen)
08993 {
08994     STMT *s = (STMT *) stmt;
08995     SQLULEN *uval = (SQLULEN *) val;
08996     SQLINTEGER dummy;
08997     char dummybuf[16];
08998 
08999     if (!buflen) {
09000         buflen = &dummy;
09001     }
09002     if (!uval) {
09003         uval = (SQLPOINTER) dummybuf;
09004     }
09005     switch (attr) {
09006     case SQL_QUERY_TIMEOUT:
09007         *uval = 0;
09008         *buflen = sizeof (SQLULEN);
09009         return SQL_SUCCESS;
09010     case SQL_ATTR_CURSOR_TYPE:
09011         *uval = s->curtype;
09012         *buflen = sizeof (SQLULEN);
09013         return SQL_SUCCESS;
09014     case SQL_ATTR_CURSOR_SCROLLABLE:
09015         *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
09016             SQL_SCROLLABLE : SQL_NONSCROLLABLE;
09017         *buflen = sizeof (SQLULEN);
09018         return SQL_SUCCESS;
09019 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09020     case SQL_ATTR_CURSOR_SENSITIVITY:
09021         *uval = SQL_UNSPECIFIED;
09022         *buflen = sizeof (SQLULEN);
09023         return SQL_SUCCESS;
09024 #endif
09025     case SQL_ATTR_ROW_NUMBER:
09026         if (s->s3stmt) {
09027             *uval = (s->s3stmt_rownum < 0) ?
09028                     SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09029         } else {
09030             *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09031         }
09032         *buflen = sizeof (SQLULEN);
09033         return SQL_SUCCESS;
09034     case SQL_ATTR_ASYNC_ENABLE:
09035         *uval = SQL_ASYNC_ENABLE_OFF;
09036         *buflen = sizeof (SQLULEN);
09037         return SQL_SUCCESS;
09038     case SQL_CONCURRENCY:
09039         *uval = SQL_CONCUR_LOCK;
09040         *buflen = sizeof (SQLULEN);
09041         return SQL_SUCCESS;
09042     case SQL_ATTR_RETRIEVE_DATA:
09043         *uval = s->retr_data;
09044         *buflen = sizeof (SQLULEN);
09045         return SQL_SUCCESS;
09046     case SQL_ROWSET_SIZE:
09047     case SQL_ATTR_ROW_ARRAY_SIZE:
09048         *uval = s->rowset_size;
09049         *buflen = sizeof (SQLULEN);
09050         return SQL_SUCCESS;
09051     /* Needed for some driver managers, but dummies for now */
09052     case SQL_ATTR_IMP_ROW_DESC:
09053     case SQL_ATTR_APP_ROW_DESC:
09054     case SQL_ATTR_IMP_PARAM_DESC:
09055     case SQL_ATTR_APP_PARAM_DESC:
09056         *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
09057         *buflen = sizeof (SQLHDESC);
09058         return SQL_SUCCESS;
09059     case SQL_ATTR_ROW_STATUS_PTR:
09060         *((SQLUSMALLINT **) uval) = s->row_status;
09061         *buflen = sizeof (SQLUSMALLINT *);
09062         return SQL_SUCCESS;
09063     case SQL_ATTR_ROWS_FETCHED_PTR:
09064         *((SQLULEN **) uval) = s->row_count;
09065         *buflen = sizeof (SQLULEN *);
09066         return SQL_SUCCESS;
09067     case SQL_ATTR_USE_BOOKMARKS: {
09068         STMT *s = (STMT *) stmt;
09069 
09070         *(SQLUINTEGER *) uval = s->bkmrk;
09071         *buflen = sizeof (SQLUINTEGER);
09072         return SQL_SUCCESS;
09073     }
09074     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09075         *(SQLPOINTER *) uval = s->bkmrkptr;
09076         *buflen = sizeof (SQLPOINTER);
09077         return SQL_SUCCESS;
09078     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09079         *((SQLULEN **) uval) = s->parm_bind_offs;
09080         *buflen = sizeof (SQLULEN *);
09081         return SQL_SUCCESS;
09082     case SQL_ATTR_PARAM_BIND_TYPE:
09083         *((SQLULEN *) uval) = s->parm_bind_type;
09084         *buflen = sizeof (SQLULEN);
09085         return SQL_SUCCESS;
09086     case SQL_ATTR_PARAM_OPERATION_PTR:
09087         *((SQLUSMALLINT **) uval) = s->parm_oper;
09088         *buflen = sizeof (SQLUSMALLINT *);
09089         return SQL_SUCCESS;
09090     case SQL_ATTR_PARAM_STATUS_PTR:
09091         *((SQLUSMALLINT **) uval) = s->parm_status;
09092         *buflen = sizeof (SQLUSMALLINT *);
09093         return SQL_SUCCESS;
09094     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09095         *((SQLULEN **) uval) = s->parm_proc;
09096         *buflen = sizeof (SQLULEN *);
09097         return SQL_SUCCESS;
09098     case SQL_ATTR_PARAMSET_SIZE:
09099         *((SQLULEN *) uval) = s->paramset_size;
09100         *buflen = sizeof (SQLULEN);
09101         return SQL_SUCCESS;
09102     case SQL_ATTR_ROW_BIND_TYPE:
09103         *(SQLULEN *) uval = s->bind_type;
09104         *buflen = sizeof (SQLULEN);
09105         return SQL_SUCCESS;
09106     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09107         *((SQLULEN **) uval) = s->bind_offs;
09108         *buflen = sizeof (SQLULEN *);
09109         return SQL_SUCCESS;
09110     case SQL_ATTR_MAX_ROWS:
09111         *((SQLULEN *) uval) = s->max_rows;
09112         *buflen = sizeof (SQLULEN);
09113         return SQL_SUCCESS;
09114     case SQL_ATTR_MAX_LENGTH:
09115         *((SQLULEN *) uval) = 1000000000;
09116         *buflen = sizeof (SQLULEN);
09117         return SQL_SUCCESS;
09118 #ifdef SQL_ATTR_METADATA_ID
09119     case SQL_ATTR_METADATA_ID:
09120         *((SQLULEN *) uval) = SQL_FALSE;
09121         *buflen = sizeof (SQLULEN);
09122         return SQL_SUCCESS;
09123 #endif
09124     }
09125     return drvunimplstmt(stmt);
09126 }
09127 
09128 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09129 
09139 SQLRETURN SQL_API
09140 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09141                SQLINTEGER bufmax, SQLINTEGER *buflen)
09142 {
09143     SQLRETURN ret;
09144 
09145     HSTMT_LOCK(stmt);
09146     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09147     HSTMT_UNLOCK(stmt);
09148     return ret;
09149 }
09150 #endif
09151 
09152 #ifdef WINTERFACE
09153 
09163 SQLRETURN SQL_API
09164 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09165                 SQLINTEGER bufmax, SQLINTEGER *buflen)
09166 {
09167     SQLRETURN ret;
09168 
09169     HSTMT_LOCK(stmt);
09170     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09171     HSTMT_UNLOCK(stmt);
09172     return ret;
09173 }
09174 #endif
09175 
09185 static SQLRETURN
09186 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09187                SQLINTEGER buflen)
09188 {
09189     STMT *s = (STMT *) stmt;
09190 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
09191     SQLBIGINT uval;
09192 
09193     uval = (SQLBIGINT) val;
09194 #else
09195     SQLULEN uval;
09196 
09197     uval = (SQLULEN) val;
09198 #endif
09199     switch (attr) {
09200     case SQL_ATTR_CURSOR_TYPE:
09201         if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
09202             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09203         } else {
09204             s->curtype = SQL_CURSOR_STATIC;
09205         }
09206         if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
09207             val != (SQLPOINTER) SQL_CURSOR_STATIC) {
09208             goto e01s02;
09209         }
09210         return SQL_SUCCESS;
09211     case SQL_ATTR_CURSOR_SCROLLABLE:
09212         if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
09213             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09214         } else {
09215             s->curtype = SQL_CURSOR_STATIC;
09216         }
09217         return SQL_SUCCESS;
09218     case SQL_ATTR_ASYNC_ENABLE:
09219         if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
09220     e01s02:
09221             setstat(s, -1, "option value changed", "01S02");
09222             return SQL_SUCCESS_WITH_INFO;
09223         }
09224         return SQL_SUCCESS;
09225     case SQL_CONCURRENCY:
09226         if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
09227             goto e01s02;
09228         }
09229         return SQL_SUCCESS;
09230 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09231     case SQL_ATTR_CURSOR_SENSITIVITY:
09232         if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
09233             goto e01s02;
09234         }
09235         return SQL_SUCCESS;
09236 #endif
09237     case SQL_ATTR_QUERY_TIMEOUT:
09238         return SQL_SUCCESS;
09239     case SQL_ATTR_RETRIEVE_DATA:
09240         if (val != (SQLPOINTER) SQL_RD_ON &&
09241             val != (SQLPOINTER) SQL_RD_OFF) {
09242             goto e01s02;
09243         }
09244         s->retr_data = uval;
09245         return SQL_SUCCESS;
09246     case SQL_ROWSET_SIZE:
09247     case SQL_ATTR_ROW_ARRAY_SIZE:
09248         if (uval < 1) {
09249             setstat(s, -1, "invalid rowset size", "HY000");
09250             return SQL_ERROR;
09251         } else {
09252             SQLUSMALLINT *rst = &s->row_status1;
09253 
09254             if (uval > 1) {
09255                 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
09256                 if (!rst) {
09257                     return nomem(s);
09258                 }
09259             }
09260             if (s->row_status0 != &s->row_status1) {
09261                 freep(&s->row_status0);
09262             }
09263             s->row_status0 = rst;
09264             s->rowset_size = uval;
09265         }
09266         return SQL_SUCCESS;
09267     case SQL_ATTR_ROW_STATUS_PTR:
09268         s->row_status = (SQLUSMALLINT *) val;
09269         return SQL_SUCCESS;
09270     case SQL_ATTR_ROWS_FETCHED_PTR:
09271         s->row_count = (SQLULEN *) val;
09272         return SQL_SUCCESS;
09273     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09274         s->parm_bind_offs = (SQLULEN *) val;
09275         return SQL_SUCCESS;
09276     case SQL_ATTR_PARAM_BIND_TYPE:
09277         s->parm_bind_type = uval;
09278         return SQL_SUCCESS;
09279     case SQL_ATTR_PARAM_OPERATION_PTR:
09280         s->parm_oper = (SQLUSMALLINT *) val;
09281         return SQL_SUCCESS;
09282     case SQL_ATTR_PARAM_STATUS_PTR:
09283         s->parm_status = (SQLUSMALLINT *) val;
09284         return SQL_SUCCESS;
09285     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09286         s->parm_proc = (SQLULEN *) val;
09287         return SQL_SUCCESS;
09288     case SQL_ATTR_PARAMSET_SIZE:
09289         if (uval < 1) {
09290             goto e01s02;
09291         }
09292         s->paramset_size = uval;
09293         s->paramset_count = 0;
09294         return SQL_SUCCESS;
09295     case SQL_ATTR_ROW_BIND_TYPE:
09296         s->bind_type = uval;
09297         return SQL_SUCCESS;
09298     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09299         s->bind_offs = (SQLULEN *) val;
09300         return SQL_SUCCESS;
09301     case SQL_ATTR_USE_BOOKMARKS:
09302         if (val != (SQLPOINTER) SQL_UB_OFF &&
09303             val != (SQLPOINTER) SQL_UB_ON &&
09304             val != (SQLPOINTER) SQL_UB_VARIABLE) {
09305             goto e01s02;
09306         }
09307         if (*s->ov3 && val == (SQLPOINTER) SQL_UB_VARIABLE) {
09308             s->bkmrk = SQL_UB_VARIABLE;
09309             return SQL_SUCCESS;
09310         }
09311         if (val == (SQLPOINTER) SQL_UB_VARIABLE) {
09312             s->bkmrk = SQL_UB_ON;
09313             goto e01s02;
09314         }
09315         s->bkmrk = (val == (SQLPOINTER) SQL_UB_ON) ? SQL_UB_ON : SQL_UB_OFF;
09316         return SQL_SUCCESS;
09317     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09318         s->bkmrkptr = (SQLINTEGER *) val;
09319         return SQL_SUCCESS;
09320     case SQL_ATTR_MAX_ROWS:
09321         s->max_rows = uval;
09322         return SQL_SUCCESS;
09323     case SQL_ATTR_MAX_LENGTH:
09324         if (val != (SQLPOINTER) 1000000000) {
09325             goto e01s02;
09326         }
09327         return SQL_SUCCESS;
09328 #ifdef SQL_ATTR_METADATA_ID
09329     case SQL_ATTR_METADATA_ID:
09330         if (val != (SQLPOINTER) SQL_FALSE) {
09331             goto e01s02;
09332         }
09333         return SQL_SUCCESS;
09334 #endif
09335     }
09336     return drvunimplstmt(stmt);
09337 }
09338 
09339 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09340 
09349 SQLRETURN SQL_API
09350 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09351                SQLINTEGER buflen)
09352 {
09353     SQLRETURN ret;
09354 
09355     HSTMT_LOCK(stmt);
09356     ret = drvsetstmtattr(stmt, attr, val, buflen);
09357     HSTMT_UNLOCK(stmt);
09358     return ret;
09359 }
09360 #endif
09361 
09362 #ifdef WINTERFACE
09363 
09372 SQLRETURN SQL_API
09373 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09374                 SQLINTEGER buflen)
09375 {
09376     SQLRETURN ret;
09377 
09378     HSTMT_LOCK(stmt);
09379     ret = drvsetstmtattr(stmt, attr, val, buflen);
09380     HSTMT_UNLOCK(stmt);
09381     return ret;
09382 }
09383 #endif
09384 
09393 static SQLRETURN
09394 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09395 {
09396     STMT *s = (STMT *) stmt;
09397     SQLUINTEGER *ret = (SQLUINTEGER *) param;
09398 
09399     switch (opt) {
09400     case SQL_QUERY_TIMEOUT:
09401         *ret = 0;
09402         return SQL_SUCCESS;
09403     case SQL_CURSOR_TYPE:
09404         *ret = s->curtype;
09405         return SQL_SUCCESS;
09406     case SQL_ROW_NUMBER:
09407         if (s->s3stmt) {
09408             *ret = (s->s3stmt_rownum < 0) ?
09409                    SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09410         } else {
09411             *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09412         }
09413         return SQL_SUCCESS;
09414     case SQL_ASYNC_ENABLE:
09415         *ret = SQL_ASYNC_ENABLE_OFF;
09416         return SQL_SUCCESS;
09417     case SQL_CONCURRENCY:
09418         *ret = SQL_CONCUR_LOCK;
09419         return SQL_SUCCESS;
09420     case SQL_ATTR_RETRIEVE_DATA:
09421         *ret = s->retr_data;
09422         return SQL_SUCCESS;
09423     case SQL_ROWSET_SIZE:
09424     case SQL_ATTR_ROW_ARRAY_SIZE:
09425         *ret = s->rowset_size;
09426         return SQL_SUCCESS;
09427     case SQL_ATTR_MAX_ROWS:
09428         *ret = s->max_rows;
09429         return SQL_SUCCESS;
09430     case SQL_ATTR_MAX_LENGTH:
09431         *ret = 1000000000;
09432         return SQL_SUCCESS;
09433     }
09434     return drvunimplstmt(stmt);
09435 }
09436 
09445 SQLRETURN SQL_API
09446 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09447 {
09448     SQLRETURN ret;
09449 
09450     HSTMT_LOCK(stmt);
09451     ret = drvgetstmtoption(stmt, opt, param);
09452     HSTMT_UNLOCK(stmt);
09453     return ret;
09454 }
09455 
09456 #ifdef WINTERFACE
09457 
09465 SQLRETURN SQL_API
09466 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09467 {
09468     SQLRETURN ret;
09469 
09470     HSTMT_LOCK(stmt);
09471     ret = drvgetstmtoption(stmt, opt, param);
09472     HSTMT_UNLOCK(stmt);
09473     return ret;
09474 }
09475 #endif
09476 
09485 static SQLRETURN
09486 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
09487 {
09488     STMT *s = (STMT *) stmt;
09489 
09490     switch (opt) {
09491     case SQL_CURSOR_TYPE:
09492         if (param == SQL_CURSOR_FORWARD_ONLY) {
09493             s->curtype = param;
09494         } else {
09495             s->curtype = SQL_CURSOR_STATIC;
09496         }
09497         if (param != SQL_CURSOR_FORWARD_ONLY &&
09498             param != SQL_CURSOR_STATIC) {
09499             goto e01s02;
09500         }
09501         return SQL_SUCCESS;
09502     case SQL_ASYNC_ENABLE:
09503         if (param != SQL_ASYNC_ENABLE_OFF) {
09504             goto e01s02;
09505         }
09506         return SQL_SUCCESS;
09507     case SQL_CONCURRENCY:
09508         if (param != SQL_CONCUR_LOCK) {
09509             goto e01s02;
09510         }
09511         return SQL_SUCCESS;
09512     case SQL_QUERY_TIMEOUT:
09513         return SQL_SUCCESS;
09514     case SQL_RETRIEVE_DATA:
09515         if (param != SQL_RD_ON && param != SQL_RD_OFF) {
09516     e01s02:
09517             setstat(s, -1, "option value changed", "01S02");
09518             return SQL_SUCCESS_WITH_INFO;
09519         }
09520         s->retr_data = (int) param;
09521         return SQL_SUCCESS;
09522     case SQL_ROWSET_SIZE:
09523     case SQL_ATTR_ROW_ARRAY_SIZE:
09524         if (param < 1) {
09525             setstat(s, -1, "invalid rowset size", "HY000");
09526             return SQL_ERROR;
09527         } else {
09528             SQLUSMALLINT *rst = &s->row_status1;
09529 
09530             if (param > 1) {
09531                 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
09532                 if (!rst) {
09533                     return nomem(s);
09534                 }
09535             }
09536             if (s->row_status0 != &s->row_status1) {
09537                 freep(&s->row_status0);
09538             }
09539             s->row_status0 = rst;
09540             s->rowset_size = param;
09541         }
09542         return SQL_SUCCESS;
09543     case SQL_ATTR_MAX_ROWS:
09544         s->max_rows = param;
09545         return SQL_SUCCESS;
09546     case SQL_ATTR_MAX_LENGTH:
09547         if (param != 1000000000) {
09548             goto e01s02;
09549         }
09550         return SQL_SUCCESS;
09551     }
09552     return drvunimplstmt(stmt);
09553 }
09554 
09563 SQLRETURN SQL_API
09564 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
09565                  SETSTMTOPTION_LAST_ARG_TYPE param)
09566 {
09567     SQLRETURN ret;
09568 
09569     HSTMT_LOCK(stmt);
09570     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09571     HSTMT_UNLOCK(stmt);
09572     return ret;
09573 }
09574 
09575 #ifdef WINTERFACE
09576 
09584 SQLRETURN SQL_API
09585 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
09586                   SETSTMTOPTION_LAST_ARG_TYPE param)
09587 {
09588     SQLRETURN ret;
09589 
09590     HSTMT_LOCK(stmt);
09591     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09592     HSTMT_UNLOCK(stmt);
09593     return ret;
09594 }
09595 #endif
09596 
09603 static SQLRETURN
09604 chkunbound(STMT *s)
09605 {
09606     int i;
09607 
09608     if (!s->bindcols || s->nbindcols < s->ncols) {
09609 unbound:
09610         setstat(s, -1, "unbound columns", (*s->ov3) ? "HY000" : "S1000");
09611         return SQL_ERROR;
09612     }
09613     for (i = 0; i < s->ncols; i++) {
09614         BINDCOL *b = &s->bindcols[i];
09615 
09616         if (b->type == SQL_UNKNOWN_TYPE || !b->valp) {
09617             goto unbound;
09618         }
09619     }
09620     return SQL_SUCCESS;
09621 }
09622 
09634 static SQLRETURN
09635 setposbind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
09636 {
09637     DBC *d = (DBC *) s->dbc;
09638     SQLPOINTER dp = 0;
09639     SQLLEN *lp = 0;
09640     BINDCOL *b = &s->bindcols[i];
09641     COL *c = &s->cols[i];
09642     char strbuf[128], *cp;
09643 
09644     if (b->valp) {
09645         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09646             dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
09647         } else {
09648             dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
09649         }
09650         if (s->bind_offs) {
09651             dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
09652         }
09653     }
09654     if (b->lenp) {
09655         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09656             lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
09657         } else {
09658             lp = b->lenp + rsi;
09659         }
09660         if (s->bind_offs) {
09661             lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
09662         }
09663     }
09664     if (!dp || !lp) {
09665         setstat(s, -1, "unbound column in positional update",
09666                 (*s->ov3) ? "HY000" : "S1000");
09667         return SQL_ERROR;
09668     }
09669     if (*lp == SQL_NULL_DATA) {
09670         sqlite3_bind_null(stmt, si);
09671         if (d->trace) {
09672             fprintf(d->trace, "-- parameter %d: NULL\n", si);
09673             fflush(d->trace);
09674         }
09675         return SQL_SUCCESS;
09676     }
09677     switch (b->type) {
09678     case SQL_C_UTINYINT:
09679     case SQL_C_TINYINT:
09680     case SQL_C_STINYINT:
09681         sqlite3_bind_int(stmt, si, *(SQLCHAR *) dp);
09682         if (d->trace) {
09683             fprintf(d->trace, "-- parameter %d: %d\n", si, *(SQLCHAR *) dp);
09684             fflush(d->trace);
09685         }
09686         break;
09687 #ifdef SQL_BIT
09688     case SQL_C_BIT:
09689         sqlite3_bind_int(stmt, si, (*(SQLCHAR *) dp) ? 1 : 0);
09690         if (d->trace) {
09691             fprintf(d->trace, "-- parameter %d: %d\n", si,
09692                     (*(SQLCHAR *) dp) ? 1 : 0);
09693             fflush(d->trace);
09694         }
09695         break;
09696 #endif
09697     case SQL_C_USHORT:
09698         sqlite3_bind_int(stmt, si, *(SQLUSMALLINT *) dp);
09699         if (d->trace) {
09700             fprintf(d->trace, "-- parameter %d: %d\n", si,
09701                     *(SQLUSMALLINT *) dp);
09702             fflush(d->trace);
09703         }
09704         break;
09705     case SQL_C_SHORT:
09706     case SQL_C_SSHORT:
09707         sqlite3_bind_int(stmt, si, *(SQLSMALLINT *) dp);
09708         if (d->trace) {
09709             fprintf(d->trace, "-- parameter %d: %d\n", si,
09710                     *(SQLSMALLINT *) dp);
09711             fflush(d->trace);
09712         }
09713         break;
09714     case SQL_C_ULONG:
09715         sqlite3_bind_int(stmt, si, *(SQLUINTEGER *) dp);
09716         if (d->trace) {
09717             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09718                     (long) *(SQLUINTEGER *) dp);
09719             fflush(d->trace);
09720         }
09721         break;
09722     case SQL_C_LONG:
09723     case SQL_C_SLONG:
09724         sqlite3_bind_int(stmt, si, *(SQLINTEGER *) dp);
09725         if (d->trace) {
09726             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09727                     (long) *(SQLINTEGER *) dp);
09728             fflush(d->trace);
09729         }
09730         break;
09731 #ifdef SQL_BIGINT
09732     case SQL_C_UBIGINT:
09733     case SQL_C_SBIGINT:
09734         sqlite3_bind_int64(stmt, si, *(SQLBIGINT *) dp);
09735         if (d->trace) {
09736             fprintf(d->trace,
09737 #ifdef _WIN32
09738                     "-- parameter %d: %I64d\n",
09739 #else
09740                     "-- parameter %d: %lld\n",
09741 #endif
09742                     si, (sqlite_int64) *(SQLBIGINT *) dp);
09743             fflush(d->trace);
09744         }
09745         break;
09746 #endif
09747     case SQL_C_FLOAT:
09748         sqlite3_bind_double(stmt, si, *(float *) dp);
09749         if (d->trace) {
09750             fprintf(d->trace, "-- parameter %d: %g\n", si,
09751                     *(float *) dp);
09752             fflush(d->trace);
09753         }
09754         break;
09755     case SQL_C_DOUBLE:
09756         sqlite3_bind_double(stmt, si, *(double *) dp);
09757         if (d->trace) {
09758             fprintf(d->trace, "-- parameter %d: %g\n", si,
09759                     *(double *) dp);
09760             fflush(d->trace);
09761         }
09762         break;
09763     case SQL_C_BINARY:
09764         sqlite3_bind_blob(stmt, si, (char *) dp, *lp, SQLITE_STATIC);
09765         if (d->trace) {
09766             fprintf(d->trace, "-- parameter %d: [BLOB]\n", si);
09767             fflush(d->trace);
09768         }
09769         break;
09770 #ifdef WCHARSUPPORT
09771     case SQL_C_WCHAR:
09772         cp = uc_to_utf((SQLWCHAR *) dp, *lp);
09773         if (!cp) {
09774             return nomem(s);
09775         }
09776         sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
09777         if (d->trace) {
09778             fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
09779             fflush(d->trace);
09780         }
09781         uc_free(cp);
09782         break;
09783 #endif
09784     case SQL_C_CHAR:
09785 #if defined(_WIN32) || defined(_WIN64)
09786         if (*s->oemcp) {
09787             cp = wmb_to_utf((char *) dp, *lp);
09788             if (!cp) {
09789                 return nomem(s);
09790             }
09791             sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
09792             if (d->trace) {
09793                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
09794                 fflush(d->trace);
09795             }
09796             uc_free(cp);
09797         } else
09798 #endif
09799         {
09800             if (*lp == SQL_NTS) {
09801                 sqlite3_bind_text(stmt, si, (char *) dp, -1,
09802                                   SQLITE_STATIC);
09803                 if (d->trace) {
09804                     fprintf(d->trace, "-- parameter %d: '%s'\n", si,
09805                             (char *) dp);
09806                     fflush(d->trace);
09807                 }
09808             } else {
09809                 sqlite3_bind_text(stmt, si, (char *) dp, *lp,
09810                                   SQLITE_STATIC);
09811                 if (d->trace) {
09812                     fprintf(d->trace, "-- parameter %d: '%*s'\n", si,
09813                             (int) *lp, (char *) dp);
09814                     fflush(d->trace);
09815                 }
09816             }
09817         }
09818         break;
09819 #ifdef SQL_C_TYPE_DATE
09820     case SQL_C_TYPE_DATE:
09821 #endif
09822     case SQL_C_DATE:
09823         if (*s->jdconv) {
09824             int a, b, x1, x2, y, m, dd;
09825             double v;
09826 
09827             y = ((DATE_STRUCT *) dp)->year;
09828             m = ((DATE_STRUCT *) dp)->month;
09829             dd = ((DATE_STRUCT *) dp)->day;
09830             if (m <= 2) {
09831                 y--;
09832                 m += 12;
09833             }
09834             a = y / 100;
09835             b = 2 - a + (a / 4);
09836             x1 = 36525 * (y + 4716) / 100;
09837             x2 = 306001 * (m + 1) / 10000;
09838             v = x1 + x2 + dd + b - 1524.5;
09839             sqlite3_bind_double(stmt, si, v);
09840             if (d->trace) {
09841                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
09842                 fflush(d->trace);
09843             }
09844         } else {
09845             sprintf(strbuf, "%04d-%02d-%02d",
09846                     ((DATE_STRUCT *) dp)->year,
09847                     ((DATE_STRUCT *) dp)->month,
09848                     ((DATE_STRUCT *) dp)->day);
09849             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
09850             if (d->trace) {
09851                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
09852                 fflush(d->trace);
09853             }
09854         }
09855         break;
09856 #ifdef SQL_C_TYPE_TIME
09857     case SQL_C_TYPE_TIME:
09858 #endif
09859     case SQL_C_TIME:
09860         if (*s->jdconv) {
09861             double v;
09862 
09863             v = 2451544.5 +
09864                (((TIME_STRUCT *) dp)->hour * 3600000.0 +
09865                 ((TIME_STRUCT *) dp)->minute * 60000.0 +
09866                 ((TIME_STRUCT *) dp)->second * 1000.0) / 86400000.0;
09867             sqlite3_bind_double(stmt, si, v);
09868             if (d->trace) {
09869                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
09870                 fflush(d->trace);
09871             }
09872         } else {
09873             sprintf(strbuf, "%02d:%02d:%02d",
09874                     ((TIME_STRUCT *) dp)->hour,
09875                     ((TIME_STRUCT *) dp)->minute,
09876                     ((TIME_STRUCT *) dp)->second);
09877             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
09878             if (d->trace) {
09879                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
09880                 fflush(d->trace);
09881             }
09882         }
09883         break;
09884 #ifdef SQL_C_TYPE_TIMESTAMP
09885     case SQL_C_TYPE_TIMESTAMP:
09886 #endif
09887     case SQL_C_TIMESTAMP:
09888         if (*s->jdconv) {
09889             int a, b, x1, x2, y, m, dd;
09890             double v;
09891 
09892             y = ((TIMESTAMP_STRUCT *) dp)->year;
09893             m = ((TIMESTAMP_STRUCT *) dp)->month;
09894             dd = ((TIMESTAMP_STRUCT *) dp)->day;
09895             if (m <= 2) {
09896                 y--;
09897                 m += 12;
09898             }
09899             a = y / 100;
09900             b = 2 - a + (a / 4);
09901             x1 = 36525 * (y + 4716) / 100;
09902             x2 = 306001 * (m + 1) / 10000;
09903             v = x1 + x2 + dd + b - 1524.5 +
09904                (((TIMESTAMP_STRUCT *) dp)->hour * 3600000.0 +
09905                 ((TIMESTAMP_STRUCT *) dp)->minute * 60000.0 +
09906                 ((TIMESTAMP_STRUCT *) dp)->second * 1000.0 +
09907                 ((TIMESTAMP_STRUCT *) dp)->fraction / 1.0E6)
09908                / 86400000.0;
09909             sqlite3_bind_double(stmt, si, v);
09910             if (d->trace) {
09911                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
09912                 fflush(d->trace);
09913             }
09914         } else {
09915             int frac;
09916 
09917             frac = (int) ((TIMESTAMP_STRUCT *) dp)->fraction;
09918             frac /= 1000000;
09919             frac = frac % 1000;
09920             if (frac < 0) {
09921                 frac = 0;
09922             }
09923             if (c->prec && c->prec <= 16) {
09924                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:00.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             } else if (c->prec && c->prec <= 19) {
09931                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
09932                         ((TIMESTAMP_STRUCT *) dp)->year,
09933                         ((TIMESTAMP_STRUCT *) dp)->month,
09934                         ((TIMESTAMP_STRUCT *) dp)->day,
09935                         ((TIMESTAMP_STRUCT *) dp)->hour,
09936                         ((TIMESTAMP_STRUCT *) dp)->minute,
09937                         ((TIMESTAMP_STRUCT *) dp)->second);
09938             } else {
09939                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
09940                         ((TIMESTAMP_STRUCT *) dp)->year,
09941                         ((TIMESTAMP_STRUCT *) dp)->month,
09942                         ((TIMESTAMP_STRUCT *) dp)->day,
09943                         ((TIMESTAMP_STRUCT *) dp)->hour,
09944                         ((TIMESTAMP_STRUCT *) dp)->minute,
09945                         ((TIMESTAMP_STRUCT *) dp)->second,
09946                         frac);
09947             }
09948             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
09949             if (d->trace) {
09950                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
09951                 fflush(d->trace);
09952             }
09953         }
09954         break;
09955     default:
09956         setstat(s, -1, "unsupported column type in positional update",
09957                 (*s->ov3) ? "HY000" : "S1000");
09958         return SQL_ERROR;
09959     }
09960     return SQL_SUCCESS;
09961 }
09962 
09974 static SQLRETURN
09975 setposibind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
09976 {
09977     DBC *d = (DBC *) s->dbc;
09978     char **data;
09979     int pos;
09980 
09981     pos = s->rowprs;
09982     if (pos < 0) {
09983         setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
09984         return SQL_ERROR;
09985     }
09986     pos += rsi;
09987     data = s->rows + s->ncols + (pos * s->ncols) + i;
09988     if (*data == NULL) {
09989         sqlite3_bind_null(stmt, si);
09990         if (d->trace) {
09991             fprintf(d->trace, "-- parameter %d: NULL\n", si);
09992             fflush(d->trace);
09993         }
09994     } else {
09995         sqlite3_bind_text(stmt, si, *data, -1, SQLITE_STATIC);
09996         if (d->trace) {
09997             fprintf(d->trace, "-- parameter %d: '%s'\n", si, *data);
09998             fflush(d->trace);
09999         }
10000     }
10001     return SQL_SUCCESS;
10002 }
10003 
10011 static SQLRETURN
10012 setposrefr(STMT *s, int rsi)
10013 {
10014     int i, withinfo = 0;
10015     SQLRETURN ret = SQL_SUCCESS;
10016 
10017     for (i = 0; s->bindcols && i < s->ncols; i++) {
10018         BINDCOL *b = &s->bindcols[i];
10019         SQLPOINTER dp = 0;
10020         SQLLEN *lp = 0;
10021 
10022         b->offs = 0;
10023         if (b->valp) {
10024             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10025                 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
10026             } else {
10027                 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
10028             }
10029             if (s->bind_offs) {
10030                 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
10031             }
10032         }
10033         if (b->lenp) {
10034             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10035                 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
10036             } else {
10037                 lp = b->lenp + rsi;
10038             }
10039             if (s->bind_offs) {
10040                 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
10041             }
10042         }
10043         if (dp || lp) {
10044             int rowp = s->rowp;
10045 
10046             s->rowp = s->rowprs + rsi;
10047             ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp,
10048                              b->max, lp, 0);
10049             s->rowp = rowp;
10050             if (!SQL_SUCCEEDED(ret)) {
10051                 s->row_status0[rsi] = SQL_ROW_ERROR;
10052                 break;
10053             }
10054             if (ret != SQL_SUCCESS) {
10055                 withinfo = 1;
10056 #ifdef SQL_ROW_SUCCESS_WITH_INFO
10057                 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
10058 #endif
10059             }
10060         }
10061     }
10062     if (SQL_SUCCEEDED(ret)) {
10063         ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10064     }
10065     return ret;
10066 }
10067 
10077 static SQLRETURN
10078 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10079 {
10080     STMT *s = (STMT *) stmt;
10081     DBC *d = (DBC *) s->dbc;
10082     int rowp, i, k, rc, nretry = 0;
10083     dstr *sql = 0;
10084     const char *endp;
10085     sqlite3_stmt *s3stmt = NULL;
10086     SQLRETURN ret;
10087 
10088     if (lock != SQL_LOCK_NO_CHANGE) {
10089         setstat(s, -1, "unsupported locking mode",
10090                 (*s->ov3) ? "HY000" : "S1000");
10091         return SQL_ERROR;
10092     }
10093     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10094         setstat(s, -1, "incompatible statement",
10095                 (*s->ov3) ? "HY000" : "S1000");
10096         return SQL_ERROR;
10097     }
10098     if (op == SQL_ADD) {
10099         if (s->one_tbl <= 0) {
10100             setstat(s, -1, "incompatible rowset",
10101                     (*s->ov3) ? "HY000" : "S1000");
10102             return SQL_ERROR;
10103         }
10104         if (row == 0 || row > s->rowset_size + 1) {
10105             goto rowoor;
10106         }
10107         ret = chkunbound(s);
10108         if (ret != SQL_SUCCESS) {
10109             return ret;
10110         }
10111         sql = dsappend(sql, "INSERT INTO ");
10112         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10113             sql = dsappendq(sql, s->dyncols[0].db);
10114             sql = dsappend(sql, ".");
10115         }
10116         sql = dsappendq(sql, s->dyncols[0].table);
10117         for (i = 0; i < s->ncols; i++) {
10118             sql = dsappend(sql, (i > 0) ? "," : "(");
10119             sql = dsappendq(sql, s->dyncols[i].column);
10120         }
10121         sql = dsappend(sql, ") VALUES ");
10122         for (i = 0; i < s->ncols; i++) {
10123             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10124         }
10125         sql = dsappend(sql, ")");
10126         if (dserr(sql)) {
10127             dsfree(sql);
10128             return nomem(s);
10129         }
10130 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10131         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10132 #else
10133         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10134 #endif
10135         do {
10136             s3stmt = NULL;
10137 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10138             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10139                                     &s3stmt, &endp);
10140 #else
10141             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10142                                  &s3stmt, &endp);
10143 #endif
10144             if (rc != SQLITE_OK) {
10145                 if (s3stmt) {
10146                     sqlite3_finalize(s3stmt);
10147                     s3stmt = NULL;
10148                 }
10149             }
10150         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10151         dbtracerc(d, rc, NULL);
10152         dsfree(sql);
10153         if (rc != SQLITE_OK) {
10154 istmterr:
10155             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10156                     sqlite3_errmsg(d->sqlite), rc);
10157             if (s3stmt) {
10158                 dbtraceapi(d, "sqlite3_finalize", NULL);
10159                 sqlite3_finalize(s3stmt);
10160             }
10161             return SQL_ERROR;
10162         }
10163         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10164             ret = setposbind(s, s3stmt, i, k, row - 1);
10165             if (ret != SQL_SUCCESS) {
10166                 dbtraceapi(d, "sqlite3_finalize", NULL);
10167                 sqlite3_finalize(s3stmt);
10168                 return ret;
10169             }
10170             k++;
10171         }
10172         rc = sqlite3_step(s3stmt);
10173         if (rc != SQLITE_DONE) {
10174             goto istmterr;
10175         }
10176         sqlite3_finalize(s3stmt);
10177         if (sqlite3_changes(d->sqlite) > 0 && row <= s->rowset_size) {
10178             if (s->row_status0) {
10179                 s->row_status0[row - 1] = SQL_ROW_ADDED;
10180             }
10181             if (s->row_status) {
10182                 s->row_status[row - 1] = SQL_ROW_ADDED;
10183             }
10184         }
10185         return SQL_SUCCESS;
10186     } else if (op == SQL_UPDATE || op == SQL_DELETE) {
10187         if (s->one_tbl <= 0 || s->has_pk <= 0) {
10188             setstat(s, -1, "incompatible rowset",
10189                     (*s->ov3) ? "HY000" : "S1000");
10190             return SQL_ERROR;
10191         }
10192         if (row == 0) {
10193             ret = SQL_SUCCESS;
10194             for (i = 1; i <= s->rowset_size; i++) {
10195                 ret = drvsetpos(stmt, i, op, lock);
10196                 if (!SQL_SUCCEEDED(ret)) {
10197                     break;
10198                 }
10199             }
10200             return ret;
10201         }
10202         if (row > s->rowset_size) {
10203             goto rowoor;
10204         }
10205     }
10206     if (op != SQL_POSITION && op != SQL_REFRESH &&
10207         op != SQL_DELETE && op != SQL_UPDATE) {
10208         return drvunimplstmt(stmt);
10209     }
10210     if (op == SQL_POSITION) {
10211         rowp = s->rowp + row - 1;
10212         if (!s->rows || row == 0 || rowp < -1 || rowp >= s->nrows) {
10213 rowoor:
10214             setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10215             return SQL_ERROR;
10216         }
10217         s->rowp = rowp;
10218     } else if (op == SQL_REFRESH) {
10219         if (row > s->rowset_size) {
10220             goto rowoor;
10221         }
10222         if (row == 0) {
10223             ret = SQL_SUCCESS;
10224             for (i = 0; i < s->rowset_size; i++) {
10225                 ret = setposrefr(s, i);
10226                 if (!SQL_SUCCEEDED(ret)) {
10227                     break;
10228                 }
10229             }
10230             return ret;
10231         }
10232         return setposrefr(s, row - 1);
10233     } else if (op == SQL_DELETE) {
10234         sql = dsappend(sql, "DELETE FROM ");
10235         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10236             sql = dsappendq(sql, s->dyncols[0].db);
10237             sql = dsappend(sql, ".");
10238         }
10239         sql = dsappendq(sql, s->dyncols[0].table);
10240         for (i = k = 0; i < s->ncols; i++) {
10241             if (s->dyncols[i].ispk <= 0) {
10242                 continue;
10243             }
10244             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10245             sql = dsappendq(sql, s->dyncols[i].column);
10246             sql = dsappend(sql, " = ?");
10247             k++;
10248         }
10249         if (dserr(sql)) {
10250             dsfree(sql);
10251             return nomem(s);
10252         }
10253 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10254         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10255 #else
10256         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10257 #endif
10258         do {
10259             s3stmt = NULL;
10260 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10261             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10262                                     &s3stmt, &endp);
10263 #else
10264             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10265                                  &s3stmt, &endp);
10266 #endif
10267             if (rc != SQLITE_OK) {
10268                 if (s3stmt) {
10269                     sqlite3_finalize(s3stmt);
10270                     s3stmt = NULL;
10271                 }
10272             }
10273         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10274         dbtracerc(d, rc, NULL);
10275         dsfree(sql);
10276         if (rc != SQLITE_OK) {
10277 dstmterr:
10278             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10279                     sqlite3_errmsg(d->sqlite), rc);
10280             if (s3stmt) {
10281                 dbtraceapi(d, "sqlite3_finalize", NULL);
10282                 sqlite3_finalize(s3stmt);
10283             }
10284             return SQL_ERROR;
10285         }
10286         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10287             if (s->dyncols[i].ispk <= 0) {
10288                 continue;
10289             }
10290             ret = setposibind(s, s3stmt, i, k, row - 1);
10291             if (ret != SQL_SUCCESS) {
10292                 dbtraceapi(d, "sqlite3_finalize", NULL);
10293                 sqlite3_finalize(s3stmt);
10294                 return ret;
10295             }
10296             k++;
10297         }
10298         rc = sqlite3_step(s3stmt);
10299         if (rc != SQLITE_DONE) {
10300             goto dstmterr;
10301         }
10302         sqlite3_finalize(s3stmt);
10303         if (sqlite3_changes(d->sqlite) > 0) {
10304             if (s->row_status0) {
10305                 s->row_status0[row - 1] = SQL_ROW_DELETED;
10306             }
10307             if (s->row_status) {
10308                 s->row_status[row - 1] = SQL_ROW_DELETED;
10309             }
10310         }
10311         return SQL_SUCCESS;
10312     } else if (op == SQL_UPDATE) {
10313         ret = chkunbound(s);
10314         if (ret != SQL_SUCCESS) {
10315             return ret;
10316         }
10317         sql = dsappend(sql, "UPDATE ");
10318         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10319             sql = dsappendq(sql, s->dyncols[0].db);
10320             sql = dsappend(sql, ".");
10321         }
10322         sql = dsappendq(sql, s->dyncols[0].table);
10323         for (i = 0; i < s->ncols; i++) {
10324             sql = dsappend(sql, (i > 0) ? ", " : " SET ");
10325             sql = dsappendq(sql, s->dyncols[i].column);
10326             sql = dsappend(sql, " = ?");
10327         }
10328         for (i = k = 0; i < s->ncols; i++) {
10329             if (s->dyncols[i].ispk <= 0) {
10330                 continue;
10331             }
10332             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10333             sql = dsappendq(sql, s->dyncols[i].column);
10334             sql = dsappend(sql, " = ?");
10335             k++;
10336         }
10337         if (dserr(sql)) {
10338             dsfree(sql);
10339             return nomem(s);
10340         }
10341 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10342         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10343 #else
10344         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10345 #endif
10346         do {
10347             s3stmt = NULL;
10348 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10349             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10350                                     &s3stmt, &endp);
10351 #else
10352             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10353                                  &s3stmt, &endp);
10354 #endif
10355             if (rc != SQLITE_OK) {
10356                 if (s3stmt) {
10357                     sqlite3_finalize(s3stmt);
10358                     s3stmt = NULL;
10359                 }
10360             }
10361         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10362         dbtracerc(d, rc, NULL);
10363         dsfree(sql);
10364         if (rc != SQLITE_OK) {
10365 ustmterr:
10366             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10367                     sqlite3_errmsg(d->sqlite), rc);
10368             if (s3stmt) {
10369                 dbtraceapi(d, "sqlite3_finalize", NULL);
10370                 sqlite3_finalize(s3stmt);
10371             }
10372             return SQL_ERROR;
10373         }
10374         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10375             ret = setposbind(s, s3stmt, i, k, row - 1);
10376             if (ret != SQL_SUCCESS) {
10377                 dbtraceapi(d, "sqlite3_finalize", NULL);
10378                 sqlite3_finalize(s3stmt);
10379                 return ret;
10380             }
10381             k++;
10382         }
10383         for (i = 0; s->bindcols && i < s->ncols; i++) {
10384             if (s->dyncols[i].ispk <= 0) {
10385                 continue;
10386             }
10387             ret = setposibind(s, s3stmt, i, k, row - 1);
10388             if (ret != SQL_SUCCESS) {
10389                 dbtraceapi(d, "sqlite3_finalize", NULL);
10390                 sqlite3_finalize(s3stmt);
10391                 return ret;
10392             }
10393             k++;
10394         }
10395         rc = sqlite3_step(s3stmt);
10396         if (rc != SQLITE_DONE) {
10397             goto ustmterr;
10398         }
10399         sqlite3_finalize(s3stmt);
10400         if (sqlite3_changes(d->sqlite) > 0) {
10401             if (s->row_status0) {
10402                 s->row_status0[row - 1] = SQL_ROW_UPDATED;
10403             }
10404             if (s->row_status) {
10405                 s->row_status[row - 1] = SQL_ROW_UPDATED;
10406             }
10407         }
10408         return SQL_SUCCESS;
10409     }
10410     return SQL_SUCCESS;
10411 }
10412 
10422 SQLRETURN SQL_API
10423 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10424 {
10425     SQLRETURN ret;
10426 
10427     HSTMT_LOCK(stmt);
10428     ret = drvsetpos(stmt, row, op, lock);
10429     HSTMT_UNLOCK(stmt);
10430     return ret;
10431 }
10432 
10440 static SQLRETURN
10441 drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
10442 {
10443     STMT *s = (STMT *) stmt;
10444     DBC *d = (DBC *) s->dbc;
10445     int row, i, k, rc, nretry = 0;
10446     dstr *sql = 0;
10447     const char *endp;
10448     sqlite3_stmt *s3stmt = NULL;
10449     SQLRETURN ret;
10450 
10451     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10452         setstat(s, -1, "incompatible statement",
10453                 (*s->ov3) ? "HY000" : "S1000");
10454         return SQL_ERROR;
10455     }
10456     if (op == SQL_ADD) {
10457         if (s->one_tbl <= 0) {
10458             setstat(s, -1, "incompatible rowset",
10459                     (*s->ov3) ? "HY000" : "S1000");
10460             return SQL_ERROR;
10461         }
10462         ret = chkunbound(s);
10463         if (ret != SQL_SUCCESS) {
10464             return ret;
10465         }
10466         sql = dsappend(sql, "INSERT INTO ");
10467         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10468             sql = dsappendq(sql, s->dyncols[0].db);
10469             sql = dsappend(sql, ".");
10470         }
10471         sql = dsappendq(sql, s->dyncols[0].table);
10472         for (i = 0; i < s->ncols; i++) {
10473             sql = dsappend(sql, (i > 0) ? "," : "(");
10474             sql = dsappendq(sql, s->dyncols[i].column);
10475         }
10476         sql = dsappend(sql, ") VALUES ");
10477         for (i = 0; i < s->ncols; i++) {
10478             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10479         }
10480         sql = dsappend(sql, ")");
10481         if (dserr(sql)) {
10482             dsfree(sql);
10483             return nomem(s);
10484         }
10485 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10486         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10487 #else
10488         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10489 #endif
10490         do {
10491             s3stmt = NULL;
10492 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10493             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10494                                     &s3stmt, &endp);
10495 #else
10496             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10497                                  &s3stmt, &endp);
10498 #endif
10499             if (rc != SQLITE_OK) {
10500                 if (s3stmt) {
10501                     sqlite3_finalize(s3stmt);
10502                     s3stmt = NULL;
10503                 }
10504             }
10505         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10506         dbtracerc(d, rc, NULL);
10507         dsfree(sql);
10508         if (rc != SQLITE_OK) {
10509             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10510                     sqlite3_errmsg(d->sqlite), rc);
10511             if (s3stmt) {
10512                 dbtraceapi(d, "sqlite3_finalize", NULL);
10513                 sqlite3_finalize(s3stmt);
10514             }
10515             return SQL_ERROR;
10516         }
10517         for (row = 0; row < s->rowset_size; row++) {
10518             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10519                 ret = setposbind(s, s3stmt, i, k, row);
10520                 if (ret != SQL_SUCCESS) {
10521 istmterr:
10522                     if (s->row_status0) {
10523                         s->row_status0[row] = SQL_ROW_ERROR;
10524                     }
10525                     if (s->row_status) {
10526                         s->row_status[row] = SQL_ROW_ERROR;
10527                     }
10528                     dbtraceapi(d, "sqlite3_finalize", NULL);
10529                     sqlite3_finalize(s3stmt);
10530                     return ret;
10531                 }
10532                 k++;
10533             }
10534             rc = sqlite3_step(s3stmt);
10535             if (rc != SQLITE_DONE) {
10536                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10537                         sqlite3_errmsg(d->sqlite), rc);
10538                 ret = SQL_ERROR;
10539                 goto istmterr;
10540             }
10541             if (sqlite3_changes(d->sqlite) > 0) {
10542                 if (s->row_status0) {
10543                     s->row_status0[row] = SQL_ROW_ADDED;
10544                 }
10545                 if (s->row_status) {
10546                     s->row_status[row] = SQL_ROW_ADDED;
10547                 }
10548             }
10549             if (s->bkmrk == SQL_UB_VARIABLE &&
10550                 s->bkmrkcol.type == SQL_C_VARBOOKMARK &&
10551                 s->bkmrkcol.valp) {
10552                 SQLPOINTER *val;
10553 
10554                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10555                     val = (SQLPOINTER)
10556                         ((char *) s->bkmrkcol.valp + s->bind_type * row);
10557                 } else {
10558                     val = (SQLPOINTER)
10559                         ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10560                 }
10561                 if (s->bind_offs) {
10562                     val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10563                 }
10564                 *(sqlite_int64 *) val = sqlite3_last_insert_rowid(d->sqlite);
10565                 if (s->bkmrkcol.lenp) {
10566                     SQLLEN *ival;
10567 
10568                     if (s->bind_type != SQL_BIND_BY_COLUMN) {
10569                         ival = (SQLLEN *)
10570                             ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10571                     } else {
10572                         ival = &s->bkmrkcol.lenp[row];
10573                     }
10574                     if (s->bind_offs) {
10575                         ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10576                     }
10577                     *ival = sizeof (sqlite_int64);
10578                 }
10579             }
10580             dbtraceapi(d, "sqlite3_reset", NULL);
10581             sqlite3_reset(s3stmt);
10582         }
10583         dbtraceapi(d, "sqlite3_finalize", NULL);
10584         sqlite3_finalize(s3stmt);
10585         return SQL_SUCCESS;
10586     } else if (op == SQL_DELETE_BY_BOOKMARK) {
10587         if (s->has_rowid < 0 ||
10588             s->bkmrk != SQL_UB_VARIABLE ||
10589             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10590             !s->bkmrkcol.valp) {
10591             setstat(s, -1, "incompatible rowset",
10592                     (*s->ov3) ? "HY000" : "S1000");
10593             return SQL_ERROR;
10594         }
10595         sql = dsappend(sql, "DELETE FROM ");
10596         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10597             sql = dsappendq(sql, s->dyncols[0].db);
10598             sql = dsappend(sql, ".");
10599         }
10600         sql = dsappendq(sql, s->dyncols[0].table);
10601         sql = dsappend(sql, " WHERE ");
10602         sql = dsappendq(sql, s->dyncols[0].column);
10603         sql = dsappend(sql, " = ?");
10604         if (dserr(sql)) {
10605             dsfree(sql);
10606             return nomem(s);
10607         }
10608 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10609         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10610 #else
10611         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10612 #endif
10613         do {
10614             s3stmt = NULL;
10615 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10616             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10617                                     &s3stmt, &endp);
10618 #else
10619             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10620                                  &s3stmt, &endp);
10621 #endif
10622             if (rc != SQLITE_OK) {
10623                 if (s3stmt) {
10624                     sqlite3_finalize(s3stmt);
10625                     s3stmt = NULL;
10626                 }
10627             }
10628         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10629         dbtracerc(d, rc, NULL);
10630         dsfree(sql);
10631         if (rc != SQLITE_OK) {
10632             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10633                     sqlite3_errmsg(d->sqlite), rc);
10634             if (s3stmt) {
10635                 dbtraceapi(d, "sqlite3_finalize", NULL);
10636                 sqlite3_finalize(s3stmt);
10637             }
10638             return SQL_ERROR;
10639         }
10640         for (row = 0; row < s->rowset_size; row++) {
10641             SQLPOINTER *val;
10642             sqlite_int64 rowid;
10643 
10644             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10645                 val = (SQLPOINTER)
10646                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
10647             } else {
10648                 val = (SQLPOINTER)
10649                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10650             }
10651             if (s->bind_offs) {
10652                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10653             }
10654             if (s->bkmrkcol.lenp) {
10655                 SQLLEN *ival;
10656 
10657                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10658                     ival = (SQLLEN *)
10659                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10660                 } else {
10661                     ival = &s->bkmrkcol.lenp[row];
10662                 }
10663                 if (s->bind_offs) {
10664                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10665                 }
10666                 if (*ival != sizeof (sqlite_int64)) {
10667                     continue;
10668                 }
10669             }
10670             rowid = *(sqlite_int64 *) val;
10671             sqlite3_bind_int64(s3stmt, 1, rowid);
10672             if (d->trace) {
10673                 fprintf(d->trace,
10674 #ifdef _WIN32
10675                         "-- parameter 1: %I64d\n",
10676 #else
10677                         "-- parameter 1: %lld\n",
10678 #endif
10679                         rowid);
10680                 fflush(d->trace);
10681             }
10682             rc = sqlite3_step(s3stmt);
10683             if (rc != SQLITE_DONE) {
10684                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10685                         sqlite3_errmsg(d->sqlite), rc);
10686                 if (s->row_status0) {
10687                     s->row_status0[row] = SQL_ROW_ERROR;
10688                 }
10689                 if (s->row_status) {
10690                     s->row_status[row] = SQL_ROW_ERROR;
10691                 }
10692                 dbtraceapi(d, "sqlite3_finalize", NULL);
10693                 sqlite3_finalize(s3stmt);
10694                 return SQL_ERROR;
10695             }
10696             if (sqlite3_changes(d->sqlite) > 0) {
10697                 if (s->row_status0) {
10698                     s->row_status0[row] = SQL_ROW_DELETED;
10699                 }
10700                 if (s->row_status) {
10701                     s->row_status[row] = SQL_ROW_DELETED;
10702                 }
10703             }
10704             dbtraceapi(d, "sqlite3_reset", NULL);
10705             sqlite3_reset(s3stmt);
10706         }
10707         dbtraceapi(d, "sqlite3_finalize", NULL);
10708         sqlite3_finalize(s3stmt);
10709         return SQL_SUCCESS;
10710     } else if (op == SQL_UPDATE_BY_BOOKMARK) {
10711         if (s->has_rowid < 0 ||
10712             s->bkmrk != SQL_UB_VARIABLE ||
10713             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10714             !s->bkmrkcol.valp) {
10715             setstat(s, -1, "incompatible rowset",
10716                     (*s->ov3) ? "HY000" : "S1000");
10717             return SQL_ERROR;
10718         }
10719         ret = chkunbound(s);
10720         if (ret != SQL_SUCCESS) {
10721             return ret;
10722         }
10723         sql = dsappend(sql, "UPDATE ");
10724         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10725             sql = dsappendq(sql, s->dyncols[0].db);
10726             sql = dsappend(sql, ".");
10727         }
10728         sql = dsappendq(sql, s->dyncols[0].table);
10729         for (i = 0, k = 0; i < s->ncols; i++) {
10730             if (i == s->has_rowid) {
10731                 continue;
10732             }
10733             sql = dsappend(sql, (k > 0) ? ", " : " SET ");
10734             sql = dsappendq(sql, s->dyncols[i].column);
10735             sql = dsappend(sql, " = ?");
10736             k++;
10737         }
10738         sql = dsappend(sql, " WHERE ");
10739         sql = dsappendq(sql, s->dyncols[s->has_rowid].column);
10740         sql = dsappend(sql, " = ?");
10741         if (dserr(sql)) {
10742             dsfree(sql);
10743             return nomem(s);
10744         }
10745 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10746         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10747 #else
10748         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10749 #endif
10750         do {
10751             s3stmt = NULL;
10752 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10753             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10754                                     &s3stmt, &endp);
10755 #else
10756             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10757                                  &s3stmt, &endp);
10758 #endif
10759             if (rc != SQLITE_OK) {
10760                 if (s3stmt) {
10761                     sqlite3_finalize(s3stmt);
10762                     s3stmt = NULL;
10763                 }
10764             }
10765         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10766         dbtracerc(d, rc, NULL);
10767         dsfree(sql);
10768         if (rc != SQLITE_OK) {
10769             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10770                     sqlite3_errmsg(d->sqlite), rc);
10771             if (s3stmt) {
10772                 dbtraceapi(d, "sqlite3_finalize", NULL);
10773                 sqlite3_finalize(s3stmt);
10774             }
10775             return SQL_ERROR;
10776         }
10777         for (row = 0; row < s->rowset_size; row++) {
10778             SQLPOINTER *val;
10779             sqlite_int64 rowid;
10780 
10781             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10782                 val = (SQLPOINTER)
10783                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
10784             } else {
10785                 val = (SQLPOINTER)
10786                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10787             }
10788             if (s->bind_offs) {
10789                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10790             }
10791             if (s->bkmrkcol.lenp) {
10792                 SQLLEN *ival;
10793 
10794                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10795                     ival = (SQLLEN *)
10796                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10797                 } else {
10798                     ival = &s->bkmrkcol.lenp[row];
10799                 }
10800                 if (s->bind_offs) {
10801                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10802                 }
10803                 if (*ival != sizeof (sqlite_int64)) {
10804                     continue;
10805                 }
10806             }
10807             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10808                 if (i == s->has_rowid) {
10809                     continue;
10810                 }
10811                 ret = setposbind(s, s3stmt, i, k, row);
10812                 if (ret != SQL_SUCCESS) {
10813 ustmterr:
10814                     if (s->row_status0) {
10815                         s->row_status0[row] = SQL_ROW_ERROR;
10816                     }
10817                     if (s->row_status) {
10818                         s->row_status[row] = SQL_ROW_ERROR;
10819                     }
10820                     dbtraceapi(d, "sqlite3_finalize", NULL);
10821                     sqlite3_finalize(s3stmt);
10822                     return ret;
10823                 }
10824                 k++;
10825             }
10826             rowid = *(sqlite_int64 *) val;
10827             sqlite3_bind_int64(s3stmt, k, rowid);
10828             if (d->trace) {
10829                 fprintf(d->trace,
10830 #ifdef _WIN32
10831                         "-- parameter %d: %I64d\n",
10832 #else
10833                         "-- parameter %d: %lld\n",
10834 #endif
10835                         k, rowid);
10836                 fflush(d->trace);
10837             }
10838             rc = sqlite3_step(s3stmt);
10839             if (rc != SQLITE_DONE) {
10840                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10841                         sqlite3_errmsg(d->sqlite), rc);
10842                 ret = SQL_ERROR;
10843                 goto ustmterr;
10844             }
10845             if (sqlite3_changes(d->sqlite) > 0) {
10846                 if (s->row_status0) {
10847                     s->row_status0[row] = SQL_ROW_UPDATED;
10848                 }
10849                 if (s->row_status) {
10850                     s->row_status[row] = SQL_ROW_UPDATED;
10851                 }
10852             }
10853             dbtraceapi(d, "sqlite3_reset", NULL);
10854             sqlite3_reset(s3stmt);
10855         }
10856         dbtraceapi(d, "sqlite3_finalize", NULL);
10857         sqlite3_finalize(s3stmt);
10858         return SQL_SUCCESS;
10859     }
10860     setstat(s, -1, "unsupported operation", (*s->ov3) ? "HY000" : "S1000");
10861     return SQL_ERROR;
10862 }
10863 
10871 SQLRETURN SQL_API
10872 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
10873 {
10874     SQLRETURN ret;
10875 
10876     HSTMT_LOCK(stmt);
10877     ret = drvbulkoperations(stmt, oper);
10878     HSTMT_UNLOCK(stmt);
10879     return ret;
10880 }
10881 
10882 
10887 SQLRETURN SQL_API
10888 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
10889                     SQLUSMALLINT rowset)
10890 {
10891     SQLRETURN ret;
10892 
10893     HSTMT_LOCK(stmt);
10894     ret = drvunimplstmt(stmt);
10895     HSTMT_UNLOCK(stmt);
10896     return ret;
10897 }
10898 
10899 #define strmak(dst, src, max, lenp) { \
10900     int len = strlen(src); \
10901     int cnt = min(len + 1, max); \
10902     strncpy(dst, src, cnt); \
10903     *lenp = (cnt > len) ? len : cnt; \
10904 }
10905 
10916 static SQLRETURN
10917 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
10918            SQLSMALLINT *valLen)
10919 {
10920     DBC *d;
10921     char dummyc[16];
10922     SQLSMALLINT dummy;
10923 #if defined(_WIN32) || defined(_WIN64)
10924     char pathbuf[301], *drvname;
10925 #else
10926     static char drvname[] = "sqlite3odbc.so";
10927 #endif
10928 
10929     if (dbc == SQL_NULL_HDBC) {
10930         return SQL_INVALID_HANDLE;
10931     }
10932     d = (DBC *) dbc;
10933     if (valMax) {
10934         valMax--;
10935     }
10936     if (!valLen) {
10937         valLen = &dummy;
10938     }
10939     if (!val) {
10940         val = dummyc;
10941         valMax = sizeof (dummyc) - 1;
10942     }
10943     switch (type) {
10944     case SQL_MAX_USER_NAME_LEN:
10945         *((SQLSMALLINT *) val) = 16;
10946         *valLen = sizeof (SQLSMALLINT);
10947         break;
10948     case SQL_USER_NAME:
10949         strmak(val, "", valMax, valLen);
10950         break;
10951     case SQL_DRIVER_ODBC_VER:
10952 #if 0
10953         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
10954 #else
10955         strmak(val, "03.00", valMax, valLen);
10956 #endif
10957         break;
10958     case SQL_ACTIVE_CONNECTIONS:
10959     case SQL_ACTIVE_STATEMENTS:
10960         *((SQLSMALLINT *) val) = 0;
10961         *valLen = sizeof (SQLSMALLINT);
10962         break;
10963 #ifdef SQL_ASYNC_MODE
10964     case SQL_ASYNC_MODE:
10965         *((SQLUINTEGER *) val) = SQL_AM_NONE;
10966         *valLen = sizeof (SQLUINTEGER);
10967         break;
10968 #endif
10969 #ifdef SQL_CREATE_TABLE
10970     case SQL_CREATE_TABLE:
10971         *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
10972                                  SQL_CT_COLUMN_DEFAULT |
10973                                  SQL_CT_COLUMN_CONSTRAINT |
10974                                  SQL_CT_CONSTRAINT_NON_DEFERRABLE;
10975         *valLen = sizeof (SQLUINTEGER);
10976         break;
10977 #endif
10978 #ifdef SQL_CREATE_VIEW
10979     case SQL_CREATE_VIEW:
10980         *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
10981         *valLen = sizeof (SQLUINTEGER);
10982         break;
10983 #endif
10984 #ifdef SQL_DDL_INDEX
10985     case SQL_DDL_INDEX:
10986         *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
10987         *valLen = sizeof (SQLUINTEGER);
10988         break;
10989 #endif
10990 #ifdef SQL_DROP_TABLE
10991     case SQL_DROP_TABLE:
10992         *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
10993         *valLen = sizeof (SQLUINTEGER);
10994         break;
10995 #endif
10996 #ifdef SQL_DROP_VIEW
10997     case SQL_DROP_VIEW:
10998         *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
10999         *valLen = sizeof (SQLUINTEGER);
11000         break;
11001 #endif
11002 #ifdef SQL_INDEX_KEYWORDS
11003     case SQL_INDEX_KEYWORDS:
11004         *((SQLUINTEGER *) val) = SQL_IK_ALL;
11005         *valLen = sizeof (SQLUINTEGER);
11006         break;
11007 #endif
11008     case SQL_DATA_SOURCE_NAME:
11009         strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
11010         break;
11011     case SQL_DRIVER_NAME:
11012 #if defined(_WIN32) || defined(_WIN64)
11013         GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
11014         drvname = strrchr(pathbuf, '\\');
11015         if (drvname == NULL) {
11016             drvname = strrchr(pathbuf, '/');
11017         }
11018         if (drvname == NULL) {
11019             drvname = pathbuf;
11020         } else {
11021             drvname++;
11022         }
11023 #endif
11024         strmak(val, drvname, valMax, valLen);
11025         break;
11026     case SQL_DRIVER_VER:
11027         strmak(val, DRIVER_VER_INFO, valMax, valLen);
11028         break;
11029     case SQL_FETCH_DIRECTION:
11030         *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
11031             SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
11032         *valLen = sizeof (SQLUINTEGER);
11033         break;
11034     case SQL_ODBC_VER:
11035         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11036         break;
11037     case SQL_ODBC_SAG_CLI_CONFORMANCE:
11038         *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
11039         *valLen = sizeof (SQLSMALLINT);
11040         break;
11041     case SQL_STANDARD_CLI_CONFORMANCE:
11042         *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
11043         *valLen = sizeof (SQLUINTEGER);
11044         break;
11045     case SQL_SQL_CONFORMANCE:
11046         *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
11047         *valLen = sizeof (SQLUINTEGER);
11048         break;
11049     case SQL_SERVER_NAME:
11050     case SQL_DATABASE_NAME:
11051         strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
11052         break;
11053     case SQL_SEARCH_PATTERN_ESCAPE:
11054         strmak(val, "\\", valMax, valLen);
11055         break;
11056     case SQL_ODBC_SQL_CONFORMANCE:
11057         *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
11058         *valLen = sizeof (SQLSMALLINT);
11059         break;
11060     case SQL_ODBC_API_CONFORMANCE:
11061         *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
11062         *valLen = sizeof (SQLSMALLINT);
11063         break;
11064     case SQL_DBMS_NAME:
11065         strmak(val, "SQLite", valMax, valLen);
11066         break;
11067     case SQL_DBMS_VER:
11068         strmak(val, SQLITE_VERSION, valMax, valLen);
11069         break;
11070     case SQL_COLUMN_ALIAS:
11071     case SQL_NEED_LONG_DATA_LEN:
11072         strmak(val, "Y", valMax, valLen);
11073         break;
11074     case SQL_ROW_UPDATES:
11075     case SQL_ACCESSIBLE_PROCEDURES:
11076     case SQL_PROCEDURES:
11077     case SQL_EXPRESSIONS_IN_ORDERBY:
11078     case SQL_ODBC_SQL_OPT_IEF:
11079     case SQL_LIKE_ESCAPE_CLAUSE:
11080     case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11081     case SQL_OUTER_JOINS:
11082     case SQL_ACCESSIBLE_TABLES:
11083     case SQL_MULT_RESULT_SETS:
11084     case SQL_MULTIPLE_ACTIVE_TXN:
11085     case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11086         strmak(val, "N", valMax, valLen);
11087         break;
11088 #ifdef SQL_CATALOG_NAME
11089     case SQL_CATALOG_NAME:
11090 #if defined(_WIN32) || defined(_WIN64)
11091         strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
11092 #else
11093         strmak(val, "N", valMax, valLen);
11094 #endif
11095         break;
11096 #endif
11097     case SQL_DATA_SOURCE_READ_ONLY:
11098         strmak(val, "N", valMax, valLen);
11099         break;
11100 #ifdef SQL_OJ_CAPABILITIES
11101     case SQL_OJ_CAPABILITIES:
11102         *((SQLUINTEGER *) val) = 0;
11103         *valLen = sizeof (SQLUINTEGER);
11104         break;
11105 #endif
11106 #ifdef SQL_MAX_IDENTIFIER_LEN
11107     case SQL_MAX_IDENTIFIER_LEN:
11108         *((SQLUSMALLINT *) val) = 255;
11109         *valLen = sizeof (SQLUSMALLINT);
11110         break;
11111 #endif
11112     case SQL_CONCAT_NULL_BEHAVIOR:
11113         *((SQLSMALLINT *) val) = SQL_CB_NULL;
11114         *valLen = sizeof (SQLSMALLINT);
11115         break;
11116     case SQL_CURSOR_COMMIT_BEHAVIOR:
11117     case SQL_CURSOR_ROLLBACK_BEHAVIOR:
11118         *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
11119         *valLen = sizeof (SQLSMALLINT);
11120         break;
11121 #ifdef SQL_CURSOR_SENSITIVITY
11122     case SQL_CURSOR_SENSITIVITY:
11123         *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
11124         *valLen = sizeof (SQLUINTEGER);
11125         break;
11126 #endif
11127     case SQL_DEFAULT_TXN_ISOLATION:
11128         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11129         *valLen = sizeof (SQLUINTEGER);
11130         break;
11131 #ifdef SQL_DESCRIBE_PARAMETER
11132     case SQL_DESCRIBE_PARAMETER:
11133         strmak(val, "Y", valMax, valLen);
11134         break;
11135 #endif
11136     case SQL_TXN_ISOLATION_OPTION:
11137         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11138         *valLen = sizeof (SQLUINTEGER);
11139         break;
11140     case SQL_IDENTIFIER_CASE:
11141         *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
11142         *valLen = sizeof (SQLSMALLINT);
11143         break;
11144     case SQL_IDENTIFIER_QUOTE_CHAR:
11145         strmak(val, "\"", valMax, valLen);
11146         break;
11147     case SQL_MAX_TABLE_NAME_LEN:
11148     case SQL_MAX_COLUMN_NAME_LEN:
11149         *((SQLSMALLINT *) val) = 255;
11150         *valLen = sizeof (SQLSMALLINT);
11151         break;
11152     case SQL_MAX_CURSOR_NAME_LEN:
11153         *((SQLSMALLINT *) val) = 255;
11154         *valLen = sizeof (SQLSMALLINT);
11155         break;
11156     case SQL_MAX_PROCEDURE_NAME_LEN:
11157         *((SQLSMALLINT *) val) = 0;
11158         break;
11159     case SQL_MAX_QUALIFIER_NAME_LEN:
11160     case SQL_MAX_OWNER_NAME_LEN:
11161         *((SQLSMALLINT *) val) = 255;
11162         break;
11163     case SQL_OWNER_TERM:
11164         strmak(val, "", valMax, valLen);
11165         break;
11166     case SQL_PROCEDURE_TERM:
11167         strmak(val, "PROCEDURE", valMax, valLen);
11168         break;
11169     case SQL_QUALIFIER_NAME_SEPARATOR:
11170         strmak(val, ".", valMax, valLen);
11171         break;
11172     case SQL_QUALIFIER_TERM:
11173 #if defined(_WIN32) || defined(_WIN64)
11174         strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
11175 #else
11176         strmak(val, "", valMax, valLen);
11177 #endif
11178         break;
11179     case SQL_QUALIFIER_USAGE:
11180 #if defined(_WIN32) || defined(_WIN64)
11181         *((SQLUINTEGER *) val) = d->xcelqrx ?
11182             (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
11183              SQL_CU_TABLE_DEFINITION) : 0;
11184 #else
11185         *((SQLUINTEGER *) val) = 0;
11186 #endif
11187         *valLen = sizeof (SQLUINTEGER);
11188         break;
11189     case SQL_SCROLL_CONCURRENCY:
11190         *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
11191         *valLen = sizeof (SQLUINTEGER);
11192         break;
11193     case SQL_SCROLL_OPTIONS:
11194         *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
11195         *valLen = sizeof (SQLUINTEGER);
11196         break;
11197     case SQL_TABLE_TERM:
11198         strmak(val, "TABLE", valMax, valLen);
11199         break;
11200     case SQL_TXN_CAPABLE:
11201         *((SQLSMALLINT *) val) = SQL_TC_ALL;
11202         *valLen = sizeof (SQLSMALLINT);
11203         break;
11204     case SQL_CONVERT_FUNCTIONS:
11205         *((SQLUINTEGER *) val) = 0;
11206         *valLen = sizeof (SQLUINTEGER);
11207        break;
11208     case SQL_SYSTEM_FUNCTIONS:
11209     case SQL_NUMERIC_FUNCTIONS:
11210     case SQL_STRING_FUNCTIONS:
11211     case SQL_TIMEDATE_FUNCTIONS:
11212         *((SQLUINTEGER *) val) = 0;
11213         *valLen = sizeof (SQLUINTEGER);
11214         break;
11215     case SQL_CONVERT_BIGINT:
11216     case SQL_CONVERT_BIT:
11217     case SQL_CONVERT_CHAR:
11218     case SQL_CONVERT_DATE:
11219     case SQL_CONVERT_DECIMAL:
11220     case SQL_CONVERT_DOUBLE:
11221     case SQL_CONVERT_FLOAT:
11222     case SQL_CONVERT_INTEGER:
11223     case SQL_CONVERT_LONGVARCHAR:
11224     case SQL_CONVERT_NUMERIC:
11225     case SQL_CONVERT_REAL:
11226     case SQL_CONVERT_SMALLINT:
11227     case SQL_CONVERT_TIME:
11228     case SQL_CONVERT_TIMESTAMP:
11229     case SQL_CONVERT_TINYINT:
11230     case SQL_CONVERT_VARCHAR:
11231         *((SQLUINTEGER *) val) =
11232             SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
11233             SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
11234             SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
11235             SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
11236             SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
11237         *valLen = sizeof (SQLUINTEGER);
11238         break;
11239     case SQL_CONVERT_BINARY:
11240     case SQL_CONVERT_VARBINARY:
11241     case SQL_CONVERT_LONGVARBINARY:
11242         *((SQLUINTEGER *) val) = 0;
11243         *valLen = sizeof (SQLUINTEGER);
11244         break;
11245     case SQL_POSITIONED_STATEMENTS:
11246         *((SQLUINTEGER *) val) = 0;
11247         *valLen = sizeof (SQLUINTEGER);
11248         break;
11249     case SQL_LOCK_TYPES:
11250         *((SQLUINTEGER *) val) = SQL_LCK_NO_CHANGE;
11251         *valLen = sizeof (SQLUINTEGER);
11252         break;
11253     case SQL_BOOKMARK_PERSISTENCE:
11254         *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
11255         *valLen = sizeof (SQLUINTEGER);
11256         break;
11257     case SQL_UNION:
11258         *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
11259         *valLen = sizeof (SQLUINTEGER);
11260         break;
11261     case SQL_OWNER_USAGE:
11262     case SQL_SUBQUERIES:
11263     case SQL_TIMEDATE_ADD_INTERVALS:
11264     case SQL_TIMEDATE_DIFF_INTERVALS:
11265         *((SQLUINTEGER *) val) = 0;
11266         *valLen = sizeof (SQLUINTEGER);
11267         break;
11268     case SQL_QUOTED_IDENTIFIER_CASE:
11269         *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
11270         *valLen = sizeof (SQLUSMALLINT);
11271         break;
11272     case SQL_POS_OPERATIONS:
11273         *((SQLUINTEGER *) val) = SQL_POS_POSITION | SQL_POS_UPDATE |
11274             SQL_POS_DELETE | SQL_POS_ADD | SQL_POS_REFRESH;
11275         *valLen = sizeof (SQLUINTEGER);
11276         break;
11277     case SQL_ALTER_TABLE:
11278         *((SQLUINTEGER *) val) = 0;
11279         *valLen = sizeof (SQLUINTEGER);
11280         break;
11281     case SQL_CORRELATION_NAME:
11282         *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
11283         *valLen = sizeof (SQLSMALLINT);
11284         break;
11285     case SQL_NON_NULLABLE_COLUMNS:
11286         *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
11287         *valLen = sizeof (SQLSMALLINT);
11288         break;
11289     case SQL_NULL_COLLATION:
11290         *((SQLSMALLINT *) val) = SQL_NC_START;
11291         *valLen = sizeof (SQLSMALLINT);
11292         break;
11293     case SQL_MAX_COLUMNS_IN_GROUP_BY:
11294     case SQL_MAX_COLUMNS_IN_ORDER_BY:
11295     case SQL_MAX_COLUMNS_IN_SELECT:
11296     case SQL_MAX_COLUMNS_IN_TABLE:
11297     case SQL_MAX_ROW_SIZE:
11298     case SQL_MAX_TABLES_IN_SELECT:
11299         *((SQLSMALLINT *) val) = 0;
11300         *valLen = sizeof (SQLSMALLINT);
11301         break;
11302     case SQL_MAX_BINARY_LITERAL_LEN:
11303     case SQL_MAX_CHAR_LITERAL_LEN:
11304         *((SQLUINTEGER *) val) = 0;
11305         *valLen = sizeof (SQLUINTEGER);
11306         break;
11307     case SQL_MAX_COLUMNS_IN_INDEX:
11308         *((SQLSMALLINT *) val) = 0;
11309         *valLen = sizeof (SQLSMALLINT);
11310         break;
11311     case SQL_MAX_INDEX_SIZE:
11312         *((SQLUINTEGER *) val) = 0;
11313         *valLen = sizeof (SQLUINTEGER);
11314         break;
11315 #ifdef SQL_MAX_IDENTIFIER_LENGTH
11316     case SQL_MAX_IDENTIFIER_LENGTH:
11317         *((SQLUINTEGER *) val) = 255;
11318         *valLen = sizeof (SQLUINTEGER);
11319         break;
11320 #endif
11321     case SQL_MAX_STATEMENT_LEN:
11322         *((SQLUINTEGER *) val) = 16384;
11323         *valLen = sizeof (SQLUINTEGER);
11324         break;
11325     case SQL_QUALIFIER_LOCATION:
11326         *((SQLSMALLINT *) val) = SQL_QL_START;
11327         *valLen = sizeof (SQLSMALLINT);
11328         break;
11329     case SQL_GETDATA_EXTENSIONS:
11330         *((SQLUINTEGER *) val) =
11331             SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
11332         *valLen = sizeof (SQLUINTEGER);
11333         break;
11334     case SQL_STATIC_SENSITIVITY:
11335         *((SQLUINTEGER *) val) = 0;
11336         *valLen = sizeof (SQLUINTEGER);
11337         break;
11338     case SQL_FILE_USAGE:
11339 #if defined(_WIN32) || defined(_WIN64)
11340         *((SQLSMALLINT *) val) =
11341             d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
11342 #else
11343         *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
11344 #endif
11345         *valLen = sizeof (SQLSMALLINT);
11346         break;
11347     case SQL_GROUP_BY:
11348         *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
11349         *valLen = sizeof (SQLSMALLINT);
11350         break;
11351     case SQL_KEYWORDS:
11352         strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
11353                "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
11354                valMax, valLen);
11355         break;
11356     case SQL_SPECIAL_CHARACTERS:
11357 #ifdef SQL_COLLATION_SEQ
11358     case SQL_COLLATION_SEQ:
11359 #endif
11360         strmak(val, "", valMax, valLen);
11361         break;
11362     case SQL_BATCH_SUPPORT:
11363     case SQL_BATCH_ROW_COUNT:
11364     case SQL_PARAM_ARRAY_ROW_COUNTS:
11365         *((SQLUINTEGER *) val) = 0;
11366         *valLen = sizeof (SQLUINTEGER);
11367         break;
11368     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
11369         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
11370         *valLen = sizeof (SQLUINTEGER);
11371         break;
11372     case SQL_STATIC_CURSOR_ATTRIBUTES1:
11373         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
11374             SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_POS_POSITION |
11375             SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_REFRESH |
11376             SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_BULK_ADD |
11377             SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK;
11378         *valLen = sizeof (SQLUINTEGER);
11379         break;
11380     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
11381     case SQL_STATIC_CURSOR_ATTRIBUTES2:
11382         *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
11383             SQL_CA2_LOCK_CONCURRENCY;
11384         *valLen = sizeof (SQLUINTEGER);
11385         break;
11386     case SQL_KEYSET_CURSOR_ATTRIBUTES1:
11387     case SQL_KEYSET_CURSOR_ATTRIBUTES2:
11388     case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
11389     case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
11390         *((SQLUINTEGER *) val) = 0;
11391         *valLen = sizeof (SQLUINTEGER);
11392         break;
11393     case SQL_ODBC_INTERFACE_CONFORMANCE:
11394         *((SQLUINTEGER *) val) = SQL_OIC_CORE;
11395         *valLen = sizeof (SQLUINTEGER);
11396         break;
11397     default:
11398         setstatd(d, -1, "unsupported info option %d",
11399                  (*d->ov3) ? "HYC00" : "S1C00", type);
11400         return SQL_ERROR;
11401     }
11402     return SQL_SUCCESS;
11403 }
11404 
11405 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
11406 
11416 SQLRETURN SQL_API
11417 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11418            SQLSMALLINT *valLen)
11419 {
11420     SQLRETURN ret;
11421 
11422     HDBC_LOCK(dbc);
11423     ret = drvgetinfo(dbc, type, val, valMax, valLen);
11424     HDBC_UNLOCK(dbc);
11425     return ret;
11426 }
11427 #endif
11428 
11429 #ifdef WINTERFACE
11430 
11440 SQLRETURN SQL_API
11441 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11442             SQLSMALLINT *valLen)
11443 {
11444     SQLRETURN ret;
11445     SQLSMALLINT len = 0;
11446 
11447     HDBC_LOCK(dbc);
11448     ret = drvgetinfo(dbc, type, val, valMax, &len);
11449     HDBC_UNLOCK(dbc);
11450     if (ret == SQL_SUCCESS) {
11451         SQLWCHAR *v = NULL;
11452 
11453         switch (type) {
11454         case SQL_USER_NAME:
11455         case SQL_DRIVER_ODBC_VER:
11456         case SQL_DATA_SOURCE_NAME:
11457         case SQL_DRIVER_NAME:
11458         case SQL_DRIVER_VER:
11459         case SQL_ODBC_VER:
11460         case SQL_SERVER_NAME:
11461         case SQL_DATABASE_NAME:
11462         case SQL_SEARCH_PATTERN_ESCAPE:
11463         case SQL_DBMS_NAME:
11464         case SQL_DBMS_VER:
11465         case SQL_NEED_LONG_DATA_LEN:
11466         case SQL_ROW_UPDATES:
11467         case SQL_ACCESSIBLE_PROCEDURES:
11468         case SQL_PROCEDURES:
11469         case SQL_EXPRESSIONS_IN_ORDERBY:
11470         case SQL_ODBC_SQL_OPT_IEF:
11471         case SQL_LIKE_ESCAPE_CLAUSE:
11472         case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11473         case SQL_OUTER_JOINS:
11474         case SQL_COLUMN_ALIAS:
11475         case SQL_ACCESSIBLE_TABLES:
11476         case SQL_MULT_RESULT_SETS:
11477         case SQL_MULTIPLE_ACTIVE_TXN:
11478         case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11479         case SQL_DATA_SOURCE_READ_ONLY:
11480 #ifdef SQL_DESCRIBE_PARAMETER
11481         case SQL_DESCRIBE_PARAMETER:
11482 #endif
11483         case SQL_IDENTIFIER_QUOTE_CHAR:
11484         case SQL_OWNER_TERM:
11485         case SQL_PROCEDURE_TERM:
11486         case SQL_QUALIFIER_NAME_SEPARATOR:
11487         case SQL_QUALIFIER_TERM:
11488         case SQL_TABLE_TERM:
11489         case SQL_KEYWORDS:
11490         case SQL_SPECIAL_CHARACTERS:
11491 #ifdef SQL_CATALOG_NAME
11492         case SQL_CATALOG_NAME:
11493 #endif
11494 #ifdef SQL_COLLATION_SEQ
11495         case SQL_COLLATION_SEQ:
11496 #endif
11497             if (val) {
11498                 if (len > 0) {
11499                     v = uc_from_utf((SQLCHAR *) val, len);
11500                     if (v) {
11501                         int vmax = valMax / sizeof (SQLWCHAR);
11502 
11503                         uc_strncpy(val, v, vmax);
11504                         if (len < vmax) {
11505                             len = min(vmax, uc_strlen(v));
11506                             v[len] = 0;
11507                         } else {
11508                             len = vmax;
11509                         }
11510                         uc_free(v);
11511                         len *= sizeof (SQLWCHAR);
11512                     } else {
11513                         len = 0;
11514                     }
11515                 }
11516                 if (len <= 0) {
11517                     len = 0;
11518                     if (valMax >= sizeof (SQLWCHAR)) {
11519                         *((SQLWCHAR *)val) = 0;
11520                     }
11521                 }
11522             } else {
11523                 len *= sizeof (SQLWCHAR);
11524             }
11525             break;
11526         }
11527         if (valLen) {
11528             *valLen = len;
11529         }
11530     }
11531     return ret;
11532 }
11533 #endif
11534 
11543 SQLRETURN SQL_API
11544 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
11545                 SQLUSMALLINT *flags)
11546 {
11547     int i;
11548     SQLUSMALLINT exists[100];
11549 
11550     if (dbc == SQL_NULL_HDBC) {
11551         return SQL_INVALID_HANDLE;
11552     }
11553     for (i = 0; i < array_size(exists); i++) {
11554         exists[i] = SQL_FALSE;
11555     }
11556     exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
11557     exists[SQL_API_SQLFETCH] = SQL_TRUE;
11558     exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
11559     exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
11560     exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
11561     exists[SQL_API_SQLFREEENV] = SQL_TRUE;
11562     exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
11563     exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
11564     exists[SQL_API_SQLCANCEL] = SQL_TRUE;
11565     exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
11566     exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
11567     exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
11568     exists[SQL_API_SQLCONNECT] = SQL_TRUE;
11569     exists[SQL_API_SQLPREPARE] = SQL_TRUE;
11570     exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
11571     exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
11572     exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
11573     exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
11574     exists[SQL_API_SQLERROR] = SQL_TRUE;
11575     exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
11576     exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
11577     exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
11578     exists[SQL_API_SQLBULKOPERATIONS] = SQL_TRUE;
11579     exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
11580     exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
11581     exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
11582     exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
11583     exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
11584     exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
11585     exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
11586     exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
11587     exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
11588     exists[SQL_API_SQLGETDATA] = SQL_TRUE;
11589     exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
11590     exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
11591     exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
11592     exists[SQL_API_SQLGETINFO] = SQL_TRUE;
11593     exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
11594     exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
11595     exists[SQL_API_SQLTABLES] = SQL_TRUE;
11596     exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
11597     exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
11598     exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
11599     exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
11600     exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
11601     exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
11602     exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
11603     exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
11604     exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
11605     exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
11606     exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
11607     exists[SQL_API_SQLSETPOS] = SQL_TRUE;
11608     exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
11609     exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
11610     exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
11611     exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
11612     exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
11613     if (func == SQL_API_ALL_FUNCTIONS) {
11614         memcpy(flags, exists, sizeof (exists));
11615     } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
11616         int i;
11617 #define SET_EXISTS(x) \
11618         flags[(x) >> 4] |= (1 << ((x) & 0xF))
11619 #define CLR_EXISTS(x) \
11620         flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
11621 
11622         memset(flags, 0,
11623                sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
11624         for (i = 0; i < array_size(exists); i++) {
11625             if (exists[i]) {
11626                 flags[i >> 4] |= (1 << (i & 0xF));
11627             }
11628         }
11629         SET_EXISTS(SQL_API_SQLALLOCHANDLE);
11630         SET_EXISTS(SQL_API_SQLFREEHANDLE);
11631         SET_EXISTS(SQL_API_SQLGETSTMTATTR);
11632         SET_EXISTS(SQL_API_SQLSETSTMTATTR);
11633         SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
11634         SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
11635         SET_EXISTS(SQL_API_SQLGETENVATTR);
11636         SET_EXISTS(SQL_API_SQLSETENVATTR);
11637         SET_EXISTS(SQL_API_SQLCLOSECURSOR);
11638         SET_EXISTS(SQL_API_SQLBINDPARAM);
11639 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11640         /*
11641          * Some unixODBC versions have problems with
11642          * SQLError() vs. SQLGetDiagRec() with loss
11643          * of error/warning messages.
11644          */
11645         SET_EXISTS(SQL_API_SQLGETDIAGREC);
11646 #endif
11647         SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
11648         SET_EXISTS(SQL_API_SQLFETCHSCROLL);
11649         SET_EXISTS(SQL_API_SQLENDTRAN);
11650     } else {
11651         if (func < array_size(exists)) {
11652             *flags = exists[func];
11653         } else {
11654             switch (func) {
11655             case SQL_API_SQLALLOCHANDLE:
11656             case SQL_API_SQLFREEHANDLE:
11657             case SQL_API_SQLGETSTMTATTR:
11658             case SQL_API_SQLSETSTMTATTR:
11659             case SQL_API_SQLGETCONNECTATTR:
11660             case SQL_API_SQLSETCONNECTATTR:
11661             case SQL_API_SQLGETENVATTR:
11662             case SQL_API_SQLSETENVATTR:
11663             case SQL_API_SQLCLOSECURSOR:
11664             case SQL_API_SQLBINDPARAM:
11665 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11666             /*
11667              * Some unixODBC versions have problems with
11668              * SQLError() vs. SQLGetDiagRec() with loss
11669              * of error/warning messages.
11670              */
11671             case SQL_API_SQLGETDIAGREC:
11672 #endif
11673             case SQL_API_SQLGETDIAGFIELD:
11674             case SQL_API_SQLFETCHSCROLL:
11675             case SQL_API_SQLENDTRAN:
11676                 *flags = SQL_TRUE;
11677                 break;
11678             default:
11679                 *flags = SQL_FALSE;
11680             }
11681         }
11682     }
11683     return SQL_SUCCESS;
11684 }
11685 
11692 static SQLRETURN
11693 drvallocenv(SQLHENV *env)
11694 {
11695     ENV *e;
11696 
11697     if (env == NULL) {
11698         return SQL_INVALID_HANDLE;
11699     }
11700     e = (ENV *) xmalloc(sizeof (ENV));
11701     if (e == NULL) {
11702         *env = SQL_NULL_HENV;
11703         return SQL_ERROR;
11704     }
11705     e->magic = ENV_MAGIC;
11706     e->ov3 = 0;
11707 #if defined(_WIN32) || defined(_WIN64)
11708     InitializeCriticalSection(&e->cs);
11709 #else
11710 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
11711     nvfs_init();
11712 #endif
11713 #endif
11714     e->dbcs = NULL;
11715     *env = (SQLHENV) e;
11716     return SQL_SUCCESS;
11717 }
11718 
11725 SQLRETURN SQL_API
11726 SQLAllocEnv(SQLHENV *env)
11727 {
11728     return drvallocenv(env);
11729 }
11730 
11737 static SQLRETURN
11738 drvfreeenv(SQLHENV env)
11739 {
11740     ENV *e;
11741 
11742     if (env == SQL_NULL_HENV) {
11743         return SQL_INVALID_HANDLE;
11744     }
11745     e = (ENV *) env;
11746     if (e->magic != ENV_MAGIC) {
11747         return SQL_SUCCESS;
11748     }
11749 #if defined(_WIN32) || defined(_WIN64)
11750     EnterCriticalSection(&e->cs);
11751 #endif
11752     if (e->dbcs) {
11753 #if defined(_WIN32) || defined(_WIN64)
11754         LeaveCriticalSection(&e->cs);
11755 #endif
11756         return SQL_ERROR;
11757     }
11758     e->magic = DEAD_MAGIC;
11759 #if defined(_WIN32) || defined(_WIN64)
11760     LeaveCriticalSection(&e->cs);
11761     DeleteCriticalSection(&e->cs);
11762 #endif
11763     xfree(e);
11764     return SQL_SUCCESS;
11765 }
11766 
11773 SQLRETURN SQL_API
11774 SQLFreeEnv(SQLHENV env)
11775 {
11776     return drvfreeenv(env);
11777 }
11778 
11786 static SQLRETURN
11787 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
11788 {
11789     DBC *d;
11790     ENV *e;
11791     const char *verstr;
11792     int maj = 0, min = 0, lev = 0;
11793 
11794     if (dbc == NULL) {
11795         return SQL_ERROR;
11796     }
11797     d = (DBC *) xmalloc(sizeof (DBC));
11798     if (d == NULL) {
11799         *dbc = SQL_NULL_HDBC;
11800         return SQL_ERROR;
11801     }
11802     memset(d, 0, sizeof (DBC));
11803     d->curtype = SQL_CURSOR_STATIC;
11804     d->ov3 = &d->ov3val;
11805     verstr = sqlite3_libversion();
11806     sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
11807     d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
11808     e = (ENV *) env;
11809 #if defined(_WIN32) || defined(_WIN64)
11810     if (e->magic == ENV_MAGIC) {
11811         EnterCriticalSection(&e->cs);
11812     }
11813 #endif
11814     if (e->magic == ENV_MAGIC) {
11815         DBC *n, *p;
11816 
11817         d->env = e;
11818         d->ov3 = &e->ov3;
11819         p = NULL;
11820         n = e->dbcs;
11821         while (n) {
11822             p = n;
11823             n = n->next;
11824         }
11825         if (p) {
11826             p->next = d;
11827         } else {
11828             e->dbcs = d;
11829         }
11830     }
11831 #if defined(_WIN32) || defined(_WIN64)
11832     InitializeCriticalSection(&d->cs);
11833     d->owner = 0;
11834     if (e->magic == ENV_MAGIC) {
11835         LeaveCriticalSection(&e->cs);
11836     }
11837     d->oemcp = 1;
11838 #endif
11839     d->autocommit = 1;
11840     d->magic = DBC_MAGIC;
11841     *dbc = (SQLHDBC) d;
11842     drvgetgpps(d);
11843     return SQL_SUCCESS;
11844 }
11845 
11853 SQLRETURN SQL_API
11854 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
11855 {
11856     return drvallocconnect(env, dbc);
11857 }
11858 
11865 static SQLRETURN
11866 drvfreeconnect(SQLHDBC dbc)
11867 {
11868     DBC *d;
11869     ENV *e;
11870     SQLRETURN ret = SQL_ERROR;
11871 
11872     if (dbc == SQL_NULL_HDBC) {
11873         return SQL_INVALID_HANDLE;
11874     }
11875     d = (DBC *) dbc;
11876     if (d->magic != DBC_MAGIC) {
11877         return SQL_INVALID_HANDLE;
11878     }
11879     e = d->env;
11880     if (e && e->magic == ENV_MAGIC) {
11881 #if defined(_WIN32) || defined(_WIN64)
11882         EnterCriticalSection(&e->cs);
11883 #endif
11884     } else {
11885         e = NULL;
11886     }
11887     HDBC_LOCK(dbc);
11888     if (d->sqlite) {
11889         setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
11890         HDBC_UNLOCK(dbc);
11891         goto done;
11892     }
11893     while (d->stmt) {
11894         freestmt((HSTMT) d->stmt);
11895     }
11896     if (e && e->magic == ENV_MAGIC) {
11897         DBC *n, *p;
11898 
11899         p = NULL;
11900         n = e->dbcs;
11901         while (n) {
11902             if (n == d) {
11903                 break;
11904             }
11905             p = n;
11906             n = n->next;
11907         }
11908         if (n) {
11909             if (p) {
11910                 p->next = d->next;
11911             } else {
11912                 e->dbcs = d->next;
11913             }
11914         }
11915     }
11916     drvrelgpps(d);
11917     d->magic = DEAD_MAGIC;
11918     if (d->trace) {
11919         fclose(d->trace);
11920     }
11921 #if defined(_WIN32) || defined(_WIN64)
11922     d->owner = 0;
11923     LeaveCriticalSection(&d->cs);
11924     DeleteCriticalSection(&d->cs);
11925 #endif
11926     xfree(d);
11927     ret = SQL_SUCCESS;
11928 done:
11929 #if defined(_WIN32) || defined(_WIN64)
11930     if (e) {
11931         LeaveCriticalSection(&e->cs);
11932     }
11933 #endif
11934     return ret;
11935 }
11936 
11943 SQLRETURN SQL_API
11944 SQLFreeConnect(SQLHDBC dbc)
11945 {
11946     return drvfreeconnect(dbc);
11947 }
11948 
11959 static SQLRETURN
11960 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11961                   SQLINTEGER bufmax, SQLINTEGER *buflen)
11962 {
11963     DBC *d;
11964     SQLINTEGER dummy;
11965 
11966     if (dbc == SQL_NULL_HDBC) {
11967         return SQL_INVALID_HANDLE;
11968     }
11969     d = (DBC *) dbc;
11970     if (!val) {
11971         val = (SQLPOINTER) &dummy;
11972     }
11973     if (!buflen) {
11974         buflen = &dummy;
11975     }
11976     switch (attr) {
11977     case SQL_ATTR_CONNECTION_DEAD:
11978         *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
11979         *buflen = sizeof (SQLINTEGER);
11980         break;
11981     case SQL_ATTR_ACCESS_MODE:
11982         *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
11983         *buflen = sizeof (SQLINTEGER);
11984         break;
11985     case SQL_ATTR_AUTOCOMMIT:
11986         *((SQLINTEGER *) val) =
11987             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
11988         *buflen = sizeof (SQLINTEGER);
11989         break;
11990     case SQL_ATTR_LOGIN_TIMEOUT:
11991         *((SQLINTEGER *) val) = 100;
11992         *buflen = sizeof (SQLINTEGER);
11993         break;
11994     case SQL_ATTR_ODBC_CURSORS:
11995         *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
11996         *buflen = sizeof (SQLINTEGER);
11997         break;
11998     case SQL_ATTR_PACKET_SIZE:
11999         *((SQLINTEGER *) val) = 16384;
12000         *buflen = sizeof (SQLINTEGER);
12001         break;
12002     case SQL_ATTR_TXN_ISOLATION:
12003         *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
12004         *buflen = sizeof (SQLINTEGER);
12005         break;
12006     case SQL_ATTR_TRACEFILE:
12007     case SQL_ATTR_TRANSLATE_LIB:
12008         *((SQLCHAR *) val) = 0;
12009         *buflen = 0;
12010         break;
12011     case SQL_ATTR_CURRENT_CATALOG:
12012 #if defined(_WIN32) || defined(_WIN64)
12013         if (d->xcelqrx) {
12014             if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
12015                 strcpy((char *) val, "main");
12016                 *buflen = 4;
12017                 break;
12018             }
12019         }
12020 #endif
12021         *((SQLCHAR *) val) = 0;
12022         *buflen = 0;
12023         break;
12024     case SQL_ATTR_TRACE:
12025     case SQL_ATTR_QUIET_MODE:
12026     case SQL_ATTR_TRANSLATE_OPTION:
12027     case SQL_ATTR_KEYSET_SIZE:
12028     case SQL_ATTR_QUERY_TIMEOUT:
12029         *((SQLINTEGER *) val) = 0;
12030         *buflen = sizeof (SQLINTEGER);
12031         break;
12032     case SQL_ATTR_PARAM_BIND_TYPE:
12033         *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
12034         *buflen = sizeof (SQLUINTEGER);
12035         break;
12036     case SQL_ATTR_ROW_BIND_TYPE:
12037         *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
12038         *buflen = sizeof (SQLULEN);
12039         break;
12040     case SQL_ATTR_USE_BOOKMARKS:
12041         *((SQLINTEGER *) val) = SQL_UB_OFF;
12042         *buflen = sizeof (SQLINTEGER);
12043         break;
12044     case SQL_ATTR_ASYNC_ENABLE:
12045         *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
12046         *buflen = sizeof (SQLINTEGER);
12047         break;
12048     case SQL_ATTR_NOSCAN:
12049         *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
12050         *buflen = sizeof (SQLINTEGER);
12051         break;
12052     case SQL_ATTR_CONCURRENCY:
12053         *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
12054         *buflen = sizeof (SQLINTEGER);
12055         break;
12056 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
12057     case SQL_ATTR_CURSOR_SENSITIVITY:
12058         *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
12059         *buflen = sizeof (SQLINTEGER);
12060         break;
12061 #endif
12062     case SQL_ATTR_SIMULATE_CURSOR:
12063         *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
12064         *buflen = sizeof (SQLINTEGER);
12065         break;
12066     case SQL_ATTR_MAX_ROWS:
12067         *((SQLINTEGER *) val) = 0;
12068         *buflen = sizeof (SQLINTEGER);
12069     case SQL_ATTR_MAX_LENGTH:
12070         *((SQLINTEGER *) val) = 1000000000;
12071         *buflen = sizeof (SQLINTEGER);
12072         break;
12073     case SQL_ATTR_CURSOR_TYPE:
12074         *((SQLINTEGER *) val) = d->curtype;
12075         *buflen = sizeof (SQLINTEGER);
12076         break;
12077     case SQL_ATTR_RETRIEVE_DATA:
12078         *((SQLINTEGER *) val) = SQL_RD_ON;
12079         *buflen = sizeof (SQLINTEGER);
12080         break;
12081 #ifdef SQL_ATTR_METADATA_ID
12082     case SQL_ATTR_METADATA_ID:
12083         *((SQLULEN *) val) = SQL_FALSE;
12084         return SQL_SUCCESS;
12085 #endif
12086     default:
12087         *((SQLINTEGER *) val) = 0;
12088         *buflen = sizeof (SQLINTEGER);
12089         setstatd(d, -1, "unsupported connect attribute %d",
12090                  (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
12091         return SQL_ERROR;
12092     }
12093     return SQL_SUCCESS;
12094 }
12095 
12096 #ifndef WINTERFACE
12097 
12107 SQLRETURN SQL_API
12108 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12109                   SQLINTEGER bufmax, SQLINTEGER *buflen)
12110 {
12111     SQLRETURN ret;
12112 
12113     HDBC_LOCK(dbc);
12114     ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
12115     HDBC_UNLOCK(dbc);
12116     return ret;
12117 }
12118 #endif
12119 
12120 #ifdef WINTERFACE
12121 
12131 SQLRETURN SQL_API
12132 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12133                    SQLINTEGER bufmax, SQLINTEGER *buflen)
12134 {
12135     SQLRETURN ret;
12136     SQLINTEGER len = 0;
12137 
12138     HDBC_LOCK(dbc);
12139     ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
12140     if (ret == SQL_SUCCESS) {
12141         SQLWCHAR *v = NULL;
12142 
12143         switch (attr) {
12144         case SQL_ATTR_TRACEFILE:
12145         case SQL_ATTR_CURRENT_CATALOG:
12146         case SQL_ATTR_TRANSLATE_LIB:
12147             if (val) {
12148                 if (len > 0) {
12149                     v = uc_from_utf((SQLCHAR *) val, len);
12150                     if (v) {
12151                         int vmax = bufmax / sizeof (SQLWCHAR);
12152 
12153                         uc_strncpy(val, v, vmax);
12154                         if (len < vmax) {
12155                             len = min(vmax, uc_strlen(v));
12156                             v[len] = 0;
12157                         } else {
12158                             len = vmax;
12159                         }
12160                         uc_free(v);
12161                         len *= sizeof (SQLWCHAR);
12162                     } else {
12163                         len = 0;
12164                     }
12165                 }
12166                 if (len <= 0) {
12167                     len = 0;
12168                     if (bufmax >= sizeof (SQLWCHAR)) {
12169                         *((SQLWCHAR *)val) = 0;
12170                     }
12171                 }
12172             } else {
12173                 len *= sizeof (SQLWCHAR);
12174             }
12175             break;
12176         }
12177         if (buflen) {
12178             *buflen = len;
12179         }
12180     }
12181     HDBC_UNLOCK(dbc);
12182     return ret;
12183 }
12184 #endif
12185 
12195 static SQLRETURN
12196 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12197                   SQLINTEGER len)
12198 {
12199     DBC *d;
12200 
12201     if (dbc == SQL_NULL_HDBC) {
12202         return SQL_INVALID_HANDLE;
12203     }
12204     d = (DBC *) dbc;
12205     switch (attr) {
12206     case SQL_AUTOCOMMIT:
12207         d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
12208         if (d->autocommit && d->intrans) {
12209             return endtran(d, SQL_COMMIT, 1);
12210         } else if (!d->autocommit) {
12211             s3stmt_end(d->cur_s3stmt);
12212         }
12213         break;
12214         return SQL_SUCCESS;
12215 #ifdef SQL_ATTR_METADATA_ID
12216     case SQL_ATTR_METADATA_ID:
12217         if (val == (SQLPOINTER) SQL_FALSE) {
12218             break;
12219         }
12220         /* fall through */
12221 #endif
12222     default:
12223         setstatd(d, -1, "option value changed", "01S02");
12224         return SQL_SUCCESS_WITH_INFO;
12225     }
12226     return SQL_SUCCESS;
12227 }
12228 
12229 #ifndef WINTERFACE
12230 
12239 SQLRETURN SQL_API
12240 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12241                   SQLINTEGER len)
12242 {
12243     SQLRETURN ret;
12244 
12245     HDBC_LOCK(dbc);
12246     ret = drvsetconnectattr(dbc, attr, val, len);
12247     HDBC_UNLOCK(dbc);
12248     return ret;
12249 }
12250 #endif
12251 
12252 #ifdef WINTERFACE
12253 
12262 SQLRETURN SQL_API
12263 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12264                    SQLINTEGER len)
12265 {
12266     SQLRETURN ret;
12267 
12268     HDBC_LOCK(dbc);
12269     ret = drvsetconnectattr(dbc, attr, val, len);
12270     HDBC_UNLOCK(dbc);
12271     return ret;
12272 }
12273 #endif
12274 
12283 static SQLRETURN
12284 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12285 {
12286     DBC *d;
12287     SQLINTEGER dummy;
12288 
12289     if (dbc == SQL_NULL_HDBC) {
12290         return SQL_INVALID_HANDLE;
12291     }
12292     d = (DBC *) dbc;
12293     if (!param) {
12294         param = (SQLPOINTER) &dummy;
12295     }
12296     switch (opt) {
12297     case SQL_ACCESS_MODE:
12298         *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
12299         break;
12300     case SQL_AUTOCOMMIT:
12301         *((SQLINTEGER *) param) =
12302             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12303         break;
12304     case SQL_LOGIN_TIMEOUT:
12305         *((SQLINTEGER *) param) = 100;
12306         break;
12307     case SQL_ODBC_CURSORS:
12308         *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
12309         break;
12310     case SQL_PACKET_SIZE:
12311         *((SQLINTEGER *) param) = 16384;
12312         break;
12313     case SQL_TXN_ISOLATION:
12314         *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
12315         break;
12316     case SQL_OPT_TRACE:
12317     case SQL_OPT_TRACEFILE:
12318     case SQL_QUIET_MODE:
12319     case SQL_TRANSLATE_DLL:
12320     case SQL_TRANSLATE_OPTION:
12321     case SQL_KEYSET_SIZE:
12322     case SQL_QUERY_TIMEOUT:
12323     case SQL_BIND_TYPE:
12324     case SQL_CURRENT_QUALIFIER:
12325         *((SQLINTEGER *) param) = 0;
12326         break;
12327     case SQL_USE_BOOKMARKS:
12328         *((SQLINTEGER *) param) = SQL_UB_OFF;
12329         break;
12330     case SQL_ASYNC_ENABLE:
12331         *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
12332         break;
12333     case SQL_NOSCAN:
12334         *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
12335         break;
12336     case SQL_CONCURRENCY:
12337         *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
12338         break;
12339     case SQL_SIMULATE_CURSOR:
12340         *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
12341         break;
12342     case SQL_MAX_ROWS:
12343         *((SQLINTEGER *) param) = 0;
12344         break;
12345     case SQL_ROWSET_SIZE:
12346     case SQL_MAX_LENGTH:
12347         *((SQLINTEGER *) param) = 1000000000;
12348         break;
12349     case SQL_CURSOR_TYPE:
12350         *((SQLINTEGER *) param) = d->curtype;
12351         break;
12352     case SQL_RETRIEVE_DATA:
12353         *((SQLINTEGER *) param) = SQL_RD_ON;
12354         break;
12355     default:
12356         *((SQLINTEGER *) param) = 0;
12357         setstatd(d, -1, "unsupported connect option %d",
12358                  (*d->ov3) ? "HYC00" : "S1C00", opt);
12359         return SQL_ERROR;
12360     }
12361     return SQL_SUCCESS;
12362 }
12363 
12364 #ifndef WINTERFACE
12365 
12373 SQLRETURN SQL_API
12374 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12375 {
12376     SQLRETURN ret;
12377 
12378     HDBC_LOCK(dbc);
12379     ret = drvgetconnectoption(dbc, opt, param);
12380     HDBC_UNLOCK(dbc);
12381     return ret;
12382 }
12383 #endif
12384 
12385 #ifdef WINTERFACE
12386 
12394 SQLRETURN SQL_API
12395 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12396 {
12397     SQLRETURN ret;
12398 
12399     HDBC_LOCK(dbc);
12400     ret = drvgetconnectoption(dbc, opt, param);
12401     if (SQL_SUCCEEDED(ret)) {
12402         switch (opt) {
12403         case SQL_OPT_TRACEFILE:
12404         case SQL_CURRENT_QUALIFIER:
12405         case SQL_TRANSLATE_DLL:
12406             if (param) {
12407                 *(SQLWCHAR *) param = 0;
12408             }
12409             break;
12410         }
12411     }
12412     HDBC_UNLOCK(dbc);
12413     return ret;
12414 }
12415 #endif
12416 
12425 static SQLRETURN
12426 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
12427 {
12428     DBC *d;
12429 
12430     if (dbc == SQL_NULL_HDBC) {
12431         return SQL_INVALID_HANDLE;
12432     }
12433     d = (DBC *) dbc;
12434     switch (opt) {
12435     case SQL_AUTOCOMMIT:
12436         d->autocommit = param == SQL_AUTOCOMMIT_ON;
12437         if (d->autocommit && d->intrans) {
12438             return endtran(d, SQL_COMMIT, 1);
12439         } else if (!d->autocommit) {
12440             s3stmt_end(d->cur_s3stmt);
12441         }
12442         break;
12443     default:
12444         setstatd(d, -1, "option value changed", "01S02");
12445         return SQL_SUCCESS_WITH_INFO;
12446     }
12447     return SQL_SUCCESS;
12448 }
12449 
12450 #ifndef WINTERFACE
12451 
12459 SQLRETURN SQL_API
12460 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12461 {
12462     SQLRETURN ret;
12463 
12464     HDBC_LOCK(dbc);
12465     ret = drvsetconnectoption(dbc, opt, param);
12466     HDBC_UNLOCK(dbc);
12467     return ret;
12468 }
12469 #endif
12470 
12471 #ifdef WINTERFACE
12472 
12480 SQLRETURN SQL_API
12481 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12482 {
12483     SQLRETURN ret;
12484 
12485     HDBC_LOCK(dbc);
12486     ret = drvsetconnectoption(dbc, opt, param);
12487     HDBC_UNLOCK(dbc);
12488     return ret;
12489 }
12490 #endif
12491 
12492 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12493 
12504 static int
12505 getdsnattr(char *dsn, char *attr, char *out, int outLen)
12506 {
12507     char *str = dsn, *start;
12508     int len = strlen(attr);
12509 
12510     while (*str) {
12511         while (*str && *str == ';') {
12512             ++str;
12513         }
12514         start = str;
12515         if ((str = strchr(str, '=')) == NULL) {
12516             return 0;
12517         }
12518         if (str - start == len && strncasecmp(start, attr, len) == 0) {
12519             start = ++str;
12520             while (*str && *str != ';') {
12521                 ++str;
12522             }
12523             len = min(outLen - 1, str - start);
12524             strncpy(out, start, len);
12525             out[len] = '\0';
12526             return 1;
12527         }
12528         while (*str && *str != ';') {
12529             ++str;
12530         }
12531     }
12532     return 0;
12533 }
12534 #endif
12535 
12547 static SQLRETURN
12548 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
12549            int pwdLen, int isu)
12550 {
12551     DBC *d;
12552     int len;
12553     SQLRETURN ret;
12554     char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12555     char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
12556     char loadext[SQL_MAX_MESSAGE_LENGTH];
12557     char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
12558     char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
12559     char jdflag[32];
12560 #if defined(_WIN32) || defined(_WIN64)
12561     char oemcp[32];
12562 #endif
12563 
12564     if (dbc == SQL_NULL_HDBC) {
12565         return SQL_INVALID_HANDLE;
12566     }
12567     d = (DBC *) dbc;
12568     if (d->magic != DBC_MAGIC) {
12569         return SQL_INVALID_HANDLE;
12570     }
12571     if (d->sqlite != NULL) {
12572         setstatd(d, -1, "connection already established", "08002");
12573         return SQL_ERROR;
12574     }
12575     buf[0] = '\0';
12576     if (dsnLen == SQL_NTS) {
12577         len = sizeof (buf) - 1;
12578     } else {
12579         len = min(sizeof (buf) - 1, dsnLen);
12580     }
12581     if (dsn != NULL) {
12582         strncpy(buf, (char *) dsn, len);
12583     }
12584     buf[len] = '\0';
12585     if (buf[0] == '\0') {
12586         setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
12587         return SQL_ERROR;
12588     }
12589 #if defined(_WIN32) || defined(_WIN64)
12590     /*
12591      * When DSN is in UTF it must be converted to ANSI
12592      * here for ANSI SQLGetPrivateProfileString()
12593      */
12594     if (isu) {
12595         char *cdsn = utf_to_wmb(buf, len);
12596 
12597         if (!cdsn) {
12598             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12599             return SQL_ERROR;
12600         }
12601         strcpy(buf, cdsn);
12602         uc_free(cdsn);
12603     }
12604 #endif
12605     busy[0] = '\0';
12606     dbname[0] = '\0';
12607 #ifdef WITHOUT_DRIVERMGR
12608     getdsnattr(buf, "database", dbname, sizeof (dbname));
12609     if (dbname[0] == '\0') {
12610         strncpy(dbname, buf, sizeof (dbname));
12611         dbname[sizeof (dbname) - 1] = '\0';
12612     }
12613     getdsnattr(buf, "timeout", busy, sizeof (busy));
12614     sflag[0] = '\0';
12615     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12616     spflag[0] = '\0';
12617     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12618     ntflag[0] = '\0';
12619     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12620     nwflag[0] = '\0';
12621     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12622     snflag[0] = '\0';
12623     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12624     lnflag[0] = '\0';
12625     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12626     ncflag[0] = '\0';
12627     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12628     fkflag[0] = '\0';
12629     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12630     loadext[0] = '\0';
12631     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12632     jmode[0] = '\0';
12633     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12634     jdflag[0] = '\0';
12635     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
12636 #if defined(_WIN32) || defined(_WIN64)
12637     oemcp[0] = '\0';
12638     getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
12639 #endif
12640     biflag[0] = '\0';
12641     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12642 #else
12643     SQLGetPrivateProfileString(buf, "timeout", "100000",
12644                                busy, sizeof (busy), ODBC_INI);
12645     SQLGetPrivateProfileString(buf, "database", "",
12646                                dbname, sizeof (dbname), ODBC_INI);
12647 #if defined(_WIN32) || defined(_WIN64)
12648     /* database name read from registry is not UTF8 !!! */
12649     isu = 0;
12650 #endif
12651     SQLGetPrivateProfileString(buf, "stepapi", "",
12652                                sflag, sizeof (sflag), ODBC_INI);
12653     SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
12654                                spflag, sizeof (spflag), ODBC_INI);
12655     SQLGetPrivateProfileString(buf, "notxn", "",
12656                                ntflag, sizeof (ntflag), ODBC_INI);
12657     SQLGetPrivateProfileString(buf, "nowchar", "",
12658                                nwflag, sizeof (nwflag), ODBC_INI);
12659     SQLGetPrivateProfileString(buf, "shortnames", "",
12660                                snflag, sizeof (snflag), ODBC_INI);
12661     SQLGetPrivateProfileString(buf, "longnames", "",
12662                                lnflag, sizeof (lnflag), ODBC_INI);
12663     SQLGetPrivateProfileString(buf, "nocreat", "",
12664                                ncflag, sizeof (ncflag), ODBC_INI);
12665     SQLGetPrivateProfileString(buf, "fksupport", "",
12666                                fkflag, sizeof (fkflag), ODBC_INI);
12667     SQLGetPrivateProfileString(buf, "loadext", "",
12668                                loadext, sizeof (loadext), ODBC_INI);
12669     SQLGetPrivateProfileString(buf, "journalmode", "",
12670                                jmode, sizeof (jmode), ODBC_INI);
12671     SQLGetPrivateProfileString(buf, "jdconv", "",
12672                                jdflag, sizeof (jdflag), ODBC_INI);
12673 #if defined(_WIN32) || defined(_WIN64)
12674     SQLGetPrivateProfileString(buf, "oemcp", "1",
12675                                oemcp, sizeof (oemcp), ODBC_INI);
12676 #endif
12677     SQLGetPrivateProfileString(buf, "bigint", "",
12678                                biflag, sizeof (biflag), ODBC_INI);
12679 #endif
12680     tracef[0] = '\0';
12681 #ifdef WITHOUT_DRIVERMGR
12682     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12683 #else
12684     SQLGetPrivateProfileString(buf, "tracefile", "",
12685                                tracef, sizeof (tracef), ODBC_INI);
12686 #endif
12687     if (tracef[0] != '\0') {
12688         d->trace = fopen(tracef, "a");
12689     }
12690     d->nowchar = getbool(nwflag);
12691     d->shortnames = getbool(snflag);
12692     d->longnames = getbool(lnflag);
12693     d->nocreat = getbool(ncflag);
12694     d->fksupport = getbool(fkflag);
12695     d->jdconv = getbool(jdflag);
12696 #if defined(_WIN32) || defined(_WIN64)
12697     d->oemcp = getbool(oemcp);
12698 #else
12699     d->oemcp = 0;
12700 #endif
12701     d->dobigint = getbool(biflag);
12702     d->pwd = pwd;
12703     d->pwdLen = 0;
12704     if (d->pwd) {
12705         d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
12706     }
12707     ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
12708                   jmode, busy);
12709     if (ret == SQL_SUCCESS) {
12710         dbloadext(d, loadext);
12711     }
12712     return ret;
12713 }
12714 
12715 #ifndef WINTERFACE
12716 
12728 SQLRETURN SQL_API
12729 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
12730            SQLCHAR *uid, SQLSMALLINT uidLen,
12731            SQLCHAR *pwd, SQLSMALLINT pwdLen)
12732 {
12733     SQLRETURN ret;
12734 
12735     HDBC_LOCK(dbc);
12736     ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
12737     HDBC_UNLOCK(dbc);
12738     return ret;
12739 }
12740 #endif
12741 
12742 #ifdef WINTERFACE
12743 
12755 SQLRETURN SQL_API
12756 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
12757             SQLWCHAR *uid, SQLSMALLINT uidLen,
12758             SQLWCHAR *pwd, SQLSMALLINT pwdLen)
12759 {
12760     char *dsna = NULL;
12761     char *pwda = NULL;
12762     SQLRETURN ret;
12763 
12764     HDBC_LOCK(dbc);
12765     if (dsn) {
12766         dsna = uc_to_utf_c(dsn, dsnLen);
12767         if (!dsna) {
12768             DBC *d = (DBC *) dbc;
12769 
12770             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12771             ret = SQL_ERROR;
12772             goto done;
12773         }
12774     }
12775     if (pwd) {
12776         pwda = uc_to_utf_c(pwd, pwdLen);
12777         if (!pwda) {
12778             DBC *d = (DBC *) dbc;
12779 
12780             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12781             ret = SQL_ERROR;
12782             goto done;
12783         }
12784     }
12785     ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
12786 done:
12787     HDBC_UNLOCK(dbc);
12788     uc_free(dsna);
12789     uc_free(pwda);
12790     return ret;
12791 }
12792 #endif
12793 
12800 static SQLRETURN
12801 drvdisconnect(SQLHDBC dbc)
12802 {
12803     DBC *d;
12804     int rc;
12805 
12806     if (dbc == SQL_NULL_HDBC) {
12807         return SQL_INVALID_HANDLE;
12808     }
12809     d = (DBC *) dbc;
12810     if (d->magic != DBC_MAGIC) {
12811         return SQL_INVALID_HANDLE;
12812     }
12813     if (d->intrans) {
12814         setstatd(d, -1, "incomplete transaction", "25000");
12815         return SQL_ERROR;
12816     }
12817     if (d->cur_s3stmt) {
12818         s3stmt_end(d->cur_s3stmt);
12819     }
12820     if (d->sqlite) {
12821         if (d->trace) {
12822             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
12823                     d->dbname);
12824             fflush(d->trace);
12825         }
12826         rc = sqlite3_close(d->sqlite);
12827         if (rc == SQLITE_BUSY) {
12828             setstatd(d, -1, "unfinished statements", "25000");
12829             return SQL_ERROR;
12830         }
12831         d->sqlite = NULL;
12832     }
12833     freep(&d->dbname);
12834     freep(&d->dsn);
12835     return SQL_SUCCESS;
12836 }
12837 
12844 SQLRETURN SQL_API
12845 SQLDisconnect(SQLHDBC dbc)
12846 {
12847     SQLRETURN ret;
12848 
12849     HDBC_LOCK(dbc);
12850     ret = drvdisconnect(dbc);
12851     HDBC_UNLOCK(dbc);
12852     return ret;
12853 }
12854 
12855 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12856 
12870 static SQLRETURN
12871 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
12872                  SQLCHAR *connIn, SQLSMALLINT connInLen,
12873                  SQLCHAR *connOut, SQLSMALLINT connOutMax,
12874                  SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
12875 {
12876     DBC *d;
12877     int len;
12878     SQLRETURN ret;
12879     char buf[SQL_MAX_MESSAGE_LENGTH * 8], dbname[SQL_MAX_MESSAGE_LENGTH];
12880     char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
12881     char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
12882     char pwd[SQL_MAX_MESSAGE_LENGTH];
12883     char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
12884     char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
12885     char jdflag[32];
12886 
12887     if (dbc == SQL_NULL_HDBC) {
12888         return SQL_INVALID_HANDLE;
12889     }
12890     if (drvcompl != SQL_DRIVER_COMPLETE &&
12891         drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
12892         drvcompl != SQL_DRIVER_PROMPT &&
12893         drvcompl != SQL_DRIVER_NOPROMPT) {
12894         return SQL_NO_DATA;
12895     }
12896     d = (DBC *) dbc;
12897     if (d->sqlite) {
12898         setstatd(d, -1, "connection already established", "08002");
12899         return SQL_ERROR;
12900     }
12901     buf[0] = '\0';
12902     if (connInLen == SQL_NTS) {
12903         len = sizeof (buf) - 1;
12904     } else {
12905         len = min(connInLen, sizeof (buf) - 1);
12906     }
12907     if (connIn != NULL) {
12908         strncpy(buf, (char *) connIn, len);
12909     }
12910     buf[len] = '\0';
12911     if (!buf[0]) {
12912         setstatd(d, -1, "invalid connect attributes",
12913                  (*d->ov3) ? "HY090" : "S1090");
12914         return SQL_ERROR;
12915     }
12916     dsn[0] = '\0';
12917     getdsnattr(buf, "DSN", dsn, sizeof (dsn));
12918 
12919     /* special case: connIn is sole DSN value without keywords */
12920     if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
12921         strncpy(dsn, buf, sizeof (dsn) - 1);
12922         dsn[sizeof (dsn) - 1] = '\0';
12923     }
12924 
12925     busy[0] = '\0';
12926     getdsnattr(buf, "timeout", busy, sizeof (busy));
12927 #ifndef WITHOUT_DRIVERMGR
12928     if (dsn[0] && !busy[0]) {
12929         SQLGetPrivateProfileString(dsn, "timeout", "100000",
12930                                    busy, sizeof (busy), ODBC_INI);
12931     }
12932 #endif
12933     dbname[0] = '\0';
12934     getdsnattr(buf, "database", dbname, sizeof (dbname));
12935 #ifndef WITHOUT_DRIVERMGR
12936     if (dsn[0] && !dbname[0]) {
12937         SQLGetPrivateProfileString(dsn, "database", "",
12938                                    dbname, sizeof (dbname), ODBC_INI);
12939     }
12940 #endif
12941     sflag[0] = '\0';
12942     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12943 #ifndef WITHOUT_DRIVERMGR
12944     if (dsn[0] && !sflag[0]) {
12945         SQLGetPrivateProfileString(dsn, "stepapi", "",
12946                                    sflag, sizeof (sflag), ODBC_INI);
12947     }
12948 #endif
12949     spflag[0] = '\0';
12950     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12951 #ifndef WITHOUT_DRIVERMGR
12952     if (dsn[0] && !spflag[0]) {
12953         SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
12954                                    spflag, sizeof (spflag), ODBC_INI);
12955     }
12956 #endif
12957     ntflag[0] = '\0';
12958     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12959 #ifndef WITHOUT_DRIVERMGR
12960     if (dsn[0] && !ntflag[0]) {
12961         SQLGetPrivateProfileString(dsn, "notxn", "",
12962                                    ntflag, sizeof (ntflag), ODBC_INI);
12963     }
12964 #endif
12965     snflag[0] = '\0';
12966     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12967 #ifndef WITHOUT_DRIVERMGR
12968     if (dsn[0] && !snflag[0]) {
12969         SQLGetPrivateProfileString(dsn, "shortnames", "",
12970                                    snflag, sizeof (snflag), ODBC_INI);
12971     }
12972 #endif
12973     lnflag[0] = '\0';
12974     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12975 #ifndef WITHOUT_DRIVERMGR
12976     if (dsn[0] && !lnflag[0]) {
12977         SQLGetPrivateProfileString(dsn, "longnames", "",
12978                                    lnflag, sizeof (lnflag), ODBC_INI);
12979     }
12980 #endif
12981     ncflag[0] = '\0';
12982     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12983 #ifndef WITHOUT_DRIVERMGR
12984     if (dsn[0] && !ncflag[0]) {
12985         SQLGetPrivateProfileString(dsn, "nocreat", "",
12986                                    ncflag, sizeof (ncflag), ODBC_INI);
12987     }
12988 #endif
12989     nwflag[0] = '\0';
12990     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12991 #ifndef WITHOUT_DRIVERMGR
12992     if (dsn[0] && !nwflag[0]) {
12993         SQLGetPrivateProfileString(dsn, "nowchar", "",
12994                                    nwflag, sizeof (nwflag), ODBC_INI);
12995     }
12996 #endif
12997     fkflag[0] = '\0';
12998     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12999 #ifndef WITHOUT_DRIVERMGR
13000     if (dsn[0] && !fkflag[0]) {
13001         SQLGetPrivateProfileString(dsn, "fksupport", "",
13002                                    fkflag, sizeof (fkflag), ODBC_INI);
13003     }
13004 #endif
13005     loadext[0] = '\0';
13006     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
13007 #ifndef WITHOUT_DRIVERMGR
13008     if (dsn[0] && !loadext[0]) {
13009         SQLGetPrivateProfileString(dsn, "loadext", "",
13010                                    loadext, sizeof (loadext), ODBC_INI);
13011     }
13012 #endif
13013     jmode[0] = '\0';
13014     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
13015 #ifndef WITHOUT_DRIVERMGR
13016     if (dsn[0] && !jmode[0]) {
13017         SQLGetPrivateProfileString(dsn, "journalmode", "",
13018                                    jmode, sizeof (jmode), ODBC_INI);
13019     }
13020 #endif
13021     biflag[0] = '\0';
13022     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
13023 #ifndef WITHOUT_DRIVERMGR
13024     if (dsn[0] && !biflag[0]) {
13025         SQLGetPrivateProfileString(dsn, "bigint", "",
13026                                    biflag, sizeof (biflag), ODBC_INI);
13027     }
13028 #endif
13029     jdflag[0] = '\0';
13030     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
13031 #ifndef WITHOUT_DRIVERMGR
13032     if (dsn[0] && !jdflag[0]) {
13033         SQLGetPrivateProfileString(dsn, "jdconv", "",
13034                                    jdflag, sizeof (jdflag), ODBC_INI);
13035     }
13036 #endif
13037     pwd[0] = '\0';
13038     getdsnattr(buf, "pwd", pwd, sizeof (pwd));
13039 #ifndef WITHOUT_DRIVERMGR
13040     if (dsn[0] && !pwd[0]) {
13041         SQLGetPrivateProfileString(dsn, "pwd", "",
13042                                    pwd, sizeof (pwd), ODBC_INI);
13043     }
13044 #endif
13045 
13046     if (!dbname[0] && !dsn[0]) {
13047         strcpy(dsn, "SQLite");
13048         strncpy(dbname, buf, sizeof (dbname));
13049         dbname[sizeof (dbname) - 1] = '\0';
13050     }
13051     tracef[0] = '\0';
13052     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
13053 #ifndef WITHOUT_DRIVERMGR
13054     if (dsn[0] && !tracef[0]) {
13055         SQLGetPrivateProfileString(dsn, "tracefile", "",
13056                                    tracef, sizeof (tracef), ODBC_INI);
13057     }
13058 #endif
13059     if (connOut || connOutLen) {
13060         int count;
13061 
13062         buf[0] = '\0';
13063         count = snprintf(buf, sizeof (buf),
13064                          "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
13065                          "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
13066                          "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
13067                          "JournalMode=%s;LoadExt=%s;BigInt=%s;JDConv=%s;"
13068                          "PWD=%s",
13069                          dsn, dbname, sflag, busy, spflag, ntflag,
13070                          snflag, lnflag, ncflag, nwflag, fkflag, tracef,
13071                          jmode, loadext, biflag, jdflag, pwd);
13072         if (count < 0) {
13073             buf[sizeof (buf) - 1] = '\0';
13074         }
13075         len = min(connOutMax - 1, strlen(buf));
13076         if (connOut) {
13077             strncpy((char *) connOut, buf, len);
13078             connOut[len] = '\0';
13079         }
13080         if (connOutLen) {
13081             *connOutLen = len;
13082         }
13083     }
13084     if (tracef[0] != '\0') {
13085         d->trace = fopen(tracef, "a");
13086     }
13087     d->shortnames = getbool(snflag);
13088     d->longnames = getbool(lnflag);
13089     d->nocreat = getbool(ncflag);
13090     d->nowchar = getbool(nwflag);
13091     d->fksupport = getbool(fkflag);
13092     d->dobigint = getbool(biflag);
13093     d->jdconv = getbool(jdflag);
13094     d->oemcp = 0;
13095     d->pwdLen = strlen(pwd);
13096     d->pwd = (d->pwdLen > 0) ? pwd : NULL;
13097     ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
13098     memset(pwd, 0, sizeof (pwd));
13099     if (ret == SQL_SUCCESS) {
13100         dbloadext(d, loadext);
13101     }
13102     return ret;
13103 }
13104 #endif
13105 
13112 static SQLRETURN
13113 freestmt(SQLHSTMT stmt)
13114 {
13115     STMT *s;
13116     DBC *d;
13117 
13118     if (stmt == SQL_NULL_HSTMT) {
13119         return SQL_INVALID_HANDLE;
13120     }
13121     s = (STMT *) stmt;
13122     s3stmt_drop(s);
13123     freeresult(s, 1);
13124     freep(&s->query);
13125     d = (DBC *) s->dbc;
13126     if (d && d->magic == DBC_MAGIC) {
13127         STMT *p, *n;
13128 
13129         p = NULL;
13130         n = d->stmt;
13131         while (n) {
13132             if (n == s) {
13133                 break;
13134             }
13135             p = n;
13136             n = n->next;
13137         }
13138         if (n) {
13139             if (p) {
13140                 p->next = s->next;
13141             } else {
13142                 d->stmt = s->next;
13143             }
13144         }
13145     }
13146     freeparams(s);
13147     freep(&s->bindparms);
13148     if (s->row_status0 != &s->row_status1) {
13149         freep(&s->row_status0);
13150         s->rowset_size = 1;
13151         s->row_status0 = &s->row_status1;
13152     }
13153     xfree(s);
13154     return SQL_SUCCESS;
13155 }
13156 
13164 static SQLRETURN
13165 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
13166 {
13167     DBC *d;
13168     STMT *s, *sl, *pl;
13169 
13170     if (dbc == SQL_NULL_HDBC) {
13171         return SQL_INVALID_HANDLE;
13172     }
13173     d = (DBC *) dbc;
13174     if (d->magic != DBC_MAGIC || stmt == NULL) {
13175         return SQL_INVALID_HANDLE;
13176     }
13177     s = (STMT *) xmalloc(sizeof (STMT));
13178     if (s == NULL) {
13179         *stmt = SQL_NULL_HSTMT;
13180         return SQL_ERROR;
13181     }
13182     *stmt = (SQLHSTMT) s;
13183     memset(s, 0, sizeof (STMT));
13184     s->dbc = dbc;
13185     s->ov3 = d->ov3;
13186     s->bkmrk = SQL_UB_OFF;
13187     s->bkmrkptr = 0;
13188     s->oemcp = &d->oemcp;
13189     s->jdconv = &d->jdconv;
13190     s->nowchar[0] = d->nowchar;
13191     s->nowchar[1] = 0;
13192     s->dobigint = d->dobigint;
13193     s->curtype = d->curtype;
13194     s->row_status0 = &s->row_status1;
13195     s->rowset_size = 1;
13196     s->longnames = d->longnames;
13197     s->retr_data = SQL_RD_ON;
13198     s->max_rows = 0;
13199     s->bind_type = SQL_BIND_BY_COLUMN;
13200     s->bind_offs = NULL;
13201     s->paramset_size = 1;
13202     s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
13203     s->one_tbl = -1;
13204     s->has_pk = -1;
13205     s->has_rowid = -1;
13206 #ifdef _WIN64
13207     sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
13208 #else
13209     sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
13210 #endif
13211     sl = d->stmt;
13212     pl = NULL;
13213     while (sl) {
13214         pl = sl;
13215         sl = sl->next;
13216     }
13217     if (pl) {
13218         pl->next = s;
13219     } else {
13220         d->stmt = s;
13221     }
13222     return SQL_SUCCESS;
13223 }
13224 
13232 SQLRETURN SQL_API
13233 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
13234 {
13235     SQLRETURN ret;
13236 
13237     HDBC_LOCK(dbc);
13238     ret = drvallocstmt(dbc, stmt);
13239     HDBC_UNLOCK(dbc);
13240     return ret;
13241 }
13242 
13250 static SQLRETURN
13251 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13252 {
13253     STMT *s;
13254     SQLRETURN ret = SQL_SUCCESS;
13255     SQLHDBC dbc;
13256 
13257     if (stmt == SQL_NULL_HSTMT) {
13258         return SQL_INVALID_HANDLE;
13259     }
13260     HSTMT_LOCK(stmt);
13261     s = (STMT *) stmt;
13262     dbc = s->dbc;
13263     switch (opt) {
13264     case SQL_RESET_PARAMS:
13265         freeparams(s);
13266         break;
13267     case SQL_UNBIND:
13268         unbindcols(s);
13269         break;
13270     case SQL_CLOSE:
13271         s3stmt_end_if(s);
13272         freeresult(s, 0);
13273         break;
13274     case SQL_DROP:
13275         s3stmt_end_if(s);
13276         ret = freestmt(stmt);
13277         break;
13278     default:
13279         setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
13280         ret = SQL_ERROR;
13281         break;
13282     }
13283     HDBC_UNLOCK(dbc);
13284     return ret;
13285 }
13286 
13294 SQLRETURN SQL_API
13295 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13296 {
13297     return drvfreestmt(stmt, opt);
13298 }
13299 
13306 SQLRETURN SQL_API
13307 SQLCancel(SQLHSTMT stmt)
13308 {
13309     if (stmt != SQL_NULL_HSTMT) {
13310         DBC *d = (DBC *) ((STMT *) stmt)->dbc;
13311 #if defined(_WIN32) || defined(_WIN64)
13312         /* interrupt when other thread owns critical section */
13313         if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
13314             d->owner != 0) {
13315             d->busyint = 1;
13316             sqlite3_interrupt(d->sqlite);
13317             return SQL_SUCCESS;
13318         }
13319 #else
13320         if (d->magic == DBC_MAGIC) {
13321             d->busyint = 1;
13322             sqlite3_interrupt(d->sqlite);
13323         }
13324 #endif
13325     }
13326     return drvfreestmt(stmt, SQL_CLOSE);
13327 }
13328 
13338 static SQLRETURN
13339 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13340                  SQLSMALLINT *lenp)
13341 {
13342     STMT *s;
13343 
13344     if (stmt == SQL_NULL_HSTMT) {
13345         return SQL_INVALID_HANDLE;
13346     }
13347     s = (STMT *) stmt;
13348     if (lenp && !cursor) {
13349         *lenp = strlen((char *) s->cursorname);
13350         return SQL_SUCCESS;
13351     }
13352     if (cursor) {
13353         if (buflen > 0) {
13354             strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
13355             cursor[buflen - 1] = '\0';
13356         }
13357         if (lenp) {
13358             *lenp = min(strlen((char *) s->cursorname), buflen - 1);
13359         }
13360     }
13361     return SQL_SUCCESS;
13362 }
13363 
13364 #ifndef WINTERFACE
13365 
13374 SQLRETURN SQL_API
13375 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13376                  SQLSMALLINT *lenp)
13377 {
13378     SQLRETURN ret;
13379 #if defined(_WIN32) || defined(_WIN64)
13380     SQLSMALLINT len = 0;
13381 #endif
13382 
13383     HSTMT_LOCK(stmt);
13384 #if defined(_WIN32) || defined(_WIN64)
13385     if (!((STMT *) stmt)->oemcp[0]) {
13386         ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13387         goto done;
13388     }
13389     ret = drvgetcursorname(stmt, cursor, buflen, &len);
13390     if (ret == SQL_SUCCESS) {
13391         char *c = NULL;
13392 
13393         if (cursor) {
13394             c = utf_to_wmb((char *) cursor, len);
13395             if (!c) {
13396                 ret = nomem((STMT *) stmt);
13397                 goto done;
13398             }
13399             c[len] = 0;
13400             len = strlen(c);
13401             if (buflen > 0) {
13402                 strncpy((char *) cursor, c, buflen - 1);
13403                 cursor[buflen - 1] = 0;
13404             }
13405             uc_free(c);
13406         }
13407         if (lenp) {
13408             *lenp = min(len, buflen - 1);
13409         }
13410     }
13411 done:
13412     ;
13413 #else
13414     ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13415 #endif
13416     HSTMT_UNLOCK(stmt);
13417     return ret;
13418 }
13419 #endif
13420 
13421 #ifdef WINTERFACE
13422 
13431 SQLRETURN SQL_API
13432 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
13433                   SQLSMALLINT *lenp)
13434 {
13435     SQLRETURN ret;
13436     SQLSMALLINT len = 0;
13437 
13438     HSTMT_LOCK(stmt);
13439     ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
13440     if (ret == SQL_SUCCESS) {
13441         SQLWCHAR *c = NULL;
13442 
13443         if (cursor) {
13444             c = uc_from_utf((SQLCHAR *) cursor, len);
13445             if (!c) {
13446                 ret = nomem((STMT *) stmt);
13447                 goto done;
13448             }
13449             c[len] = 0;
13450             len = uc_strlen(c);
13451             if (buflen > 0) {
13452                 uc_strncpy(cursor, c, buflen - 1);
13453                 cursor[buflen - 1] = 0;
13454             }
13455             uc_free(c);
13456         }
13457         if (lenp) {
13458             *lenp = min(len, buflen - 1);
13459         }
13460     }
13461 done:
13462     HSTMT_UNLOCK(stmt);
13463     return ret;
13464 }
13465 #endif
13466 
13475 static SQLRETURN
13476 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13477 {
13478     STMT *s;
13479 
13480     if (stmt == SQL_NULL_HSTMT) {
13481         return SQL_INVALID_HANDLE;
13482     }
13483     s = (STMT *) stmt;
13484     if (!cursor ||
13485         !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
13486           (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
13487         setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
13488         return SQL_ERROR;
13489     }
13490     if (len == SQL_NTS) {
13491         len = sizeof (s->cursorname) - 1;
13492     } else {
13493         len = min(sizeof (s->cursorname) - 1, len);
13494     }
13495     strncpy((char *) s->cursorname, (char *) cursor, len);
13496     s->cursorname[len] = '\0';
13497     return SQL_SUCCESS;
13498 }
13499 
13500 #ifndef WINTERFACE
13501 
13509 SQLRETURN SQL_API
13510 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13511 {
13512 #if defined(_WIN32) || defined(_WIN64)
13513     char *c = NULL;
13514 #endif
13515     SQLRETURN ret;
13516 
13517     HSTMT_LOCK(stmt);
13518 #if defined(_WIN32) || defined(_WIN64)
13519     if (!((STMT *) stmt)->oemcp[0]) {
13520         ret = drvsetcursorname(stmt, cursor, len);
13521         goto done2;
13522     }
13523     if (cursor) {
13524         c = wmb_to_utf_c((char *) cursor, len);
13525         if (!c) {
13526             ret = nomem((STMT *) stmt);
13527             goto done;
13528         }
13529     }
13530     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13531 #else
13532     ret = drvsetcursorname(stmt, cursor, len);
13533 #endif
13534 #if defined(_WIN32) || defined(_WIN64)
13535 done:
13536     uc_free(c);
13537 done2:
13538     ;
13539 #endif
13540     HSTMT_UNLOCK(stmt);
13541     return ret;
13542 }
13543 #endif
13544 
13545 #ifdef WINTERFACE
13546 
13554 SQLRETURN SQL_API
13555 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
13556 {
13557     char *c = NULL;
13558     SQLRETURN ret;
13559 
13560     HSTMT_LOCK(stmt);
13561     if (cursor) {
13562         c = uc_to_utf_c(cursor, len);
13563         if (!c) {
13564             ret = nomem((STMT *) stmt);
13565             goto done;
13566         }
13567     }
13568     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13569 done:
13570     uc_free(c);
13571     HSTMT_UNLOCK(stmt);
13572     return ret;
13573 }
13574 #endif
13575 
13582 SQLRETURN SQL_API
13583 SQLCloseCursor(SQLHSTMT stmt)
13584 {
13585     return drvfreestmt(stmt, SQL_CLOSE);
13586 }
13587 
13596 SQLRETURN SQL_API
13597 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
13598 {
13599     SQLRETURN ret;
13600 
13601     switch (type) {
13602     case SQL_HANDLE_ENV:
13603         ret = drvallocenv((SQLHENV *) output);
13604         if (ret == SQL_SUCCESS) {
13605             ENV *e = (ENV *) *output;
13606 
13607             if (e && e->magic == ENV_MAGIC) {
13608                 e->ov3 = 1;
13609             }
13610         }
13611         return ret;
13612     case SQL_HANDLE_DBC:
13613         return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
13614     case SQL_HANDLE_STMT:
13615         HDBC_LOCK((SQLHDBC) input);
13616         ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
13617         HDBC_UNLOCK((SQLHDBC) input);
13618         return ret;
13619     }
13620     return SQL_ERROR;
13621 }
13622 
13630 SQLRETURN SQL_API
13631 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
13632 {
13633     switch (type) {
13634     case SQL_HANDLE_ENV:
13635         return drvfreeenv((SQLHENV) h);
13636     case SQL_HANDLE_DBC:
13637         return drvfreeconnect((SQLHDBC) h);
13638     case SQL_HANDLE_STMT:
13639         return drvfreestmt((SQLHSTMT) h, SQL_DROP);
13640     }
13641     return SQL_ERROR;
13642 }
13643 
13649 static void
13650 freedyncols(STMT *s)
13651 {
13652     if (s->dyncols) {
13653         int i;
13654 
13655         for (i = 0; i < s->dcols; i++) {
13656             freep(&s->dyncols[i].typename);
13657         }
13658         if (s->cols == s->dyncols) {
13659             s->cols = NULL;
13660             s->ncols = 0;
13661         }
13662         freep(&s->dyncols);
13663     }
13664     s->dcols = 0;
13665 }
13666 
13678 static void
13679 freeresult(STMT *s, int clrcols)
13680 {
13681     freep(&s->bincache);
13682     s->bincell = NULL;
13683     s->binlen = 0;
13684     if (s->rows) {
13685         if (s->rowfree) {
13686             s->rowfree(s->rows);
13687             s->rowfree = NULL;
13688         }
13689         s->rows = NULL;
13690     }
13691     s->nrows = -1;
13692     if (clrcols > 0) {
13693         freep(&s->bindcols);
13694         s->nbindcols = 0;
13695     }
13696     if (clrcols) {
13697         freedyncols(s);
13698         s->cols = NULL;
13699         s->ncols = 0;
13700         s->nowchar[1] = 0;
13701         s->one_tbl = -1;
13702         s->has_pk = -1;
13703         s->has_rowid = -1;
13704     }
13705 }
13706 
13712 static void
13713 unbindcols(STMT *s)
13714 {
13715     int i;
13716 
13717     for (i = 0; s->bindcols && i < s->nbindcols; i++) {
13718         s->bindcols[i].type = SQL_UNKNOWN_TYPE;
13719         s->bindcols[i].max = 0;
13720         s->bindcols[i].lenp = NULL;
13721         s->bindcols[i].valp = NULL;
13722         s->bindcols[i].index = i;
13723         s->bindcols[i].offs = 0;
13724     }
13725 }
13726 
13734 static SQLRETURN
13735 mkbindcols(STMT *s, int ncols)
13736 {
13737     if (s->bindcols) {
13738         if (s->nbindcols < ncols) {
13739             int i;
13740             BINDCOL *bindcols =
13741                 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
13742 
13743             if (!bindcols) {
13744                 return nomem(s);
13745             }
13746             for (i = s->nbindcols; i < ncols; i++) {
13747                 bindcols[i].type = SQL_UNKNOWN_TYPE;
13748                 bindcols[i].max = 0;
13749                 bindcols[i].lenp = NULL;
13750                 bindcols[i].valp = NULL;
13751                 bindcols[i].index = i;
13752                 bindcols[i].offs = 0;
13753             }
13754             s->bindcols = bindcols;
13755             s->nbindcols = ncols;
13756         }
13757     } else if (ncols > 0) {
13758         s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
13759         if (!s->bindcols) {
13760             return nomem(s);
13761         }
13762         s->nbindcols = ncols;
13763         unbindcols(s);
13764     }
13765     return SQL_SUCCESS;
13766 }
13767 
13781 static SQLRETURN
13782 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
13783            SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
13784 {
13785     char **data, valdummy[16];
13786     SQLLEN dummy;
13787     SQLINTEGER *ilenp = NULL;
13788     int valnull = 0;
13789     int type = otype;
13790     SQLRETURN sret = SQL_NO_DATA;
13791 
13792     if (!lenp) {
13793         lenp = &dummy;
13794     }
13795     /* workaround for JDK 1.7.0 on x86_64 */
13796     if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
13797         ilenp = (SQLINTEGER *) lenp;
13798         lenp = &dummy;
13799     }
13800     if (col >= s->ncols) {
13801         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13802         return SQL_ERROR;
13803     }
13804     if (s->retr_data != SQL_RD_ON) {
13805         return SQL_SUCCESS;
13806     }
13807     if (!s->rows) {
13808         *lenp = SQL_NULL_DATA;
13809         goto done;
13810     }
13811     if (s->rowp < 0 || s->rowp >= s->nrows) {
13812         *lenp = SQL_NULL_DATA;
13813         goto done;
13814     }
13815     type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
13816                       s->nowchar[0]);
13817 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
13818     /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
13819     if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
13820         type = SQL_C_CHAR;
13821     }
13822 #endif
13823     data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
13824     if (!val) {
13825         valnull = 1;
13826         val = (SQLPOINTER) valdummy;
13827     }
13828     if (*data == NULL) {
13829         *lenp = SQL_NULL_DATA;
13830         switch (type) {
13831         case SQL_C_UTINYINT:
13832         case SQL_C_TINYINT:
13833         case SQL_C_STINYINT:
13834 #ifdef SQL_BIT
13835         case SQL_C_BIT:
13836 #endif
13837             *((SQLCHAR *) val) = 0;
13838             break;
13839         case SQL_C_USHORT:
13840         case SQL_C_SHORT:
13841         case SQL_C_SSHORT:
13842             *((SQLSMALLINT *) val) = 0;
13843             break;
13844         case SQL_C_ULONG:
13845         case SQL_C_LONG:
13846         case SQL_C_SLONG:
13847             *((SQLINTEGER *) val) = 0;
13848             break;
13849 #ifdef SQL_BIGINT
13850         case SQL_C_SBIGINT:
13851         case SQL_C_UBIGINT:
13852             *((SQLBIGINT *) val) = 0;
13853             break;
13854 #endif
13855         case SQL_C_FLOAT:
13856             *((float *) val) = 0;
13857             break;
13858         case SQL_C_DOUBLE:
13859             *((double *) val) = 0;
13860             break;
13861         case SQL_C_BINARY:
13862         case SQL_C_CHAR:
13863             if (len > 0) {
13864                 *((SQLCHAR *) val) = '\0';
13865             }
13866             break;
13867 #ifdef WCHARSUPPORT
13868         case SQL_C_WCHAR:
13869             if (len > 0) {
13870                 *((SQLWCHAR *) val) = '\0';
13871             }
13872             break;
13873 #endif
13874 #ifdef SQL_C_TYPE_DATE
13875         case SQL_C_TYPE_DATE:
13876 #endif
13877         case SQL_C_DATE:
13878             memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
13879             break;
13880 #ifdef SQL_C_TYPE_TIME
13881         case SQL_C_TYPE_TIME:
13882 #endif
13883         case SQL_C_TIME:
13884             memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
13885             break;
13886 #ifdef SQL_C_TYPE_TIMESTAMP
13887         case SQL_C_TYPE_TIMESTAMP:
13888 #endif
13889         case SQL_C_TIMESTAMP:
13890             memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
13891             break;
13892         default:
13893             return SQL_ERROR;
13894         }
13895     } else {
13896         char *endp = NULL;
13897 #if defined(_WIN32) || defined(_WIN64)
13898 #ifdef SQL_BIGINT
13899         char endc;
13900 #endif
13901 #endif
13902 
13903         switch (type) {
13904         case SQL_C_UTINYINT:
13905         case SQL_C_TINYINT:
13906         case SQL_C_STINYINT:
13907             *((SQLCHAR *) val) = strtol(*data, &endp, 0);
13908             if (endp && endp == *data) {
13909                 *lenp = SQL_NULL_DATA;
13910             } else {
13911                 *lenp = sizeof (SQLCHAR);
13912             }
13913             break;
13914 #ifdef SQL_BIT
13915         case SQL_C_BIT:
13916             *((SQLCHAR *) val) = getbool(*data);
13917             *lenp = sizeof (SQLCHAR);
13918             break;
13919 #endif
13920         case SQL_C_USHORT:
13921         case SQL_C_SHORT:
13922         case SQL_C_SSHORT:
13923             *((SQLSMALLINT *) val) = strtol(*data, &endp, 0);
13924             if (endp && endp == *data) {
13925                 *lenp = SQL_NULL_DATA;
13926             } else {
13927                 *lenp = sizeof (SQLSMALLINT);
13928             }
13929             break;
13930         case SQL_C_ULONG:
13931         case SQL_C_LONG:
13932         case SQL_C_SLONG:
13933             *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
13934             if (endp && endp == *data) {
13935                 *lenp = SQL_NULL_DATA;
13936             } else {
13937                 *lenp = sizeof (SQLINTEGER);
13938             }
13939             break;
13940 #ifdef SQL_BIGINT
13941         case SQL_C_UBIGINT:
13942 #if defined(_WIN32) || defined(_WIN64)
13943             if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
13944                 *lenp = SQL_NULL_DATA;
13945             } else {
13946                 *lenp = sizeof (SQLUBIGINT);
13947             }
13948 #else
13949 #ifdef __osf__
13950             *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
13951 #else
13952             *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
13953 #endif
13954             if (endp && endp == *data) {
13955                 *lenp = SQL_NULL_DATA;
13956             } else {
13957                 *lenp = sizeof (SQLUBIGINT);
13958             }
13959 #endif
13960             break;
13961         case SQL_C_SBIGINT:
13962 #if defined(_WIN32) || defined(_WIN64)
13963             if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
13964                 *lenp = SQL_NULL_DATA;
13965             } else {
13966                 *lenp = sizeof (SQLBIGINT);
13967             }
13968 #else
13969 #ifdef __osf__
13970             *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
13971 #else
13972             *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
13973 #endif
13974             if (endp && endp == *data) {
13975                 *lenp = SQL_NULL_DATA;
13976             } else {
13977                 *lenp = sizeof (SQLBIGINT);
13978             }
13979 #endif
13980             break;
13981 #endif
13982         case SQL_C_FLOAT:
13983             *((float *) val) = ln_strtod(*data, &endp);
13984             if (endp && endp == *data) {
13985                 *lenp = SQL_NULL_DATA;
13986             } else {
13987                 *lenp = sizeof (float);
13988             }
13989             break;
13990         case SQL_C_DOUBLE:
13991             *((double *) val) = ln_strtod(*data, &endp);
13992             if (endp && endp == *data) {
13993                 *lenp = SQL_NULL_DATA;
13994             } else {
13995                 *lenp = sizeof (double);
13996             }
13997             break;
13998         case SQL_C_BINARY: {
13999             int dlen, offs = 0;
14000             char *bin;
14001 
14002             if (valnull) {
14003                 freep(&s->bincache);
14004                 s->binlen = 0;
14005                 goto doCHAR;
14006             }
14007             if (*data == s->bincell) {
14008                 if (s->bincache) {
14009                     bin = s->bincache;
14010                     dlen = s->binlen;
14011                 } else {
14012                     goto doCHAR;
14013                 }
14014             } else {
14015                 char *dp;
14016                 int i;
14017 
14018                 freep(&s->bincache);
14019                 dp = *data;
14020                 dlen = strlen(dp);
14021                 s->bincell = dp;
14022                 s->binlen = 0;
14023                 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
14024                     dp[dlen - 1] != '\'') {
14025                     goto doCHAR;
14026                 }
14027                 dlen -= 2;
14028                 dp += 2;
14029                 dlen = dlen / 2;
14030                 s->bincache = bin = xmalloc(dlen + 1);
14031                 if (!bin) {
14032                     return nomem(s);
14033                 }
14034                 s->binlen = dlen;
14035                 memset(bin, 0, dlen);
14036                 bin[dlen] = '\0';       /* terminator, just in case */
14037                 for (i = 0; i < dlen; i++) {
14038                     char *x;
14039                     int v;
14040 
14041                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14042                         goto converr;
14043                     }
14044                     v = x - xdigits;
14045                     bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
14046                     ++dp;
14047                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14048 converr:
14049                         freep(&s->bincache);
14050                         s->binlen = 0;
14051                         setstat(s, -1, "conversion error",
14052                                 (*s->ov3) ? "HY000" : "S1000");
14053                         return SQL_ERROR;
14054                     }
14055                     v = x - xdigits;
14056                     bin[i] |= (v >= 16) ? (v - 6) : v;
14057                     ++dp;
14058                 }
14059                 bin = s->bincache;
14060             }
14061             if (partial && len && s->bindcols) {
14062                 if (s->bindcols[col].offs >= dlen) {
14063                     *lenp = 0;
14064                     if (!dlen && s->bindcols[col].offs == dlen) {
14065                         s->bindcols[col].offs = 1;
14066                         sret = SQL_SUCCESS;
14067                         goto done;
14068                     }
14069                     s->bindcols[col].offs = 0;
14070                     sret = SQL_NO_DATA;
14071                     goto done;
14072                 }
14073                 offs = s->bindcols[col].offs;
14074                 dlen -= offs;
14075             }
14076             if (val && len) {
14077                 memcpy(val, bin + offs, min(len, dlen));
14078             }
14079             if (len < 1) {
14080                 *lenp = dlen;
14081             } else {
14082                 *lenp = min(len, dlen);
14083                 if (*lenp == len && *lenp != dlen) {
14084                     *lenp = SQL_NO_TOTAL;
14085                 }
14086             }
14087             if (partial && len && s->bindcols) {
14088                 if (*lenp == SQL_NO_TOTAL) {
14089                     *lenp = dlen;
14090                     s->bindcols[col].offs += len;
14091                     setstat(s, -1, "data right truncated", "01004");
14092                     if (s->bindcols[col].lenp) {
14093                         *s->bindcols[col].lenp = dlen;
14094                     }
14095                     sret = SQL_SUCCESS_WITH_INFO;
14096                     goto done;
14097                 }
14098                 s->bindcols[col].offs += *lenp;
14099             }
14100             if (*lenp == SQL_NO_TOTAL) {
14101                 *lenp = dlen;
14102                 setstat(s, -1, "data right truncated", "01004");
14103                 sret = SQL_SUCCESS_WITH_INFO;
14104                 goto done;
14105             }
14106             break;
14107         }
14108         doCHAR:
14109 #ifdef WCHARSUPPORT
14110         case SQL_C_WCHAR:
14111 #endif
14112         case SQL_C_CHAR: {
14113             int doz, zlen = len - 1;
14114             int dlen = strlen(*data);
14115             int offs = 0;
14116 #ifdef WCHARSUPPORT
14117             SQLWCHAR *ucdata = NULL;
14118             SQLCHAR *cdata = (SQLCHAR *) *data;
14119 #endif
14120 
14121 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14122             /* MS Access hack part 2 (reserved error -7748) */
14123             if (!valnull &&
14124                 (s->cols == statSpec2P || s->cols == statSpec3P) &&
14125                 type == SQL_C_WCHAR) {
14126                 if (len > 0 && len <= sizeof (SQLWCHAR)) {
14127                     ((char *) val)[0] = data[0][0];
14128                     memset((char *) val + 1, 0, len - 1);
14129                     *lenp = 1;
14130                     sret = SQL_SUCCESS;
14131                     goto done;
14132                 }
14133             }
14134 #endif
14135 
14136 #ifdef WCHARSUPPORT
14137             switch (type) {
14138             case SQL_C_CHAR:
14139                 doz = 1;
14140                 break;
14141             case SQL_C_WCHAR:
14142                 doz = sizeof (SQLWCHAR);
14143                 break;
14144             default:
14145                 doz = 0;
14146                 break;
14147             }
14148             if (type == SQL_C_WCHAR) {
14149                 ucdata = uc_from_utf(cdata, dlen);
14150                 if (!ucdata) {
14151                     return nomem(s);
14152                 }
14153                 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
14154             }
14155 #if defined(_WIN32) || defined(_WIN64)
14156             else if (*s->oemcp && type == SQL_C_CHAR) {
14157                 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
14158                 if (!ucdata) {
14159                     return nomem(s);
14160                 }
14161                 cdata = (SQLCHAR *) ucdata;
14162                 dlen = strlen((char *) cdata);
14163             }
14164 #endif
14165 #else
14166             doz = (type == SQL_C_CHAR) ? 1 : 0;
14167 #endif
14168             if (partial && len && s->bindcols) {
14169                 if (s->bindcols[col].offs >= dlen) {
14170 #ifdef WCHARSUPPORT
14171                     uc_free(ucdata);
14172 #endif
14173                     *lenp = 0;
14174                     if (doz && val) {
14175 #ifdef WCHARSUPPORT
14176                         if (type == SQL_C_WCHAR) {
14177                             ((SQLWCHAR *) val)[0] = 0;
14178                         } else {
14179                             ((char *) val)[0] = '\0';
14180                         }
14181 #else
14182                         ((char *) val)[0] = '\0';
14183 #endif
14184                     }
14185                     if (!dlen && s->bindcols[col].offs == dlen) {
14186                         s->bindcols[col].offs = 1;
14187                         sret = SQL_SUCCESS;
14188                         goto done;
14189                     }
14190                     s->bindcols[col].offs = 0;
14191                     sret = SQL_NO_DATA;
14192                     goto done;
14193                 }
14194                 offs = s->bindcols[col].offs;
14195                 dlen -= offs;
14196             }
14197             if (val && !valnull && len) {
14198 #ifdef WCHARSUPPORT
14199                 if (type == SQL_C_WCHAR) {
14200                     uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
14201                                (len - doz) / sizeof (SQLWCHAR));
14202                 } else {
14203                     strncpy(val, (char *) cdata + offs, len - doz);
14204                 }
14205 #else
14206                 strncpy(val, *data + offs, len - doz);
14207 #endif
14208             }
14209             if (valnull || len < 1) {
14210                 *lenp = dlen;
14211             } else {
14212                 *lenp = min(len - doz, dlen);
14213                 if (*lenp == len - doz && *lenp != dlen) {
14214                     *lenp = SQL_NO_TOTAL;
14215                 } else if (*lenp < zlen) {
14216                     zlen = *lenp;
14217                 }
14218             }
14219             if (len && !valnull && doz) {
14220 #ifdef WCHARSUPPORT
14221                 if (type == SQL_C_WCHAR) {
14222                     ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
14223                 } else {
14224                     ((char *) val)[zlen] = '\0';
14225                 }
14226 #else
14227                 ((char *) val)[zlen] = '\0';
14228 #endif
14229             }
14230 #ifdef WCHARSUPPORT
14231             uc_free(ucdata);
14232 #endif
14233             if (partial && len && s->bindcols) {
14234                 if (*lenp == SQL_NO_TOTAL) {
14235                     *lenp = dlen;
14236                     s->bindcols[col].offs += len - doz;
14237                     setstat(s, -1, "data right truncated", "01004");
14238                     if (s->bindcols[col].lenp) {
14239                         *s->bindcols[col].lenp = dlen;
14240                     }
14241                     sret = SQL_SUCCESS_WITH_INFO;
14242                     goto done;
14243                 }
14244                 s->bindcols[col].offs += *lenp;
14245             }
14246             if (*lenp == SQL_NO_TOTAL) {
14247                 *lenp = dlen;
14248                 setstat(s, -1, "data right truncated", "01004");
14249                 sret = SQL_SUCCESS_WITH_INFO;
14250                 goto done;
14251             }
14252             break;
14253         }
14254 #ifdef SQL_C_TYPE_DATE
14255         case SQL_C_TYPE_DATE:
14256 #endif
14257         case SQL_C_DATE:
14258             if (str2date(*s->jdconv, *data, (DATE_STRUCT *) val) < 0) {
14259                 *lenp = SQL_NULL_DATA;
14260             } else {
14261                 *lenp = sizeof (DATE_STRUCT);
14262             }
14263             break;
14264 #ifdef SQL_C_TYPE_TIME
14265         case SQL_C_TYPE_TIME:
14266 #endif
14267         case SQL_C_TIME:
14268             if (str2time(*s->jdconv, *data, (TIME_STRUCT *) val) < 0) {
14269                 *lenp = SQL_NULL_DATA;
14270             } else {
14271                 *lenp = sizeof (TIME_STRUCT);
14272             }
14273             break;
14274 #ifdef SQL_C_TYPE_TIMESTAMP
14275         case SQL_C_TYPE_TIMESTAMP:
14276 #endif
14277         case SQL_C_TIMESTAMP:
14278             if (str2timestamp(*s->jdconv, *data,
14279                               (TIMESTAMP_STRUCT *) val) < 0) {
14280                 *lenp = SQL_NULL_DATA;
14281             } else {
14282                 *lenp = sizeof (TIMESTAMP_STRUCT);
14283             }
14284             switch (s->cols[col].prec) {
14285             case 0:
14286                 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
14287                 break;
14288             case 1:
14289                 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
14290                 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
14291                 break;
14292             case 2:
14293                 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
14294                 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
14295                 break;
14296             }
14297             break;
14298         default:
14299             return SQL_ERROR;
14300         }
14301     }
14302     sret = SQL_SUCCESS;
14303 done:
14304     if (ilenp) {
14305         *ilenp = *lenp;
14306     }
14307     return sret;
14308 }
14309 
14321 static SQLRETURN
14322 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14323            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14324 {
14325     STMT *s;
14326     int sz = 0;
14327 
14328     if (stmt == SQL_NULL_HSTMT) {
14329         return SQL_INVALID_HANDLE;
14330     }
14331     s = (STMT *) stmt;
14332     if (col < 1) {
14333         if (col == 0 && s->bkmrk == SQL_UB_ON &&
14334             type == SQL_C_BOOKMARK) {
14335             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14336             s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
14337             s->bkmrkcol.lenp = val ? lenp : 0;
14338             s->bkmrkcol.valp = val;
14339             s->bkmrkcol.offs = 0;
14340             if (val && lenp) {
14341                 *lenp = 0;
14342             }
14343             return SQL_SUCCESS;
14344         } else if (col == 0 && s->bkmrk == SQL_UB_VARIABLE &&
14345                    type == SQL_C_VARBOOKMARK &&
14346                    max >= sizeof (sqlite_int64)) {
14347             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14348             s->bkmrkcol.max = val ? max : 0;
14349             s->bkmrkcol.lenp = val ? lenp : 0;
14350             s->bkmrkcol.valp = val;
14351             s->bkmrkcol.offs = 0;
14352             if (val && lenp) {
14353                 *lenp = 0;
14354             }
14355             return SQL_SUCCESS;
14356         }
14357         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14358         return SQL_ERROR;
14359     }
14360     if (mkbindcols(s, col) != SQL_SUCCESS) {
14361         return SQL_ERROR;
14362     }
14363     --col;
14364     if (type == SQL_C_DEFAULT) {
14365         type = mapdeftype(type, s->cols[col].type, 0,
14366                           s->nowchar[0] || s->nowchar[1]);
14367     }
14368     switch (type) {
14369     case SQL_C_LONG:
14370     case SQL_C_ULONG:
14371     case SQL_C_SLONG:
14372         sz = sizeof (SQLINTEGER);
14373         break;
14374     case SQL_C_TINYINT:
14375     case SQL_C_UTINYINT:
14376     case SQL_C_STINYINT:
14377         sz = sizeof (SQLCHAR);
14378         break;
14379     case SQL_C_SHORT:
14380     case SQL_C_USHORT:
14381     case SQL_C_SSHORT:
14382         sz = sizeof (SQLSMALLINT);
14383         break;
14384     case SQL_C_FLOAT:
14385         sz = sizeof (SQLFLOAT);
14386         break;
14387     case SQL_C_DOUBLE:
14388         sz = sizeof (SQLDOUBLE);
14389         break;
14390     case SQL_C_TIMESTAMP:
14391         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14392         break;
14393     case SQL_C_TIME:
14394         sz = sizeof (SQL_TIME_STRUCT);
14395         break;
14396     case SQL_C_DATE:
14397         sz = sizeof (SQL_DATE_STRUCT);
14398         break;
14399     case SQL_C_CHAR:
14400         break;
14401 #ifdef WCHARSUPPORT
14402     case SQL_C_WCHAR:
14403         break;
14404 #endif
14405 #ifdef SQL_C_TYPE_DATE
14406     case SQL_C_TYPE_DATE:
14407         sz = sizeof (SQL_DATE_STRUCT);
14408         break;
14409 #endif
14410 #ifdef SQL_C_TYPE_TIME
14411     case SQL_C_TYPE_TIME:
14412         sz = sizeof (SQL_TIME_STRUCT);
14413         break;
14414 #endif
14415 #ifdef SQL_C_TYPE_TIMESTAMP
14416     case SQL_C_TYPE_TIMESTAMP:
14417         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14418         break;
14419 #endif
14420 #ifdef SQL_BIT
14421     case SQL_C_BIT:
14422         sz = sizeof (SQLCHAR);
14423         break;
14424 #endif
14425     case SQL_C_BINARY:
14426         break;
14427 #ifdef SQL_BIGINT
14428     case SQL_C_SBIGINT:
14429     case SQL_C_UBIGINT:
14430         sz = sizeof (SQLBIGINT);
14431         break;
14432 #endif
14433     default:
14434         if (val == NULL) {
14435             /* fall through, unbinding column */
14436             break;
14437         }
14438         setstat(s, -1, "invalid type %d", "HY003", type);
14439         return SQL_ERROR;
14440     }
14441     if (val == NULL) {
14442         /* unbind column */
14443         s->bindcols[col].type = SQL_UNKNOWN_TYPE;
14444         s->bindcols[col].max = 0;
14445         s->bindcols[col].lenp = NULL;
14446         s->bindcols[col].valp = NULL;
14447         s->bindcols[col].offs = 0;
14448     } else {
14449         if (sz == 0 && max < 0) {
14450             setstat(s, -1, "invalid length", "HY090");
14451             return SQL_ERROR;
14452         }
14453         s->bindcols[col].type = type;
14454         s->bindcols[col].max = (sz == 0) ? max : sz;
14455         s->bindcols[col].lenp = lenp;
14456         s->bindcols[col].valp = val;
14457         s->bindcols[col].offs = 0;
14458         if (lenp) {
14459             *lenp = 0;
14460         }
14461     }
14462     return SQL_SUCCESS;
14463 }
14464 
14476 SQLRETURN SQL_API
14477 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14478            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14479 {
14480     SQLRETURN ret;
14481 
14482     HSTMT_LOCK(stmt);
14483     ret = drvbindcol(stmt, col, type, val, max, lenp);
14484     HSTMT_UNLOCK(stmt);
14485     return ret;
14486 }
14487 
14492 static COL tableSpec2[] = {
14493     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14494     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14495     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14496     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14497     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14498 };
14499 
14500 static COL tableSpec3[] = {
14501     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14502     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14503     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14504     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14505     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14506 };
14507 
14522 static SQLRETURN
14523 drvtables(SQLHSTMT stmt,
14524           SQLCHAR *cat, SQLSMALLINT catLen,
14525           SQLCHAR *schema, SQLSMALLINT schemaLen,
14526           SQLCHAR *table, SQLSMALLINT tableLen,
14527           SQLCHAR *type, SQLSMALLINT typeLen)
14528 {
14529     SQLRETURN ret;
14530     STMT *s;
14531     DBC *d;
14532     int ncols, asize, rc, size, npatt;
14533     char *errp = NULL, *sql, tname[512];
14534     char *where = "(type = 'table' or type = 'view')";
14535 
14536     ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
14537                       tableSpec3, array_size(tableSpec3), &asize);
14538     if (ret != SQL_SUCCESS) {
14539         return ret;
14540     }
14541     s = (STMT *) stmt;
14542     d = (DBC *) s->dbc;
14543     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
14544         int size = 3 * asize;
14545 
14546         s->rows = xmalloc(size * sizeof (char *));
14547         if (!s->rows) {
14548             s->nrows = 0;
14549             return nomem(s);
14550         }
14551         memset(s->rows, 0, sizeof (char *) * size);
14552         s->ncols = asize;
14553         s->rows[s->ncols + 0] = "";
14554         s->rows[s->ncols + 1] = "";
14555         s->rows[s->ncols + 2] = "";
14556         s->rows[s->ncols + 3] = "TABLE";
14557         s->rows[s->ncols + 5] = "";
14558         s->rows[s->ncols + 6] = "";
14559         s->rows[s->ncols + 7] = "";
14560         s->rows[s->ncols + 8] = "VIEW";
14561 #ifdef MEMORY_DEBUG
14562         s->rowfree = xfree__;
14563 #else
14564         s->rowfree = sqlite3_free;
14565 #endif
14566         s->nrows = 2;
14567         s->rowp = s->rowprs = -1;
14568         return SQL_SUCCESS;
14569     }
14570     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
14571         table = NULL;
14572         goto doit;
14573     }
14574     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
14575         schema[0] == '%') {
14576         if ((!cat || catLen == 0 || !cat[0]) &&
14577             (!table || tableLen == 0 || !table[0])) {
14578             table = NULL;
14579             goto doit;
14580         }
14581     }
14582     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
14583         char tmp[256], *t;
14584         int with_view = 0, with_table = 0;
14585 
14586         if (typeLen == SQL_NTS) {
14587             strncpy(tmp, (char *) type, sizeof (tmp));
14588             tmp[sizeof (tmp) - 1] = '\0';
14589         } else {
14590             int len = min(sizeof (tmp) - 1, typeLen);
14591 
14592             strncpy(tmp, (char *) type, len);
14593             tmp[len] = '\0';
14594         }
14595         t = tmp;
14596         while (*t) {
14597             *t = TOLOWER(*t);
14598             t++;
14599         }
14600         t = tmp;
14601         unescpat(t);
14602         while (t) {
14603             if (t[0] == '\'') {
14604                 ++t;
14605             }
14606             if (strncmp(t, "table", 5) == 0) {
14607                 with_table++;
14608             } else if (strncmp(t, "view", 4) == 0) {
14609                 with_view++;
14610             }
14611             t = strchr(t, ',');
14612             if (t) {
14613                 ++t;
14614             }
14615         }
14616         if (with_view && with_table) {
14617             /* where is already preset */
14618         } else if (with_view && !with_table) {
14619             where = "type = 'view'";
14620         } else if (!with_view && with_table) {
14621             where = "type = 'table'";
14622         } else {
14623             return SQL_SUCCESS;
14624         }
14625     }
14626 doit:
14627     if (!table) {
14628         size = 1;
14629         tname[0] = '%';
14630     } else {
14631         if (tableLen == SQL_NTS) {
14632             size = sizeof (tname) - 1;
14633         } else {
14634             size = min(sizeof (tname) - 1, tableLen);
14635         }
14636         strncpy(tname, (char *) table, size);
14637     }
14638     tname[size] = '\0';
14639     npatt = unescpat(tname);
14640 #if defined(_WIN32) || defined(_WIN64)
14641     sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14642                           "%s as 'TABLE_SCHEM', "
14643                           "tbl_name as 'TABLE_NAME', "
14644                           "upper(type) as 'TABLE_TYPE', "
14645                           "NULL as 'REMARKS' "
14646                           "from sqlite_master where %s "
14647                           "and tbl_name %s %Q",
14648                           d->xcelqrx ? "'main'" : "NULL",
14649                           d->xcelqrx ? "''" : "NULL",
14650                           where,
14651                           npatt ? "like" : "=", tname);
14652 #else
14653     sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14654                           "NULL as 'TABLE_OWNER', "
14655                           "tbl_name as 'TABLE_NAME', "
14656                           "upper(type) as 'TABLE_TYPE', "
14657                           "NULL as 'REMARKS' "
14658                           "from sqlite_master where %s "
14659                           "and tbl_name %s %Q", where,
14660                           npatt ? "like" : "=", tname);
14661 #endif
14662     if (!sql) {
14663         return nomem(s);
14664     }
14665     ret = starttran(s);
14666     if (ret != SQL_SUCCESS) {
14667         sqlite3_free(sql);
14668         return ret;
14669     }
14670     dbtraceapi(d, "sqlite3_get_table", sql);
14671     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
14672     sqlite3_free(sql);
14673     if (rc == SQLITE_OK) {
14674         if (ncols != s->ncols) {
14675             freeresult(s, 0);
14676             s->nrows = 0;
14677         } else {
14678             s->rowfree = sqlite3_free_table;
14679         }
14680     } else {
14681         s->nrows = 0;
14682         s->rows = NULL;
14683         s->rowfree = NULL;
14684     }
14685     if (errp) {
14686         sqlite3_free(errp);
14687         errp = NULL;
14688     }
14689     s->rowp = s->rowprs = -1;
14690     return SQL_SUCCESS;
14691 }
14692 
14693 #ifndef WINTERFACE
14694 
14708 SQLRETURN SQL_API
14709 SQLTables(SQLHSTMT stmt,
14710           SQLCHAR *cat, SQLSMALLINT catLen,
14711           SQLCHAR *schema, SQLSMALLINT schemaLen,
14712           SQLCHAR *table, SQLSMALLINT tableLen,
14713           SQLCHAR *type, SQLSMALLINT typeLen)
14714 {
14715 #if defined(_WIN32) || defined(_WIN64)
14716     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14717 #endif
14718     SQLRETURN ret;
14719 
14720     HSTMT_LOCK(stmt);
14721 #if defined(_WIN32) || defined(_WIN64)
14722     if (!((STMT *) stmt)->oemcp[0]) {
14723         ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14724                         table, tableLen, type, typeLen);
14725         goto done2;
14726     }
14727     if (cat) {
14728         c = wmb_to_utf_c((char *) cat, catLen);
14729         if (!c) {
14730             ret = nomem((STMT *) stmt);
14731             goto done;
14732         }
14733     }
14734     if (schema) {
14735         s = wmb_to_utf_c((char *) schema, schemaLen);
14736         if (!s) {
14737             ret = nomem((STMT *) stmt);
14738             goto done;
14739         }
14740     }
14741     if (table) {
14742         t = wmb_to_utf_c((char *) table, tableLen);
14743         if (!t) {
14744             ret = nomem((STMT *) stmt);
14745             goto done;
14746         }
14747     }
14748     if (type) {
14749         y = wmb_to_utf_c((char *) type, typeLen);
14750         if (!y) {
14751             ret = nomem((STMT *) stmt);
14752             goto done;
14753         }
14754     }
14755     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14756                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14757 #else
14758     ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14759                     table, tableLen, type, typeLen);
14760 #endif
14761 #if defined(_WIN32) || defined(_WIN64)
14762 done:
14763     uc_free(y);
14764     uc_free(t);
14765     uc_free(s);
14766     uc_free(c);
14767 done2:
14768     ;
14769 #endif
14770     HSTMT_UNLOCK(stmt);
14771     return ret;
14772 }
14773 #endif
14774 
14775 #ifdef WINTERFACE
14776 
14790 SQLRETURN SQL_API
14791 SQLTablesW(SQLHSTMT stmt,
14792            SQLWCHAR *cat, SQLSMALLINT catLen,
14793            SQLWCHAR *schema, SQLSMALLINT schemaLen,
14794            SQLWCHAR *table, SQLSMALLINT tableLen,
14795            SQLWCHAR *type, SQLSMALLINT typeLen)
14796 {
14797     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14798     SQLRETURN ret;
14799 
14800     HSTMT_LOCK(stmt);
14801     if (cat) {
14802         c = uc_to_utf_c(cat, catLen);
14803         if (!c) {
14804             ret = nomem((STMT *) stmt);
14805             goto done;
14806         }
14807     }
14808     if (schema) {
14809         s = uc_to_utf_c(schema, schemaLen);
14810         if (!s) {
14811             ret = nomem((STMT *) stmt);
14812             goto done;
14813         }
14814     }
14815     if (table) {
14816         t = uc_to_utf_c(table, tableLen);
14817         if (!t) {
14818             ret = nomem((STMT *) stmt);
14819             goto done;
14820         }
14821     }
14822     if (type) {
14823         y = uc_to_utf_c(type, typeLen);
14824         if (!y) {
14825             ret = nomem((STMT *) stmt);
14826             goto done;
14827         }
14828     }
14829     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14830                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14831 done:
14832     uc_free(y);
14833     uc_free(t);
14834     uc_free(s);
14835     uc_free(c);
14836     HSTMT_UNLOCK(stmt);
14837     return ret;
14838 }
14839 #endif
14840 
14845 static COL colSpec2[] = {
14846     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14847     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14848     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14849     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
14850     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
14851     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
14852     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
14853     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
14854     { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
14855     { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
14856     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
14857     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
14858     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
14859     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
14860     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
14861     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
14862     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
14863     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
14864 };
14865 
14866 static COL colSpec3[] = {
14867     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14868     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14869     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14870     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
14871     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
14872     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
14873     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
14874     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
14875     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
14876     { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
14877     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
14878     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
14879     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
14880     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
14881     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
14882     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
14883     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
14884     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
14885 };
14886 
14901 static SQLRETURN
14902 drvcolumns(SQLHSTMT stmt,
14903            SQLCHAR *cat, SQLSMALLINT catLen,
14904            SQLCHAR *schema, SQLSMALLINT schemaLen,
14905            SQLCHAR *table, SQLSMALLINT tableLen,
14906            SQLCHAR *col, SQLSMALLINT colLen)
14907 {
14908     SQLRETURN sret;
14909     STMT *s;
14910     DBC *d;
14911     int ret, nrows, ncols, asize, i, k, roffs, namec;
14912     int tnrows, tncols, npatt;
14913     PTRDIFF_T size;
14914     char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
14915 
14916     sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
14917                        colSpec3, array_size(colSpec3), &asize);
14918     if (sret != SQL_SUCCESS) {
14919         return sret;
14920     }
14921     s = (STMT *) stmt;
14922     d = (DBC *) s->dbc;
14923     if (!table) {
14924         size = 1;
14925         tname[0] = '%';
14926     } else {
14927         if (tableLen == SQL_NTS) {
14928             size = sizeof (tname) - 1;
14929         } else {
14930             size = min(sizeof (tname) - 1, tableLen);
14931         }
14932         strncpy(tname, (char *) table, size);
14933     }
14934     tname[size] = '\0';
14935     npatt = unescpat(tname);
14936     size = 0;
14937     if (col) {
14938         if (colLen == SQL_NTS) {
14939             size = sizeof (cname) - 1;
14940         } else {
14941             size = min(sizeof (cname) - 1, colLen);
14942         }
14943         strncpy(cname, (char *) col, size);
14944     }
14945     cname[size] = '\0';
14946     if (!strcmp(cname, "%")) {
14947         cname[0] = '\0';
14948     }
14949     sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
14950                           "(type = 'table' or type = 'view') "
14951                           "and tbl_name %s %Q", npatt ? "like" : "=", tname);
14952     if (!sql) {
14953         return nomem(s);
14954     }
14955     sret = starttran(s);
14956     if (sret != SQL_SUCCESS) {
14957         sqlite3_free(sql);
14958         return sret;
14959     }
14960     dbtraceapi(d, "sqlite3_get_table", sql);
14961     ret = sqlite3_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
14962     sqlite3_free(sql);
14963     if (ret != SQLITE_OK) {
14964         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14965                 errp ? errp : "unknown error", ret);
14966         if (errp) {
14967             sqlite3_free(errp);
14968             errp = NULL;
14969         }
14970         return SQL_ERROR;
14971     }
14972     if (errp) {
14973         sqlite3_free(errp);
14974         errp = NULL;
14975     }
14976     /* pass 1: compute number of rows of result set */
14977     if (tncols * tnrows <= 0) {
14978         sqlite3_free_table(trows);
14979         return SQL_SUCCESS;
14980     }
14981     size = 0;
14982     for (i = 1; i <= tnrows; i++) {
14983         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
14984         if (!sql) {
14985             sqlite3_free_table(trows);
14986             return nomem(s);
14987         }
14988         dbtraceapi(d, "sqlite3_get_table", sql);
14989         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
14990         sqlite3_free(sql);
14991         if (ret != SQLITE_OK) {
14992             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14993                     errp ? errp : "unknown error", ret);
14994             if (errp) {
14995                 sqlite3_free(errp);
14996                 errp = NULL;
14997             }
14998             sqlite3_free_table(trows);
14999             return SQL_ERROR;
15000         }
15001         if (errp) {
15002             sqlite3_free(errp);
15003             errp = NULL;
15004         }
15005         if (ncols * nrows > 0) {
15006             namec = -1;
15007             for (k = 0; k < ncols; k++) {
15008                 if (strcmp(rowp[k], "name") == 0) {
15009                     namec = k;
15010                     break;
15011                 }
15012             }
15013             if (cname[0]) {
15014                 if (namec >= 0) {
15015                     for (k = 1; k <= nrows; k++) {
15016                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15017                             size++;
15018                         }
15019                     }
15020                 }
15021             } else {
15022                 size += nrows;
15023             }
15024         }
15025         sqlite3_free_table(rowp);
15026     }
15027     /* pass 2: fill result set */
15028     if (size <= 0) {
15029         sqlite3_free_table(trows);
15030         return SQL_SUCCESS;
15031     }
15032     s->nrows = size;
15033     size = (size + 1) * asize;
15034     s->rows = xmalloc((size + 1) * sizeof (char *));
15035     if (!s->rows) {
15036         s->nrows = 0;
15037         sqlite3_free_table(trows);
15038         return nomem(s);
15039     }
15040     s->rows[0] = (char *) size;
15041     s->rows += 1;
15042     memset(s->rows, 0, sizeof (char *) * size);
15043     s->rowfree = freerows;
15044     roffs = 1;
15045     for (i = 1; i <= tnrows; i++) {
15046         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15047         if (!sql) {
15048             sqlite3_free_table(trows);
15049             return nomem(s);
15050         }
15051         dbtraceapi(d, "sqlite3_get_table", sql);
15052         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15053         sqlite3_free(sql);
15054         if (ret != SQLITE_OK) {
15055             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15056                     errp ? errp : "unknown error", ret);
15057             if (errp) {
15058                 sqlite3_free(errp);
15059                 errp = NULL;
15060             }
15061             sqlite3_free_table(trows);
15062             return SQL_ERROR;
15063         }
15064         if (errp) {
15065             sqlite3_free(errp);
15066             errp = NULL;
15067         }
15068         if (ncols * nrows > 0) {
15069             int m, mr, nr = nrows;
15070 
15071             namec = -1;
15072             for (k = 0; k < ncols; k++) {
15073                 if (strcmp(rowp[k], "name") == 0) {
15074                     namec = k;
15075                     break;
15076                 }
15077             }
15078             if (cname[0]) {
15079                 nr = 0;
15080                 if (namec >= 0) {
15081                     for (k = 1; k <= nrows; k++) {
15082                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15083                             nr++;
15084                         }
15085                     }
15086                 }
15087             }
15088             for (k = 0; k < nr; k++) {
15089                 m = asize * (roffs + k);
15090 #if defined(_WIN32) || defined(_WIN64)
15091                 s->rows[m + 0] = xstrdup(d->xcelqrx ? "main" : "");
15092                 s->rows[m + 1] = xstrdup("");
15093 #else
15094                 s->rows[m + 0] = xstrdup("");
15095                 s->rows[m + 1] = xstrdup("");
15096 #endif
15097                 s->rows[m + 2] = xstrdup(trows[i]);
15098                 s->rows[m + 8] = xstrdup("10");
15099                 s->rows[m + 9] = xstrdup("0");
15100                 s->rows[m + 15] = xstrdup("16384");
15101             }
15102             for (k = 0; nr && k < ncols; k++) {
15103                 if (strcmp(rowp[k], "cid") == 0) {
15104                     for (mr = 0, m = 1; m <= nrows; m++) {
15105                         char buf[256];
15106                         int ir, coln = k;
15107 
15108                         if (cname[0] &&
15109                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15110                             continue;
15111                         }
15112                         ir = asize * (roffs + mr);
15113                         sscanf(rowp[m * ncols + k], "%d", &coln);
15114                         sprintf(buf, "%d", coln + 1);
15115                         s->rows[ir + 16] = xstrdup(buf);
15116                         ++mr;
15117                     }
15118                 } else if (k == namec) {
15119                     for (mr = 0, m = 1; m <= nrows; m++) {
15120                         int ir;
15121 
15122                         if (cname[0] &&
15123                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15124                             continue;
15125                         }
15126                         ir = asize * (roffs + mr);
15127                         s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
15128                         ++mr;
15129                     }
15130                 } else if (strcmp(rowp[k], "notnull") == 0) {
15131                     for (mr = 0, m = 1; m <= nrows; m++) {
15132                         int ir;
15133 
15134                         if (cname[0] &&
15135                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15136                             continue;
15137                         }
15138                         ir = asize * (roffs + mr);
15139                         if (*rowp[m * ncols + k] != '0') {
15140                             s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
15141                         } else {
15142                             s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
15143                         }
15144                         s->rows[ir + 17] =
15145                             xstrdup((*rowp[m * ncols + k] != '0') ?
15146                                     "NO" : "YES");
15147                         ++mr;
15148                     }
15149                 } else if (strcmp(rowp[k], "dflt_value") == 0) {
15150                     for (mr = 0, m = 1; m <= nrows; m++) {
15151                         char *dflt = unquote(rowp[m * ncols + k]);
15152                         int ir;
15153 
15154                         if (cname[0] &&
15155                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15156                             continue;
15157                         }
15158                         ir = asize * (roffs + mr);
15159                         s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
15160                         ++mr;
15161                     }
15162                 } else if (strcmp(rowp[k], "type") == 0) {
15163                     for (mr = 0, m = 1; m <= nrows; m++) {
15164                         char *typename = rowp[m * ncols + k];
15165                         int sqltype, mm, dd, ir;
15166                         char buf[256];
15167 
15168                         if (cname[0] &&
15169                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15170                             continue;
15171                         }
15172                         ir = asize * (roffs + mr);
15173                         s->rows[ir + 5] = xstrdup(typename);
15174                         sqltype = mapsqltype(typename, NULL, *s->ov3,
15175                                              s->nowchar[0], s->dobigint);
15176                         getmd(typename, sqltype, &mm, &dd);
15177 #ifdef SQL_LONGVARCHAR
15178                         if (sqltype == SQL_VARCHAR && mm > 255) {
15179                             sqltype = SQL_LONGVARCHAR;
15180                         }
15181 #endif
15182 #ifdef WINTERFACE
15183 #ifdef SQL_WLONGVARCHAR
15184                         if (sqltype == SQL_WVARCHAR && mm > 255) {
15185                             sqltype = SQL_WLONGVARCHAR;
15186                         }
15187 #endif
15188 #endif
15189                         if (sqltype == SQL_VARBINARY && mm > 255) {
15190                             sqltype = SQL_LONGVARBINARY;
15191                         }
15192                         sprintf(buf, "%d", sqltype);
15193                         s->rows[ir + 4] = xstrdup(buf);
15194                         s->rows[ir + 13] = xstrdup(buf);
15195                         sprintf(buf, "%d", mm);
15196                         s->rows[ir + 7] = xstrdup(buf);
15197                         sprintf(buf, "%d", dd);
15198                         s->rows[ir + 6] = xstrdup(buf);
15199                         ++mr;
15200                     }
15201                 }
15202             }
15203             roffs += nr;
15204         }
15205         sqlite3_free_table(rowp);
15206     }
15207     sqlite3_free_table(trows);
15208     return SQL_SUCCESS;
15209 }
15210 
15211 #ifndef WINTERFACE
15212 
15226 SQLRETURN SQL_API
15227 SQLColumns(SQLHSTMT stmt,
15228            SQLCHAR *cat, SQLSMALLINT catLen,
15229            SQLCHAR *schema, SQLSMALLINT schemaLen,
15230            SQLCHAR *table, SQLSMALLINT tableLen,
15231            SQLCHAR *col, SQLSMALLINT colLen)
15232 {
15233 #if defined(_WIN32) || defined(_WIN64)
15234     char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15235 #endif
15236     SQLRETURN ret;
15237 
15238     HSTMT_LOCK(stmt);
15239 #if defined(_WIN32) || defined(_WIN64)
15240     if (!((STMT *) stmt)->oemcp[0]) {
15241         ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15242                          table, tableLen, col, colLen);
15243         goto done2;
15244     }
15245     if (cat) {
15246         c = wmb_to_utf_c((char *) cat, catLen);
15247         if (!c) {
15248             ret = nomem((STMT *) stmt);
15249             goto done;
15250         }
15251     }
15252     if (schema) {
15253         s = wmb_to_utf_c((char *) schema, schemaLen);
15254         if (!s) {
15255             ret = nomem((STMT *) stmt);
15256             goto done;
15257         }
15258     }
15259     if (table) {
15260         t = wmb_to_utf_c((char *) table, tableLen);
15261         if (!t) {
15262             ret = nomem((STMT *) stmt);
15263             goto done;
15264         }
15265     }
15266     if (col) {
15267         k = wmb_to_utf_c((char