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 + sizeof (*dsp));
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 + sizeof (*dsp));
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 + sizeof (*dsp));
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 + sizeof (*dsp));
00726 
00727         if (!ndsp) {
00728             strcpy(dsp->buffer, "OUT OF MEMORY");
00729             dsp->max = dsp->len = 13;
00730             dsp->oom = 1;
00731             return dsp;
00732         }
00733         dsp = ndsp;
00734         dsp->max = max;
00735     }
00736 copy:
00737     q = dsp->buffer + dsp->len;
00738     *q++ = '"';
00739     for (p = str; *p; ++p) {
00740         *q++ = *p;
00741         if (p[0] == '"') {
00742             *q++ = '"';
00743         }
00744     }
00745     *q++ = '"';
00746     *q = '\0';
00747     dsp->len += len;
00748     return dsp;
00749 }
00750 
00757 static const char *
00758 dsval(dstr *dsp)
00759 {
00760     if (dsp) {
00761         return (const char *) dsp->buffer;
00762     }
00763     return "ERROR";
00764 }
00765 
00772 static int
00773 dserr(dstr *dsp)
00774 {
00775     return !dsp || dsp->oom;
00776 }
00777 
00783 static void
00784 dsfree(dstr *dsp)
00785 {
00786     if (dsp) {
00787         xfree(dsp);
00788     }
00789 }
00790 
00791 #ifdef WCHARSUPPORT
00792 
00799 static int
00800 uc_strlen(SQLWCHAR *str)
00801 {
00802     int len = 0;
00803 
00804     if (str) {
00805         while (*str) {
00806             ++len;
00807             ++str;
00808         }
00809     }
00810     return len;
00811 }
00812 
00821 static SQLWCHAR *
00822 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
00823 {
00824     int i = 0;
00825 
00826     while (i < len) {
00827         if (!src[i]) {
00828             break;
00829         }
00830         dest[i] = src[i];
00831         ++i;
00832     }
00833     if (i < len) {
00834         dest[i] = 0;
00835     }
00836     return dest;
00837 }
00838 
00847 static void
00848 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
00849 {
00850     ucLen = ucLen / sizeof (SQLWCHAR);
00851     if (!uc || ucLen < 0) {
00852         return;
00853     }
00854     if (len < 0) {
00855         len = ucLen * 5;
00856     }
00857     uc[0] = 0;
00858     if (str) {
00859         int i = 0;
00860 
00861         while (i < len && *str && i < ucLen) {
00862             unsigned char c = str[0];
00863 
00864             if (c < 0x80) {
00865                 uc[i++] = c;
00866                 ++str;
00867             } else if (c <= 0xc1 || c >= 0xf5) {
00868                 /* illegal, ignored */
00869                 ++str;
00870             } else if (c < 0xe0) {
00871                 if ((str[1] & 0xc0) == 0x80) {
00872                     unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
00873 
00874                     uc[i++] = t;
00875                     str += 2;
00876                 } else {
00877                     uc[i++] = c;
00878                     ++str;
00879                 }
00880             } else if (c < 0xf0) {
00881                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
00882                     unsigned long t = ((c & 0x0f) << 12) |
00883                         ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
00884 
00885                     uc[i++] = t;
00886                     str += 3;
00887                 } else {
00888                     uc[i++] = c;
00889                     ++str;
00890                 }
00891             } else if (c < 0xf8) {
00892                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00893                     (str[3] & 0xc0) == 0x80) {
00894                     unsigned long t = ((c & 0x03) << 18) |
00895                         ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
00896                         (str[3] & 0x3f);
00897 
00898                     if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00899                         t >= 0x10000) {
00900                         t -= 0x10000;
00901                         uc[i++] = 0xd800 | ((t >> 10) & 0x3ff);
00902                         if (i >= ucLen) {
00903                             break;
00904                         }
00905                         t = 0xdc00 | (t & 0x3ff);
00906                     }
00907                     uc[i++] = t;
00908                     str += 4;
00909                 } else {
00910                     uc[i++] = c;
00911                     ++str;
00912                 }
00913             } else {
00914                 /* ignore */
00915                 ++str;
00916             }
00917         }
00918         if (i < ucLen) {
00919             uc[i] = 0;
00920         }
00921     }
00922 }
00923 
00931 static SQLWCHAR *
00932 uc_from_utf(unsigned char *str, int len)
00933 {
00934     SQLWCHAR *uc = NULL;
00935     int ucLen;
00936 
00937     if (str) {
00938         if (len == SQL_NTS) {
00939             len = strlen((char *) str);
00940         }
00941         ucLen = sizeof (SQLWCHAR) * (len + 1);
00942         uc = xmalloc(ucLen);
00943         if (uc) {
00944             uc_from_utf_buf(str, len, uc, ucLen);
00945         }
00946     }
00947     return uc;
00948 }
00949 
00957 static char *
00958 uc_to_utf(SQLWCHAR *str, int len)
00959 {
00960     int i;
00961     char *cp, *ret = NULL;
00962 
00963     if (!str) {
00964         return ret;
00965     }
00966     if (len == SQL_NTS) {
00967         len = uc_strlen(str);
00968     } else {
00969         len = len / sizeof (SQLWCHAR);
00970     }
00971     cp = xmalloc(len * 6 + 1);
00972     if (!cp) {
00973         return ret;
00974     }
00975     ret = cp;
00976     for (i = 0; i < len; i++) {
00977         unsigned long c = str[i];
00978 
00979         if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
00980             c &= 0xffff;
00981         }
00982         if (c < 0x80) {
00983             *cp++ = c;
00984         } else if (c < 0x800) {
00985             *cp++ = 0xc0 | ((c >> 6) & 0x1f);
00986             *cp++ = 0x80 | (c & 0x3f);
00987         } else if (c < 0x10000) {
00988             if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00989                 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
00990                 unsigned long c2 = str[i + 1] & 0xffff;
00991 
00992                 if (c2 >= 0xdc00 && c2 <= 0xdfff) {
00993                     c = (((c & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
00994                     *cp++ = 0xf0 | ((c >> 18) & 0x07);
00995                     *cp++ = 0x80 | ((c >> 12) & 0x3f);
00996                     *cp++ = 0x80 | ((c >> 6) & 0x3f);
00997                     *cp++ = 0x80 | (c & 0x3f);
00998                     ++i;
00999                     continue;
01000                 }
01001             }
01002             *cp++ = 0xe0 | ((c >> 12) & 0x0f);
01003             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01004             *cp++ = 0x80 | (c & 0x3f);
01005         } else if (c <= 0x10ffff) {
01006             *cp++ = 0xf0 | ((c >> 18) & 0x07);
01007             *cp++ = 0x80 | ((c >> 12) & 0x3f);
01008             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01009             *cp++ = 0x80 | (c & 0x3f);
01010         }
01011     }
01012     *cp = '\0';
01013     return ret;
01014 }
01015 
01016 #endif
01017 
01018 #ifdef WINTERFACE
01019 
01027 static char *
01028 uc_to_utf_c(SQLWCHAR *str, int len)
01029 {
01030     if (len != SQL_NTS) {
01031         len = len * sizeof (SQLWCHAR);
01032     }
01033     return uc_to_utf(str, len);
01034 }
01035 
01036 #endif
01037 
01038 #if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
01039 
01045 static void
01046 uc_free(void *str)
01047 {
01048     if (str) {
01049         xfree(str);
01050     }
01051 }
01052 
01053 #endif
01054 
01055 #if defined(_WIN32) || defined(_WIN64)
01056 
01064 static char *
01065 wmb_to_utf(char *str, int len)
01066 {
01067     WCHAR *wstr;
01068     OSVERSIONINFO ovi;
01069     int nchar, is2k, cp = CP_OEMCP;
01070 
01071     ovi.dwOSVersionInfoSize = sizeof (ovi);
01072     GetVersionEx(&ovi);
01073     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01074     if (AreFileApisANSI()) {
01075         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01076     }
01077     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01078     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01079     if (!wstr) {
01080         return NULL;
01081     }
01082     wstr[0] = 0;
01083     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01084     wstr[nchar] = 0;
01085     str = xmalloc((nchar + 1) * 7);
01086     if (!str) {
01087         xfree(wstr);
01088         return NULL;
01089     }
01090     str[0] = '\0';
01091     nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
01092     str[nchar] = '\0';
01093     xfree(wstr);
01094     return str;
01095 }
01096 
01097 #ifndef WINTERFACE
01098 
01106 static char *
01107 wmb_to_utf_c(char *str, int len)
01108 {
01109     if (len == SQL_NTS) {
01110         len = strlen(str);
01111     }
01112     return wmb_to_utf(str, len);
01113 }
01114 
01115 #endif
01116 
01124 static char *
01125 utf_to_wmb(char *str, int len)
01126 {
01127     WCHAR *wstr;
01128     OSVERSIONINFO ovi;
01129     int nchar, is2k, cp = CP_OEMCP;
01130 
01131     ovi.dwOSVersionInfoSize = sizeof (ovi);
01132     GetVersionEx(&ovi);
01133     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01134     if (AreFileApisANSI()) {
01135         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01136     }
01137     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
01138     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01139     if (!wstr) {
01140         return NULL;
01141     }
01142     wstr[0] = 0;
01143     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
01144     wstr[nchar] = 0;
01145     str = xmalloc((nchar + 1) * 7);
01146     if (!str) {
01147         xfree(wstr);
01148         return NULL;
01149     }
01150     str[0] = '\0';
01151     nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
01152     str[nchar] = '\0';
01153     xfree(wstr);
01154     return str;
01155 }
01156 
01157 #ifdef WINTERFACE
01158 
01166 static WCHAR *
01167 wmb_to_uc(char *str, int len)
01168 {
01169     WCHAR *wstr;
01170     OSVERSIONINFO ovi;
01171     int nchar, is2k, cp = CP_OEMCP;
01172 
01173     ovi.dwOSVersionInfoSize = sizeof (ovi);
01174     GetVersionEx(&ovi);
01175     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01176     if (AreFileApisANSI()) {
01177         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01178     }
01179     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01180     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01181     if (!wstr) {
01182         return NULL;
01183     }
01184     wstr[0] = 0;
01185     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01186     wstr[nchar] = 0;
01187     return wstr;
01188 }
01189 
01197 static char *
01198 uc_to_wmb(WCHAR *wstr, int len)
01199 {
01200     char *str;
01201     OSVERSIONINFO ovi;
01202     int nchar, is2k, cp = CP_OEMCP;
01203 
01204     ovi.dwOSVersionInfoSize = sizeof (ovi);
01205     GetVersionEx(&ovi);
01206     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01207     if (AreFileApisANSI()) {
01208         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01209     }
01210     nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
01211     str = xmalloc((nchar + 1) * 2);
01212     if (!str) {
01213         return NULL;
01214     }
01215     str[0] = '\0';
01216     nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
01217     str[nchar] = '\0';
01218     return str;
01219 }
01220 
01221 #endif /* WINTERFACE */
01222 
01223 #endif /* _WIN32 || _WIN64 */
01224 
01225 
01226 #ifdef USE_DLOPEN_FOR_GPPS
01227 
01228 #include <dlfcn.h>
01229 
01230 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
01231 
01232 /*
01233  * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
01234  * dlopen(), in theory this makes the driver independent from the
01235  * driver manager, i.e. the same driver binary can run with iODBC
01236  * and unixODBC.
01237  */
01238 
01239 static void
01240 drvgetgpps(DBC *d)
01241 {
01242     void *lib;
01243     int (*gpps)();
01244 
01245     lib = dlopen("libodbcinst.so.2", RTLD_LAZY);
01246     if (!lib) {
01247         lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
01248     }
01249     if (!lib) {
01250         lib = dlopen("libodbcinst.so", RTLD_LAZY);
01251     }
01252     if (!lib) {
01253         lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
01254     }
01255     if (!lib) {
01256         lib = dlopen("libiodbcinst.so", RTLD_LAZY);
01257     }
01258     if (lib) {
01259         gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
01260         if (!gpps) {
01261             dlclose(lib);
01262             return;
01263         }
01264         d->instlib = lib;
01265         d->gpps = gpps;
01266     }
01267 }
01268 
01269 static void
01270 drvrelgpps(DBC *d)
01271 {
01272     if (d->instlib) {
01273         dlclose(d->instlib);
01274         d->instlib = 0;
01275     }
01276 }
01277 
01278 static int
01279 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
01280         int bufsiz, char *fname)
01281 {
01282     if (d->gpps) {
01283         return d->gpps(sect, ent, def, buf, bufsiz, fname);
01284     }
01285     strncpy(buf, def, bufsiz);
01286     buf[bufsiz - 1] = '\0';
01287     return 1;
01288 }
01289 #else
01290 #include <odbcinst.h>
01291 #define drvgetgpps(d)
01292 #define drvrelgpps(d)
01293 #endif
01294 
01295 /*
01296  * Internal function to bind SQLite3 parameters.
01297  */
01298 
01299 static void
01300 s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
01301 {
01302     int i;
01303 
01304     if (stmt && p && nparams > 0) {
01305         for (i = 0; i < nparams; i++, p++) {
01306             switch (p->s3type) {
01307             default:
01308             case SQLITE_NULL:
01309                 sqlite3_bind_null(stmt, i + 1);
01310                 if (d->trace) {
01311                     fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
01312                     fflush(d->trace);
01313                 }
01314                 break;
01315             case SQLITE_TEXT:
01316                 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
01317                                   SQLITE_STATIC);
01318                 if (d->trace) {
01319                     fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
01320                             p->s3size, (char *) p->s3val);
01321                     fflush(d->trace);
01322                 }
01323                 break;
01324             case SQLITE_BLOB:
01325                 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
01326                                   SQLITE_STATIC);
01327                 if (d->trace) {
01328                     fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
01329                     fflush(d->trace);
01330                 }
01331                 break;
01332             case SQLITE_FLOAT:
01333                 sqlite3_bind_double(stmt, i + 1, p->s3dval);
01334                 if (d->trace) {
01335                     fprintf(d->trace, "-- parameter %d: %g\n",
01336                             i + 1, p->s3dval);
01337                     fflush(d->trace);
01338                 }
01339                 break;
01340             case SQLITE_INTEGER:
01341                 if (p->s3size > sizeof (int)) {
01342                     sqlite3_bind_int64(stmt, i + 1, p->s3lival);
01343                     if (d->trace) {
01344                         fprintf(d->trace,
01345 #ifdef _WIN32
01346                                 "-- parameter %d: %I64d\n",
01347 #else
01348                                 "-- parameter %d: %lld\n",
01349 #endif
01350                                 i + 1, p->s3lival);
01351                         fflush(d->trace);
01352                     }
01353                 } else {
01354                     sqlite3_bind_int(stmt, i + 1, p->s3ival);
01355                     if (d->trace) {
01356                         fprintf(d->trace, "-- parameter %d: %d\n",
01357                                 i + 1, p->s3ival);
01358                         fflush(d->trace);
01359                     }
01360                 }
01361                 break;
01362             }
01363         }
01364     }
01365 }
01366 
01374 typedef struct tblres {
01375     char **resarr;      
01376     char *errmsg;       
01377     sqlite3_stmt *stmt; 
01378     STMT *s;            
01379     int nalloc;         
01380     int nrow;           
01381     int ncol;           
01382     PTRDIFF_T ndata;    
01383     int rc;             
01384 } TBLRES;
01385 
01386 /*
01387  * Driver's version of sqlite3_get_table() and friends which are
01388  * capable of dealing with blobs.
01389  */
01390 
01391 static int
01392 drvgettable_row(TBLRES *t, int ncol, int rc)
01393 {
01394     int need;
01395     int i;
01396     char *p;
01397 
01398     if (t->nrow == 0 && rc == SQLITE_ROW) {
01399         need = ncol * 2;
01400     } else {
01401         need = ncol;
01402     }
01403     if (t->ndata + need >= t->nalloc) {
01404         char **resnew;
01405         int nalloc = t->nalloc * 2 + need + 1;
01406 
01407         if (nalloc < t->nalloc) {
01408             goto nomem;
01409         }
01410         resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
01411         if (!resnew) {
01412 nomem:
01413             t->rc = SQLITE_NOMEM;
01414             return 1;
01415         }
01416         t->nalloc = nalloc;
01417         t->resarr = resnew;
01418     }
01419     /* column names when first row */
01420     if (t->nrow == 0) {
01421         t->ncol = ncol;
01422         for (i = 0; i < ncol; i++) {
01423             p = (char *) sqlite3_column_name(t->stmt, i);
01424             if (p) {
01425                 char *q = xmalloc(strlen(p) + 1);
01426 
01427                 if (!q) {
01428                     goto nomem;
01429                 }
01430                 strcpy(q, p);
01431                 p = q;
01432             }
01433             t->resarr[t->ndata++] = p;
01434         }
01435         if (t->s && t->s->guessed_types) {
01436             int ncol2 = ncol;
01437 
01438             setupdyncols(t->s, t->stmt, &ncol2);
01439             t->s->guessed_types = 0;
01440             t->s->ncols = ncol;
01441         }
01442     } else if (t->ncol != ncol) {
01443         t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
01444                                     " more incompatible queries");
01445         t->rc = SQLITE_ERROR;
01446         return 1;
01447     }
01448     /* copy row data */
01449     if (rc == SQLITE_ROW) {
01450         for (i = 0; i < ncol; i++) {
01451             int coltype = sqlite3_column_type(t->stmt, i);
01452 
01453             p = NULL;
01454             if (coltype == SQLITE_BLOB) {
01455                 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
01456                 char *qp;
01457                 unsigned const char *bp;
01458 
01459                 bp = sqlite3_column_blob(t->stmt, i);
01460                 qp = xmalloc(nbytes * 2 + 4);
01461                 if (!qp) {
01462                     goto nomem;
01463                 }
01464                 p = qp;
01465                 *qp++ = 'X';
01466                 *qp++ = '\'';
01467                 for (k = 0; k < nbytes; k++) {
01468                     *qp++ = xdigits[(bp[k] >> 4)];
01469                     *qp++ = xdigits[(bp[k] & 0xF)];
01470                 }
01471                 *qp++ = '\'';
01472                 *qp = '\0';
01473 #ifdef _MSC_VER
01474             } else if (coltype == SQLITE_FLOAT) {
01475                 struct lconv *lc = 0;
01476                 double val = sqlite3_column_double(t->stmt, i);
01477                 char buffer[128];
01478 
01479                 /*
01480                  * This avoids floating point rounding
01481                  * and formatting problems of some SQLite
01482                  * versions in conjunction with MSVC 2010.
01483                  */
01484                 snprintf(buffer, sizeof (buffer), "%.15g", val);
01485                 lc = localeconv();
01486                 if (lc && lc->decimal_point && lc->decimal_point[0] &&
01487                     lc->decimal_point[0] != '.') {
01488                     p = strchr(buffer, lc->decimal_point[0]);
01489                     if (p) {
01490                         *p = '.';
01491                     }
01492                 }
01493                 p = xstrdup(buffer);
01494                 if (!p) {
01495                     goto nomem;
01496                 }
01497 #endif
01498             } else if (coltype != SQLITE_NULL) {
01499                 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
01500                 if (!p) {
01501                     goto nomem;
01502                 }
01503             }
01504             t->resarr[t->ndata++] = p;
01505         }
01506         t->nrow++;
01507     }
01508     return 0;
01509 }
01510 
01511 static int
01512 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
01513             int *ncolp, char **errp, int nparam, BINDPARM *p)
01514 {
01515     DBC *d = (DBC *) s->dbc;
01516     int rc = SQLITE_OK, keep = sql == NULL;
01517     TBLRES tres;
01518     const char *sqlleft = 0;
01519     int nretry = 0, haveerr = 0;
01520 
01521     if (!resp) {
01522         return SQLITE_ERROR;
01523     }
01524     *resp = NULL;
01525     if (nrowp) {
01526         *nrowp = 0;
01527     }
01528     if (ncolp) {
01529         *ncolp = 0;
01530     }
01531     tres.errmsg = NULL;
01532     tres.nrow = 0;
01533     tres.ncol = 0;
01534     tres.ndata = 1;
01535     tres.nalloc = 20;
01536     tres.rc = SQLITE_OK;
01537     tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
01538     tres.stmt = NULL;
01539     tres.s = s;
01540     if (!tres.resarr) {
01541         return SQLITE_NOMEM;
01542     }
01543     tres.resarr[0] = 0;
01544     if (sql == NULL) {
01545         tres.stmt = s->s3stmt;
01546         if (tres.stmt == NULL) {
01547             return SQLITE_NOMEM;
01548         }
01549         goto retrieve;
01550     }
01551     while (sql && *sql && (rc == SQLITE_OK ||
01552                            (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
01553         int ncol;
01554 
01555         tres.stmt = NULL;
01556 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
01557         dbtraceapi(d, "sqlite3_prepare_v2", sql);
01558         rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01559 #else
01560         dbtraceapi(d, "sqlite3_prepare", sql);
01561         rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01562 #endif
01563         if (rc != SQLITE_OK) {
01564             if (tres.stmt) {
01565                 dbtraceapi(d, "sqlite3_finalize", 0);
01566                 sqlite3_finalize(tres.stmt);
01567                 tres.stmt = NULL;
01568             }
01569             continue;
01570         }
01571         if (!tres.stmt) {
01572             /* this happens for a comment or white-space */
01573             sql = sqlleft;
01574             continue;
01575         }
01576 retrieve:
01577         if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
01578             if (errp) {
01579                 *errp =
01580                     sqlite3_mprintf("%s", "parameter marker count incorrect");
01581             }
01582             haveerr = 1;
01583             rc = SQLITE_ERROR;
01584             goto tbldone;
01585         }
01586         s3bind(d, tres.stmt, nparam, p);
01587         ncol = sqlite3_column_count(tres.stmt);
01588         while (1) {
01589             if (s->max_rows && tres.nrow >= s->max_rows) {
01590                 rc = SQLITE_OK;
01591                 break;
01592             }
01593             rc = sqlite3_step(tres.stmt);
01594             if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
01595                 if (drvgettable_row(&tres, ncol, rc)) {
01596                     rc = SQLITE_ABORT;
01597                     goto tbldone;
01598                 }
01599             }
01600             if (rc != SQLITE_ROW) {
01601                 if (keep) {
01602                     dbtraceapi(d, "sqlite3_reset", 0);
01603                     rc = sqlite3_reset(tres.stmt);
01604                     s->s3stmt_noreset = 1;
01605                 } else {
01606                     dbtraceapi(d, "sqlite3_finalize", 0);
01607                     rc = sqlite3_finalize(tres.stmt);
01608                 }
01609                 tres.stmt = 0;
01610                 if (rc != SQLITE_SCHEMA) {
01611                     nretry = 0;
01612                     sql = sqlleft;
01613                     while (sql && ISSPACE(*sql)) {
01614                         sql++;
01615                     }
01616                 }
01617                 if (rc == SQLITE_DONE) {
01618                     rc = SQLITE_OK;
01619                 }
01620                 break;
01621             }
01622         }
01623     }
01624 tbldone:
01625     if (tres.stmt) {
01626         if (keep) {
01627             if (!s->s3stmt_noreset) {
01628                 dbtraceapi(d, "sqlite3_reset", 0);
01629                 sqlite3_reset(tres.stmt);
01630                 s->s3stmt_noreset = 1;
01631             }
01632         } else {
01633             dbtraceapi(d, "sqlite3_finalize", 0);
01634             sqlite3_finalize(tres.stmt);
01635         }
01636     }
01637     if (haveerr) {
01638         /* message already in *errp if any */
01639     } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
01640         *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
01641     } else if (errp) {
01642         *errp = NULL;
01643     }
01644     if (tres.resarr) {
01645         tres.resarr[0] = (char *) (tres.ndata - 1);
01646     }
01647     if (rc == SQLITE_ABORT) {
01648         freerows(&tres.resarr[1]);
01649         if (tres.errmsg) {
01650             if (errp) {
01651                 if (*errp) {
01652                     sqlite3_free(*errp);
01653                 }
01654                 *errp = tres.errmsg;
01655             } else {
01656                 sqlite3_free(tres.errmsg);
01657             }
01658         }
01659         return tres.rc;
01660     }
01661     sqlite3_free(tres.errmsg);
01662     if (rc != SQLITE_OK) {
01663         freerows(&tres.resarr[1]);
01664         return rc;
01665     }
01666     *resp = &tres.resarr[1];
01667     if (ncolp) {
01668         *ncolp = tres.ncol;
01669     }
01670     if (nrowp) {
01671         *nrowp = tres.nrow;
01672     }
01673     return rc;
01674 }
01675 
01684 #if defined(__GNUC__) && (__GNUC__ >= 2)
01685 static void setstatd(DBC *, int, char *, char *, ...)
01686     __attribute__((format (printf, 3, 5)));
01687 #endif
01688 
01689 static void
01690 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
01691 {
01692     va_list ap;
01693 
01694     if (!d) {
01695         return;
01696     }
01697     d->naterr = naterr;
01698     d->logmsg[0] = '\0';
01699     if (msg) {
01700         int count;
01701 
01702         va_start(ap, st);
01703         count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
01704         va_end(ap);
01705         if (count < 0) {
01706             d->logmsg[sizeof (d->logmsg) - 1] = '\0';
01707         }
01708     }
01709     if (!st) {
01710         st = "?????";
01711     }
01712     strncpy(d->sqlstate, st, 5);
01713     d->sqlstate[5] = '\0';
01714 }
01715 
01724 #if defined(__GNUC__) && (__GNUC__ >= 2)
01725 static void setstat(STMT *, int, char *, char *, ...)
01726     __attribute__((format (printf, 3, 5)));
01727 #endif
01728 
01729 static void
01730 setstat(STMT *s, int naterr, char *msg, char *st, ...)
01731 {
01732     va_list ap;
01733 
01734     if (!s) {
01735         return;
01736     }
01737     s->naterr = naterr;
01738     s->logmsg[0] = '\0';
01739     if (msg) {
01740         int count;
01741 
01742         va_start(ap, st);
01743         count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
01744         va_end(ap);
01745         if (count < 0) {
01746             s->logmsg[sizeof (s->logmsg) - 1] = '\0';
01747         }
01748     }
01749     if (!st) {
01750         st = "?????";
01751     }
01752     strncpy(s->sqlstate, st, 5);
01753     s->sqlstate[5] = '\0';
01754 }
01755 
01762 static SQLRETURN
01763 drvunimpldbc(HDBC dbc)
01764 {
01765     DBC *d;
01766 
01767     if (dbc == SQL_NULL_HDBC) {
01768         return SQL_INVALID_HANDLE;
01769     }
01770     d = (DBC *) dbc;
01771     setstatd(d, -1, "not supported", "IM001");
01772     return SQL_ERROR;
01773 }
01774 
01781 static SQLRETURN
01782 drvunimplstmt(HSTMT stmt)
01783 {
01784     STMT *s;
01785 
01786     if (stmt == SQL_NULL_HSTMT) {
01787         return SQL_INVALID_HANDLE;
01788     }
01789     s = (STMT *) stmt;
01790     setstat(s, -1, "not supported", "IM001");
01791     return SQL_ERROR;
01792 }
01793 
01799 static void
01800 freep(void *x)
01801 {
01802     if (x && ((char **) x)[0]) {
01803         xfree(((char **) x)[0]);
01804         ((char **) x)[0] = NULL;
01805     }
01806 }
01807 
01814 static SQLRETURN
01815 nomem(STMT *s)
01816 {
01817     setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
01818     return SQL_ERROR;
01819 }
01820 
01827 static SQLRETURN
01828 noconn(STMT *s)
01829 {
01830     setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
01831     return SQL_ERROR;
01832 }
01833 
01841 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
01842 
01843 static double
01844 ln_strtod(const char *data, char **endp)
01845 {
01846     struct lconv *lc = 0;
01847     char buf[128], *p, *end;
01848     double value;
01849 
01850     lc = localeconv();
01851     if (lc && lc->decimal_point && lc->decimal_point[0] &&
01852         lc->decimal_point[0] != '.') {
01853         strncpy(buf, data, sizeof (buf) - 1);
01854         buf[sizeof (buf) - 1] = '\0';
01855         p = strchr(buf, '.');
01856         if (p) {
01857             *p = lc->decimal_point[0];
01858         }
01859         p = buf;
01860     } else {
01861         p = (char *) data;
01862     }
01863     value = strtod(p, &end);
01864     end = (char *) data + (end - p);
01865     if (endp) {
01866         *endp = end;
01867     }
01868     return value;
01869 }
01870 
01871 #else
01872 
01873 #define ln_strtod(A,B) strtod(A,B)
01874 
01875 #endif
01876 
01882 static char *
01883 unquote(char *str)
01884 {
01885     if (str) {
01886         int len = strlen(str);
01887 
01888         if (len > 1) {
01889             int end = len - 1;
01890 
01891             if ((str[0] == '\'' && str[end] == '\'') ||
01892                 (str[0] == '"' && str[end] == '"') ||
01893                 (str[0] == '[' && str[end] == ']')) {
01894                 memmove(str, str + 1, end - 1);
01895                 str[end - 1] = '\0';
01896             }
01897         }
01898     }
01899     return str;
01900 }
01901 
01909 static int
01910 unescpat(char *str)
01911 {
01912     char *p, *q;
01913     int count = 0;
01914 
01915     p = str;
01916     while ((q = strchr(p, '_')) != NULL) {
01917         if (q == str || q[-1] != '\\') {
01918             count++;
01919         }
01920         p = q + 1;
01921     }
01922     p = str;
01923     while ((q = strchr(p, '%')) != NULL) {
01924         if (q == str || q[-1] != '\\') {
01925             count++;
01926         }
01927         p = q + 1;
01928     }
01929     p = str;
01930     while ((q = strchr(p, '\\')) != NULL) {
01931         if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
01932             memmove(q, q + 1, strlen(q));
01933         }
01934         p = q + 1;
01935     }
01936     return count;
01937 }
01938 
01947 static int
01948 namematch(char *str, char *pat, int esc)
01949 {
01950     int cp, ch;
01951 
01952     while (1) {
01953         cp = TOLOWER(*pat);
01954         if (cp == '\0') {
01955             if (*str != '\0') {
01956                 goto nomatch;
01957             }
01958             break;
01959         }
01960         if (*str == '\0' && cp != '%') {
01961             goto nomatch;
01962         }
01963         if (cp == '%') {
01964             while (*pat == '%') {
01965                 ++pat;
01966             }
01967             cp = TOLOWER(*pat);
01968             if (cp == '\0') {
01969                 break;
01970             }
01971             while (1) {
01972                 if (cp != '_' && cp != '\\') {
01973                     while (*str) {
01974                         ch = TOLOWER(*str);
01975                         if (ch == cp) {
01976                             break;
01977                         }
01978                         ++str;
01979                     }
01980                 }
01981                 if (namematch(str, pat, esc)) {
01982                     goto match;
01983                 }
01984                 if (*str == '\0') {
01985                     goto nomatch;
01986                 }
01987                 ch = TOLOWER(*str);
01988                 ++str;
01989             }
01990         }
01991         if (cp == '_') {
01992             pat++;
01993             str++;
01994             continue;
01995         }
01996         if (esc && cp == '\\' &&
01997             (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
01998             ++pat;
01999             cp = TOLOWER(*pat);
02000         }
02001         ch = TOLOWER(*str++);
02002         ++pat;
02003         if (ch != cp) {
02004             goto nomatch;
02005         }
02006     }
02007 match:
02008     return 1;
02009 nomatch:
02010     return 0;
02011 }
02012 
02020 static int
02021 busy_handler(void *udata, int count)
02022 {
02023     DBC *d = (DBC *) udata;
02024     long t1;
02025     int ret = 0;
02026 #if !defined(_WIN32) && !defined(_WIN64)
02027     struct timeval tv;
02028 #ifdef HAVE_NANOSLEEP
02029     struct timespec ts;
02030 #endif
02031 #endif
02032 
02033     if (d->busyint) {
02034         d->busyint = 0;
02035         return ret;
02036     }
02037     if (d->timeout <= 0) {
02038         return ret;
02039     }
02040     if (count <= 1) {
02041 #if defined(_WIN32) || defined(_WIN64)
02042         d->t0 = GetTickCount();
02043 #else
02044         gettimeofday(&tv, NULL);
02045         d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02046 #endif
02047     }
02048 #if defined(_WIN32) || defined(_WIN64)
02049     t1 = GetTickCount();
02050 #else
02051     gettimeofday(&tv, NULL);
02052     t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02053 #endif
02054     if (t1 - d->t0 > d->timeout) {
02055         goto done;
02056     }
02057 #if defined(_WIN32) || defined(_WIN64)
02058     Sleep(10);
02059 #else
02060 #ifdef HAVE_NANOSLEEP
02061     ts.tv_sec = 0;
02062     ts.tv_nsec = 10000000;
02063     do {
02064         ret = nanosleep(&ts, &ts);
02065         if (ret < 0 && errno != EINTR) {
02066             ret = 0;
02067         }
02068     } while (ret);
02069 #else
02070 #ifdef HAVE_USLEEP
02071     usleep(10000);
02072 #else
02073     tv.tv_sec = 0;
02074     tv.tv_usec = 10000;
02075     select(0, NULL, NULL, NULL, &tv);
02076 #endif
02077 #endif
02078 #endif
02079     ret = 1;
02080 done:
02081     return ret;
02082 }
02083 
02095 static int
02096 setsqliteopts(sqlite3 *x, DBC *d)
02097 {
02098     int count = 0, step = 0, max, rc = SQLITE_ERROR;
02099 
02100 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
02101     max = d->longnames ? 3 : 1;
02102 #else
02103     max = 3;
02104 #endif
02105     if (d->shortnames) {
02106         max = 3;
02107     }
02108     while (step < max) {
02109         if (step < 1) {
02110             rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
02111                               NULL, NULL, NULL);
02112             if (rc == SQLITE_OK) {
02113                 rc = sqlite3_exec(x, d->fksupport ?
02114                                   "PRAGMA foreign_keys = on;" :
02115                                   "PRAGMA foreign_keys = off;",
02116                                   NULL, NULL, NULL);
02117             }
02118         } else if (step < 2) {
02119             rc = sqlite3_exec(x, d->shortnames ?
02120                               "PRAGMA full_column_names = off;" :
02121                               "PRAGMA full_column_names = on;",
02122                               NULL, NULL, NULL);
02123         } else if (step < 3) {
02124             rc = sqlite3_exec(x, d->shortnames ?
02125                               "PRAGMA short_column_names = on;" :
02126                               "PRAGMA short_column_names = off;",
02127                               NULL, NULL, NULL);
02128         }
02129         if (rc != SQLITE_OK) {
02130             if (rc != SQLITE_BUSY ||
02131                 !busy_handler((void *) d, ++count)) {
02132                 return rc;
02133             }
02134             continue;
02135         }
02136         count = 0;
02137         ++step;
02138     }
02139     sqlite3_busy_handler(x, busy_handler, (void *) d);
02140     return SQLITE_OK;
02141 }
02142 
02152 static void
02153 freerows(char **rowp)
02154 {
02155     PTRDIFF_T size, i;
02156 
02157     if (!rowp) {
02158         return;
02159     }
02160     --rowp;
02161     size = (PTRDIFF_T) rowp[0];
02162     for (i = 1; i <= size; i++) {
02163         freep(&rowp[i]);
02164     }
02165     freep(&rowp);
02166 }
02167 
02178 static int
02179 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
02180            int dobigint)
02181 {
02182     char *p, *q;
02183     int testsign = 0, result;
02184 
02185 #ifdef WINTERFACE
02186     result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
02187 #else
02188     result = SQL_VARCHAR;
02189 #endif
02190     if (!typename) {
02191         return result;
02192     }
02193     q = p = xmalloc(strlen(typename) + 1);
02194     if (!p) {
02195         return result;
02196     }
02197     strcpy(p, typename);
02198     while (*q) {
02199         *q = TOLOWER(*q);
02200         ++q;
02201     }
02202     if (strncmp(p, "inter", 5) == 0) {
02203     } else if (strncmp(p, "int", 3) == 0 ||
02204         strncmp(p, "mediumint", 9) == 0) {
02205         testsign = 1;
02206         result = SQL_INTEGER;
02207     } else if (strncmp(p, "numeric", 7) == 0) {
02208         result = SQL_DOUBLE;
02209     } else if (strncmp(p, "tinyint", 7) == 0) {
02210         testsign = 1;
02211         result = SQL_TINYINT;
02212     } else if (strncmp(p, "smallint", 8) == 0) {
02213         testsign = 1;
02214         result = SQL_SMALLINT;
02215     } else if (strncmp(p, "float", 5) == 0) {
02216         result = SQL_DOUBLE;
02217     } else if (strncmp(p, "double", 6) == 0 ||
02218         strncmp(p, "real", 4) == 0) {
02219         result = SQL_DOUBLE;
02220     } else if (strncmp(p, "timestamp", 9) == 0) {
02221 #ifdef SQL_TYPE_TIMESTAMP
02222         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02223 #else
02224         result = SQL_TIMESTAMP;
02225 #endif
02226     } else if (strncmp(p, "datetime", 8) == 0) {
02227 #ifdef SQL_TYPE_TIMESTAMP
02228         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02229 #else
02230         result = SQL_TIMESTAMP;
02231 #endif
02232     } else if (strncmp(p, "time", 4) == 0) {
02233 #ifdef SQL_TYPE_TIME
02234         result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
02235 #else
02236         result = SQL_TIME;
02237 #endif
02238     } else if (strncmp(p, "date", 4) == 0) {
02239 #ifdef SQL_TYPE_DATE
02240         result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
02241 #else
02242         result = SQL_DATE;
02243 #endif
02244 #ifdef SQL_LONGVARCHAR
02245     } else if (strncmp(p, "text", 4) == 0 ||
02246                strncmp(p, "memo", 4) == 0 ||
02247                strncmp(p, "longvarchar", 11) == 0) {
02248 #ifdef WINTERFACE
02249         result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
02250 #else
02251         result = SQL_LONGVARCHAR;
02252 #endif
02253 #ifdef WINTERFACE
02254     } else if (strncmp(p, "wtext", 5) == 0 ||
02255                strncmp(p, "wvarchar", 8) == 0 ||
02256                strncmp(p, "longwvarchar", 12) == 0) {
02257         result = SQL_WLONGVARCHAR;
02258 #endif
02259 #endif
02260 #ifdef SQL_BIT
02261     } else if (strncmp(p, "bool", 4) == 0 ||
02262                strncmp(p, "bit", 3) == 0) {
02263         result = SQL_BIT;
02264 #endif
02265 #ifdef SQL_BIGINT
02266     } else if (strncmp(p, "bigint", 6) == 0) {
02267         testsign = 1;
02268         result = SQL_BIGINT;
02269 #endif
02270     } else if (strncmp(p, "blob", 4) == 0) {
02271         result = SQL_BINARY;
02272     } else if (strncmp(p, "varbinary", 9) == 0) {
02273         result = SQL_VARBINARY;
02274     } else if (strncmp(p, "longvarbinary", 13) == 0) {
02275         result = SQL_LONGVARBINARY;
02276     }
02277     if (nosign) {
02278         if (testsign) {
02279             *nosign = strstr(p, "unsigned") != NULL;
02280         } else {
02281             *nosign = 1;
02282         }
02283     }
02284 #ifdef SQL_BIGINT
02285     if (dobigint && result == SQL_INTEGER) {
02286         result = SQL_BIGINT;
02287     }
02288 #endif
02289     xfree(p);
02290     return result;
02291 }
02292 
02302 static void
02303 getmd(const char *typename, int sqltype, int *mp, int *dp)
02304 {
02305     int m = 0, d = 0;
02306 
02307     switch (sqltype) {
02308     case SQL_INTEGER:       m = 10; d = 9; break;
02309     case SQL_TINYINT:       m = 4; d = 3; break;
02310     case SQL_SMALLINT:      m = 6; d = 5; break;
02311     case SQL_FLOAT:         m = 25; d = 24; break;
02312     case SQL_DOUBLE:        m = 54; d = 53; break;
02313     case SQL_VARCHAR:       m = 255; d = 0; break;
02314 #ifdef WINTERFACE
02315 #ifdef SQL_WVARCHAR
02316     case SQL_WVARCHAR:      m = 255; d = 0; break;
02317 #endif
02318 #endif
02319 #ifdef SQL_TYPE_DATE
02320     case SQL_TYPE_DATE:
02321 #endif
02322     case SQL_DATE:          m = 10; d = 0; break;
02323 #ifdef SQL_TYPE_TIME
02324     case SQL_TYPE_TIME:
02325 #endif
02326     case SQL_TIME:          m = 8; d = 0; break;
02327 #ifdef SQL_TYPE_TIMESTAMP
02328     case SQL_TYPE_TIMESTAMP:
02329 #endif
02330     case SQL_TIMESTAMP:     m = 32; d = 3; break;
02331 #ifdef SQL_LONGVARCHAR
02332     case SQL_LONGVARCHAR :  m = 65536; d = 0; break;
02333 #endif
02334 #ifdef WINTERFACE
02335 #ifdef SQL_WLONGVARCHAR
02336     case SQL_WLONGVARCHAR:  m = 65536; d = 0; break;
02337 #endif
02338 #endif
02339     case SQL_BINARY:
02340     case SQL_VARBINARY:     m = 255; d = 0; break;
02341     case SQL_LONGVARBINARY: m = 65536; d = 0; break;
02342 #ifdef SQL_BIGINT
02343     case SQL_BIGINT:        m = 20; d = 19; break;
02344 #endif
02345 #ifdef SQL_BIT
02346     case SQL_BIT:           m = 1; d = 1; break;
02347 #endif
02348     }
02349     if (m && typename) {
02350         int mm, dd;
02351         char clbr[4];
02352 
02353         if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
02354             m = mm;
02355             d = dd;
02356         } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
02357             if (sqltype == SQL_TIMESTAMP) {
02358                 d = mm;
02359             }
02360 #ifdef SQL_TYPE_TIMESTAMP
02361             else if (sqltype == SQL_TYPE_TIMESTAMP) {
02362                 d = mm;
02363             }
02364 #endif
02365             else {
02366                 m = d = mm;
02367             }
02368         }
02369     }
02370     if (mp) {
02371         *mp = m;
02372     }
02373     if (dp) {
02374         *dp = d;
02375     }
02376 }
02377 
02387 static int
02388 mapdeftype(int type, int stype, int nosign, int nowchar)
02389 {
02390     if (type == SQL_C_DEFAULT) {
02391         switch (stype) {
02392         case SQL_INTEGER:
02393             type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
02394             break;
02395         case SQL_TINYINT:
02396             type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
02397             break;
02398         case SQL_SMALLINT:
02399             type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
02400             break;
02401         case SQL_FLOAT:
02402             type = SQL_C_FLOAT;
02403             break;
02404         case SQL_DOUBLE:
02405             type = SQL_C_DOUBLE;
02406             break;
02407         case SQL_TIMESTAMP:
02408             type = SQL_C_TIMESTAMP;
02409             break;
02410         case SQL_TIME:
02411             type = SQL_C_TIME;
02412             break;
02413         case SQL_DATE:
02414             type = SQL_C_DATE;
02415             break;
02416 #ifdef SQL_C_TYPE_TIMESTAMP
02417         case SQL_TYPE_TIMESTAMP:
02418             type = SQL_C_TYPE_TIMESTAMP;
02419             break;
02420 #endif
02421 #ifdef SQL_C_TYPE_TIME
02422         case SQL_TYPE_TIME:
02423             type = SQL_C_TYPE_TIME;
02424             break;
02425 #endif
02426 #ifdef SQL_C_TYPE_DATE
02427         case SQL_TYPE_DATE:
02428             type = SQL_C_TYPE_DATE;
02429             break;
02430 #endif
02431 #ifdef WINTERFACE
02432         case SQL_WVARCHAR:
02433         case SQL_WCHAR:
02434 #ifdef SQL_WLONGVARCHAR
02435         case SQL_WLONGVARCHAR:
02436 #endif
02437             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02438             break;
02439 #endif
02440         case SQL_BINARY:
02441         case SQL_VARBINARY:
02442         case SQL_LONGVARBINARY:
02443             type = SQL_C_BINARY;
02444             break;
02445 #ifdef SQL_BIT
02446         case SQL_BIT:
02447             type = SQL_C_BIT;
02448             break;
02449 #endif
02450 #ifdef SQL_BIGINT
02451         case SQL_BIGINT:
02452             type = SQL_C_CHAR;
02453             break;
02454 #endif
02455         default:
02456 #ifdef WINTERFACE
02457             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02458 #else
02459             type = SQL_C_CHAR;
02460 #endif
02461             break;
02462         }
02463     }
02464     return type;
02465 }
02466 
02473 static int
02474 checkddl(char *sql)
02475 {
02476     int isddl = 0;
02477 
02478     while (*sql && ISSPACE(*sql)) {
02479         ++sql;
02480     }
02481     if (*sql && *sql != ';') {
02482         int i, size;
02483         static const struct {
02484             int len;
02485             const char *str;
02486         } ddlstr[] = {
02487             { 5, "alter" },
02488             { 7, "analyze" },
02489             { 6, "attach" },
02490             { 5, "begin" },
02491             { 6, "commit" },
02492             { 6, "create" },
02493             { 6, "detach" },
02494             { 4, "drop" },
02495             { 3, "end" },
02496             { 7, "reindex" },
02497             { 7, "release" },
02498             { 8, "rollback" },
02499             { 9, "savepoint" },
02500             { 6, "vacuum" }
02501         };
02502 
02503         size = strlen(sql);
02504         for (i = 0; i < array_size(ddlstr); i++) {
02505             if (size >= ddlstr[i].len &&
02506                 strncasecmp(sql, ddlstr[i].str, ddlstr[i].len) == 0) {
02507                 isddl = 1;
02508                 break;
02509             }
02510         }
02511     }
02512     return isddl;
02513 }
02514 
02526 static char *
02527 fixupsql(char *sql, int sqlLen, int cte, int *nparam, int *isselect,
02528          char **errmsg)
02529 {
02530     char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
02531     int np = 0, isddl = -1, size;
02532 
02533     if (errmsg) {
02534         *errmsg = NULL;
02535     }
02536     if (sqlLen != SQL_NTS) {
02537         qz = q = xmalloc(sqlLen + 1);
02538         if (!qz) {
02539             return NULL;
02540         }
02541         memcpy(q, sql, sqlLen);
02542         q[sqlLen] = '\0';
02543         size = sqlLen * 4;
02544     } else {
02545         size = strlen(sql) * 4;
02546     }
02547     size += sizeof (char *) - 1;
02548     size &= ~(sizeof (char *) - 1);
02549     p = xmalloc(size);
02550     if (!p) {
02551 errout:
02552         freep(&qz);
02553         return NULL;
02554     }
02555     memset(p, 0, size);
02556     out = p;
02557     while (*q) {
02558         switch (*q) {
02559         case '\'':
02560         case '\"':
02561             if (q == inq) {
02562                 inq = NULL;
02563             } else if (!inq) {
02564                 inq = q + 1;
02565 
02566                 while (*inq) {
02567                     if (*inq == *q) {
02568                         if (inq[1] == *q) {
02569                             inq++;
02570                         } else {
02571                             break;
02572                         }
02573                     }
02574                     inq++;
02575                 }
02576             }
02577             *p++ = *q;
02578             break;
02579         case '-':
02580             *p++ = *q;
02581             if (!inq && q[1] == '-') {
02582                 ++q;
02583                 while (*q) {
02584                     *p++ = *q++;
02585                     if (*q == '\n') {
02586                         break;
02587                     }
02588                 }
02589             }
02590             break;
02591         case '?':
02592             *p++ = *q;
02593             if (!inq) {
02594                 np++;
02595             }
02596             break;
02597         case ';':
02598             if (!inq) {
02599                 if (isddl < 0) {
02600                     isddl = checkddl(out);
02601                 }
02602                 if (isddl == 0) {
02603                     char *qq = q;
02604 
02605                     do {
02606                         ++qq;
02607                     } while (*qq && ISSPACE(*qq));
02608                     if (*qq && *qq != ';') {
02609                         freep(&out);
02610                         if (errmsg) {
02611                             *errmsg = "only one SQL statement allowed";
02612                         }
02613                         goto errout;
02614                     }
02615                 }
02616             }
02617             *p++ = *q;
02618             break;
02619         case '{':
02620             /*
02621              * Deal with escape sequences:
02622              * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
02623              * {oj ...}, {fn ...} etc.
02624              */
02625             if (!inq) {
02626                 int ojfn = 0, brc = 0;
02627                 char *inq2 = NULL, *end = q + 1, *start;
02628 
02629                 while (*end && ISSPACE(*end)) {
02630                     ++end;
02631                 }
02632                 if (*end != 'd' && *end != 'D' &&
02633                     *end != 't' && *end != 'T') {
02634                     ojfn = 1;
02635                 }
02636                 start = end;
02637                 while (*end) {
02638                     if (inq2 && *end == *inq2) {
02639                         inq2 = NULL;
02640                     } else if (inq2 == NULL && *end == '{') {
02641                         char *nerr = 0, *nsql;
02642 
02643                         nsql = fixupsql(end, SQL_NTS, cte, 0, 0, &nerr);
02644                         if (nsql && !nerr) {
02645                             strcpy(end, nsql);
02646                         } else {
02647                             brc++;
02648                         }
02649                         freep(&nsql);
02650                     } else if (inq2 == NULL && *end == '}') {
02651                         if (brc-- <= 0) {
02652                             break;
02653                         }
02654                     } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
02655                         inq2 = end;
02656                     } else if (inq2 == NULL && *end == '?') {
02657                         np++;
02658                     }
02659                     ++end;
02660                 }
02661                 if (*end == '}') {
02662                     char *end2 = end - 1;
02663 
02664                     if (ojfn) {
02665                         while (start < end) {
02666                             if (ISSPACE(*start)) {
02667                                 break;
02668                             }
02669                             ++start;
02670                         }
02671                         while (start < end) {
02672                             *p++ = *start;
02673                             ++start;
02674                         }
02675                         q = end;
02676                         break;
02677                     } else {
02678                         while (start < end2 && *start != '\'') {
02679                             ++start;
02680                         }
02681                         while (end2 > start && *end2 != '\'') {
02682                             --end2;
02683                         }
02684                         if (*start == '\'' && *end2 == '\'') {
02685                             while (start <= end2) {
02686                                 *p++ = *start;
02687                                 ++start;
02688                             }
02689                             q = end;
02690                             break;
02691                         }
02692                     }
02693                 }
02694             }
02695             /* FALL THROUGH */
02696         default:
02697             *p++ = *q;
02698         }
02699         ++q;
02700     }
02701     freep(&qz);
02702     *p = '\0';
02703     if (nparam) {
02704         *nparam = np;
02705     }
02706     if (isselect) {
02707         if (isddl < 0) {
02708             isddl = checkddl(out);
02709         }
02710         if (isddl > 0) {
02711             *isselect = 2;
02712         } else {
02713             int incom = 0;
02714 
02715             p = out;
02716             while (*p) {
02717                 switch (*p) {
02718                 case '-':
02719                     if (!incom && p[1] == '-') {
02720                         incom = -1;
02721                     }
02722                     break;
02723                 case '\n':
02724                     if (incom < 0) {
02725                         incom = 0;
02726                     }
02727                     break;
02728                 case '/':
02729                     if (incom > 0 && p[-1] == '*') {
02730                         incom = 0;
02731                         p++;
02732                         continue;
02733                     } else if (!incom && p[1] == '*') {
02734                         incom = 1;
02735                     }
02736                     break;
02737                 }
02738                 if (!incom && !ISSPACE(*p)) {
02739                     break;
02740                 }
02741                 p++;
02742             }
02743             size = strlen(p);
02744             if (size >= 6 &&
02745                 (strncasecmp(p, "select", 6) == 0 ||
02746                  strncasecmp(p, "pragma", 6) == 0)) {
02747                 *isselect = 1;
02748             } else if (cte && size >= 4 && strncasecmp(p, "with", 4) == 0) {
02749                 *isselect = 1;
02750             } else if (size >= 7 && strncasecmp(p, "explain", 7) == 0) {
02751                 *isselect = 1;
02752             } else {
02753                 *isselect = 0;
02754             }
02755         }
02756     }
02757     return out;
02758 }
02759 
02765 static void
02766 replilike(char *sql)
02767 {
02768     char *q = sql, *inq = NULL;
02769 
02770     while (*q) {
02771         switch (*q) {
02772         case '\'':
02773         case '\"':
02774             if (q == inq) {
02775                 inq = NULL;
02776             } else if (!inq) {
02777                 inq = q + 1;
02778 
02779                 while (*inq) {
02780                     if (*inq == *q) {
02781                         if (inq[1] == *q) {
02782                             inq++;
02783                         } else {
02784                             break;
02785                         }
02786                     }
02787                     inq++;
02788                 }
02789             }
02790             break;
02791         case '-':
02792             if (!inq && q[1] == '-') {
02793                 ++q;
02794                 while (*q) {
02795                     if (*q == '\n') {
02796                         break;
02797                     }
02798                 }
02799             }
02800             break;
02801         default:
02802             if (!inq && ISSPACE(*q) && q[1]) {
02803                 if (strncasecmp(q + 1, "ilike", 5) == 0) {
02804                     if ((q[2] != '\0') && (q[3] != '\0') &&
02805                         (q[4] != '\0') && (q[5] != '\0') &&
02806                         ((q[6] == '\0') || ISSPACE(q[6]))) {
02807                         q++;
02808                         memmove(q, q + 1, strlen(q));
02809                         q += 3;
02810                     }
02811                 }
02812             }
02813             break;
02814         }
02815         ++q;
02816     }
02817 }
02818 
02827 static int
02828 findcol(char **cols, int ncols, char *name)
02829 {
02830     int i;
02831 
02832     if (cols) {
02833         for (i = 0; i < ncols; i++) {
02834             if (strcmp(cols[i], name) == 0) {
02835                 return i;
02836             }
02837         }
02838     }
02839     return -1;
02840 }
02841 
02858 static void
02859 fixupdyncols(STMT *s, DBC *d)
02860 {
02861     int i, k;
02862 #ifndef FULL_METADATA
02863     int pk, nn, t, r, nrows, ncols;
02864     char **rowp, *flagp, flags[128];
02865 #endif
02866 
02867     if (!s->dyncols) {
02868         return;
02869     }
02870     /* fixup labels */
02871     if (!s->longnames) {
02872         if (s->dcols > 1) {
02873             char *table = s->dyncols[0].table;
02874 
02875             for (i = 1; table[0] && i < s->dcols; i++) {
02876                 if (strcmp(s->dyncols[i].table, table)) {
02877                     break;
02878                 }
02879             }
02880             if (i >= s->dcols) {
02881                 for (i = 0; i < s->dcols; i++) {
02882                     s->dyncols[i].label = s->dyncols[i].column;
02883                 }
02884             }
02885         } else if (s->dcols == 1) {
02886             s->dyncols[0].label = s->dyncols[0].column;
02887         }
02888     }
02889     for (i = 0; i < s->dcols; i++) {
02890         s->dyncols[i].type =
02891             mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
02892                        s->nowchar[0] || s->nowchar[1], s->dobigint);
02893         getmd(s->dyncols[i].typename, s->dyncols[i].type,
02894               &s->dyncols[i].size, &s->dyncols[i].prec);
02895 #ifdef SQL_LONGVARCHAR
02896         if (s->dyncols[i].type == SQL_VARCHAR &&
02897             s->dyncols[i].size > 255) {
02898             s->dyncols[i].type = SQL_LONGVARCHAR;
02899         }
02900 #endif
02901 #ifdef WINTERFACE
02902 #ifdef SQL_WLONGVARCHAR
02903         if (s->dyncols[i].type == SQL_WVARCHAR &&
02904             s->dyncols[i].size > 255) {
02905             s->dyncols[i].type = SQL_WLONGVARCHAR;
02906         }
02907 #endif
02908 #endif
02909         if (s->dyncols[i].type == SQL_VARBINARY &&
02910             s->dyncols[i].size > 255) {
02911             s->dyncols[i].type = SQL_LONGVARBINARY;
02912         }
02913     }
02914 #ifndef FULL_METADATA
02915     if (s->dcols > array_size(flags)) {
02916         flagp = xmalloc(sizeof (flags[0]) * s->dcols);
02917         if (flagp == NULL) {
02918             return;
02919         }
02920     } else {
02921         flagp = flags;
02922     }
02923     memset(flagp, 0, sizeof (flags[0]) * s->dcols);
02924     for (i = 0; i < s->dcols; i++) {
02925         s->dyncols[i].autoinc = SQL_FALSE;
02926         s->dyncols[i].notnull = SQL_NULLABLE;
02927     }
02928     for (i = 0; i < s->dcols; i++) {
02929         int ret, lastpk = -1, autoinccount = 0;
02930         char *sql;
02931 
02932         if (!s->dyncols[i].table[0]) {
02933             continue;
02934         }
02935         if (flagp[i]) {
02936             continue;
02937         }
02938         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
02939         if (!sql) {
02940             continue;
02941         }
02942         dbtraceapi(d, "sqlite3_get_table", sql);
02943         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
02944         sqlite3_free(sql);
02945         if (ret != SQLITE_OK) {
02946             continue;
02947         }
02948         k = findcol(rowp, ncols, "name");
02949         t = findcol(rowp, ncols, "type");
02950         pk = findcol(rowp, ncols, "pk");
02951         nn = findcol(rowp, ncols, "notnull");
02952         if (k < 0 || t < 0) {
02953             goto freet;
02954         }
02955         for (r = 1; r <= nrows; r++) {
02956             int m;
02957 
02958             for (m = i; m < s->dcols; m++) {
02959                 char *colname = s->dyncols[m].column;
02960 
02961                 if (s->longnames) {
02962                     char *dotp = strchr(colname, '.');
02963 
02964                     if (dotp) {
02965                         colname = dotp + 1;
02966                     }
02967                 }
02968                 if (!flagp[m] &&
02969                     strcmp(colname, rowp[r * ncols + k]) == 0 &&
02970                     strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
02971                     char *typename = rowp[r * ncols + t];
02972 
02973                     flagp[m] = i + 1;
02974                     freep(&s->dyncols[m].typename);
02975                     s->dyncols[m].typename = xstrdup(typename);
02976                     s->dyncols[m].type =
02977                         mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
02978                                    s->nowchar[0] || s->nowchar[1],
02979                                    s->dobigint);
02980                     getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
02981                           &s->dyncols[m].prec);
02982 #ifdef SQL_LONGVARCHAR
02983                     if (s->dyncols[m].type == SQL_VARCHAR &&
02984                         s->dyncols[m].size > 255) {
02985                         s->dyncols[m].type = SQL_LONGVARCHAR;
02986                     }
02987 #endif
02988 #ifdef WINTERFACE
02989 #ifdef SQL_WLONGVARCHAR
02990                     if (s->dyncols[i].type == SQL_WVARCHAR &&
02991                         s->dyncols[i].size > 255) {
02992                         s->dyncols[i].type = SQL_WLONGVARCHAR;
02993                     }
02994 #endif
02995 #endif
02996                     if (s->dyncols[i].type == SQL_VARBINARY &&
02997                         s->dyncols[i].size > 255) {
02998                         s->dyncols[i].type = SQL_LONGVARBINARY;
02999                     }
03000                     if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
03001                         s->dyncols[m].ispk = 1;
03002                         if (++autoinccount > 1) {
03003                             if (lastpk >= 0) {
03004                                 s->dyncols[lastpk].autoinc = SQL_FALSE;
03005                                 lastpk = -1;
03006                             }
03007                         } else {
03008                             lastpk = m;
03009                             if (strlen(typename) == 7 &&
03010                                 strncasecmp(typename, "integer", 7) == 0) {
03011                                 s->dyncols[m].autoinc = SQL_TRUE;
03012                             }
03013                         }
03014                     } else {
03015                         s->dyncols[m].ispk = 0;
03016                     }
03017                     if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
03018                         s->dyncols[m].notnull = SQL_NO_NULLS;
03019                     }
03020                 }
03021             }
03022         }
03023 freet:
03024         sqlite3_free_table(rowp);
03025     }
03026     for (i = k = 0; i < s->dcols; i++) {
03027         if (flagp[i] == 0) {
03028             break;
03029         }
03030         if (k == 0) {
03031             k = flagp[i];
03032         } else if (flagp[i] != k) {
03033             k = 0;
03034             break;
03035         }
03036     }
03037     s->one_tbl = k ? 1 : 0;
03038     k = 0;
03039     if (s->one_tbl) {
03040         for (i = 0; i < s->dcols; i++) {
03041             if (s->dyncols[i].ispk > 0) {
03042                 ++k;
03043             }
03044         }
03045     }
03046     s->has_pk = k;
03047     if (flagp != flags) {
03048         freep(&flagp);
03049     }
03050 #else
03051     for (i = 1, k = 0; i < s->dcols; i++) {
03052         if (strcmp(s->dyncols[i].table, s->dyncols[0].table) == 0) {
03053             k++;
03054         }
03055     }
03056     s->one_tbl = (k && k + 1 == s->dcols) ? 1 : 0;
03057     k = 0;
03058     if (s->one_tbl) {
03059         for (i = 0; i < s->dcols; i++) {
03060             if (s->dyncols[i].ispk > 0) {
03061                 ++k;
03062                 if (s->has_rowid < 0 && s->dyncols[i].isrowid > 0) {
03063                     s->has_rowid = i;
03064                 }
03065             }
03066         }
03067     }
03068     s->has_pk = k;
03069 #endif
03070 }
03071 
03078 static void
03079 convJD2YMD(double jd, DATE_STRUCT *ds)
03080 {
03081     int z, a, b, c, d, e, x1;
03082     sqlite_int64 ijd;
03083 
03084     ijd = jd * 86400000.0 + 0.5;
03085     z = (int) ((ijd + 43200000) / 86400000);
03086     a = (int) ((z - 1867216.25) / 36524.25);
03087     a = z + 1 + a - (a / 4);
03088     b = a + 1524;
03089     c = (int) ((b - 122.1) / 365.25);
03090     d = (36525 * c) / 100;
03091     e = (int) ((b - d) / 30.6001);
03092     x1 = (int) (30.6001 * e);
03093     ds->day = b - d - x1;
03094     ds->month = (e < 14) ? (e - 1) : (e - 13);
03095     ds->year = (ds->month > 2) ? (c - 4716) : (c - 4715);
03096 }
03097 
03098 
03106 static void
03107 convJD2HMS(double jd, TIME_STRUCT *ts, int *fp)
03108 {
03109     int s;
03110     double ds;
03111     sqlite_int64 ijd;
03112 
03113     ijd = jd * 86400000.0 + 0.5;
03114     s = (int)((ijd + 43200000) % 86400000);
03115     ds = s / 1000.0;
03116     if (fp) {
03117         *fp = (s % 1000) * 1000000;
03118     }
03119     s = (int) ds;
03120     ds -= s;
03121     ts->hour = s / 3600;
03122     s -= ts->hour * 3600;
03123     ts->minute = s / 60;
03124     ds += s - ts->minute *60;
03125     ts->second = (int) ds;
03126 }
03127 
03135 static int
03136 getmdays(int year, int month)
03137 {
03138     static const int mdays[] = {
03139         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
03140     };
03141     int mday;
03142 
03143     if (month < 1) {
03144         return 0;
03145     }
03146     mday = mdays[(month - 1) % 12];
03147     if (mday == 28 && year % 4 == 0 &&
03148         (!(year % 100 == 0) || year % 400 == 0)) {
03149         mday++;
03150     }
03151     return mday;
03152 }
03153 
03169 static int
03170 str2date(int jdconv, char *str, DATE_STRUCT *ds)
03171 {
03172     int i, err = 0;
03173     double jd;
03174     char *p, *q, sepc = '\0';
03175 
03176     ds->year = ds->month = ds->day = 0;
03177     if (jdconv) {
03178         p = strchr(str, '.');
03179         if (p) {
03180             /* julian day format */
03181             p = 0;
03182             jd = ln_strtod(str, &p);
03183             if (p && p > str) {
03184                 convJD2YMD(jd, ds);
03185                 return 0;
03186             }
03187         }
03188     }
03189     p = str;
03190     while (*p && !ISDIGIT(*p)) {
03191         ++p;
03192     }
03193     q = p;
03194     i = 0;
03195     while (*q && !ISDIGIT(*q)) {
03196         ++i;
03197         ++q;
03198     }
03199     if (i >= 8) {
03200         char buf[8];
03201 
03202         strncpy(buf, p + 0, 4); buf[4] = '\0';
03203         ds->year = strtol(buf, NULL, 10);
03204         strncpy(buf, p + 4, 2); buf[2] = '\0';
03205         ds->month = strtol(buf, NULL, 10);
03206         strncpy(buf, p + 6, 2); buf[2] = '\0';
03207         ds->day = strtol(buf, NULL, 10);
03208         goto done;
03209     }
03210     i = 0;
03211     while (i < 3) {
03212         int n;
03213 
03214         q = NULL;
03215         n = strtol(p, &q, 10);
03216         if (!q || q == p) {
03217             if (*q == '\0') {
03218                 if (i == 0) {
03219                     err = 1;
03220                 }
03221                 goto done;
03222             }
03223         }
03224         if (!sepc) {
03225             sepc = *q;
03226         }
03227         if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
03228             switch (i) {
03229             case 0: ds->year = n; break;
03230             case 1: ds->month = n; break;
03231             case 2: ds->day = n; break;
03232             }
03233             ++i;
03234             if (*q) {
03235                 ++q;
03236             }
03237         } else {
03238             i = 0;
03239             while (*q && !ISDIGIT(*q)) {
03240                 ++q;
03241             }
03242         }
03243         p = q;
03244     }
03245 done:
03246     /* final check for overflow */
03247     if (err ||
03248         ds->month < 1 || ds->month > 12 ||
03249         ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
03250         if (sepc == '/') {
03251             /* Try MM/DD/YYYY format */
03252             int t[3];
03253 
03254             t[0] = ds->year;
03255             t[1] = ds->month;
03256             t[2] = ds->day;
03257             ds->year = t[2];
03258             ds->day = t[1];
03259             ds->month = t[0];
03260             if (ds->month >= 1 && ds->month <= 12 &&
03261                 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
03262                 return 0;
03263             }
03264         }
03265         return -1;
03266     }
03267     return 0;
03268 }
03269 
03284 static int
03285 str2time(int jdconv, char *str, TIME_STRUCT *ts)
03286 {
03287     int i, err = 0, ampm = -1;
03288     double jd;
03289     char *p, *q;
03290 
03291     ts->hour = ts->minute = ts->second = 0;
03292     if (jdconv) {
03293         p = strchr(str, '.');
03294         if (p) {
03295             /* julian day format */
03296             p = 0;
03297             jd = ln_strtod(str, &p);
03298             if (p && p > str) {
03299                 convJD2HMS(jd, ts, 0);
03300                 return 0;
03301             }
03302         }
03303     }
03304     p = str;
03305     while (*p && !ISDIGIT(*p)) {
03306         ++p;
03307     }
03308     q = p;
03309     i = 0;
03310     while (*q && ISDIGIT(*q)) {
03311         ++i;
03312         ++q;
03313     }
03314     if (i >= 6) {
03315         char buf[4];
03316 
03317         strncpy(buf, p + 0, 2); buf[2] = '\0';
03318         ts->hour = strtol(buf, NULL, 10);
03319         strncpy(buf, p + 2, 2); buf[2] = '\0';
03320         ts->minute = strtol(buf, NULL, 10);
03321         strncpy(buf, p + 4, 2); buf[2] = '\0';
03322         ts->second = strtol(buf, NULL, 10);
03323         goto done;
03324     }
03325     i = 0;
03326     while (i < 3) {
03327         int n;
03328 
03329         q = NULL;
03330         n = strtol(p, &q, 10);
03331         if (!q || q == p) {
03332             if (*q == '\0') {
03333                 if (i == 0) {
03334                     err = 1;
03335                 }
03336                 goto done;
03337             }
03338         }
03339         if (*q == ':' || *q == '\0' || i == 2) {
03340             switch (i) {
03341             case 0: ts->hour = n; break;
03342             case 1: ts->minute = n; break;
03343             case 2: ts->second = n; break;
03344             }
03345             ++i;
03346             if (*q) {
03347                 ++q;
03348             }
03349         } else {
03350             i = 0;
03351             while (*q && !ISDIGIT(*q)) {
03352                 ++q;
03353             }
03354         }
03355         p = q;
03356     }
03357     if (!err) {
03358         while (*p) {
03359             if ((p[0] == 'p' || p[0] == 'P') &&
03360                 (p[1] == 'm' || p[1] == 'M')) {
03361                 ampm = 1;
03362             } else if ((p[0] == 'a' || p[0] == 'A') &&
03363                 (p[1] == 'm' || p[1] == 'M')) {
03364                 ampm = 0;
03365             }
03366             ++p;
03367         }
03368         if (ampm > 0) {
03369             if (ts->hour < 12) {
03370                 ts->hour += 12;
03371             }
03372         } else if (ampm == 0) {
03373             if (ts->hour == 12) {
03374                 ts->hour = 0;
03375             }
03376         }
03377     }
03378 done:
03379     /* final check for overflow */
03380     if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
03381         return -1;
03382     }
03383     return 0;
03384 }
03385 
03405 static int
03406 str2timestamp(int jdconv, char *str, TIMESTAMP_STRUCT *tss)
03407 {
03408     int i, m, n, err = 0, ampm = -1;
03409     double jd;
03410     char *p, *q, in = '\0', sepc = '\0';
03411 
03412     tss->year = tss->month = tss->day = 0;
03413     tss->hour = tss->minute = tss->second = 0;
03414     tss->fraction = 0;
03415     if (jdconv) {
03416         p = strchr(str, '.');
03417         if (p) {
03418             q = strchr(str, '-');
03419             if (q == str) {
03420                 q = 0;
03421             }
03422             if (!q) {
03423                 q = strchr(str, '/');
03424                 if (!q) {
03425                     q = strchr(str, ':');
03426                 }
03427             }
03428             if (!q || q > p) {
03429                 /* julian day format */
03430                 p = 0;
03431                 jd = ln_strtod(str, &p);
03432                 if (p && p > str) {
03433                     DATE_STRUCT ds;
03434                     TIME_STRUCT ts;
03435 
03436                     convJD2YMD(jd, &ds);
03437                     convJD2HMS(jd, &ts, &n);
03438                     tss->year = ds.year;
03439                     tss->month = ds.month;
03440                     tss->day = ds.day;
03441                     tss->hour = ts.hour;
03442                     tss->minute = ts.minute;
03443                     tss->second = ts.second;
03444                     tss->fraction = n;
03445                     return 0;
03446                 }
03447             }
03448         }
03449     }
03450     p = str;
03451     while (*p && !ISDIGIT(*p)) {
03452         ++p;
03453     }
03454     q = p;
03455     i = 0;
03456     while (*q && ISDIGIT(*q)) {
03457         ++i;
03458         ++q;
03459     }
03460     if (i >= 14) {
03461         char buf[16];
03462 
03463         strncpy(buf, p + 0, 4); buf[4] = '\0';
03464         tss->year = strtol(buf, NULL, 10);
03465         strncpy(buf, p + 4, 2); buf[2] = '\0';
03466         tss->month = strtol(buf, NULL, 10);
03467         strncpy(buf, p + 6, 2); buf[2] = '\0';
03468         tss->day = strtol(buf, NULL, 10);
03469         strncpy(buf, p + 8, 2); buf[2] = '\0';
03470         tss->hour = strtol(buf, NULL, 10);
03471         strncpy(buf, p + 10, 2); buf[2] = '\0';
03472         tss->minute = strtol(buf, NULL, 10);
03473         strncpy(buf, p + 12, 2); buf[2] = '\0';
03474         tss->second = strtol(buf, NULL, 10);
03475         if (i > 14) {
03476             m = i - 14;
03477             strncpy(buf, p + 14, m);
03478             while (m < 9) {
03479                 buf[m] = '0';
03480                 ++m;
03481             }
03482             buf[m] = '\0';
03483             tss->fraction = strtol(buf, NULL, 10);
03484         }
03485         m = 7;
03486         goto done;
03487     }
03488     m = i = 0;
03489     while ((m & 7) != 7) {
03490         q = NULL;
03491         n = strtol(p, &q, 10);
03492         if (!q || q == p) {
03493             if (*q == '\0') {
03494                 if (m < 1) {
03495                     err = 1;
03496                 }
03497                 goto done;
03498             }
03499         }
03500         if (in == '\0') {
03501             switch (*q) {
03502             case '-':
03503             case '/':
03504                 if ((m & 1) == 0) {
03505                     in = *q;
03506                     i = 0;
03507                 }
03508                 break;
03509             case ':':
03510                 if ((m & 2) == 0) {
03511                     in = *q;
03512                     i = 0;
03513                 }
03514                 break;
03515             case ' ':
03516             case '.':
03517                 break;
03518             default:
03519                 in = '\0';
03520                 i = 0;
03521                 break;
03522             }
03523         }
03524         switch (in) {
03525         case '-':
03526         case '/':
03527             if (!sepc) {
03528                 sepc = in;
03529             }
03530             switch (i) {
03531             case 0: tss->year = n; break;
03532             case 1: tss->month = n; break;
03533             case 2: tss->day = n; break;
03534             }
03535             if (++i >= 3) {
03536                 i = 0;
03537                 m |= 1;
03538                 if (!(m & 2)) {
03539                     m |= 8;
03540                 }
03541                 goto skip;
03542             } else {
03543                 ++q;
03544             }
03545             break;
03546         case ':':
03547             switch (i) {
03548             case 0: tss->hour = n; break;
03549             case 1: tss->minute = n; break;
03550             case 2: tss->second = n; break;
03551             }
03552             if (++i >= 3) {
03553                 i = 0;
03554                 m |= 2;
03555                 if (*q == '.') {
03556                     in = '.';
03557                     goto skip2;
03558                 }
03559                 if (*q == ' ') {
03560                     if ((m & 1) == 0) {
03561                         char *e = NULL;
03562 
03563                         (void) strtol(q + 1, &e, 10);
03564                         if (e && *e == '-') {
03565                             goto skip;
03566                         }
03567                     }
03568                     in = '.';
03569                     goto skip2;
03570                 }
03571                 goto skip;
03572             } else {
03573                 ++q;
03574             }
03575             break;
03576         case '.':
03577             if (++i >= 1) {
03578                 int ndig = q - p;
03579 
03580                 if (p[0] == '+' || p[0] == '-') {
03581                     ndig--;
03582                 }
03583                 while (ndig < 9) {
03584                     n = n * 10;
03585                     ++ndig;
03586                 }
03587                 tss->fraction = n;
03588                 m |= 4;
03589                 i = 0;
03590             }
03591         default:
03592         skip:
03593             in = '\0';
03594         skip2:
03595             while (*q && !ISDIGIT(*q)) {
03596                 if ((q[0] == 'a' || q[0] == 'A') &&
03597                     (q[1] == 'm' || q[1] == 'M')) {
03598                     ampm = 0;
03599                     ++q;
03600                 } else if ((q[0] == 'p' || q[0] == 'P') &&
03601                            (q[1] == 'm' || q[1] == 'M')) {
03602                     ampm = 1;
03603                     ++q;
03604                 }
03605                 ++q;
03606             }
03607         }
03608         p = q;
03609     }
03610     if ((m & 7) > 1 && (m & 8)) {
03611         /* ISO8601 timezone */
03612         if (p > str && ISDIGIT(*p)) {
03613             int nn, sign;
03614 
03615             q = p - 1;
03616             if (*q != '+' && *q != '-') {
03617                 goto done;
03618             }
03619             sign = (*q == '+') ? -1 : 1;
03620             q = NULL;
03621             n = strtol(p, &q, 10);
03622             if (!q || *q++ != ':' || !ISDIGIT(*q)) {
03623                 goto done;
03624             }
03625             p = q;
03626             q = NULL;
03627             nn = strtol(p, &q, 10);
03628             tss->minute += nn * sign;
03629             if ((SQLSMALLINT) tss->minute < 0) {
03630                 tss->hour -= 1;
03631                 tss->minute += 60;
03632             } else if (tss->minute >= 60) {
03633                 tss->hour += 1;
03634                 tss->minute -= 60;
03635             }
03636             tss->hour += n * sign;
03637             if ((SQLSMALLINT) tss->hour < 0) {
03638                 tss->day -= 1;
03639                 tss->hour += 24;
03640             } else if (tss->hour >= 24) {
03641                 tss->day += 1;
03642                 tss->hour -= 24;
03643             }
03644             if ((short) tss->day < 1 || tss->day >= 28) {
03645                 int mday, pday, pmon;
03646 
03647                 mday = getmdays(tss->year, tss->month);
03648                 pmon = tss->month - 1;
03649                 if (pmon < 1) {
03650                     pmon = 12;
03651                 }
03652                 pday = getmdays(tss->year, pmon);
03653                 if ((SQLSMALLINT) tss->day < 1) {
03654                     tss->month -= 1;
03655                     tss->day = pday;
03656                 } else if (tss->day > mday) {
03657                     tss->month += 1;
03658                     tss->day = 1;
03659                 }
03660                 if ((SQLSMALLINT) tss->month < 1) {
03661                     tss->year -= 1;
03662                     tss->month = 12;
03663                 } else if (tss->month > 12) {
03664                     tss->year += 1;
03665                     tss->month = 1;
03666                 }
03667             }
03668         }
03669     }
03670 done:
03671     if ((m & 1) &&
03672         (tss->month < 1 || tss->month > 12 ||
03673          tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
03674         if (sepc == '/') {
03675             /* Try MM/DD/YYYY format */
03676             int t[3];
03677 
03678             t[0] = tss->year;
03679             t[1] = tss->month;
03680             t[2] = tss->day;
03681             tss->year = t[2];
03682             tss->day = t[1];
03683             tss->month = t[0];
03684         }
03685     }
03686     /* Replace missing year/month/day with current date */
03687     if (!err && (m & 1) == 0) {
03688 #ifdef _WIN32
03689         SYSTEMTIME t;
03690 
03691         GetLocalTime(&t);
03692         tss->year = t.wYear;
03693         tss->month = t.wMonth;
03694         tss->day = t.wDay;
03695 #else
03696         struct timeval tv;
03697         struct tm tm;
03698 
03699         gettimeofday(&tv, NULL);
03700         tm = *localtime(&tv.tv_sec);
03701         tss->year = tm.tm_year + 1900;
03702         tss->month = tm.tm_mon + 1;
03703         tss->day = tm.tm_mday;
03704 #endif
03705     }
03706     /* Normalize fraction */
03707     if (tss->fraction < 0) {
03708         tss->fraction = 0;
03709     }
03710     /* Final check for overflow */
03711     if (err ||
03712         tss->month < 1 || tss->month > 12 ||
03713         tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
03714         tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
03715         return -1;
03716     }
03717     if ((m & 7) > 1) {
03718         if (ampm > 0) {
03719             if (tss->hour < 12) {
03720                 tss->hour += 12;
03721             }
03722         } else if (ampm == 0) {
03723             if (tss->hour == 12) {
03724                 tss->hour = 0;
03725             }
03726         }
03727     }
03728     return ((m & 7) < 1) ? -1 : 0;
03729 }
03730 
03737 static int
03738 getbool(char *string)
03739 {
03740     if (string) {
03741         return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
03742     }
03743     return 0;
03744 }
03745 
03753 static void
03754 blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03755 {
03756 #if 0
03757     DBC *d = (DBC *) sqlite3_user_data(ctx);
03758 #endif
03759     char *filename = 0;
03760 
03761     if (nargs > 0) {
03762         if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
03763             filename = (char *) sqlite3_value_text(args[0]);
03764         }
03765     }
03766     if (filename) {
03767 #ifdef _WIN32
03768         char *wname = utf_to_wmb(filename, -1);
03769         FILE *f;
03770 #else
03771         FILE *f = fopen(filename, "r");
03772 #endif
03773         char *p;
03774         long n, nn;
03775 
03776 #ifdef _WIN32
03777         if (wname) {
03778             f = fopen(wname, "rb");
03779         } else {
03780             sqlite3_result_error(ctx, "out of memory", -1);
03781             return;
03782         }
03783         uc_free(wname);
03784 #endif
03785         if (f) {
03786             if (fseek(f, 0, SEEK_END) == 0) {
03787                 n = ftell(f);
03788                 if (fseek(f, 0, SEEK_SET) == 0) {
03789                     p = sqlite3_malloc(n);
03790                     if (p) {
03791                         nn = fread(p, 1, n, f);
03792                         if (nn != n) {
03793                             sqlite3_result_error(ctx, "read error", -1);
03794                             sqlite3_free(p);
03795                         } else {
03796                             sqlite3_result_blob(ctx, p, n, sqlite3_free);
03797                         }
03798                     } else {
03799                         sqlite3_result_error(ctx, "out of memory", -1);
03800                     }
03801                 } else {
03802                     sqlite3_result_error(ctx, "seek error", -1);
03803                 }
03804             } else {
03805                 sqlite3_result_error(ctx, "seek error", -1);
03806             }
03807             fclose(f);
03808         } else {
03809             sqlite3_result_error(ctx, "cannot open file", -1);
03810         }
03811     } else {
03812         sqlite3_result_error(ctx, "no filename given", -1);
03813     }
03814 }
03815 
03823 static void
03824 blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03825 {
03826 #if 0
03827     DBC *d = (DBC *) sqlite3_user_data(ctx);
03828 #endif
03829     char *filename = 0;
03830     char *p = 0;
03831     int n = 0;
03832 
03833     if (nargs > 0) {
03834         p = (char *) sqlite3_value_blob(args[0]);
03835         n = sqlite3_value_bytes(args[0]);
03836     }
03837     if (nargs > 1) {
03838         if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
03839             filename = (char *) sqlite3_value_text(args[1]);
03840         }
03841     }
03842     if (p) {
03843         if (filename) {
03844 #ifdef _WIN32
03845             char *wname = utf_to_wmb(filename, -1);
03846             FILE *f;
03847 #else
03848             FILE *f = fopen(filename, "w");
03849 #endif
03850             int nn;
03851 
03852 #ifdef _WIN32
03853             if (wname) {
03854                 f = fopen(wname, "wb");
03855             } else {
03856                 sqlite3_result_error(ctx, "out of memory", -1);
03857                 return;
03858             }
03859             uc_free(wname);
03860 #endif
03861             if (f) {
03862                 nn = fwrite(p, 1, n, f);
03863                 fclose(f);
03864                 if (nn != n) {
03865                     sqlite3_result_error(ctx, "write error", -1);
03866                 } else {
03867                     sqlite3_result_int(ctx, nn);
03868                 }
03869             } else {
03870                 sqlite3_result_error(ctx, "cannot open file", -1);
03871             }
03872         } else {
03873             sqlite3_result_error(ctx, "no filename given", -1);
03874         }
03875     } else {
03876         sqlite3_result_null(ctx);
03877     }
03878 }
03879 
03887 static void
03888 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03889 dbtrace(void *arg, const char *msg, sqlite_uint64 et)
03890 #else
03891 dbtrace(void *arg, const char *msg)
03892 #endif
03893 {
03894     DBC *d = (DBC *) arg;
03895 
03896     if (msg && d->trace) {
03897         int len = strlen(msg);
03898 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03899         unsigned long s, f;
03900 #endif
03901 
03902         if (len > 0) {
03903             char *end = "\n";
03904 
03905             if (msg[len - 1] != ';') {
03906                 end = ";\n";
03907             }
03908             fprintf(d->trace, "%s%s", msg, end);
03909 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03910             s = et / 1000000000LL;
03911             f = et % 1000000000LL;
03912             fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
03913 #endif
03914             fflush(d->trace);
03915         }
03916     }
03917 }
03918 
03926 static void
03927 dbtraceapi(DBC *d, char *fn, const char *sql)
03928 {
03929     if (fn && d->trace) {
03930         if (sql) {
03931             fprintf(d->trace, "-- %s: %s\n", fn, sql);
03932         } else {
03933             fprintf(d->trace, "-- %s\n", fn);
03934         }
03935         fflush(d->trace);
03936     }
03937 }
03938 
03946 static void
03947 dbtracerc(DBC *d, int rc, char *err)
03948 {
03949     if (rc != SQLITE_OK && d->trace) {
03950         fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
03951         fprintf(d->trace, err ? ": %s\n" : "\n", err);
03952         fflush(d->trace);
03953     }
03954 }
03955 
03970 static SQLRETURN
03971 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
03972        char *spflag, char *ntflag, char *jmode, char *busy)
03973 {
03974     char *endp = NULL;
03975     int rc, tmp, busyto = 100000;
03976 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03977     int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
03978     char *uname = name;
03979     const char *vfs_name = NULL;
03980 #endif
03981 
03982     if (d->sqlite) {
03983         if (d->trace) {
03984             fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
03985                     d->dbname);
03986             fflush(d->trace);
03987         }
03988 #if defined(HAVE_SQLITE3CLOSEV2) && (HAVE_SQLITE3CLOSEV2)
03989         sqlite3_close_v2(d->sqlite);
03990 #else
03991         sqlite3_close(d->sqlite);
03992 #endif
03993         d->sqlite = NULL;
03994     }
03995 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03996     if (d->nocreat) {
03997         flags &= ~ SQLITE_OPEN_CREATE;
03998     }
03999 #if defined(_WIN32) || defined(_WIN64)
04000     if (!isu) {
04001         char expname[SQL_MAX_MESSAGE_LENGTH * 2];
04002 
04003         expname[0] = '\0';
04004         rc = ExpandEnvironmentStrings(name, expname, sizeof (expname));
04005         if (rc <= sizeof (expname)) {
04006             uname = wmb_to_utf(expname, rc - 1);
04007         } else {
04008             uname = wmb_to_utf(name, -1);
04009         }
04010         if (!uname) {
04011             rc = SQLITE_NOMEM;
04012             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
04013             return SQL_ERROR;
04014         }
04015     }
04016 #endif
04017 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
04018     vfs_name = nvfs_makevfs(uname);
04019 #endif
04020 #ifdef SQLITE_OPEN_URI
04021     flags |= SQLITE_OPEN_URI;
04022 #endif
04023     rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
04024 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
04025     if (uname != name) {
04026         uc_free(uname);
04027     }
04028 #endif
04029 #else
04030 #if defined(_WIN32) || defined(_WIN64)
04031     if (d->nocreat) {
04032         char *cname = NULL;
04033 
04034         if (isu) {
04035             cname = utf_to_wmb(name, -1);
04036         }
04037         if (GetFileAttributesA(cname ? cname : name) ==
04038             INVALID_FILE_ATTRIBUTES) {
04039             uc_free(cname);
04040             rc = SQLITE_CANTOPEN;
04041             setstatd(d, rc, "cannot open database",
04042                      (*d->ov3) ? "HY000" : "S1000");
04043             return SQL_ERROR;
04044         }
04045         uc_free(cname);
04046     }
04047 #else
04048     if (d->nocreat && access(name, 004) < 0) {
04049         rc = SQLITE_CANTOPEN;
04050         setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
04051         return SQL_ERROR;
04052     }
04053 #endif
04054 #if defined(_WIN32) || defined(_WIN64)
04055     if (!isu) {
04056         WCHAR *wname = wmb_to_uc(name, -1);
04057 
04058         if (!wname) {
04059             rc = SQLITE_NOMEM;
04060             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
04061             return SQL_ERROR;
04062         }
04063         rc = sqlite3_open16(wname, &d->sqlite);
04064         uc_free(wname);
04065     } else
04066 #endif
04067     rc = sqlite3_open(name, &d->sqlite);
04068 #endif /* !HAVE_SQLITE3VFS */
04069     if (rc != SQLITE_OK) {
04070 connfail:
04071         setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
04072         if (d->sqlite) {
04073             sqlite3_close(d->sqlite);
04074             d->sqlite = NULL;
04075         }
04076         return SQL_ERROR;
04077     }
04078 #if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
04079     if (d->pwd) {
04080         sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
04081     }
04082 #endif
04083     d->pwd = NULL;
04084     d->pwdLen = 0;
04085     if (d->trace) {
04086 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
04087         sqlite3_profile(d->sqlite, dbtrace, d);
04088 #else
04089         sqlite3_trace(d->sqlite, dbtrace, d);
04090 #endif
04091     }
04092     d->step_enable = getbool(sflag);
04093     d->trans_disable = getbool(ntflag);
04094     d->curtype = d->step_enable ?
04095         SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
04096     tmp = strtol(busy, &endp, 0);
04097     if (endp && *endp == '\0' && endp != busy) {
04098         busyto = tmp;
04099     }
04100     if (busyto < 1 || busyto > 1000000) {
04101         busyto = 1000000;
04102     }
04103     d->timeout = busyto;
04104     freep(&d->dbname);
04105     d->dbname = xstrdup(name);
04106     freep(&d->dsn);
04107     d->dsn = xstrdup(dsn);
04108     if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
04109         if (d->trace) {
04110             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
04111                     d->dbname);
04112             fflush(d->trace);
04113         }
04114         sqlite3_close(d->sqlite);
04115         d->sqlite = NULL;
04116         goto connfail;
04117     }
04118     if (!spflag || spflag[0] == '\0') {
04119         spflag = "NORMAL";
04120     }
04121     if (spflag[0] != '\0') {
04122         char syncp[128];
04123 
04124         sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
04125         sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
04126     }
04127     if (jmode[0] != '\0') {
04128         char jourp[128];
04129 
04130         sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
04131         sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
04132     }
04133     if (d->trace) {
04134         fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
04135         fflush(d->trace);
04136     }
04137 #if defined(_WIN32) || defined(_WIN64)
04138     {
04139         char pname[MAX_PATH];
04140         HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
04141                                FALSE, GetCurrentProcessId());
04142 
04143         pname[0] = '\0';
04144         if (h) {
04145             HMODULE m = NULL, l = LoadLibrary("psapi.dll");
04146             DWORD need;
04147             typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
04148             typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
04149             epmfunc epm;
04150             gmbfunc gmb;
04151 
04152             if (l) {
04153                 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
04154                 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
04155                 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
04156                     gmb(h, m, pname, sizeof (pname));
04157                 }
04158                 FreeLibrary(l);
04159             }
04160             CloseHandle(h);
04161         }
04162         d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
04163                      strncasecmp(pname, "MSQRY", 5) == 0;
04164         if (d->trace && d->xcelqrx) {
04165 
04166             fprintf(d->trace, "-- enabled EXCEL quirks\n");
04167             fflush(d->trace);
04168         }
04169     }
04170 #endif
04171     sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
04172                             d, blob_import, 0, 0);
04173     sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
04174                             d, blob_export, 0, 0);
04175     return SQL_SUCCESS;
04176 }
04177 
04184 static void
04185 dbloadext(DBC *d, char *exts)
04186 {
04187 #if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
04188     char *p;
04189     char path[SQL_MAX_MESSAGE_LENGTH];
04190     int plen = 0;
04191 
04192     if (!d->sqlite) {
04193         return;
04194     }
04195     sqlite3_enable_load_extension(d->sqlite, 1);
04196 #if defined(_WIN32) || defined(_WIN64)
04197     GetModuleFileName(hModule, path, sizeof (path));
04198     p = strrchr(path, '\\');
04199     plen = p ? ((p + 1) - path) : 0;
04200 #endif
04201     do {
04202         p = strchr(exts, ',');
04203         if (p) {
04204             strncpy(path + plen, exts, p - exts);
04205             path[plen + (p - exts)] = '\0';
04206         } else {
04207             strcpy(path + plen, exts);
04208         }
04209         if (exts[0]) {
04210             char *errmsg = NULL;
04211             int rc;
04212 #if defined(_WIN32) || defined(_WIN64)
04213             int i;
04214             char *q;
04215 
04216             q = path + plen;
04217             if (!(q[0] &&
04218                   ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
04219                    q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
04220                 q = path;
04221             }
04222             /* sqlite3_load_extension() dislikes backslashes */
04223             for (i = 0; q[i] != '\0'; i++) {
04224                 if (q[i] == '\\') {
04225                     q[i] = '/';
04226                 }
04227             }
04228             rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
04229 #else
04230             rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
04231 #endif
04232             if (rc != SQLITE_OK) {
04233 #if defined(_WIN32) || defined(_WIN64)
04234                 char buf[512], msg[512];
04235 
04236                 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
04237                 wsprintf(msg, buf, q, errmsg ?
04238                          errmsg : "no error info available");
04239                 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
04240                 MessageBox(NULL, msg, buf,
04241                            MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
04242                            MB_SETFOREGROUND);
04243 #else
04244                 fprintf(stderr, "extension '%s' did not load%s%s\n",
04245                         path, errmsg ? ": " : "", errmsg ? errmsg : "");
04246 #endif
04247             }
04248         }
04249         if (p) {
04250             exts = p + 1;
04251         }
04252     } while (p);
04253 #endif /* HAVE_SQLITE3LOADEXTENSION */
04254 }
04255 
04262 static void
04263 dbattas(DBC *d, char *attas)
04264 {
04265     char *p;
04266     char as[SQL_MAX_MESSAGE_LENGTH];
04267 
04268     if (!d->sqlite) {
04269         return;
04270     }
04271     do {
04272         p = strchr(attas, ',');
04273         if (p) {
04274             strncpy(as, attas, p - attas);
04275             as[p - attas] = '\0';
04276         } else {
04277             strcpy(as, attas);
04278         }
04279         if (attas[0]) {
04280             char *sql;
04281 
04282             sql = sqlite3_mprintf("ATTACH %Q AS %s", d->dbname, as);
04283             if (sql != NULL) {
04284                 sqlite3_exec(d->sqlite, sql, NULL, NULL, NULL);
04285                 sqlite3_free(sql);
04286             }
04287         }
04288         if (p) {
04289             attas = p + 1;
04290         }
04291     } while (p);
04292 }
04293 
04303 static char *
04304 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
04305 {
04306     char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
04307     char guess[64];
04308 
04309     guess[0] = '\0';
04310     if (!typename) {
04311         int coltype = sqlite3_column_type(s3stmt, col);
04312 
04313         if (guessed_types) {
04314             guessed_types[0]++;
04315         }
04316         if (d->trace) {
04317             sprintf(guess, " (guessed from %d)", coltype);
04318         }
04319         switch (coltype) {
04320         case SQLITE_INTEGER: typename = "integer"; break;
04321         case SQLITE_FLOAT:   typename = "double";  break;
04322         default:
04323         case SQLITE_TEXT:    typename = "varchar"; break;
04324         case SQLITE_BLOB:    typename = "blob";    break;
04325 #if 0
04326         case SQLITE_NULL:    typename = "null";    break;
04327 #endif
04328         }
04329     }
04330     if (d->trace) {
04331         fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
04332                 guess, typename);
04333         fflush(d->trace);
04334     }
04335     return typename;
04336 }
04337 
04338 #ifdef FULL_METADATA
04339 
04348 static void
04349 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
04350 {
04351     int nn = 0, pk = 0, ai = 0;
04352     const char *dn = NULL, *tn = NULL, *cn = NULL, *dummy[4];
04353 
04354     dn = sqlite3_column_database_name(s3stmt, col);
04355     tn = sqlite3_column_table_name(s3stmt, col);
04356     cn = sqlite3_column_origin_name(s3stmt, col);
04357     dummy[0] = dummy[1] = 0;
04358     if (tn && cn) {
04359         sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
04360                                       dummy, dummy + 1,
04361                                       &nn, &pk, &ai);
04362     }
04363     ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
04364     ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
04365     ci->ispk = pk ? 1 : 0;
04366     if (d->trace) {
04367         fprintf(d->trace, "-- column %d %s\n",
04368                 col + 1, nn ? "notnull" : "nullable");
04369         if (ai) {
04370             fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
04371         }
04372         fflush(d->trace);
04373     }
04374     ci->isrowid = 0;
04375     if (ci->ispk && tn) {
04376         nn = pk = ai = 0;
04377         dummy[2] = dummy[3] = 0;
04378 
04379         sqlite3_table_column_metadata(d->sqlite, dn, tn, "rowid",
04380                                       dummy + 2, dummy + 3,
04381                                       &nn, &pk, &ai);
04382         if (pk && dummy[0] && dummy[0] == dummy[2]) {
04383             ci->isrowid = 1;
04384         }
04385     }
04386 }
04387 
04388 #endif
04389 
04396 static int
04397 s3stmt_step(STMT *s)
04398 {
04399     DBC *d = (DBC *) s->dbc;
04400     char **rowd = NULL;
04401     const char *errp = NULL;
04402     int i, ncols, rc;
04403 
04404     if (s != d->cur_s3stmt || !s->s3stmt) {
04405         setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
04406         return SQL_ERROR;
04407     }
04408     rc = sqlite3_step(s->s3stmt);
04409     if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
04410         ++s->s3stmt_rownum;
04411         ncols = sqlite3_column_count(s->s3stmt);
04412         if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
04413             PTRDIFF_T size;
04414             char *p;
04415             COL *dyncols;
04416             const char *colname, *typename;
04417 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04418             char *tblname;
04419 #endif
04420 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04421             char *dbname;
04422 #endif
04423 
04424             for (i = size = 0; i < ncols; i++) {
04425                 colname = sqlite3_column_name(s->s3stmt, i);
04426                 size += 3 + 3 * strlen(colname);
04427             }
04428 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04429             tblname = (char *) size;
04430             for (i = 0; i < ncols; i++) {
04431                 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
04432                 size += 2 + (p ? strlen(p) : 0);
04433             }
04434 #endif
04435 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04436             dbname = (char *) size;
04437             for (i = 0; i < ncols; i++) {
04438                 p = (char *) sqlite3_column_database_name(s->s3stmt, i);
04439                 size += 2 + (p ? strlen(p) : 0);
04440             }
04441 #endif
04442             dyncols = xmalloc(ncols * sizeof (COL) + size);
04443             if (!dyncols) {
04444                 freedyncols(s);
04445                 s->ncols = 0;
04446                 dbtraceapi(d, "sqlite3_finalize", 0);
04447                 sqlite3_finalize(s->s3stmt);
04448                 s->s3stmt = NULL;
04449                 d->cur_s3stmt = NULL;
04450                 return nomem(s);
04451             }
04452             p = (char *) (dyncols + ncols);
04453 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04454             tblname = p + (PTRDIFF_T) tblname;
04455 #endif
04456 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04457             dbname = p + (PTRDIFF_T) dbname;
04458 #endif
04459             for (i = 0; i < ncols; i++) {
04460                 char *q;
04461 
04462                 colname = sqlite3_column_name(s->s3stmt, i);
04463                 if (d->trace) {
04464                     fprintf(d->trace, "-- column %d name: '%s'\n",
04465                             i + 1, colname);
04466                     fflush(d->trace);
04467                 }
04468 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04469                 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
04470                 strcpy(tblname, q ? q : "");
04471                 if (d->trace) {
04472                     fprintf(d->trace, "-- table %d name: '%s'\n",
04473                             i + 1, tblname);
04474                     fflush(d->trace);
04475                 }
04476                 dyncols[i].table = tblname;
04477                 tblname += strlen(tblname) + 1;
04478 #endif
04479 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04480                 q = (char *) sqlite3_column_database_name(s->s3stmt, i);
04481                 strcpy(dbname, q ? q : "");
04482                 if (d->trace) {
04483                     fprintf(d->trace, "-- database %d name: '%s'\n",
04484                             i + 1, dbname);
04485                     fflush(d->trace);
04486                 }
04487                 dyncols[i].db = dbname;
04488                 dbname += strlen(dbname) + 1;
04489 #else
04490                 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
04491 #endif
04492                 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
04493                 strcpy(p, colname);
04494                 dyncols[i].label = p;
04495                 p += strlen(p) + 1;
04496                 q = strchr(colname, '.');
04497                 if (q) {
04498                     char *q2 = strchr(q + 1, '.');
04499 
04500                     /* SQLite 3.3.4 produces view.table.column sometimes */
04501                     if (q2) {
04502                         q = q2;
04503                     }
04504                 }
04505                 if (q) {
04506 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04507                     dyncols[i].table = p;
04508 #endif
04509                     strncpy(p, colname, q - colname);
04510                     p[q - colname] = '\0';
04511                     p += strlen(p) + 1;
04512                     strcpy(p, q + 1);
04513                     dyncols[i].column = p;
04514                     p += strlen(p) + 1;
04515                 } else {
04516 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04517                     dyncols[i].table = "";
04518 #endif
04519                     strcpy(p, colname);
04520                     dyncols[i].column = p;
04521                     p += strlen(p) + 1;
04522                 }
04523                 if (s->longnames) {
04524                     dyncols[i].column = dyncols[i].label;
04525                 }
04526 #ifdef SQL_LONGVARCHAR
04527                 dyncols[i].type = SQL_LONGVARCHAR;
04528                 dyncols[i].size = 65535;
04529 #else
04530                 dyncols[i].type = SQL_VARCHAR;
04531                 dyncols[i].size = 255;
04532 #endif
04533                 dyncols[i].index = i;
04534                 dyncols[i].scale = 0;
04535                 dyncols[i].prec = 0;
04536                 dyncols[i].nosign = 1;
04537                 dyncols[i].autoinc = SQL_FALSE;
04538                 dyncols[i].notnull = SQL_NULLABLE;
04539                 dyncols[i].ispk = -1;
04540                 dyncols[i].isrowid = -1;
04541 #ifdef FULL_METADATA
04542                 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
04543 #endif
04544                 dyncols[i].typename = xstrdup(typename);
04545             }
04546             freedyncols(s);
04547             s->ncols = s->dcols = ncols;
04548             s->dyncols = s->cols = dyncols;
04549             fixupdyncols(s, d);
04550             mkbindcols(s, s->ncols);
04551             d->s3stmt_needmeta = 0;
04552         }
04553         if (ncols <= 0) {
04554             goto killstmt;
04555         }
04556         if (rc == SQLITE_DONE) {
04557             freeresult(s, 0);
04558             s->nrows = 0;
04559             dbtraceapi(d, "sqlite3_finalize", 0);
04560             sqlite3_finalize(s->s3stmt);
04561             s->s3stmt = NULL;
04562             d->cur_s3stmt = NULL;
04563             return SQL_SUCCESS;
04564         }
04565         rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
04566         if (rowd) {
04567             const unsigned char *value;
04568 
04569             rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
04570             ++rowd;
04571             for (i = 0; i < ncols; i++) {
04572                 int coltype = sqlite3_column_type(s->s3stmt, i);
04573 
04574                 rowd[i] = rowd[i + ncols] = NULL;
04575                 if (coltype == SQLITE_BLOB) {
04576                     int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
04577                     char *qp;
04578                     unsigned const char *bp;
04579 
04580                     bp = sqlite3_column_blob(s->s3stmt, i);
04581                     qp = xmalloc(nbytes * 2 + 4);
04582                     if (qp) {
04583                         rowd[i + ncols] = qp;
04584                         *qp++ = 'X';
04585                         *qp++ = '\'';
04586                         for (k = 0; k < nbytes; k++) {
04587                             *qp++ = xdigits[(bp[k] >> 4)];
04588                             *qp++ = xdigits[(bp[k] & 0xF)];
04589                         }
04590                         *qp++ = '\'';
04591                         *qp = '\0';
04592                     }
04593 #ifdef _MSC_VER
04594                 } else if (coltype == SQLITE_FLOAT) {
04595                     struct lconv *lc = 0;
04596                     double d = sqlite3_column_double(s->s3stmt, i);
04597                     char *p, buffer[128];
04598 
04599                     /*
04600                      * This avoids floating point rounding
04601                      * and formatting problems of some SQLite
04602                      * versions in conjunction with MSVC 2010.
04603                      */
04604                     snprintf(buffer, sizeof (buffer), "%.15g", d);
04605                     lc = localeconv();
04606                     if (lc && lc->decimal_point && lc->decimal_point[0] &&
04607                         lc->decimal_point[0] != '.') {
04608                         p = strchr(buffer, lc->decimal_point[0]);
04609                         if (p) {
04610                             *p = '.';
04611                         }
04612                     }
04613                     rowd[i + ncols] = xstrdup(buffer);
04614 #endif
04615                 } else if (coltype != SQLITE_NULL) {
04616                     value = sqlite3_column_text(s->s3stmt, i);
04617                     rowd[i + ncols] = xstrdup((char *) value);
04618                 }
04619             }
04620             for (i = 0; i < ncols; i++) {
04621                 int coltype = sqlite3_column_type(s->s3stmt, i);
04622 
04623                 value = NULL;
04624                 if (coltype == SQLITE_BLOB) {
04625                     value = sqlite3_column_blob(s->s3stmt, i);
04626                 } else if (coltype != SQLITE_NULL) {
04627                     value = sqlite3_column_text(s->s3stmt, i);
04628                 }
04629                 if (value && !rowd[i + ncols]) {
04630                     freerows(rowd);
04631                     rowd = 0;
04632                     break;
04633                 }
04634             }
04635         }
04636         if (rowd) {
04637             freeresult(s, 0);
04638             s->nrows = 1;
04639             s->rows = rowd;
04640             s->rowfree = freerows;
04641             if (rc == SQLITE_DONE) {
04642                 dbtraceapi(d, "sqlite3_finalize", 0);
04643                 sqlite3_finalize(s->s3stmt);
04644                 s->s3stmt = NULL;
04645                 d->cur_s3stmt = NULL;
04646             }
04647             return SQL_SUCCESS;
04648         }
04649     }
04650 killstmt:
04651     dbtraceapi(d, "sqlite3_reset", 0);
04652     rc = sqlite3_reset(s->s3stmt);
04653     s->s3stmt_noreset = 1;
04654     errp = sqlite3_errmsg(d->sqlite);
04655     if (d->cur_s3stmt == s) {
04656         d->cur_s3stmt = NULL;
04657     }
04658     setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04659             errp ? errp : "unknown error", rc);
04660     return SQL_ERROR;
04661 }
04662 
04668 static void
04669 s3stmt_end(STMT *s)
04670 {
04671     DBC *d;
04672 
04673     if (!s || !s->s3stmt) {
04674         return;
04675     }
04676     d = (DBC *) s->dbc;
04677     if (d) {
04678         d->busyint = 0;
04679     }
04680     if (!s->s3stmt_noreset) {
04681         dbtraceapi(d, "sqlite3_reset", 0);
04682         sqlite3_reset(s->s3stmt);
04683         s->s3stmt_noreset = 1;
04684         s->s3stmt_rownum = -1;
04685     }
04686     if (d->cur_s3stmt == s) {
04687         d->cur_s3stmt = NULL;
04688     }
04689 }
04690 
04696 static void
04697 s3stmt_end_if(STMT *s)
04698 {
04699     DBC *d = (DBC *) s->dbc;
04700 
04701     if (d) {
04702         d->busyint = 0;
04703     }
04704     if (d && d->cur_s3stmt == s) {
04705         s3stmt_end(s);
04706     }
04707 }
04708 
04714 static void
04715 s3stmt_drop(STMT *s)
04716 {
04717     if (s->s3stmt) {
04718         DBC *d = (DBC *) s->dbc;
04719 
04720         if (d) {
04721             dbtraceapi(d, "sqlite3_finalize", 0);
04722         }
04723         sqlite3_finalize(s->s3stmt);
04724         s->s3stmt = NULL;
04725         s->s3stmt_rownum = 0;
04726     }
04727 }
04728 
04735 static SQLRETURN
04736 s3stmt_start(STMT *s)
04737 {
04738     DBC *d = (DBC *) s->dbc;
04739     const char *endp;
04740     sqlite3_stmt *s3stmt = NULL;
04741     int rc, nretry = 0;
04742 
04743     d->s3stmt_needmeta = 0;
04744     if (!s->s3stmt) {
04745 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04746         dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
04747 #else
04748         dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
04749 #endif
04750         do {
04751             s3stmt = NULL;
04752 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04753             rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
04754                                     &s3stmt, &endp);
04755 #else
04756             rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
04757                                  &s3stmt, &endp);
04758 #endif
04759             if (rc != SQLITE_OK) {
04760                 if (s3stmt) {
04761                     sqlite3_finalize(s3stmt);
04762                     s3stmt = NULL;
04763                 }
04764             }
04765         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
04766         dbtracerc(d, rc, NULL);
04767         if (rc != SQLITE_OK) {
04768             if (s3stmt) {
04769                 dbtraceapi(d, "sqlite3_finalize", NULL);
04770                 sqlite3_finalize(s3stmt);
04771             }
04772             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04773                     sqlite3_errmsg(d->sqlite), rc);
04774             return SQL_ERROR;
04775         }
04776         if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
04777             dbtraceapi(d, "sqlite3_finalize", 0);
04778             sqlite3_finalize(s3stmt);
04779             setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
04780                     (*s->ov3) ? "HY000" : "S1000");
04781             return SQL_ERROR;
04782         }
04783         s->s3stmt = s3stmt;
04784         s->s3stmt_noreset = 1;
04785         d->s3stmt_needmeta = 1;
04786     }
04787     d->cur_s3stmt = s;
04788     s->s3stmt_rownum = -1;
04789     s3bind(d, s->s3stmt, s->nparams, s->bindparms);
04790     return SQL_SUCCESS;
04791 }
04792 
04793 #ifndef WINTERFACE
04794 
04798 SQLRETURN SQL_API
04799 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
04800                SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04801                SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04802 {
04803     if (env == SQL_NULL_HENV) {
04804         return SQL_INVALID_HANDLE;
04805     }
04806     return SQL_ERROR;
04807 }
04808 #endif
04809 
04810 #ifdef WINTERFACE
04811 
04815 SQLRETURN SQL_API
04816 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
04817                 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04818                 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04819 {
04820     if (env == SQL_NULL_HENV) {
04821         return SQL_INVALID_HANDLE;
04822     }
04823     return SQL_ERROR;
04824 }
04825 #endif
04826 
04827 #ifndef WINTERFACE
04828 
04832 SQLRETURN SQL_API
04833 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
04834            SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04835            SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04836 {
04837     if (env == SQL_NULL_HENV) {
04838         return SQL_INVALID_HANDLE;
04839     }
04840     return SQL_ERROR;
04841 }
04842 #endif
04843 
04844 #ifdef WINTERFACE
04845 
04849 SQLRETURN SQL_API
04850 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
04851             SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04852             SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04853 {
04854     if (env == SQL_NULL_HENV) {
04855         return SQL_INVALID_HANDLE;
04856     }
04857     return SQL_ERROR;
04858 }
04859 #endif
04860 
04861 #ifndef WINTERFACE
04862 
04866 SQLRETURN SQL_API
04867 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
04868                  SQLCHAR *connout, SQLSMALLINT connoutMax,
04869                  SQLSMALLINT *connoutLen)
04870 {
04871     SQLRETURN ret;
04872 
04873     HDBC_LOCK(dbc);
04874     ret = drvunimpldbc(dbc);
04875     HDBC_UNLOCK(dbc);
04876     return ret;
04877 }
04878 #endif
04879 
04880 #ifdef WINTERFACE
04881 
04885 SQLRETURN SQL_API
04886 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
04887                   SQLWCHAR *connout, SQLSMALLINT connoutMax,
04888                   SQLSMALLINT *connoutLen)
04889 {
04890     SQLRETURN ret;
04891 
04892     HDBC_LOCK(dbc);
04893     ret = drvunimpldbc(dbc);
04894     HDBC_UNLOCK(dbc);
04895     return ret;
04896 }
04897 #endif
04898 
04907 static SQLRETURN
04908 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
04909 {
04910     STMT *s;
04911     int i, dlen, done = 0;
04912     BINDPARM *p;
04913 
04914     if (stmt == SQL_NULL_HSTMT) {
04915         return SQL_INVALID_HANDLE;
04916     }
04917     s = (STMT *) stmt;
04918     if (!s->query || s->nparams <= 0) {
04919 seqerr:
04920         setstat(s, -1, "sequence error", "HY010");
04921         return SQL_ERROR;
04922     }
04923     for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
04924         p = &s->bindparms[i];
04925         if (p->need > 0) {
04926             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
04927 
04928             if (len == SQL_NULL_DATA) {
04929                 freep(&p->parbuf);
04930                 p->param = NULL;
04931                 p->len = SQL_NULL_DATA;
04932                 p->need = -1;
04933             } else if (type != SQL_C_CHAR
04934 #ifdef WCHARSUPPORT
04935                        && type != SQL_C_WCHAR
04936 #endif
04937                        && type != SQL_C_BINARY) {
04938                 int size = 0;
04939 
04940                 switch (type) {
04941                 case SQL_C_TINYINT:
04942                 case SQL_C_UTINYINT:
04943                 case SQL_C_STINYINT:
04944 #ifdef SQL_BIT
04945                 case SQL_C_BIT:
04946 #endif
04947                     size = sizeof (SQLCHAR);
04948                     break;
04949                 case SQL_C_SHORT:
04950                 case SQL_C_USHORT:
04951                 case SQL_C_SSHORT:
04952                     size = sizeof (SQLSMALLINT);
04953                     break;
04954                 case SQL_C_LONG:
04955                 case SQL_C_ULONG:
04956                 case SQL_C_SLONG:
04957                     size = sizeof (SQLINTEGER);
04958                     break;
04959 #ifdef SQL_BIGINT
04960                 case SQL_C_UBIGINT:
04961                 case SQL_C_SBIGINT:
04962                     size = sizeof (SQLBIGINT);
04963                     break;
04964 #endif
04965                 case SQL_C_FLOAT:
04966                     size = sizeof (float);
04967                     break;
04968                 case SQL_C_DOUBLE:
04969                     size = sizeof (double);
04970                     break;
04971 #ifdef SQL_C_TYPE_DATE
04972                 case SQL_C_TYPE_DATE:
04973 #endif
04974                 case SQL_C_DATE:
04975                     size = sizeof (DATE_STRUCT);
04976                     break;
04977 #ifdef SQL_C_TYPE_DATE
04978                 case SQL_C_TYPE_TIME:
04979 #endif
04980                 case SQL_C_TIME:
04981                     size = sizeof (TIME_STRUCT);
04982                     break;
04983 #ifdef SQL_C_TYPE_DATE
04984                 case SQL_C_TYPE_TIMESTAMP:
04985 #endif
04986                 case SQL_C_TIMESTAMP:
04987                     size = sizeof (TIMESTAMP_STRUCT);
04988                     break;
04989                 }
04990                 freep(&p->parbuf);
04991                 p->parbuf = xmalloc(size);
04992                 if (!p->parbuf) {
04993                     return nomem(s);
04994                 }
04995                 p->param = p->parbuf;
04996                 memcpy(p->param, data, size);
04997                 p->len = size;
04998                 p->need = -1;
04999             } else if (len == SQL_NTS && (
05000                        type == SQL_C_CHAR
05001 #ifdef WCHARSUPPORT
05002                        || type == SQL_C_WCHAR
05003 #endif
05004                       )) {
05005                 char *dp = data;
05006 
05007 #ifdef WCHARSUPPORT
05008                 if (type == SQL_C_WCHAR) {
05009                     dp = uc_to_utf(data, len);
05010                     if (!dp) {
05011                         return nomem(s);
05012                     }
05013                 }
05014 #endif
05015 #if defined(_WIN32) || defined(_WIN64)
05016                 if (*s->oemcp) {
05017                     dp = wmb_to_utf(data, strlen (data));
05018                     if (!dp) {
05019                         return nomem(s);
05020                     }
05021                 }
05022 #endif
05023                 dlen = strlen(dp);
05024                 freep(&p->parbuf);
05025                 p->parbuf = xmalloc(dlen + 1);
05026                 if (!p->parbuf) {
05027                     if (dp != data) {
05028                         uc_free(dp);
05029                     }
05030                     return nomem(s);
05031                 }
05032                 p->param = p->parbuf;
05033                 strcpy(p->param, dp);
05034                 if (dp != data) {
05035                     uc_free(dp);
05036                 }
05037                 p->len = dlen;
05038                 p->need = -1;
05039             } else if (len < 0) {
05040                 setstat(s, -1, "invalid length", "HY090");
05041                 return SQL_ERROR;
05042             } else {
05043                 dlen = min(p->len - p->offs, len);
05044                 if (!p->param) {
05045                     setstat(s, -1, "no memory for parameter", "HY013");
05046                     return SQL_ERROR;
05047                 }
05048                 memcpy((char *) p->param + p->offs, data, dlen);
05049                 p->offs += dlen;
05050                 if (p->offs >= p->len) {
05051 #ifdef WCHARSUPPORT
05052                     if (type == SQL_C_WCHAR) {
05053                         char *dp = uc_to_utf(p->param, p->len);
05054                         char *np;
05055                         int nlen;
05056 
05057                         if (!dp) {
05058                             return nomem(s);
05059                         }
05060                         nlen = strlen(dp);
05061                         np = xmalloc(nlen + 1);
05062                         if (!np) {
05063                             uc_free(dp);
05064                             return nomem(s);
05065                         }
05066                         strcpy(np, dp);
05067                         uc_free(dp);
05068                         if (p->param == p->parbuf) {
05069                             freep(&p->parbuf);
05070                         }
05071                         p->parbuf = p->param = np;
05072                         p->len = nlen;
05073                     } else {
05074                         *((char *) p->param + p->len) = '\0';
05075                     }
05076                     p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
05077                             ? -1 : 0;
05078 #else
05079                     *((char *) p->param + p->len) = '\0';
05080                     p->need = (type == SQL_C_CHAR) ? -1 : 0;
05081 #endif
05082 #if defined(_WIN32) || defined(_WIN64)
05083                     if (type == SQL_C_CHAR && *s->oemcp &&
05084                         !(p->stype == SQL_BINARY ||
05085                           p->stype == SQL_VARBINARY ||
05086                           p->stype == SQL_LONGVARBINARY)) {
05087                         char *dp = wmb_to_utf(p->param, p->len);
05088 
05089                         if (!dp) {
05090                             return nomem(s);
05091                         }
05092                         if (p->param == p->parbuf) {
05093                             freep(&p->parbuf);
05094                         }
05095                         p->parbuf = p->param = dp;
05096                         p->len = strlen(dp);
05097                     }
05098                     if (p->type == SQL_C_WCHAR &&
05099                         (p->stype == SQL_VARCHAR ||
05100                          p->stype == SQL_LONGVARCHAR) &&
05101                          p->len == p->coldef * sizeof (SQLWCHAR)) {
05102                         /* fix for MS-Access */
05103                         p->len = p->coldef;
05104                     }
05105 #endif
05106                 }
05107             }
05108             done = 1;
05109             break;
05110         }
05111     }
05112     if (!done) {
05113         goto seqerr;
05114     }
05115     return SQL_SUCCESS;
05116 }
05117 
05126 SQLRETURN SQL_API
05127 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
05128 {
05129     SQLRETURN ret;
05130 
05131     HSTMT_LOCK(stmt);
05132     ret = drvputdata(stmt, data, len);
05133     HSTMT_UNLOCK(stmt);
05134     return ret;
05135 }
05136 
05142 static SQLRETURN
05143 freeparams(STMT *s)
05144 {
05145     if (s->bindparms) {
05146         int n;
05147 
05148         for (n = 0; n < s->nbindparms; n++) {
05149             freep(&s->bindparms[n].parbuf);
05150             memset(&s->bindparms[n], 0, sizeof (BINDPARM));
05151         }
05152     }
05153     return SQL_SUCCESS;
05154 }
05155 
05167 static SQLRETURN
05168 setupparam(STMT *s, char *sql, int pnum)
05169 {
05170     int type, len = 0, needalloc = 0;
05171     BINDPARM *p;
05172 
05173     if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
05174         goto error;
05175     }
05176     p = &s->bindparms[pnum];
05177     type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05178 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
05179     /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
05180     if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
05181         type = SQL_C_CHAR;
05182     }
05183 #endif
05184     if (p->need > 0) {
05185         return setupparbuf(s, p);
05186     }
05187     p->strbuf[0] = '\0';
05188     if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
05189         p->s3type = SQLITE_NULL;
05190         p->s3size = 0;
05191         return SQL_SUCCESS;
05192     }
05193     if (type == SQL_C_CHAR &&
05194         (p->stype == SQL_BINARY ||
05195          p->stype == SQL_VARBINARY ||
05196          p->stype == SQL_LONGVARBINARY)) {
05197         type = SQL_C_BINARY;
05198     }
05199     switch (type) {
05200     case SQL_C_BINARY:
05201         p->s3type = SQLITE_BLOB;
05202         p->s3val = p->param;
05203         if (!p->lenp) {
05204             len = p->len;
05205         } else if (*p->lenp == SQL_DATA_AT_EXEC) {
05206             len = p->len;
05207         } else {
05208             len = *p->lenp;
05209             if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
05210                 len = SQL_LEN_DATA_AT_EXEC(len);
05211             }
05212         }
05213         if (len < 0) {
05214             setstat(s, -1, "invalid length", "HY009");
05215             return SQL_ERROR;
05216         }
05217         p->len = len;
05218         p->max = p->len;
05219         p->s3size = len;
05220         break;
05221 #ifdef WCHARSUPPORT
05222     case SQL_C_WCHAR:
05223 #endif
05224     case SQL_C_CHAR:
05225         p->s3type = SQLITE_TEXT;
05226         p->s3size = -1;
05227         p->s3val = p->param;
05228         if (!p->parbuf) {
05229 #ifdef WCHARSUPPORT
05230             if (type == SQL_C_WCHAR) {
05231                 if (!p->lenp || *p->lenp == SQL_NTS) {
05232                     p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
05233                 } else if (*p->lenp >= 0) {
05234                     p->max = *p->lenp;
05235                 }
05236             } else
05237 #endif
05238             if (type == SQL_C_CHAR) {
05239                 if (!p->lenp || *p->lenp == SQL_NTS) {
05240                     p->len = p->max = strlen(p->param);
05241 #if defined(_WIN32) || defined(_WIN64)
05242                     needalloc = 1;
05243 #endif
05244                 } else if (*p->lenp >= 0) {
05245                     p->len = p->max = *p->lenp;
05246                     needalloc = 1;
05247                 }
05248             }
05249         }
05250         if (p->need < 0 && p->parbuf == p->param) {
05251             break;
05252         }
05253 #ifdef WCHARSUPPORT
05254         if (type == SQL_C_WCHAR) {
05255             char *dp = uc_to_utf(p->param, p->max);
05256 
05257             if (!dp) {
05258                 return nomem(s);
05259             }
05260             if (p->param == p->parbuf) {
05261                 freep(&p->parbuf);
05262             }
05263             p->parbuf = p->param = dp;
05264             p->need = -1;
05265             p->len = strlen(p->param);
05266             p->s3val = p->param;
05267             p->s3size = p->len;
05268         } else
05269 #endif
05270         if (type == SQL_C_CHAR) {
05271             p->s3val = p->param;
05272             if (needalloc) {
05273                 char *dp;
05274 
05275 #if defined(_WIN32) || defined(_WIN64)
05276                 if (*s->oemcp) {
05277                     dp = wmb_to_utf(p->param, p->len);
05278                 } else {
05279                     dp = xmalloc(p->len + 1);
05280                 }
05281 #else
05282                 dp = xmalloc(p->len + 1);
05283 #endif
05284                 if (!dp) {
05285                     return nomem(s);
05286                 }
05287 #if defined(_WIN32) || defined(_WIN64)
05288                 if (*s->oemcp) {
05289                     p->len = strlen(dp);
05290                 } else {
05291                     memcpy(dp, p->param, p->len);
05292                     dp[p->len] = '\0';
05293                 }
05294 #else
05295                 memcpy(dp, p->param, p->len);
05296                 dp[p->len] = '\0';
05297 #endif
05298                 if (p->param == p->parbuf) {
05299                     freep(&p->parbuf);
05300                 }
05301                 p->parbuf = p->param = dp;
05302                 p->need = -1;
05303                 p->s3val = p->param;
05304                 p->s3size = p->len;
05305             }
05306         }
05307         break;
05308     case SQL_C_UTINYINT:
05309     case SQL_C_TINYINT:
05310     case SQL_C_STINYINT:
05311         p->s3type = SQLITE_INTEGER;
05312         p->s3size = sizeof (int);
05313         p->s3ival = *((SQLCHAR *) p->param);
05314         break;
05315     case SQL_C_USHORT:
05316         p->s3type = SQLITE_INTEGER;
05317         p->s3size = sizeof (int);
05318         p->s3ival = *((SQLUSMALLINT *) p->param);
05319         break;
05320     case SQL_C_SHORT:
05321     case SQL_C_SSHORT:
05322         p->s3type = SQLITE_INTEGER;
05323         p->s3size = sizeof (int);
05324         p->s3ival = *((SQLSMALLINT *) p->param);
05325         break;
05326     case SQL_C_ULONG:
05327         p->s3type = SQLITE_INTEGER;
05328         p->s3size = sizeof (int);
05329         p->s3ival = *((SQLUINTEGER *) p->param);
05330         break;
05331     case SQL_C_LONG:
05332     case SQL_C_SLONG:
05333         p->s3type = SQLITE_INTEGER;
05334         p->s3size = sizeof (int);
05335         p->s3ival = *((SQLINTEGER *) p->param);
05336         break;
05337 #ifdef SQL_BIT
05338     case SQL_C_BIT:
05339         p->s3type = SQLITE_INTEGER;
05340         p->s3size = sizeof (int);
05341         p->s3ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
05342         break;
05343 #endif
05344 #ifdef SQL_BIGINT
05345     case SQL_C_SBIGINT:
05346         p->s3type = SQLITE_INTEGER;
05347         p->s3size = sizeof (sqlite_int64);
05348         p->s3lival = *((sqlite_int64 *) p->param);
05349         break;
05350     case SQL_C_UBIGINT:
05351         p->s3type = SQLITE_INTEGER;
05352         p->s3size = sizeof (sqlite_int64);
05353         p->s3lival = *((sqlite_uint64 *) p->param);
05354         break;
05355 #endif
05356     case SQL_C_FLOAT:
05357         p->s3type = SQLITE_FLOAT;
05358         p->s3size = sizeof (double);
05359         p->s3dval = *((float *) p->param);
05360         break;
05361     case SQL_C_DOUBLE:
05362         p->s3type = SQLITE_FLOAT;
05363         p->s3size = sizeof (double);
05364         p->s3dval = *((double *) p->param);
05365         break;
05366 #ifdef SQL_C_TYPE_DATE
05367     case SQL_C_TYPE_DATE:
05368 #endif
05369     case SQL_C_DATE:
05370         if (*s->jdconv) {
05371             int a, b, x1, x2, y, m, d;
05372 
05373             p->s3type = SQLITE_FLOAT;
05374             p->s3size = sizeof (double);
05375             y = ((DATE_STRUCT *) p->param)->year;
05376             m = ((DATE_STRUCT *) p->param)->month;
05377             d = ((DATE_STRUCT *) p->param)->day;
05378             if (m <= 2) {
05379                 y--;
05380                 m += 12;
05381             }
05382             a = y / 100;
05383             b = 2 - a + (a / 4);
05384             x1 = 36525 * (y + 4716) / 100;
05385             x2 = 306001 * (m + 1) / 10000;
05386             p->s3dval = x1 + x2 + d + b - 1524.5;
05387             break;
05388         }
05389         sprintf(p->strbuf, "%04d-%02d-%02d",
05390                 ((DATE_STRUCT *) p->param)->year,
05391                 ((DATE_STRUCT *) p->param)->month,
05392                 ((DATE_STRUCT *) p->param)->day);
05393         p->s3type = SQLITE_TEXT;
05394         p->s3size = -1;
05395         p->s3val = p->strbuf;
05396         break;
05397 #ifdef SQL_C_TYPE_TIME
05398     case SQL_C_TYPE_TIME:
05399 #endif
05400     case SQL_C_TIME:
05401         if (*s->jdconv) {
05402             p->s3type = SQLITE_FLOAT;
05403             p->s3size = sizeof (double);
05404             p->s3dval = 2451544.5 +
05405                (((TIME_STRUCT *) p->param)->hour * 3600000.0 +
05406                 ((TIME_STRUCT *) p->param)->minute * 60000.0 +
05407                 ((TIME_STRUCT *) p->param)->second * 1000.0) / 86400000.0;
05408             break;
05409         }
05410         sprintf(p->strbuf, "%02d:%02d:%02d",
05411                 ((TIME_STRUCT *) p->param)->hour,
05412                 ((TIME_STRUCT *) p->param)->minute,
05413                 ((TIME_STRUCT *) p->param)->second);
05414         p->s3type = SQLITE_TEXT;
05415         p->s3size = -1;
05416         p->s3val = p->strbuf;
05417         break;
05418 #ifdef SQL_C_TYPE_TIMESTAMP
05419     case SQL_C_TYPE_TIMESTAMP:
05420 #endif
05421     case SQL_C_TIMESTAMP:
05422         if (*s->jdconv) {
05423             int a, b, x1, x2, y, m, d;
05424 
05425             p->s3type = SQLITE_FLOAT;
05426             p->s3size = sizeof (double);
05427             y = ((TIMESTAMP_STRUCT *) p->param)->year;
05428             m = ((TIMESTAMP_STRUCT *) p->param)->month;
05429             d = ((TIMESTAMP_STRUCT *) p->param)->day;
05430             if (m <= 2) {
05431                 y--;
05432                 m += 12;
05433             }
05434             a = y / 100;
05435             b = 2 - a + (a / 4);
05436             x1 = 36525 * (y + 4716) / 100;
05437             x2 = 306001 * (m + 1) / 10000;
05438             p->s3dval = x1 + x2 + d + b - 1524.5 +
05439                (((TIMESTAMP_STRUCT *) p->param)->hour * 3600000.0 +
05440                 ((TIMESTAMP_STRUCT *) p->param)->minute * 60000.0 +
05441                 ((TIMESTAMP_STRUCT *) p->param)->second * 1000.0 +
05442                 ((TIMESTAMP_STRUCT *) p->param)->fraction / 1.0E6)
05443                / 86400000.0;
05444             break;
05445         }
05446         len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
05447         len /= 1000000;
05448         len = len % 1000;
05449         if (len < 0) {
05450             len = 0;
05451         }
05452         if (p->coldef && p->coldef <= 16) {
05453             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
05454                     ((TIMESTAMP_STRUCT *) p->param)->year,
05455                     ((TIMESTAMP_STRUCT *) p->param)->month,
05456                     ((TIMESTAMP_STRUCT *) p->param)->day,
05457                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05458                     ((TIMESTAMP_STRUCT *) p->param)->minute);
05459         } else if (p->coldef && p->coldef <= 19) {
05460             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
05461                     ((TIMESTAMP_STRUCT *) p->param)->year,
05462                     ((TIMESTAMP_STRUCT *) p->param)->month,
05463                     ((TIMESTAMP_STRUCT *) p->param)->day,
05464                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05465                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05466                     ((TIMESTAMP_STRUCT *) p->param)->second);
05467         } else {
05468             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
05469                     ((TIMESTAMP_STRUCT *) p->param)->year,
05470                     ((TIMESTAMP_STRUCT *) p->param)->month,
05471                     ((TIMESTAMP_STRUCT *) p->param)->day,
05472                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05473                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05474                     ((TIMESTAMP_STRUCT *) p->param)->second,
05475                     len);
05476         }
05477         p->s3type = SQLITE_TEXT;
05478         p->s3size = -1;
05479         p->s3val = p->strbuf;
05480         break;
05481     default:
05482     error:
05483         setstat(s, -1, "unsupported parameter type",
05484                 (*s->ov3) ? "07009" : "S1093");
05485         return SQL_ERROR;
05486     }
05487     return SQL_SUCCESS;
05488 }
05489 
05505 static SQLRETURN
05506 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05507              SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
05508              SQLSMALLINT scale,
05509              SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
05510 {
05511     STMT *s;
05512     BINDPARM *p;
05513 
05514     if (stmt == SQL_NULL_HSTMT) {
05515         return SQL_INVALID_HANDLE;
05516     }
05517     s = (STMT *) stmt;
05518     if (pnum == 0) {
05519         setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
05520         return SQL_ERROR;
05521     }
05522     if (!data && !len) {
05523         setstat(s, -1, "invalid buffer", "HY003");
05524         return SQL_ERROR;
05525     }
05526     --pnum;
05527     if (s->bindparms) {
05528         if (pnum >= s->nbindparms) {
05529             BINDPARM *newparms;
05530 
05531             newparms = xrealloc(s->bindparms,
05532                                 (pnum + 1) * sizeof (BINDPARM));
05533             if (!newparms) {
05534 outofmem:
05535                 return nomem(s);
05536             }
05537             s->bindparms = newparms;
05538             memset(&s->bindparms[s->nbindparms], 0,
05539                    (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
05540             s->nbindparms = pnum + 1;
05541         }
05542     } else {
05543         int npar = max(10, pnum + 1);
05544 
05545         s->bindparms = xmalloc(npar * sizeof (BINDPARM));
05546         if (!s->bindparms) {
05547             goto outofmem;
05548         }
05549         memset(s->bindparms, 0, npar * sizeof (BINDPARM));
05550         s->nbindparms = npar;
05551     }
05552     switch (buftype) {
05553     case SQL_C_STINYINT:
05554     case SQL_C_UTINYINT:
05555     case SQL_C_TINYINT:
05556 #ifdef SQL_C_BIT
05557     case SQL_C_BIT:
05558 #endif
05559         buflen = sizeof (SQLCHAR);
05560         break;
05561     case SQL_C_SHORT:
05562     case SQL_C_USHORT:
05563     case SQL_C_SSHORT:
05564         buflen = sizeof (SQLSMALLINT);
05565         break;
05566     case SQL_C_SLONG:
05567     case SQL_C_ULONG:
05568     case SQL_C_LONG:
05569         buflen = sizeof (SQLINTEGER);
05570         break;
05571     case SQL_C_FLOAT:
05572         buflen = sizeof (float);
05573         break;
05574     case SQL_C_DOUBLE:
05575         buflen = sizeof (double);
05576         break;
05577     case SQL_C_TIMESTAMP:
05578 #ifdef SQL_C_TYPE_TIMESTAMP
05579     case SQL_C_TYPE_TIMESTAMP:
05580 #endif
05581         buflen = sizeof (TIMESTAMP_STRUCT);
05582         break;
05583     case SQL_C_TIME:
05584 #ifdef SQL_C_TYPE_TIME
05585     case SQL_C_TYPE_TIME:
05586 #endif
05587         buflen = sizeof (TIME_STRUCT);
05588         break;
05589     case SQL_C_DATE:
05590 #ifdef SQL_C_TYPE_DATE
05591     case SQL_C_TYPE_DATE:
05592 #endif
05593         buflen = sizeof (DATE_STRUCT);
05594         break;
05595 #ifdef SQL_C_UBIGINT
05596     case SQL_C_UBIGINT:
05597         buflen = sizeof (SQLBIGINT);
05598         break;
05599 #endif
05600 #ifdef SQL_C_SBIGINT
05601     case SQL_C_SBIGINT:
05602         buflen = sizeof (SQLBIGINT);
05603         break;
05604 #endif
05605 #ifdef SQL_C_BIGINT
05606     case SQL_C_BIGINT:
05607         buflen = sizeof (SQLBIGINT);
05608         break;
05609 #endif
05610     }
05611     p = &s->bindparms[pnum];
05612     p->type = buftype;
05613     p->stype = ptype;
05614     p->coldef = coldef;
05615     p->scale = scale;
05616     p->max = buflen;
05617     p->inc = buflen;
05618     p->lenp = p->lenp0 = len;
05619     p->offs = 0;
05620     p->len = 0;
05621     p->param0 = data;
05622     freep(&p->parbuf);
05623     p->param = p->param0;
05624     p->bound = 1;
05625     p->need = 0;
05626     return SQL_SUCCESS;
05627 }
05628 
05644 SQLRETURN SQL_API
05645 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05646                  SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
05647                  SQLSMALLINT scale,
05648                  SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
05649 {
05650     SQLRETURN ret;
05651 
05652     HSTMT_LOCK(stmt);
05653     ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
05654                        scale, data, buflen, len);
05655     HSTMT_UNLOCK(stmt);
05656     return ret;
05657 }
05658 
05659 #ifndef HAVE_IODBC
05660 
05673 SQLRETURN SQL_API
05674 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
05675              SQLSMALLINT ptype, SQLULEN lenprec,
05676              SQLSMALLINT scale, SQLPOINTER val,
05677              SQLLEN *lenp)
05678 {
05679     SQLRETURN ret;
05680 
05681     HSTMT_LOCK(stmt);
05682     ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
05683                        lenprec, scale, val, 0, lenp);
05684     HSTMT_UNLOCK(stmt);
05685     return ret;
05686 }
05687 #endif
05688 
05696 SQLRETURN SQL_API
05697 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
05698 {
05699     STMT *s;
05700     SQLSMALLINT dummy;
05701 
05702     HSTMT_LOCK(stmt);
05703     if (stmt == SQL_NULL_HSTMT) {
05704         return SQL_INVALID_HANDLE;
05705     }
05706     s = (STMT *) stmt;
05707     if (!nparam) {
05708         nparam = &dummy;
05709     }
05710     *nparam = s->nparams;
05711     HSTMT_UNLOCK(stmt);
05712     return SQL_SUCCESS;
05713 }
05714 
05722 static SQLRETURN
05723 setupparbuf(STMT *s, BINDPARM *p)
05724 {
05725     if (!p->parbuf) {
05726         if (*p->lenp == SQL_DATA_AT_EXEC) {
05727             p->len = p->max;
05728         } else {
05729             p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
05730         }
05731         if (p->len < 0 && p->len != SQL_NTS &&
05732             p->len != SQL_NULL_DATA) {
05733             setstat(s, -1, "invalid length", "HY009");
05734             return SQL_ERROR;
05735         }
05736         if (p->len >= 0) {
05737             p->parbuf = xmalloc(p->len + 2);
05738             if (!p->parbuf) {
05739                 return nomem(s);
05740             }
05741             p->param = p->parbuf;
05742         } else {
05743             p->param = NULL;
05744         }
05745     }
05746     return SQL_NEED_DATA;
05747 }
05748 
05756 SQLRETURN SQL_API
05757 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
05758 {
05759     STMT *s;
05760     int i;
05761     SQLPOINTER dummy;
05762     SQLRETURN ret;
05763     BINDPARM *p;
05764 
05765     HSTMT_LOCK(stmt);
05766     if (stmt == SQL_NULL_HSTMT) {
05767         return SQL_INVALID_HANDLE;
05768     }
05769     s = (STMT *) stmt;
05770     if (!pind) {
05771         pind = &dummy;
05772     }
05773     if (s->pdcount < s->nparams) {
05774         s->pdcount++;
05775     }
05776     for (i = 0; i < s->pdcount; i++) {
05777         p = &s->bindparms[i];
05778         if (p->need > 0) {
05779             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05780 
05781             p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? -1 : 0;
05782         }
05783     }
05784     for (; i < s->nparams; i++) {
05785         p = &s->bindparms[i];
05786         if (p->need > 0) {
05787             *pind = (SQLPOINTER) p->param0;
05788             ret = setupparbuf(s, p);
05789             s->pdcount = i;
05790             goto done;
05791         }
05792     }
05793     ret = drvexecute(stmt, 0);
05794 done:
05795     HSTMT_UNLOCK(stmt);
05796     return ret;
05797 }
05798 
05810 SQLRETURN SQL_API
05811 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
05812                  SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
05813 {
05814     STMT *s;
05815     SQLRETURN ret = SQL_ERROR;
05816 
05817     HSTMT_LOCK(stmt);
05818     if (stmt == SQL_NULL_HSTMT) {
05819         return SQL_INVALID_HANDLE;
05820     }
05821     s = (STMT *) stmt;
05822     --pnum;
05823     if (pnum >= s->nparams) {
05824         setstat(s, -1, "invalid parameter index",
05825                 (*s->ov3) ? "HY000" : "S1000");
05826         goto done;
05827     }
05828     if (dtype) {
05829 #ifdef SQL_LONGVARCHAR
05830 #ifdef WINTERFACE
05831         *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
05832 #else
05833         *dtype = SQL_LONGVARCHAR;
05834 #endif
05835 #else
05836 #ifdef WINTERFACE
05837         *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
05838 #else
05839         *dtype = SQL_VARCHAR;
05840 #endif
05841 #endif
05842     }
05843     if (size) {
05844 #ifdef SQL_LONGVARCHAR
05845         *size = 65536;
05846 #else
05847         *size = 255;
05848 #endif
05849     }
05850     if (decdigits) {
05851         *decdigits = 0;
05852     }
05853     if (nullable) {
05854         *nullable = SQL_NULLABLE;
05855     }
05856     ret = SQL_SUCCESS;
05857 done:
05858     HSTMT_UNLOCK(stmt);
05859     return ret;
05860 }
05861 
05875 SQLRETURN SQL_API
05876 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
05877             SQLSMALLINT sqltype, SQLULEN coldef,
05878             SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
05879 {
05880     SQLRETURN ret;
05881 
05882     HSTMT_LOCK(stmt);
05883     ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
05884                        type, sqltype, coldef, scale, val,
05885                        SQL_SETPARAM_VALUE_MAX, nval);
05886     HSTMT_UNLOCK(stmt);
05887     return ret;
05888 }
05889 
05894 SQLRETURN SQL_API
05895 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
05896 {
05897     SQLRETURN ret;
05898 
05899     HSTMT_LOCK(stmt);
05900     ret = drvunimplstmt(stmt);
05901     HSTMT_UNLOCK(stmt);
05902     return ret;
05903 }
05904 
05905 #ifndef WINTERFACE
05906 
05910 SQLRETURN SQL_API
05911 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
05912                 SQLSMALLINT fieldid, SQLPOINTER value,
05913                 SQLINTEGER buflen, SQLINTEGER *strlen)
05914 {
05915     return SQL_ERROR;
05916 }
05917 #endif
05918 
05919 #ifdef WINTERFACE
05920 
05924 SQLRETURN SQL_API
05925 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05926                  SQLSMALLINT fieldid, SQLPOINTER value,
05927                  SQLINTEGER buflen, SQLINTEGER *strlen)
05928 {
05929     return SQL_ERROR;
05930 }
05931 #endif
05932 
05933 #ifndef WINTERFACE
05934 
05938 SQLRETURN SQL_API
05939 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
05940                 SQLSMALLINT fieldid, SQLPOINTER value,
05941                 SQLINTEGER buflen)
05942 {
05943     return SQL_ERROR;
05944 }
05945 #endif
05946 
05947 #ifdef WINTERFACE
05948 
05952 SQLRETURN SQL_API
05953 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05954                  SQLSMALLINT fieldid, SQLPOINTER value,
05955                  SQLINTEGER buflen)
05956 {
05957     return SQL_ERROR;
05958 }
05959 #endif
05960 
05961 #ifndef WINTERFACE
05962 
05966 SQLRETURN SQL_API
05967 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05968               SQLCHAR *name, SQLSMALLINT buflen,
05969               SQLSMALLINT *strlen, SQLSMALLINT *type,
05970               SQLSMALLINT *subtype, SQLLEN *len,
05971               SQLSMALLINT *prec, SQLSMALLINT *scale,
05972               SQLSMALLINT *nullable)
05973 {
05974     return SQL_ERROR;
05975 }
05976 #endif
05977 
05978 #ifdef WINTERFACE
05979 
05983 SQLRETURN SQL_API
05984 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
05985                SQLWCHAR *name, SQLSMALLINT buflen,
05986                SQLSMALLINT *strlen, SQLSMALLINT *type,
05987                SQLSMALLINT *subtype, SQLLEN *len,
05988                SQLSMALLINT *prec, SQLSMALLINT *scale,
05989                SQLSMALLINT *nullable)
05990 {
05991     return SQL_ERROR;
05992 }
05993 #endif
05994 
05999 SQLRETURN SQL_API
06000 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
06001               SQLSMALLINT type, SQLSMALLINT subtype,
06002               SQLLEN len, SQLSMALLINT prec,
06003               SQLSMALLINT scale, SQLPOINTER data,
06004               SQLLEN *strlen, SQLLEN *indicator)
06005 {
06006     return SQL_ERROR;
06007 }
06008 
06020 static SQLRETURN
06021 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
06022             int ncols3, int *nret)
06023 {
06024     STMT *s;
06025     DBC *d;
06026 
06027     if (stmt == SQL_NULL_HSTMT) {
06028         return SQL_INVALID_HANDLE;
06029     }
06030     s = (STMT *) stmt;
06031     if (s->dbc == SQL_NULL_HDBC) {
06032 noconn:
06033         return noconn(s);
06034     }
06035     d = (DBC *) s->dbc;
06036     if (!d->sqlite) {
06037         goto noconn;
06038     }
06039     s3stmt_end_if(s);
06040     freeresult(s, 0);
06041     if (colspec3 && *s->ov3) {
06042         s->ncols = ncols3;
06043         s->cols = colspec3;
06044     } else {
06045         s->ncols = ncols;
06046         s->cols = colspec;
06047     }
06048     mkbindcols(s, s->ncols);
06049     s->nowchar[1] = 1;
06050     s->nrows = 0;
06051     s->rowp = s->rowprs = -1;
06052     s->isselect = -1;
06053     if (nret) {
06054         *nret = s->ncols;
06055     }
06056     return SQL_SUCCESS;
06057 }
06058 
06063 static COL tablePrivSpec2[] = {
06064     { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06065     { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06066     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06067     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06068     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06069     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
06070     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
06071 };
06072 
06073 static COL tablePrivSpec3[] = {
06074     { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
06075     { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06076     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06077     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06078     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06079     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
06080     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
06081 };
06082 
06095 static SQLRETURN
06096 drvtableprivileges(SQLHSTMT stmt,
06097                    SQLCHAR *cat, SQLSMALLINT catLen,
06098                    SQLCHAR *schema, SQLSMALLINT schemaLen,
06099                    SQLCHAR *table, SQLSMALLINT tableLen)
06100 {
06101     SQLRETURN ret;
06102     STMT *s;
06103     DBC *d;
06104     int ncols, rc, size, npatt;
06105     char *errp = NULL, *sql, tname[512];
06106 
06107     ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
06108                       tablePrivSpec3, array_size(tablePrivSpec3), NULL);
06109     if (ret != SQL_SUCCESS) {
06110         return ret;
06111     }
06112     s = (STMT *) stmt;
06113     d = (DBC *) s->dbc;
06114     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
06115         table = NULL;
06116         goto doit;
06117     }
06118     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
06119         schema[0] == '%') {
06120         if ((!cat || catLen == 0 || !cat[0]) &&
06121             (!table || tableLen == 0 || !table[0])) {
06122             table = NULL;
06123             goto doit;
06124         }
06125     }
06126 doit:
06127     if (!table) {
06128         size = 1;
06129         tname[0] = '%';
06130     } else {
06131         if (tableLen == SQL_NTS) {
06132             size = sizeof (tname) - 1;
06133         } else {
06134             size = min(sizeof (tname) - 1, tableLen);
06135         }
06136         strncpy(tname, (char *) table, size);
06137     }
06138     tname[size] = '\0';
06139     npatt = unescpat(tname);
06140 #if defined(_WIN32) || defined(_WIN64)
06141     if (npatt) {
06142         sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
06143                               "%s as 'TABLE_OWNER', "
06144                               "tbl_name as 'TABLE_NAME', "
06145                               "'' as 'GRANTOR', "
06146                               "'' as 'GRANTEE', "
06147                               "'SELECT' AS 'PRIVILEGE', "
06148                               "NULL as 'IS_GRANTABLE' "
06149                               "from sqlite_master where "
06150                               "(type = 'table' or type = 'view') "
06151                               "and tbl_name like %Q "
06152                               "UNION "
06153                               "select %s as 'TABLE_QUALIFIER', "
06154                               "%s as 'TABLE_OWNER', "
06155                               "tbl_name as 'TABLE_NAME', "
06156                               "'' as 'GRANTOR', "
06157                               "'' as 'GRANTEE', "
06158                               "'UPDATE' AS 'PRIVILEGE', "
06159                               "NULL as 'IS_GRANTABLE' "
06160                               "from sqlite_master where "
06161                               "(type = 'table' or type = 'view') "
06162                               "and tbl_name like %Q "
06163                               "UNION "
06164                               "select %s as 'TABLE_QUALIFIER', "
06165                               "%s as 'TABLE_OWNER', "
06166                               "tbl_name as 'TABLE_NAME', "
06167                               "'' as 'GRANTOR', "
06168                               "'' as 'GRANTEE', "
06169                               "'DELETE' AS 'PRIVILEGE', "
06170                               "NULL as 'IS_GRANTABLE' "
06171                               "from sqlite_master where "
06172                               "(type = 'table' or type = 'view') "
06173                               "and tbl_name like %Q "
06174                               "UNION "
06175                               "select %s as 'TABLE_QUALIFIER', "
06176                               "%s as 'TABLE_OWNER', "
06177                               "tbl_name as 'TABLE_NAME', "
06178                               "'' as 'GRANTOR', "
06179                               "'' as 'GRANTEE', "
06180                               "'INSERT' AS 'PRIVILEGE', "
06181                               "NULL as 'IS_GRANTABLE' "
06182                               "from sqlite_master where "
06183                               "(type = 'table' or type = 'view') "
06184                               "and tbl_name like %Q "
06185                               "UNION "
06186                               "select %s as 'TABLE_QUALIFIER', "
06187                               "%s as 'TABLE_OWNER', "
06188                               "tbl_name as 'TABLE_NAME', "
06189                               "'' as 'GRANTOR', "
06190                               "'' as 'GRANTEE', "
06191                               "'REFERENCES' AS 'PRIVILEGE', "
06192                               "NULL as 'IS_GRANTABLE' "
06193                               "from sqlite_master where "
06194                               "(type = 'table' or type = 'view') "
06195                               "and tbl_name like %Q",
06196                               d->xcelqrx ? "'main'" : "NULL",
06197                               d->xcelqrx ? "''" : "NULL",
06198                               tname,
06199                               d->xcelqrx ? "'main'" : "NULL",
06200                               d->xcelqrx ? "''" : "NULL",
06201                               tname,
06202                               d->xcelqrx ? "'main'" : "NULL",
06203                               d->xcelqrx ? "''" : "NULL",
06204                               tname,
06205                               d->xcelqrx ? "'main'" : "NULL",
06206                               d->xcelqrx ? "''" : "NULL",
06207                               tname,
06208                               d->xcelqrx ? "'main'" : "NULL",
06209                               d->xcelqrx ? "''" : "NULL",
06210                               tname);
06211     } else {
06212         sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
06213                               "%s as 'TABLE_OWNER', "
06214                               "tbl_name as 'TABLE_NAME', "
06215                               "'' as 'GRANTOR', "
06216                               "'' as 'GRANTEE', "
06217                               "'SELECT' AS 'PRIVILEGE', "
06218                               "NULL as 'IS_GRANTABLE' "
06219                               "from sqlite_master where "
06220                               "(type = 'table' or type = 'view') "
06221                               "and lower(tbl_name) = lower(%Q) "
06222                               "UNION "
06223                               "select %s as 'TABLE_QUALIFIER', "
06224                               "%s as 'TABLE_OWNER', "
06225                               "tbl_name as 'TABLE_NAME', "
06226                               "'' as 'GRANTOR', "
06227                               "'' as 'GRANTEE', "
06228                               "'UPDATE' AS 'PRIVILEGE', "
06229                               "NULL as 'IS_GRANTABLE' "
06230                               "from sqlite_master where "
06231                               "(type = 'table' or type = 'view') "
06232                               "and lower(tbl_name) = lower(%Q) "
06233                               "UNION "
06234                               "select %s as 'TABLE_QUALIFIER', "
06235                               "%s as 'TABLE_OWNER', "
06236                               "tbl_name as 'TABLE_NAME', "
06237                               "'' as 'GRANTOR', "
06238                               "'' as 'GRANTEE', "
06239                               "'DELETE' AS 'PRIVILEGE', "
06240                               "NULL as 'IS_GRANTABLE' "
06241                               "from sqlite_master where "
06242                               "(type = 'table' or type = 'view') "
06243                               "and lower(tbl_name) = lower(%Q) "
06244                               "UNION "
06245                               "select %s as 'TABLE_QUALIFIER', "
06246                               "%s as 'TABLE_OWNER', "
06247                               "tbl_name as 'TABLE_NAME', "
06248                               "'' as 'GRANTOR', "
06249                               "'' as 'GRANTEE', "
06250                               "'INSERT' AS 'PRIVILEGE', "
06251                               "NULL as 'IS_GRANTABLE' "
06252                               "from sqlite_master where "
06253                               "(type = 'table' or type = 'view') "
06254                               "and lower(tbl_name) = lower(%Q) "
06255                               "UNION "
06256                               "select %s as 'TABLE_QUALIFIER', "
06257                               "%s as 'TABLE_OWNER', "
06258                               "tbl_name as 'TABLE_NAME', "
06259                               "'' as 'GRANTOR', "
06260                               "'' as 'GRANTEE', "
06261                               "'REFERENCES' AS 'PRIVILEGE', "
06262                               "NULL as 'IS_GRANTABLE' "
06263                               "from sqlite_master where "
06264                               "(type = 'table' or type = 'view') "
06265                               "and lower(tbl_name) = lower(%Q)",
06266                               d->xcelqrx ? "'main'" : "NULL",
06267                               d->xcelqrx ? "''" : "NULL",
06268                               tname,
06269                               d->xcelqrx ? "'main'" : "NULL",
06270                               d->xcelqrx ? "''" : "NULL",
06271                               tname,
06272                               d->xcelqrx ? "'main'" : "NULL",
06273                               d->xcelqrx ? "''" : "NULL",
06274                               tname,
06275                               d->xcelqrx ? "'main'" : "NULL",
06276                               d->xcelqrx ? "''" : "NULL",
06277                               tname,
06278                               d->xcelqrx ? "'main'" : "NULL",
06279                               d->xcelqrx ? "''" : "NULL",
06280                               tname);
06281     }
06282 #else
06283     if (npatt) {
06284         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
06285                               "NULL as 'TABLE_OWNER', "
06286                               "tbl_name as 'TABLE_NAME', "
06287                               "'' as 'GRANTOR', "
06288                               "'' as 'GRANTEE', "
06289                               "'SELECT' AS 'PRIVILEGE', "
06290                               "NULL as 'IS_GRANTABLE' "
06291                               "from sqlite_master where "
06292                               "(type = 'table' or type = 'view') "
06293                               "and tbl_name like %Q "
06294                               "UNION "
06295                               "select NULL as 'TABLE_QUALIFIER', "
06296                               "NULL as 'TABLE_OWNER', "
06297                               "tbl_name as 'TABLE_NAME', "
06298                               "'' as 'GRANTOR', "
06299                               "'' as 'GRANTEE', "
06300                               "'UPDATE' AS 'PRIVILEGE', "
06301                               "NULL as 'IS_GRANTABLE' "
06302                               "from sqlite_master where "
06303                               "(type = 'table' or type = 'view') "
06304                               "and tbl_name like %Q "
06305                               "UNION "
06306                               "select NULL as 'TABLE_QUALIFIER', "
06307                               "NULL as 'TABLE_OWNER', "
06308                               "tbl_name as 'TABLE_NAME', "
06309                               "'' as 'GRANTOR', "
06310                               "'' as 'GRANTEE', "
06311                               "'DELETE' AS 'PRIVILEGE', "
06312                               "NULL as 'IS_GRANTABLE' "
06313                               "from sqlite_master where "
06314                               "(type = 'table' or type = 'view') "
06315                               "and tbl_name like %Q "
06316                               "UNION "
06317                               "select NULL as 'TABLE_QUALIFIER', "
06318                               "NULL as 'TABLE_OWNER', "
06319                               "tbl_name as 'TABLE_NAME', "
06320                               "'' as 'GRANTOR', "
06321                               "'' as 'GRANTEE', "
06322                               "'INSERT' AS 'PRIVILEGE', "
06323                               "NULL as 'IS_GRANTABLE' "
06324                               "from sqlite_master where "
06325                               "(type = 'table' or type = 'view') "
06326                               "and tbl_name like %Q "
06327                               "UNION "
06328                               "select NULL as 'TABLE_QUALIFIER', "
06329                               "NULL as 'TABLE_OWNER', "
06330                               "tbl_name as 'TABLE_NAME', "
06331                               "'' as 'GRANTOR', "
06332                               "'' as 'GRANTEE', "
06333                               "'REFERENCES' AS 'PRIVILEGE', "
06334                               "NULL as 'IS_GRANTABLE' "
06335                               "from sqlite_master where "
06336                               "(type = 'table' or type = 'view') "
06337                               "and tbl_name like %Q",
06338                               tname, tname, tname, tname, tname);
06339     } else {
06340         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
06341                               "NULL as 'TABLE_OWNER', "
06342                               "tbl_name as 'TABLE_NAME', "
06343                               "'' as 'GRANTOR', "
06344                               "'' as 'GRANTEE', "
06345                               "'SELECT' AS 'PRIVILEGE', "
06346                               "NULL as 'IS_GRANTABLE' "
06347                               "from sqlite_master where "
06348                               "(type = 'table' or type = 'view') "
06349                               "and lower(tbl_name) = lower(%Q) "
06350                               "UNION "
06351                               "select NULL as 'TABLE_QUALIFIER', "
06352                               "NULL as 'TABLE_OWNER', "
06353                               "tbl_name as 'TABLE_NAME', "
06354                               "'' as 'GRANTOR', "
06355                               "'' as 'GRANTEE', "
06356                               "'UPDATE' AS 'PRIVILEGE', "
06357                               "NULL as 'IS_GRANTABLE' "
06358                               "from sqlite_master where "
06359                               "(type = 'table' or type = 'view') "
06360                               "and lower(tbl_name) = lower(%Q) "
06361                               "UNION "
06362                               "select NULL as 'TABLE_QUALIFIER', "
06363                               "NULL as 'TABLE_OWNER', "
06364                               "tbl_name as 'TABLE_NAME', "
06365                               "'' as 'GRANTOR', "
06366                               "'' as 'GRANTEE', "
06367                               "'DELETE' AS 'PRIVILEGE', "
06368                               "NULL as 'IS_GRANTABLE' "
06369                               "from sqlite_master where "
06370                               "(type = 'table' or type = 'view') "
06371                               "and lower(tbl_name) = lower(%Q) "
06372                               "UNION "
06373                               "select NULL as 'TABLE_QUALIFIER', "
06374                               "NULL as 'TABLE_OWNER', "
06375                               "tbl_name as 'TABLE_NAME', "
06376                               "'' as 'GRANTOR', "
06377                               "'' as 'GRANTEE', "
06378                               "'INSERT' AS 'PRIVILEGE', "
06379                               "NULL as 'IS_GRANTABLE' "
06380                               "from sqlite_master where "
06381                               "(type = 'table' or type = 'view') "
06382                               "and lower(tbl_name) = lower(%Q) "
06383                               "UNION "
06384                               "select NULL as 'TABLE_QUALIFIER', "
06385                               "NULL as 'TABLE_OWNER', "
06386                               "tbl_name as 'TABLE_NAME', "
06387                               "'' as 'GRANTOR', "
06388                               "'' as 'GRANTEE', "
06389                               "'REFERENCES' AS 'PRIVILEGE', "
06390                               "NULL as 'IS_GRANTABLE' "
06391                               "from sqlite_master where "
06392                               "(type = 'table' or type = 'view') "
06393                               "and lower(tbl_name) = lower(%Q)",
06394                               tname, tname, tname, tname, tname);
06395     }
06396 #endif
06397     if (!sql) {
06398         return nomem(s);
06399     }
06400     ret = starttran(s);
06401     if (ret != SQL_SUCCESS) {
06402         sqlite3_free(sql);
06403         return ret;
06404     }
06405     dbtraceapi(d, "sqlite3_get_table", sql);
06406     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
06407     sqlite3_free(sql);
06408     if (rc == SQLITE_OK) {
06409         if (ncols != s->ncols) {
06410             freeresult(s, 0);
06411             s->nrows = 0;
06412         } else {
06413             s->rowfree = sqlite3_free_table;
06414         }
06415     } else {
06416         s->nrows = 0;
06417         s->rows = NULL;
06418         s->rowfree = NULL;
06419     }
06420     if (errp) {
06421         sqlite3_free(errp);
06422         errp = NULL;
06423     }
06424     s->rowp = s->rowprs = -1;
06425     return SQL_SUCCESS;
06426 }
06427 
06428 
06429 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06430 
06442 SQLRETURN SQL_API
06443 SQLTablePrivileges(SQLHSTMT stmt,
06444                    SQLCHAR *catalog, SQLSMALLINT catalogLen,
06445                    SQLCHAR *schema, SQLSMALLINT schemaLen,
06446                    SQLCHAR *table, SQLSMALLINT tableLen)
06447 {
06448 #if defined(_WIN32) || defined(_WIN64)
06449     char *c = NULL, *s = NULL, *t = NULL;
06450 #endif
06451     SQLRETURN ret;
06452 
06453     HSTMT_LOCK(stmt);
06454 #if defined(_WIN32) || defined(_WIN64)
06455     if (!((STMT *) stmt)->oemcp[0]) {
06456         ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06457                                  table, tableLen);
06458         goto done2;
06459     }
06460     if (catalog) {
06461         c = wmb_to_utf_c((char *) catalog, catalogLen);
06462         if (!c) {
06463             ret = nomem((STMT *) stmt);
06464             goto done;
06465         }
06466     }
06467     if (schema) {
06468         s = wmb_to_utf_c((char *) schema, schemaLen);
06469         if (!s) {
06470             ret = nomem((STMT *) stmt);
06471             goto done;
06472         }
06473     }
06474     if (table) {
06475         t = wmb_to_utf_c((char *) table, tableLen);
06476         if (!t) {
06477             ret = nomem((STMT *) stmt);
06478             goto done;
06479         }
06480     }
06481     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06482                              (SQLCHAR *) s, SQL_NTS,
06483                              (SQLCHAR *) t, SQL_NTS);
06484 #else
06485     ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06486                              table, tableLen);
06487 #endif
06488 #if defined(_WIN32) || defined(_WIN64)
06489 done:
06490     uc_free(t);
06491     uc_free(s);
06492     uc_free(c);
06493 done2:
06494     ;
06495 #endif
06496     HSTMT_UNLOCK(stmt);
06497     return ret;
06498 }
06499 #endif
06500 
06501 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06502 #ifdef WINTERFACE
06503 
06515 SQLRETURN SQL_API
06516 SQLTablePrivilegesW(SQLHSTMT stmt,
06517                     SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06518                     SQLWCHAR *schema, SQLSMALLINT schemaLen,
06519                     SQLWCHAR *table, SQLSMALLINT tableLen)
06520 {
06521     char *c = NULL, *s = NULL, *t = NULL;
06522     SQLRETURN ret;
06523 
06524     HSTMT_LOCK(stmt);
06525     if (catalog) {
06526         c = uc_to_utf_c(catalog, catalogLen);
06527         if (!c) {
06528             ret = nomem((STMT *) stmt);
06529             goto done;
06530         }
06531     }
06532     if (schema) {
06533         s = uc_to_utf_c(schema, schemaLen);
06534         if (!s) {
06535             ret = nomem((STMT *) stmt);
06536             goto done;
06537         }
06538     }
06539     if (table) {
06540         t = uc_to_utf_c(table, tableLen);
06541         if (!t) {
06542             ret = nomem((STMT *) stmt);
06543             goto done;
06544         }
06545     }
06546     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06547                              (SQLCHAR *) s, SQL_NTS,
06548                              (SQLCHAR *) t, SQL_NTS);
06549 done:
06550     uc_free(t);
06551     uc_free(s);
06552     uc_free(c);
06553     HSTMT_UNLOCK(stmt);
06554     return ret;
06555 }
06556 #endif
06557 #endif
06558 
06563 static COL colPrivSpec2[] = {
06564     { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06565     { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06566     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06567     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06568     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06569     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06570     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06571 };
06572 
06573 static COL colPrivSpec3[] = {
06574     { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
06575     { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06576     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06577     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06578     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06579     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06580     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06581 };
06582 
06583 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06584 
06598 SQLRETURN SQL_API
06599 SQLColumnPrivileges(SQLHSTMT stmt,
06600                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
06601                     SQLCHAR *schema, SQLSMALLINT schemaLen,
06602                     SQLCHAR *table, SQLSMALLINT tableLen,
06603                     SQLCHAR *column, SQLSMALLINT columnLen)
06604 {
06605     SQLRETURN ret;
06606 
06607     HSTMT_LOCK(stmt);
06608     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06609                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06610     HSTMT_UNLOCK(stmt);
06611     return ret;
06612 }
06613 #endif
06614 
06615 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06616 #ifdef WINTERFACE
06617 
06631 SQLRETURN SQL_API
06632 SQLColumnPrivilegesW(SQLHSTMT stmt,
06633                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06634                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
06635                      SQLWCHAR *table, SQLSMALLINT tableLen,
06636                      SQLWCHAR *column, SQLSMALLINT columnLen)
06637 {
06638     SQLRETURN ret;
06639 
06640     HSTMT_LOCK(stmt);
06641     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06642                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06643     HSTMT_UNLOCK(stmt);
06644     return ret;
06645 }
06646 #endif
06647 #endif
06648 
06653 static COL pkeySpec2[] = {
06654     { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06655     { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06656     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06657     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06658     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06659     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06660 };
06661 
06662 static COL pkeySpec3[] = {
06663     { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
06664     { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06665     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06666     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06667     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06668     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06669 };
06670 
06683 static SQLRETURN
06684 drvprimarykeys(SQLHSTMT stmt,
06685                SQLCHAR *cat, SQLSMALLINT catLen,
06686                SQLCHAR *schema, SQLSMALLINT schemaLen,
06687                SQLCHAR *table, SQLSMALLINT tableLen)
06688 {
06689     STMT *s;
06690     DBC *d;
06691     SQLRETURN sret;
06692     int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
06693     int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
06694     PTRDIFF_T size;
06695     char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
06696 
06697     sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
06698                        pkeySpec3, array_size(pkeySpec3), &asize);
06699     if (sret != SQL_SUCCESS) {
06700         return sret;
06701     }
06702     s = (STMT *) stmt;
06703     d = (DBC *) s->dbc;
06704     if (!table || table[0] == '\0' || table[0] == '%') {
06705         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06706         return SQL_ERROR;
06707     }
06708     if (tableLen == SQL_NTS) {
06709         size = sizeof (tname) - 1;
06710     } else {
06711         size = min(sizeof (tname) - 1, tableLen);
06712     }
06713     strncpy(tname, (char *) table, size);
06714     tname[size] = '\0';
06715     unescpat(tname);
06716     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
06717     if (!sql) {
06718         return nomem(s);
06719     }
06720     sret = starttran(s);
06721     if (sret != SQL_SUCCESS) {
06722         sqlite3_free(sql);
06723         return sret;
06724     }
06725     dbtraceapi(d, "sqlite3_get_table", sql);
06726     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06727     sqlite3_free(sql);
06728     if (ret != SQLITE_OK) {
06729         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06730                 errp ? errp : "unknown error", ret);
06731         if (errp) {
06732             sqlite3_free(errp);
06733             errp = NULL;
06734         }
06735         return SQL_ERROR;
06736     }
06737     if (errp) {
06738         sqlite3_free(errp);
06739         errp = NULL;
06740     }
06741     size = 0;
06742     if (ncols * nrows > 0) {
06743         int typec;
06744 
06745         namec = findcol(rowp, ncols, "name");
06746         uniquec = findcol(rowp, ncols, "pk");
06747         typec = findcol(rowp, ncols, "type");
06748         if (namec >= 0 && uniquec >= 0 && typec >= 0) {
06749             for (i = 1; i <= nrows; i++) {
06750                 if (*rowp[i * ncols + uniquec] != '0') {
06751                     size++;
06752                 }
06753             }
06754         }
06755     }
06756     if (size == 0) {
06757         sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
06758         if (!sql) {
06759             sqlite3_free_table(rowp);
06760             return nomem(s);
06761         }
06762         dbtraceapi(d, "sqlite3_get_table", sql);
06763         ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
06764                                 &errp);
06765         sqlite3_free(sql);
06766         if (ret != SQLITE_OK) {
06767             sqlite3_free_table(rowp);
06768             sqlite3_free_table(rowp2);
06769             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06770                     errp ? errp : "unknown error", ret);
06771             if (errp) {
06772                 sqlite3_free(errp);
06773                 errp = NULL;
06774             }
06775             return SQL_ERROR;
06776         }
06777         if (errp) {
06778             sqlite3_free(errp);
06779             errp = NULL;
06780         }
06781     }
06782     if (ncols2 * nrows2 > 0) {
06783         namec2 = findcol(rowp2, ncols2, "name");
06784         uniquec2 = findcol(rowp2, ncols2, "unique");
06785         if (namec2 >= 0 && uniquec2 >=  0) {
06786             for (i = 1; i <= nrows2; i++) {
06787                 int nnrows, nncols, nlen = 0;
06788                 char **rowpp;
06789 
06790                 if (rowp2[i * ncols2 + namec2]) {
06791                     nlen = strlen(rowp2[i * ncols2 + namec2]);
06792                 }
06793                 if (nlen < 17 ||
06794                     strncmp(rowp2[i * ncols2 + namec2],
06795                             "sqlite_autoindex_", 17)) {
06796                     continue;
06797                 }
06798                 if (*rowp2[i * ncols2 + uniquec2] != '0') {
06799                     ret = SQLITE_ERROR;
06800                     sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06801                                           rowp2[i * ncols2 + namec2]);
06802                     if (sql) {
06803                         dbtraceapi(d, "sqlite3_get_table", sql);
06804                         ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06805                                                 &nnrows, &nncols, NULL);
06806                         sqlite3_free(sql);
06807                     }
06808                     if (ret == SQLITE_OK) {
06809                         size += nnrows;
06810                         sqlite3_free_table(rowpp);
06811                     }
06812                 }
06813             }
06814         }
06815     }
06816     if (size == 0) {
06817         sqlite3_free_table(rowp);
06818         sqlite3_free_table(rowp2);
06819         return SQL_SUCCESS;
06820     }
06821     s->nrows = size;
06822     size = (size + 1) * asize;
06823     s->rows = xmalloc((size + 1) * sizeof (char *));
06824     if (!s->rows) {
06825         s->nrows = 0;
06826         sqlite3_free_table(rowp);
06827         sqlite3_free_table(rowp2);
06828         return nomem(s);
06829     }
06830     s->rows[0] = (char *) size;
06831     s->rows += 1;
06832     memset(s->rows, 0, sizeof (char *) * size);
06833     s->rowfree = freerows;
06834     offs = s->ncols;
06835     if (rowp) {
06836         for (i = 1; i <= nrows; i++) {
06837             if (*rowp[i * ncols + uniquec] != '0') {
06838                 char buf[32];
06839 
06840 #if defined(_WIN32) || defined(_WIN64)
06841                 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
06842                 s->rows[offs + 1] = xstrdup("");
06843 #else
06844                 s->rows[offs + 0] = xstrdup("");
06845                 s->rows[offs + 1] = xstrdup("");
06846 #endif
06847                 s->rows[offs + 2] = xstrdup(tname);
06848                 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
06849                 sprintf(buf, "%d", seq++);
06850                 s->rows[offs + 4] = xstrdup(buf);
06851                 offs += s->ncols;
06852             }
06853         }
06854     }
06855     if (rowp2) {
06856         for (i = 1; i <= nrows2; i++) {
06857             int nnrows, nncols, nlen = 0;
06858             char **rowpp;
06859 
06860             if (rowp2[i * ncols2 + namec2]) {
06861                 nlen = strlen(rowp2[i * ncols2 + namec2]);
06862             }
06863             if (nlen < 17 ||
06864                 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
06865                 continue;
06866             }
06867             if (*rowp2[i * ncols2 + uniquec2] != '0') {
06868                 int k;
06869 
06870                 ret = SQLITE_ERROR;
06871                 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06872                                       rowp2[i * ncols2 + namec2]);
06873                 if (sql) {
06874                     dbtraceapi(d, "sqlite3_get_table", sql);
06875                     ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06876                                             &nnrows, &nncols, NULL);
06877                     sqlite3_free(sql);
06878                 }
06879                 if (ret != SQLITE_OK) {
06880                     continue;
06881                 }
06882                 for (k = 0; nnrows && k < nncols; k++) {
06883                     if (strcmp(rowpp[k], "name") == 0) {
06884                         int m;
06885 
06886                         for (m = 1; m <= nnrows; m++) {
06887                             int roffs = offs + (m - 1) * s->ncols;
06888 
06889 #if defined(_WIN32) || defined(_WIN64)
06890                             s->rows[roffs + 0] =
06891                                 xstrdup(d->xcelqrx ? "main" : "");
06892                             s->rows[roffs + 1] = xstrdup("");
06893 #else
06894                             s->rows[roffs + 0] = xstrdup("");
06895                             s->rows[roffs + 1] = xstrdup("");
06896 #endif
06897                             s->rows[roffs + 2] = xstrdup(tname);
06898                             s->rows[roffs + 3] =
06899                                 xstrdup(rowpp[m * nncols + k]);
06900                             s->rows[roffs + 5] =
06901                                 xstrdup(rowp2[i * ncols2 + namec2]);
06902                         }
06903                     } else if (strcmp(rowpp[k], "seqno") == 0) {
06904                         int m;
06905 
06906                         for (m = 1; m <= nnrows; m++) {
06907                             int roffs = offs + (m - 1) * s->ncols;
06908                             int pos = m - 1;
06909                             char buf[32];
06910 
06911                             sscanf(rowpp[m * nncols + k], "%d", &pos);
06912                             sprintf(buf, "%d", pos + 1);
06913                             s->rows[roffs + 4] = xstrdup(buf);
06914                         }
06915                     }
06916                 }
06917                 offs += nnrows * s->ncols;
06918                 sqlite3_free_table(rowpp);
06919             }
06920         }
06921     }
06922     sqlite3_free_table(rowp);
06923     sqlite3_free_table(rowp2);
06924     return SQL_SUCCESS;
06925 }
06926 
06927 #ifndef WINTERFACE
06928 
06940 SQLRETURN SQL_API
06941 SQLPrimaryKeys(SQLHSTMT stmt,
06942                SQLCHAR *cat, SQLSMALLINT catLen,
06943                SQLCHAR *schema, SQLSMALLINT schemaLen,
06944                SQLCHAR *table, SQLSMALLINT tableLen)
06945 {
06946 #if defined(_WIN32) || defined(_WIN64)
06947     char *c = NULL, *s = NULL, *t = NULL;
06948 #endif
06949     SQLRETURN ret;
06950 
06951     HSTMT_LOCK(stmt);
06952 #if defined(_WIN32) || defined(_WIN64)
06953     if (!((STMT *) stmt)->oemcp[0]) {
06954         ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06955                              table, tableLen);
06956         goto done2;
06957     }
06958     if (cat) {
06959         c = wmb_to_utf_c((char *) cat, catLen);
06960         if (!c) {
06961             ret = nomem((STMT *) stmt);
06962             goto done;
06963         }
06964     }
06965     if (schema) {
06966         s = wmb_to_utf_c((char *) schema, schemaLen);
06967         if (!s) {
06968             ret = nomem((STMT *) stmt);
06969             goto done;
06970         }
06971     }
06972     if (table) {
06973         t = wmb_to_utf_c((char *) table, tableLen);
06974         if (!t) {
06975             ret = nomem((STMT *) stmt);
06976             goto done;
06977         }
06978     }
06979     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06980                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06981 #else
06982     ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06983                          table, tableLen);
06984 #endif
06985 #if defined(_WIN32) || defined(_WIN64)
06986 done:
06987     uc_free(t);
06988     uc_free(s);
06989     uc_free(c);
06990 done2:
06991     ;
06992 #endif
06993     HSTMT_UNLOCK(stmt);
06994     return ret;
06995 }
06996 #endif
06997 
06998 #ifdef WINTERFACE
06999 
07011 SQLRETURN SQL_API
07012 SQLPrimaryKeysW(SQLHSTMT stmt,
07013                 SQLWCHAR *cat, SQLSMALLINT catLen,
07014                 SQLWCHAR *schema, SQLSMALLINT schemaLen,
07015                 SQLWCHAR *table, SQLSMALLINT tableLen)
07016 {
07017     char *c = NULL, *s = NULL, *t = NULL;
07018     SQLRETURN ret;
07019 
07020     HSTMT_LOCK(stmt);
07021     if (cat) {
07022         c = uc_to_utf_c(cat, catLen);
07023         if (!c) {
07024             ret = nomem((STMT *) stmt);
07025             goto done;
07026         }
07027     }
07028     if (schema) {
07029         s = uc_to_utf_c(schema, schemaLen);
07030         if (!s) {
07031             ret = nomem((STMT *) stmt);
07032             goto done;
07033         }
07034     }
07035     if (table) {
07036         t = uc_to_utf_c(table, tableLen);
07037         if (!t) {
07038             ret = nomem((STMT *) stmt);
07039             goto done;
07040         }
07041     }
07042     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
07043                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
07044 done:
07045     uc_free(t);
07046     uc_free(s);
07047     uc_free(c);
07048     HSTMT_UNLOCK(stmt);
07049     return ret;
07050 }
07051 #endif
07052 
07057 static COL scolSpec2[] = {
07058     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
07059     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
07060     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
07061     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
07062     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
07063     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
07064     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
07065     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
07066     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
07067 };
07068 
07069 static COL scolSpec3[] = {
07070     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
07071     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
07072     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
07073     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
07074     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
07075     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
07076     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
07077     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
07078     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
07079 };
07080 
07096 static SQLRETURN
07097 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
07098                   SQLCHAR *cat, SQLSMALLINT catLen,
07099                   SQLCHAR *schema, SQLSMALLINT schemaLen,
07100                   SQLCHAR *table, SQLSMALLINT tableLen,
07101                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
07102 {
07103     STMT *s;
07104     DBC *d;
07105     SQLRETURN sret;
07106     int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
07107     PTRDIFF_T size;
07108     int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
07109     int notnullcc = -1, mkrowid = 0;
07110     char *errp = NULL, *sql, tname[512];
07111     char **rowp = NULL, **rowppp = NULL;
07112 
07113     sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
07114                        scolSpec3, array_size(scolSpec3), &asize);
07115     if (sret != SQL_SUCCESS) {
07116         return sret;
07117     }
07118     s = (STMT *) stmt;
07119     d = (DBC *) s->dbc;
07120     if (!table || table[0] == '\0' || table[0] == '%') {
07121         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
07122         return SQL_ERROR;
07123     }
07124     if (tableLen == SQL_NTS) {
07125         size = sizeof (tname) - 1;
07126     } else {
07127         size = min(sizeof (tname) - 1, tableLen);
07128     }
07129     strncpy(tname, (char *) table, size);
07130     tname[size] = '\0';
07131     unescpat(tname);
07132     if (id != SQL_BEST_ROWID) {
07133         return SQL_SUCCESS;
07134     }
07135     sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
07136     if (!sql) {
07137         return nomem(s);
07138     }
07139     sret = starttran(s);
07140     if (sret != SQL_SUCCESS) {
07141         sqlite3_free(sql);
07142         return sret;
07143     }
07144     dbtraceapi(d, "sqlite3_get_table", sql);
07145     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
07146     sqlite3_free(sql);
07147     if (ret != SQLITE_OK) {
07148 doerr:
07149         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07150                 errp ? errp : "unknown error", ret);
07151         if (errp) {
07152             sqlite3_free(errp);
07153             errp = NULL;
07154         }
07155         return SQL_ERROR;
07156     }
07157     if (errp) {
07158         sqlite3_free(errp);
07159         errp = NULL;
07160     }
07161     size = 0; /* number result rows */
07162     if (ncols * nrows <= 0) {
07163         goto nodata_but_rowid;
07164     }
07165     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
07166     if (!sql) {
07167         return nomem(s);
07168     }
07169     dbtraceapi(d, "sqlite3_get_table", sql);
07170     ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
07171                             &errp);
07172     sqlite3_free(sql);
07173     if (ret != SQLITE_OK) {
07174         sqlite3_free_table(rowp);
07175         goto doerr;
07176     }
07177     if (errp) {
07178         sqlite3_free(errp);
07179         errp = NULL;
07180     }
07181     namec = findcol(rowp, ncols, "name");
07182     uniquec = findcol(rowp, ncols, "unique");
07183     if (namec < 0 || uniquec < 0) {
07184         goto nodata_but_rowid;
07185     }
07186     namecc = findcol(rowppp, nnncols, "name");
07187     typecc = findcol(rowppp, nnncols, "type");
07188     notnullcc = findcol(rowppp, nnncols, "notnull");
07189     for (i = 1; i <= nrows; i++) {
07190         int nnrows, nncols;
07191         char **rowpp = NULL;
07192 
07193         if (*rowp[i * ncols + uniquec] != '0') {
07194             ret = SQLITE_ERROR;
07195             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
07196                                   rowp[i * ncols + namec]);
07197             if (sql) {
07198                 dbtraceapi(d, "sqlite3_get_table", sql);
07199                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07200                                         &nnrows, &nncols, NULL);
07201                 sqlite3_free(sql);
07202             }
07203             if (ret == SQLITE_OK) {
07204                 size += nnrows;
07205                 sqlite3_free_table(rowpp);
07206             }
07207         }
07208     }
07209 nodata_but_rowid:
07210     if (size == 0) {
07211         size = 1;
07212         mkrowid = 1;
07213     }
07214     s->nrows = size;
07215     size = (size + 1) * asize;
07216     s->rows = xmalloc((size + 1) * sizeof (char *));
07217     if (!s->rows) {
07218         s->nrows = 0;
07219         sqlite3_free_table(rowp);
07220         sqlite3_free_table(rowppp);
07221         return nomem(s);
07222     }
07223     s->rows[0] = (char *) size;
07224     s->rows += 1;
07225     memset(s->rows, 0, sizeof (char *) * size);
07226     s->rowfree = freerows;
07227     if (mkrowid) {
07228         s->nrows = 0;
07229         goto mkrowid;
07230     }
07231     offs = 0;
07232     for (i = 1; i <= nrows; i++) {
07233         int nnrows, nncols;
07234         char **rowpp = NULL;
07235 
07236         if (*rowp[i * ncols + uniquec] != '0') {
07237             int k;
07238 
07239             ret = SQLITE_ERROR;
07240             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
07241                                   rowp[i * ncols + namec]);
07242             if (sql) {
07243                 dbtraceapi(d, "sqlite3_get_table", sql);
07244                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07245                                         &nnrows, &nncols, NULL);
07246                 sqlite3_free(sql);
07247             }
07248             if (ret != SQLITE_OK) {
07249                 continue;
07250             }
07251             for (k = 0; nnrows && k < nncols; k++) {
07252                 if (strcmp(rowpp[k], "name") == 0) {
07253                     int m;
07254 
07255                     for (m = 1; m <= nnrows; m++) {
07256                         int roffs = (offs + m) * s->ncols;
07257 
07258                         s->rows[roffs + 0] =
07259                             xstrdup(stringify(SQL_SCOPE_SESSION));
07260                         s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
07261                         s->rows[roffs + 4] = xstrdup("0");
07262                         s->rows[roffs + 7] =
07263                             xstrdup(stringify(SQL_PC_NOT_PSEUDO));
07264                         if (namecc >= 0 && typecc >= 0) {
07265                             int ii;
07266 
07267                             for (ii = 1; ii <= nnnrows; ii++) {
07268                                 if (strcmp(rowppp[ii * nnncols + namecc],
07269                                            rowpp[m * nncols + k]) == 0) {
07270                                     char *typen = rowppp[ii * nnncols + typecc];
07271                                     int sqltype, mm, dd, isnullable = 0;
07272                                     char buf[32];
07273 
07274                                     s->rows[roffs + 3] = xstrdup(typen);
07275                                     sqltype = mapsqltype(typen, NULL, *s->ov3,
07276                                                          s->nowchar[0],
07277                                                          s->dobigint);
07278                                     getmd(typen, sqltype, &mm, &dd);
07279 #ifdef SQL_LONGVARCHAR
07280                                     if (sqltype == SQL_VARCHAR && mm > 255) {
07281                                         sqltype = SQL_LONGVARCHAR;
07282                                     }
07283 #endif
07284 #ifdef WINTERFACE
07285 #ifdef SQL_WLONGVARCHAR
07286                                     if (sqltype == SQL_WVARCHAR && mm > 255) {
07287                                         sqltype = SQL_WLONGVARCHAR;
07288                                     }
07289 #endif
07290 #endif
07291                                     if (sqltype == SQL_VARBINARY && mm > 255) {
07292                                         sqltype = SQL_LONGVARBINARY;
07293                                     }
07294                                     sprintf(buf, "%d", sqltype);
07295                                     s->rows[roffs + 2] = xstrdup(buf);
07296                                     sprintf(buf, "%d", mm);
07297                                     s->rows[roffs + 5] = xstrdup(buf);
07298                                     sprintf(buf, "%d", dd);
07299                                     s->rows[roffs + 6] = xstrdup(buf);
07300                                     if (notnullcc >= 0) {
07301                                         char *inp =
07302                                            rowppp[ii * nnncols + notnullcc];
07303 
07304                                         isnullable = inp[0] != '0';
07305                                     }
07306                                     sprintf(buf, "%d", isnullable);
07307                                     s->rows[roffs + 8] = xstrdup(buf);
07308                                 }
07309                             }
07310                         }
07311                     }
07312                 }
07313             }
07314             offs += nnrows;
07315             sqlite3_free_table(rowpp);
07316         }
07317     }
07318     if (nullable == SQL_NO_NULLS) {
07319         for (i = 1; i < s->nrows; i++) {
07320             if (s->rows[i * s->ncols + 8][0] == '0') {
07321                 int m, i1 = i + 1;
07322 
07323                 for (m = 0; m < s->ncols; m++) {
07324                     freep(&s->rows[i * s->ncols + m]);
07325                 }
07326                 size = s->ncols * sizeof (char *) * (s->nrows - i1);
07327                 if (size > 0) {
07328                     memmove(s->rows + i * s->ncols,
07329                             s->rows + i1 * s->ncols,
07330                             size);
07331                     memset(s->rows + s->nrows * s->ncols, 0,
07332                            s->ncols * sizeof (char *));
07333                 }
07334                 s->nrows--;
07335                 --i;
07336             }
07337         }
07338     }
07339 mkrowid:
07340     sqlite3_free_table(rowp);
07341     sqlite3_free_table(rowppp);
07342     if (s->nrows == 0) {
07343         s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
07344         s->rows[s->ncols + 1] = xstrdup("_ROWID_");
07345         s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
07346         s->rows[s->ncols + 3] = xstrdup("integer");
07347         s->rows[s->ncols + 4] = xstrdup("0");
07348         s->rows[s->ncols + 5] = xstrdup("10");
07349         s->rows[s->ncols + 6] = xstrdup("9");
07350         s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
07351         s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
07352         s->nrows = 1;
07353     }
07354     return SQL_SUCCESS;
07355 }
07356 
07357 #ifndef WINTERFACE
07358 
07373 SQLRETURN SQL_API
07374 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
07375                   SQLCHAR *cat, SQLSMALLINT catLen,
07376                   SQLCHAR *schema, SQLSMALLINT schemaLen,
07377                   SQLCHAR *table, SQLSMALLINT tableLen,
07378                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
07379 {
07380 #if defined(_WIN32) || defined(_WIN64)
07381     char *c = NULL, *s = NULL, *t = NULL;
07382 #endif
07383     SQLRETURN ret;
07384 
07385     HSTMT_LOCK(stmt);
07386 #if defined(_WIN32) || defined(_WIN64)
07387     if (!((STMT *) stmt)->oemcp[0]) {
07388         ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07389                                 table, tableLen, scope, nullable);
07390         goto done2;
07391     }
07392     if (cat) {
07393         c = wmb_to_utf_c((char *) cat, catLen);
07394         if (!c) {
07395             ret = nomem((STMT *) stmt);
07396             goto done;
07397         }
07398     }
07399     if (schema) {
07400         s = wmb_to_utf_c((char *) schema, schemaLen);
07401         if (!s) {
07402             ret = nomem((STMT *) stmt);
07403             goto done;
07404         }
07405     }
07406     if (table) {
07407         t = wmb_to_utf_c((char *) table, tableLen);
07408         if (!t) {
07409             ret = nomem((STMT *) stmt);
07410             goto done;
07411         }
07412     }
07413     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07414                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07415                             scope, nullable);
07416 #else
07417     ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07418                             table, tableLen, scope, nullable);
07419 #endif
07420 #if defined(_WIN32) || defined(_WIN64)
07421 done:
07422     uc_free(t);
07423     uc_free(s);
07424     uc_free(c);
07425 done2:
07426     ;
07427 #endif
07428     HSTMT_UNLOCK(stmt);
07429     return ret;
07430 }
07431 #endif
07432 
07433 #ifdef WINTERFACE
07434 
07449 SQLRETURN SQL_API
07450 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
07451                    SQLWCHAR *cat, SQLSMALLINT catLen,
07452                    SQLWCHAR *schema, SQLSMALLINT schemaLen,
07453                    SQLWCHAR *table, SQLSMALLINT tableLen,
07454                    SQLUSMALLINT scope, SQLUSMALLINT nullable)
07455 {
07456     char *c = NULL, *s = NULL, *t = NULL;
07457     SQLRETURN ret;
07458 
07459     HSTMT_LOCK(stmt);
07460     if (cat) {
07461         c = uc_to_utf_c(cat, catLen);
07462         if (!c) {
07463             ret = nomem((STMT *) stmt);
07464             goto done;
07465         }
07466     }
07467     if (schema) {
07468         s = uc_to_utf_c(schema, schemaLen);
07469         if (!s) {
07470             ret = nomem((STMT *) stmt);
07471             goto done;
07472         }
07473     }
07474     if (table) {
07475         t = uc_to_utf_c(table, tableLen);
07476         if (!t) {
07477             ret = nomem((STMT *) stmt);
07478             goto done;
07479         }
07480     }
07481     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07482                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07483                             scope, nullable);
07484 done:
07485     uc_free(t);
07486     uc_free(s);
07487     uc_free(c);
07488     HSTMT_UNLOCK(stmt);
07489     return ret;
07490 }
07491 #endif
07492 
07497 static COL fkeySpec2[] = {
07498     { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07499     { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
07500     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07501     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07502     { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07503     { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
07504     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07505     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07506     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07507     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07508     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07509     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07510     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07511     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07512 };
07513 
07514 static COL fkeySpec3[] = {
07515     { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
07516     { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07517     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07518     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07519     { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
07520     { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07521     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07522     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07523     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07524     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07525     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07526     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07527     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07528     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07529 };
07530 
07549 static SQLRETURN SQL_API
07550 drvforeignkeys(SQLHSTMT stmt,
07551                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07552                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07553                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07554                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07555                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07556                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07557 {
07558     STMT *s;
07559     DBC *d;
07560     SQLRETURN sret;
07561     int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
07562     int onu, ond;
07563     PTRDIFF_T size;
07564     char **rowp, *errp = NULL, *sql, pname[512], fname[512];
07565 
07566     sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
07567                        fkeySpec3, array_size(fkeySpec3), &asize);
07568     if (sret != SQL_SUCCESS) {
07569         return sret;
07570     }
07571     s = (STMT *) stmt;
07572     sret = starttran(s);
07573     if (sret != SQL_SUCCESS) {
07574         return sret;
07575     }
07576     d = (DBC *) s->dbc;
07577     if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
07578         (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
07579         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
07580         return SQL_ERROR;
07581     }
07582     size = 0;
07583     if (PKtable) {
07584         if (PKtableLen == SQL_NTS) {
07585             size = sizeof (pname) - 1;
07586         } else {
07587             size = min(sizeof (pname) - 1, PKtableLen);
07588         }
07589         strncpy(pname, (char *) PKtable, size);
07590     }
07591     pname[size] = '\0';
07592     size = 0;
07593     if (FKtable) {
07594 
07595         if (FKtableLen == SQL_NTS) {
07596             size = sizeof (fname) - 1;
07597         } else {
07598             size = min(sizeof (fname) - 1, FKtableLen);
07599         }
07600         strncpy(fname, (char *) FKtable, size);
07601     }
07602     fname[size] = '\0';
07603     if (fname[0] != '\0') {
07604         int plen;
07605 
07606         ret = SQLITE_ERROR;
07607         sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
07608         if (sql) {
07609             dbtraceapi(d, "sqlite3_get_table", sql);
07610             ret = sqlite3_get_table(d->sqlite, sql, &rowp,
07611                                     &nrows, &ncols, &errp);
07612             sqlite3_free(sql);
07613         }
07614         if (ret != SQLITE_OK) {
07615             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07616                     errp ? errp : "unknown error", ret);
07617             if (errp) {
07618                 sqlite3_free(errp);
07619                 errp = NULL;
07620             }
07621             return SQL_ERROR;
07622         }
07623         if (errp) {
07624             sqlite3_free(errp);
07625             errp = NULL;
07626         }
07627         if (ncols * nrows <= 0) {
07628 nodata:
07629             sqlite3_free_table(rowp);
07630             return SQL_SUCCESS;
07631         }
07632         size = 0;
07633         namec = findcol(rowp, ncols, "table");
07634         seqc = findcol(rowp, ncols, "seq");
07635         fromc = findcol(rowp, ncols, "from");
07636         toc = findcol(rowp, ncols, "to");
07637         onu = findcol(rowp, ncols, "on_update");
07638         ond = findcol(rowp, ncols, "on_delete");
07639         if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07640             goto nodata;
07641         }
07642         plen = strlen(pname);
07643         for (i = 1; i <= nrows; i++) {
07644             char *ptab = unquote(rowp[i * ncols + namec]);
07645 
07646             if (plen && ptab) {
07647                 int len = strlen(ptab);
07648 
07649                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07650                     continue;
07651                 }
07652             }
07653             size++;
07654         }
07655         if (size == 0) {
07656             goto nodata;
07657         }
07658         s->nrows = size;
07659         size = (size + 1) * asize;
07660         s->rows = xmalloc((size + 1) * sizeof (char *));
07661         if (!s->rows) {
07662             s->nrows = 0;
07663             return nomem(s);
07664         }
07665         s->rows[0] = (char *) size;
07666         s->rows += 1;
07667         memset(s->rows, 0, sizeof (char *) * size);
07668         s->rowfree = freerows;
07669         offs = 0;
07670         for (i = 1; i <= nrows; i++) {
07671             int pos = 0, roffs = (offs + 1) * s->ncols;
07672             char *ptab = rowp[i * ncols + namec];
07673             char buf[32];
07674 
07675             if (plen && ptab) {
07676                 int len = strlen(ptab);
07677 
07678                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07679                     continue;
07680                 }
07681             }
07682 #if defined(_WIN32) || defined(_WIN64)
07683             s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07684             s->rows[roffs + 1] = xstrdup("");
07685 #else
07686             s->rows[roffs + 0] = xstrdup("");
07687             s->rows[roffs + 1] = xstrdup("");
07688 #endif
07689             s->rows[roffs + 2] = xstrdup(ptab);
07690             s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
07691             s->rows[roffs + 4] = xstrdup("");
07692             s->rows[roffs + 5] = xstrdup("");
07693             s->rows[roffs + 6] = xstrdup(fname);
07694             s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
07695             sscanf(rowp[i * ncols + seqc], "%d", &pos);
07696             sprintf(buf, "%d", pos + 1);
07697             s->rows[roffs + 8] = xstrdup(buf);
07698             if (onu < 0) {
07699                 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07700             } else {
07701                 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
07702                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07703                 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
07704                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
07705                 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
07706                     s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07707                 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
07708                     s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07709                 } else {
07710                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07711                 }
07712             }
07713             if (ond < 0) {
07714                 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07715             } else {
07716                 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
07717                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07718                 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
07719                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
07720                 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
07721                     s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07722                 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
07723                     s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07724                 } else {
07725                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07726                 }
07727             }
07728             s->rows[roffs + 11] = NULL;
07729             s->rows[roffs + 12] = NULL;
07730             s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07731             offs++;
07732         }
07733         sqlite3_free_table(rowp);
07734     } else {
07735         int nnrows, nncols, plen = strlen(pname);
07736         char **rowpp;
07737 
07738         sql = "select name from sqlite_master where type='table'";
07739         dbtraceapi(d, "sqlite3_get_table", sql);
07740         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
07741         if (ret != SQLITE_OK) {
07742             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07743                     errp ? errp : "unknown error", ret);
07744             if (errp) {
07745                 sqlite3_free(errp);
07746                 errp = NULL;
07747             }
07748             return SQL_ERROR;
07749         }
07750         if (errp) {
07751             sqlite3_free(errp);
07752             errp = NULL;
07753         }
07754         if (ncols * nrows <= 0) {
07755             goto nodata;
07756         }
07757         size = 0;
07758         for (i = 1; i <= nrows; i++) {
07759             int k;
07760 
07761             if (!rowp[i]) {
07762                 continue;
07763             }
07764             rowpp = NULL;
07765             ret = SQLITE_ERROR;
07766             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07767             if (sql) {
07768                 dbtraceapi(d, "sqlite3_get_table", sql);
07769                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07770                                       &nnrows, &nncols, NULL);
07771                 sqlite3_free(sql);
07772             }
07773             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07774                 sqlite3_free_table(rowpp);
07775                 continue;
07776             }
07777             namec = findcol(rowpp, nncols, "table");
07778             seqc = findcol(rowpp, nncols, "seq");
07779             fromc = findcol(rowpp, nncols, "from");
07780             toc = findcol(rowpp, nncols, "to");
07781             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07782                 sqlite3_free_table(rowpp);
07783                 continue;
07784             }
07785             for (k = 1; k <= nnrows; k++) {
07786                 char *ptab = unquote(rowpp[k * nncols + namec]);
07787 
07788                 if (plen && ptab) {
07789                     int len = strlen(ptab);
07790 
07791                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07792                         continue;
07793                     }
07794                 }
07795                 size++;
07796             }
07797             sqlite3_free_table(rowpp);
07798         }
07799         if (size == 0) {
07800             goto nodata;
07801         }
07802         s->nrows = size;
07803         size = (size + 1) * asize;
07804         s->rows = xmalloc((size + 1) * sizeof (char *));
07805         if (!s->rows) {
07806             s->nrows = 0;
07807             return nomem(s);
07808         }
07809         s->rows[0] = (char *) size;
07810         s->rows += 1;
07811         memset(s->rows, 0, sizeof (char *) * size);
07812         s->rowfree = freerows;
07813         offs = 0;
07814         for (i = 1; i <= nrows; i++) {
07815             int k;
07816 
07817             if (!rowp[i]) {
07818                 continue;
07819             }
07820             rowpp = NULL;
07821             ret = SQLITE_ERROR;
07822             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07823             if (sql) {
07824                 dbtraceapi(d, "sqlite3_get_table", sql);
07825                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07826                                         &nnrows, &nncols, NULL);
07827                 sqlite3_free(sql);
07828             }
07829             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07830                 sqlite3_free_table(rowpp);
07831                 continue;
07832             }
07833             namec = findcol(rowpp, nncols, "table");
07834             seqc = findcol(rowpp, nncols, "seq");
07835             fromc = findcol(rowpp, nncols, "from");
07836             toc = findcol(rowpp, nncols, "to");
07837             onu = findcol(rowpp, nncols, "on_update");
07838             ond = findcol(rowpp, nncols, "on_delete");
07839             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07840                 sqlite3_free_table(rowpp);
07841                 continue;
07842             }
07843             for (k = 1; k <= nnrows; k++) {
07844                 int pos = 0, roffs = (offs + 1) * s->ncols;
07845                 char *ptab = unquote(rowpp[k * nncols + namec]);
07846                 char buf[32];
07847 
07848                 if (plen && ptab) {
07849                     int len = strlen(ptab);
07850 
07851                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07852                         continue;
07853                     }
07854                 }
07855 #if defined(_WIN32) || defined(_WIN64)
07856                 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07857                 s->rows[roffs + 1] = xstrdup("");
07858 #else
07859                 s->rows[roffs + 0] = xstrdup("");
07860                 s->rows[roffs + 1] = xstrdup("");
07861 #endif
07862                 s->rows[roffs + 2] = xstrdup(ptab);
07863                 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
07864                 s->rows[roffs + 4] = xstrdup("");
07865                 s->rows[roffs + 5] = xstrdup("");
07866                 s->rows[roffs + 6] = xstrdup(rowp[i]);
07867                 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
07868                 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
07869                 sprintf(buf, "%d", pos + 1);
07870                 s->rows[roffs + 8] = xstrdup(buf);
07871                 if (onu < 0) {
07872                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07873                 } else {
07874                     if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
07875                         s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07876                     } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
07877                                == 0) {
07878                         s->rows[roffs + 9] =
07879                             xstrdup(stringify(SQL_SET_DEFAULT));
07880                     } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
07881                                == 0) {
07882                         s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07883                     } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
07884                                == 0) {
07885                         s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07886                     } else {
07887                         s->rows[roffs + 9] =
07888                             xstrdup(stringify(SQL_NO_ACTION));
07889                     }
07890                 }
07891                 if (ond < 0) {
07892                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07893                 } else {
07894                     if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
07895                         s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07896                     } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
07897                                == 0) {
07898                         s->rows[roffs + 10] =
07899                             xstrdup(stringify(SQL_SET_DEFAULT));
07900                     } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
07901                                == 0) {
07902                         s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07903                     } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
07904                                == 0) {
07905                         s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07906                     } else {
07907                         s->rows[roffs + 10] =
07908                             xstrdup(stringify(SQL_NO_ACTION));
07909                     }
07910                 }
07911                 s->rows[roffs + 11] = NULL;
07912                 s->rows[roffs + 12] = NULL;
07913                 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07914                 offs++;
07915             }
07916             sqlite3_free_table(rowpp);
07917         }
07918         sqlite3_free_table(rowp);
07919     }
07920     return SQL_SUCCESS;
07921 }
07922 
07923 #ifndef WINTERFACE
07924 
07942 SQLRETURN SQL_API
07943 SQLForeignKeys(SQLHSTMT stmt,
07944                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07945                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07946                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07947                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07948                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07949                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07950 {
07951 #if defined(_WIN32) || defined(_WIN64)
07952     char *pc = NULL, *ps = NULL, *pt = NULL;
07953     char *fc = NULL, *fs = NULL, *ft = NULL;
07954 #endif
07955     SQLRETURN ret;
07956 
07957     HSTMT_LOCK(stmt);
07958 #if defined(_WIN32) || defined(_WIN64)
07959     if (!((STMT *) stmt)->oemcp[0]) {
07960         ret = drvforeignkeys(stmt,
07961                              PKcatalog, PKcatalogLen,
07962                              PKschema, PKschemaLen, PKtable, PKtableLen,
07963                              FKcatalog, FKcatalogLen,
07964                              FKschema, FKschemaLen,
07965                              FKtable, FKtableLen);
07966         goto done2;
07967     }
07968     if (PKcatalog) {
07969         pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
07970         if (!pc) {
07971             ret = nomem((STMT *) stmt);
07972             goto done;
07973         }
07974     }
07975     if (PKschema) {
07976         ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
07977         if (!ps) {
07978             ret = nomem((STMT *) stmt);
07979             goto done;
07980         }
07981     }
07982     if (PKtable) {
07983         pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
07984         if (!pt) {
07985             ret = nomem((STMT *) stmt);
07986             goto done;
07987         }
07988     }
07989     if (FKcatalog) {
07990         fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
07991         if (!fc) {
07992             ret = nomem((STMT *) stmt);
07993             goto done;
07994         }
07995     }
07996     if (FKschema) {
07997         fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
07998         if (!fs) {
07999             ret = nomem((STMT *) stmt);
08000             goto done;
08001         }
08002     }
08003     if (FKtable) {
08004         ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
08005         if (!ft) {
08006             ret = nomem((STMT *) stmt);
08007             goto done;
08008         }
08009     }
08010     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
08011                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
08012                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
08013                          (SQLCHAR *) ft, SQL_NTS);
08014 #else
08015     ret = drvforeignkeys(stmt,
08016                          PKcatalog, PKcatalogLen,
08017                          PKschema, PKschemaLen, PKtable, PKtableLen,
08018                          FKcatalog, FKcatalogLen,
08019                          FKschema, FKschemaLen,
08020                          FKtable, FKtableLen);
08021 #endif
08022 #if defined(_WIN32) || defined(_WIN64)
08023 done:
08024     uc_free(ft);
08025     uc_free(fs);
08026     uc_free(fc);
08027     uc_free(pt);
08028     uc_free(ps);
08029     uc_free(pc);
08030 done2:
08031     ;
08032 #endif
08033     HSTMT_UNLOCK(stmt);
08034     return ret;
08035 }
08036 #endif
08037 
08038 #ifdef WINTERFACE
08039 
08057 SQLRETURN SQL_API
08058 SQLForeignKeysW(SQLHSTMT stmt,
08059                 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
08060                 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
08061                 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
08062                 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
08063                 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
08064                 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
08065 {
08066     char *pc = NULL, *ps = NULL, *pt = NULL;
08067     char *fc = NULL, *fs = NULL, *ft = NULL;
08068     SQLRETURN ret;
08069 
08070     HSTMT_LOCK(stmt);
08071     if (PKcatalog) {
08072         pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
08073         if (!pc) {
08074             ret = nomem((STMT *) stmt);
08075             goto done;
08076         }
08077     }
08078     if (PKschema) {
08079         ps = uc_to_utf_c(PKschema, PKschemaLen);
08080         if (!ps) {
08081             ret = nomem((STMT *) stmt);
08082             goto done;
08083         }
08084     }
08085     if (PKtable) {
08086         pt = uc_to_utf_c(PKtable, PKtableLen);
08087         if (!pt) {
08088             ret = nomem((STMT *) stmt);
08089             goto done;
08090         }
08091     }
08092     if (FKcatalog) {
08093         fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
08094         if (!fc) {
08095             ret = nomem((STMT *) stmt);
08096             goto done;
08097         }
08098     }
08099     if (FKschema) {
08100         fs = uc_to_utf_c(FKschema, FKschemaLen);
08101         if (!fs) {
08102             ret = nomem((STMT *) stmt);
08103             goto done;
08104         }
08105     }
08106     if (FKtable) {
08107         ft = uc_to_utf_c(FKtable, FKtableLen);
08108         if (!ft) {
08109             ret = nomem((STMT *) stmt);
08110             goto done;
08111         }
08112     }
08113     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
08114                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
08115                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
08116                          (SQLCHAR *) ft, SQL_NTS);
08117 done:
08118     uc_free(ft);
08119     uc_free(fs);
08120     uc_free(fc);
08121     uc_free(pt);
08122     uc_free(ps);
08123     uc_free(pc);
08124     HSTMT_UNLOCK(stmt);
08125     return ret;
08126 }
08127 #endif
08128 
08135 static SQLRETURN
08136 starttran(STMT *s)
08137 {
08138     int ret = SQL_SUCCESS, rc, busy_count = 0;
08139     char *errp = NULL;
08140     DBC *d = (DBC *) s->dbc;
08141 
08142     if (!d->autocommit && !d->intrans && !d->trans_disable) {
08143 begin_again:
08144         rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
08145         if (rc == SQLITE_BUSY) {
08146             if (busy_handler((void *) d, ++busy_count)) {
08147                 if (errp) {
08148                     sqlite3_free(errp);
08149                     errp = NULL;
08150                 }
08151                 goto begin_again;
08152             }
08153         }
08154         dbtracerc(d, rc, errp);
08155         if (rc != SQLITE_OK) {
08156             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
08157                     errp ? errp : "unknown error", rc);
08158             ret = SQL_ERROR;
08159         } else {
08160             d->intrans = 1;
08161         }
08162         if (errp) {
08163             sqlite3_free(errp);
08164             errp = NULL;
08165         }
08166     }
08167     return ret;
08168 }
08169 
08178 static SQLRETURN
08179 endtran(DBC *d, SQLSMALLINT comptype, int force)
08180 {
08181     int ret, busy_count = 0;
08182     char *sql, *errp = NULL;
08183 
08184     if (!d->sqlite) {
08185         setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
08186         return SQL_ERROR;
08187     }
08188     if ((!force && d->autocommit) || !d->intrans) {
08189         return SQL_SUCCESS;
08190     }
08191     switch (comptype) {
08192     case SQL_COMMIT:
08193         sql = "COMMIT TRANSACTION";
08194         goto doit;
08195     case SQL_ROLLBACK:
08196         sql = "ROLLBACK TRANSACTION";
08197     doit:
08198         ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
08199         dbtracerc(d, ret, errp);
08200         if (ret == SQLITE_BUSY && busy_count < 10) {
08201             if (busy_handler((void *) d, ++busy_count)) {
08202                 if (errp) {
08203                     sqlite3_free(errp);
08204                     errp = NULL;
08205                 }
08206                 goto doit;
08207             }
08208         }
08209         if (ret != SQLITE_OK) {
08210             setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
08211                      errp ? errp : "transaction failed");
08212             if (errp) {
08213                 sqlite3_free(errp);
08214                 errp = NULL;
08215             }
08216             return SQL_ERROR;
08217         }
08218         if (errp) {
08219             sqlite3_free(errp);
08220             errp = NULL;
08221         }
08222         d->intrans = 0;
08223         return SQL_SUCCESS;
08224     }
08225     setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
08226     return SQL_ERROR;
08227 }
08228 
08237 static SQLRETURN
08238 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
08239 {
08240     DBC *dbc = NULL;
08241     int fail = 0;
08242     SQLRETURN ret;
08243 #if defined(_WIN32) || defined(_WIN64)
08244     ENV *env;
08245 #endif
08246 
08247     switch (type) {
08248     case SQL_HANDLE_DBC:
08249         HDBC_LOCK((SQLHDBC) handle);
08250         if (handle == SQL_NULL_HDBC) {
08251             return SQL_INVALID_HANDLE;
08252         }
08253         dbc = (DBC *) handle;
08254         ret = endtran(dbc, comptype, 0);
08255         HDBC_UNLOCK((SQLHDBC) handle);
08256         return ret;
08257     case SQL_HANDLE_ENV:
08258         if (handle == SQL_NULL_HENV) {
08259             return SQL_INVALID_HANDLE;
08260         }
08261 #if defined(_WIN32) || defined(_WIN64)
08262         env = (ENV *) handle;
08263         if (env->magic != ENV_MAGIC) {
08264             return SQL_INVALID_HANDLE;
08265         }
08266         EnterCriticalSection(&env->cs);
08267 #endif
08268         dbc = ((ENV *) handle)->dbcs;
08269         while (dbc) {
08270             HDBC_LOCK((SQLHDBC) dbc);
08271             ret = endtran(dbc, comptype, 0);
08272             HDBC_UNLOCK((SQLHDBC) dbc);
08273             if (ret != SQL_SUCCESS) {
08274                 fail++;
08275             }
08276             dbc = dbc->next;
08277         }
08278 #if defined(_WIN32) || defined(_WIN64)
08279         LeaveCriticalSection(&env->cs);
08280 #endif
08281         return fail ? SQL_ERROR : SQL_SUCCESS;
08282     }
08283     return SQL_INVALID_HANDLE;
08284 }
08285 
08294 SQLRETURN SQL_API
08295 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
08296 {
08297     return drvendtran(type, handle, comptype);
08298 }
08299 
08308 SQLRETURN SQL_API
08309 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
08310 {
08311     if (dbc != SQL_NULL_HDBC) {
08312         return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
08313     }
08314     return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
08315 }
08316 
08321 SQLRETURN SQL_API
08322 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
08323 {
08324     return SQL_ERROR;
08325 }
08326 
08327 #ifndef WINTERFACE
08328 
08339 SQLRETURN SQL_API
08340 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
08341              SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08342 {
08343     int outLen = 0;
08344     SQLRETURN ret = SQL_SUCCESS;
08345 
08346     HSTMT_LOCK(stmt);
08347     if (sqlinLen == SQL_NTS) {
08348         sqlinLen = strlen((char *) sqlin);
08349     }
08350     if (sql) {
08351         if (sqlMax > 0) {
08352             strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
08353             sqlin[sqlMax - 1] = '\0';
08354             outLen = min(sqlMax - 1, sqlinLen);
08355         }
08356     } else {
08357         outLen = sqlinLen;
08358     }
08359     if (sqlLen) {
08360         *sqlLen = outLen;
08361     }
08362     if (sql && outLen < sqlinLen) {
08363         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08364         ret = SQL_SUCCESS_WITH_INFO;
08365     }
08366     HSTMT_UNLOCK(stmt);
08367     return ret;
08368 }
08369 #endif
08370 
08371 #ifdef WINTERFACE
08372 
08383 SQLRETURN SQL_API
08384 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
08385               SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08386 {
08387     int outLen = 0;
08388     SQLRETURN ret = SQL_SUCCESS;
08389 
08390     HSTMT_LOCK(stmt);
08391     if (sqlinLen == SQL_NTS) {
08392         sqlinLen = uc_strlen(sqlin);
08393     }
08394     if (sql) {
08395         if (sqlMax > 0) {
08396             uc_strncpy(sql, sqlin, sqlMax - 1);
08397             sqlin[sqlMax - 1] = 0;
08398             outLen = min(sqlMax  - 1, sqlinLen);
08399         }
08400     } else {
08401         outLen = sqlinLen;
08402     }
08403     if (sqlLen) {
08404         *sqlLen = outLen;
08405     }
08406     if (sql && outLen < sqlinLen) {
08407         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08408         ret = SQL_SUCCESS_WITH_INFO;
08409     }
08410     HSTMT_UNLOCK(stmt);
08411     return ret;
08412 }
08413 #endif
08414 
08419 static COL procSpec2[] = {
08420     { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08421     { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08422     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08423     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08424     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08425     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08426     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08427     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08428 };
08429 
08430 static COL procSpec3[] = {
08431     { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08432     { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08433     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08434     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08435     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08436     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08437     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08438     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08439 };
08440 
08441 #ifndef WINTERFACE
08442 
08454 SQLRETURN SQL_API
08455 SQLProcedures(SQLHSTMT stmt,
08456               SQLCHAR *catalog, SQLSMALLINT catalogLen,
08457               SQLCHAR *schema, SQLSMALLINT schemaLen,
08458               SQLCHAR *proc, SQLSMALLINT procLen)
08459 {
08460     SQLRETURN ret;
08461 
08462     HSTMT_LOCK(stmt);
08463     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08464                       procSpec3, array_size(procSpec3), NULL);
08465     HSTMT_UNLOCK(stmt);
08466     return ret;
08467 }
08468 #endif
08469 
08470 #ifdef WINTERFACE
08471 
08483 SQLRETURN SQL_API
08484 SQLProceduresW(SQLHSTMT stmt,
08485                SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08486                SQLWCHAR *schema, SQLSMALLINT schemaLen,
08487                SQLWCHAR *proc, SQLSMALLINT procLen)
08488 {
08489     SQLRETURN ret;
08490 
08491     HSTMT_LOCK(stmt);
08492     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08493                       procSpec3, array_size(procSpec3), NULL);
08494     HSTMT_UNLOCK(stmt);
08495     return ret;
08496 }
08497 #endif
08498 
08503 static COL procColSpec2[] = {
08504     { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08505     { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08506     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08507     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08508     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08509     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08510     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08511     { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
08512     { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
08513     { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
08514     { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
08515     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08516     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08517     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08518     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08519     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08520     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08521     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08522     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08523 };
08524 
08525 static COL procColSpec3[] = {
08526     { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08527     { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08528     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08529     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08530     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08531     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08532     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08533     { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
08534     { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
08535     { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
08536     { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
08537     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08538     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08539     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08540     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08541     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08542     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08543     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08544     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08545 };
08546 
08547 #ifndef WINTERFACE
08548 
08562 SQLRETURN SQL_API
08563 SQLProcedureColumns(SQLHSTMT stmt,
08564                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
08565                     SQLCHAR *schema, SQLSMALLINT schemaLen,
08566                     SQLCHAR *proc, SQLSMALLINT procLen,
08567                     SQLCHAR *column, SQLSMALLINT columnLen)
08568 {
08569     SQLRETURN ret;
08570 
08571     HSTMT_LOCK(stmt);
08572     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08573                       procColSpec3, array_size(procColSpec3), NULL);
08574     HSTMT_UNLOCK(stmt);
08575     return ret;
08576 }
08577 #endif
08578 
08579 #ifdef WINTERFACE
08580 
08595 SQLRETURN SQL_API
08596 SQLProcedureColumnsW(SQLHSTMT stmt,
08597                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08598                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
08599                      SQLWCHAR *proc, SQLSMALLINT procLen,
08600                      SQLWCHAR *column, SQLSMALLINT columnLen)
08601 {
08602     SQLRETURN ret;
08603 
08604     HSTMT_LOCK(stmt);
08605     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08606                       procColSpec3, array_size(procColSpec3), NULL);
08607     HSTMT_UNLOCK(stmt);
08608     return ret;
08609 }
08610 #endif
08611 
08622 SQLRETURN SQL_API
08623 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
08624               SQLINTEGER len, SQLINTEGER *lenp)
08625 {
08626     ENV *e;
08627     SQLRETURN ret = SQL_ERROR;
08628 
08629     if (env == SQL_NULL_HENV) {
08630         return SQL_INVALID_HANDLE;
08631     }
08632     e = (ENV *) env;
08633     if (!e || e->magic != ENV_MAGIC) {
08634         return SQL_INVALID_HANDLE;
08635     }
08636 #if defined(_WIN32) || defined(_WIN64)
08637     EnterCriticalSection(&e->cs);
08638 #endif
08639     switch (attr) {
08640     case SQL_ATTR_CONNECTION_POOLING:
08641         if (val) {
08642             *((SQLINTEGER *) val) = e->pool ?
08643                 SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
08644         }
08645         if (lenp) {
08646             *lenp = sizeof (SQLINTEGER);
08647         }
08648         ret = SQL_SUCCESS;
08649         break;
08650     case SQL_ATTR_CP_MATCH:
08651         *((SQLINTEGER *) val) = SQL_CP_RELAXED_MATCH;
08652         if (lenp) {
08653             *lenp = sizeof (SQLINTEGER);
08654         }
08655         ret = SQL_SUCCESS;
08656         break;
08657     case SQL_ATTR_OUTPUT_NTS:
08658         if (val) {
08659             *((SQLINTEGER *) val) = SQL_TRUE;
08660         }
08661         if (lenp) {
08662             *lenp = sizeof (SQLINTEGER);
08663         }
08664         ret = SQL_SUCCESS;
08665         break;
08666     case SQL_ATTR_ODBC_VERSION:
08667         if (val) {
08668             *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
08669         }
08670         if (lenp) {
08671             *lenp = sizeof (SQLINTEGER);
08672         }
08673         ret = SQL_SUCCESS;
08674         break;
08675     }
08676 #if defined(_WIN32) || defined(_WIN64)
08677     LeaveCriticalSection(&e->cs);
08678 #endif
08679     return ret;
08680 }
08681 
08691 SQLRETURN SQL_API
08692 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
08693 {
08694     ENV *e;
08695     SQLRETURN ret = SQL_ERROR;
08696 
08697     if (env == SQL_NULL_HENV) {
08698         return SQL_INVALID_HANDLE;
08699     }
08700     e = (ENV *) env;
08701     if (!e || e->magic != ENV_MAGIC) {
08702         return SQL_INVALID_HANDLE;
08703     }
08704 #if defined(_WIN32) || defined(_WIN64)
08705     EnterCriticalSection(&e->cs);
08706 #endif
08707     switch (attr) {
08708     case SQL_ATTR_CONNECTION_POOLING:
08709         if (val == (SQLPOINTER) SQL_CP_ONE_PER_DRIVER) {
08710             e->pool = 1;
08711             ret = SQL_SUCCESS;
08712         } else if (val == (SQLPOINTER) SQL_CP_OFF) {
08713             e->pool = 0;
08714             ret = SQL_SUCCESS;
08715         }
08716         break;
08717     case SQL_ATTR_CP_MATCH:
08718         ret = SQL_SUCCESS;
08719         break;
08720     case SQL_ATTR_OUTPUT_NTS:
08721         if (val == (SQLPOINTER) SQL_TRUE) {
08722             ret = SQL_SUCCESS;
08723         }
08724         break;
08725     case SQL_ATTR_ODBC_VERSION:
08726         if (!val) {
08727             break;
08728         }
08729         if (val == (SQLPOINTER) SQL_OV_ODBC2) {
08730             e->ov3 = 0;
08731             ret = SQL_SUCCESS;
08732         } else if (val == (SQLPOINTER) SQL_OV_ODBC3) {
08733             e->ov3 = 1;
08734             ret = SQL_SUCCESS;
08735         }
08736         break;
08737     }
08738 #if defined(_WIN32) || defined(_WIN64)
08739     LeaveCriticalSection(&e->cs);
08740 #endif
08741     return ret;
08742 }
08743 
08757 static SQLRETURN
08758 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08759               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08760               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08761 {
08762     DBC *d = NULL;
08763     STMT *s = NULL;
08764     int len, naterr;
08765     char *logmsg, *sqlst;
08766     SQLRETURN ret = SQL_ERROR;
08767 
08768     if (handle == SQL_NULL_HANDLE) {
08769         return SQL_INVALID_HANDLE;
08770     }
08771     if (sqlstate) {
08772         sqlstate[0] = '\0';
08773     }
08774     if (msg && buflen > 0) {
08775         msg[0] = '\0';
08776     }
08777     if (msglen) {
08778         *msglen = 0;
08779     }
08780     if (nativeerr) {
08781         *nativeerr = 0;
08782     }
08783     switch (htype) {
08784     case SQL_HANDLE_ENV:
08785     case SQL_HANDLE_DESC:
08786         return SQL_NO_DATA;
08787     case SQL_HANDLE_DBC:
08788         HDBC_LOCK((SQLHDBC) handle);
08789         d = (DBC *) handle;
08790         logmsg = (char *) d->logmsg;
08791         sqlst = d->sqlstate;
08792         naterr = d->naterr;
08793         break;
08794     case SQL_HANDLE_STMT:
08795         HSTMT_LOCK((SQLHSTMT) handle);
08796         s = (STMT *) handle;
08797         logmsg = (char *) s->logmsg;
08798         sqlst = s->sqlstate;
08799         naterr = s->naterr;
08800         break;
08801     default:
08802         return SQL_INVALID_HANDLE;
08803     }
08804     if (buflen < 0) {
08805         goto done;
08806     }
08807     if (recno > 1) {
08808         ret = SQL_NO_DATA;
08809         goto done;
08810     }
08811     len = strlen(logmsg);
08812     if (len == 0) {
08813         ret = SQL_NO_DATA;
08814         goto done;
08815     }
08816     if (nativeerr) {
08817         *nativeerr = naterr;
08818     }
08819     if (sqlstate) {
08820         strcpy((char *) sqlstate, sqlst);
08821     }
08822     if (msglen) {
08823         *msglen = len;
08824     }
08825     if (len >= buflen) {
08826         if (msg && buflen > 0) {
08827             strncpy((char *) msg, logmsg, buflen);
08828             msg[buflen - 1] = '\0';
08829             logmsg[0] = '\0';
08830         }
08831     } else if (msg) {
08832         strcpy((char *) msg, logmsg);
08833         logmsg[0] = '\0';
08834     }
08835     ret = SQL_SUCCESS;
08836 done:
08837     switch (htype) {
08838     case SQL_HANDLE_DBC:
08839         HDBC_UNLOCK((SQLHDBC) handle);
08840         break;
08841     case SQL_HANDLE_STMT:
08842         HSTMT_UNLOCK((SQLHSTMT) handle);
08843         break;
08844     }
08845     return ret;
08846 }
08847 
08848 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
08849 
08862 SQLRETURN SQL_API
08863 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08864               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08865               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08866 {
08867     return drvgetdiagrec(htype, handle, recno, sqlstate,
08868                          nativeerr, msg, buflen, msglen);
08869 }
08870 #endif
08871 
08872 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
08873 #ifdef WINTERFACE
08874 
08888 SQLRETURN SQL_API
08889 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08890               SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
08891               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08892 {
08893     char state[16];
08894     SQLSMALLINT len;
08895     SQLRETURN ret;
08896 
08897     ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
08898                         nativeerr, (SQLCHAR *) msg, buflen, &len);
08899     if (ret == SQL_SUCCESS) {
08900         if (sqlstate) {
08901             uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
08902                             6 * sizeof (SQLWCHAR));
08903         }
08904         if (msg) {
08905             if (len > 0) {
08906                 SQLWCHAR *m = NULL;
08907 
08908                 m = uc_from_utf((unsigned char *) msg, len);
08909                 if (m) {
08910                     if (buflen) {
08911                         buflen /= sizeof (SQLWCHAR);
08912                         uc_strncpy(msg, m, buflen);
08913                         m[len] = 0;
08914                         len = min(buflen, uc_strlen(m));
08915                     } else {
08916                         len = uc_strlen(m);
08917                     }
08918                     uc_free(m);
08919                 } else {
08920                     len = 0;
08921                 }
08922             }
08923             if (len <= 0) {
08924                 len = 0;
08925                 if (buflen > 0) {
08926                     msg[0] = 0;
08927                 }
08928             }
08929         } else {
08930             /* estimated length !!! */
08931             len *= sizeof (SQLWCHAR);
08932         }
08933         if (msglen) {
08934             *msglen = len;
08935         }
08936     } else if (ret == SQL_NO_DATA) {
08937         if (sqlstate) {
08938             sqlstate[0] = 0;
08939         }
08940         if (msg) {
08941             if (buflen > 0) {
08942                 msg[0] = 0;
08943             }
08944         }
08945         if (msglen) {
08946             *msglen = 0;
08947         }
08948     }
08949     return ret;
08950 }
08951 #endif
08952 #endif
08953 
08966 static SQLRETURN
08967 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08968                 SQLSMALLINT id, SQLPOINTER info,
08969                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08970 {
08971     DBC *d = NULL;
08972     STMT *s = NULL;
08973     int len, naterr, strbuf = 1;
08974     char *logmsg, *sqlst, *clrmsg = NULL;
08975     SQLRETURN ret = SQL_ERROR;
08976 
08977     if (handle == SQL_NULL_HANDLE) {
08978         return SQL_INVALID_HANDLE;
08979     }
08980     if (stringlen) {
08981         *stringlen = 0;
08982     }
08983     switch (htype) {
08984     case SQL_HANDLE_ENV:
08985     case SQL_HANDLE_DESC:
08986         return SQL_NO_DATA;
08987     case SQL_HANDLE_DBC:
08988         HDBC_LOCK((SQLHDBC) handle);
08989         d = (DBC *) handle;
08990         logmsg = (char *) d->logmsg;
08991         sqlst = d->sqlstate;
08992         naterr = d->naterr;
08993         break;
08994     case SQL_HANDLE_STMT:
08995         HSTMT_LOCK((SQLHSTMT) handle);
08996         s = (STMT *) handle;
08997         d = (DBC *) s->dbc;
08998         logmsg = (char *) s->logmsg;
08999         sqlst = s->sqlstate;
09000         naterr = s->naterr;
09001         break;
09002     default:
09003         return SQL_INVALID_HANDLE;
09004     }
09005     if (buflen < 0) {
09006         switch (buflen) {
09007         case SQL_IS_POINTER:
09008         case SQL_IS_UINTEGER:
09009         case SQL_IS_INTEGER:
09010         case SQL_IS_USMALLINT:
09011         case SQL_IS_SMALLINT:
09012             strbuf = 0;
09013             break;
09014         default:
09015             ret = SQL_ERROR;
09016             goto done;
09017         }
09018     }
09019     if (recno > 1) {
09020         ret = SQL_NO_DATA;
09021         goto done;
09022     }
09023     switch (id) {
09024     case SQL_DIAG_CLASS_ORIGIN:
09025         logmsg = "ISO 9075";
09026         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
09027             logmsg = "ODBC 3.0";
09028         }
09029         break;
09030     case SQL_DIAG_SUBCLASS_ORIGIN:
09031         logmsg = "ISO 9075";
09032         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
09033             logmsg = "ODBC 3.0";
09034         } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
09035             logmsg = "ODBC 3.0";
09036         } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
09037             logmsg = "ODBC 3.0";
09038         }
09039         break;
09040     case SQL_DIAG_CONNECTION_NAME:
09041     case SQL_DIAG_SERVER_NAME:
09042         logmsg = d->dsn ? d->dsn : "No DSN";
09043         break;
09044     case SQL_DIAG_SQLSTATE:
09045         logmsg = sqlst;
09046         break;
09047     case SQL_DIAG_MESSAGE_TEXT:
09048         if (info) {
09049             clrmsg = logmsg;
09050         }
09051         break;
09052     case SQL_DIAG_NUMBER:
09053         naterr = 1;
09054         /* fall through */
09055     case SQL_DIAG_NATIVE:
09056         len = strlen(logmsg);
09057         if (len == 0) {
09058             ret = SQL_NO_DATA;
09059             goto done;
09060         }
09061         if (info) {
09062             *((SQLINTEGER *) info) = naterr;
09063         }
09064         ret = SQL_SUCCESS;
09065         goto done;
09066     case SQL_DIAG_DYNAMIC_FUNCTION:
09067         logmsg = "";
09068         break;
09069     case SQL_DIAG_CURSOR_ROW_COUNT:
09070         if (htype == SQL_HANDLE_STMT) {
09071             SQLULEN count;
09072 
09073             count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
09074             *((SQLULEN *) info) = count;
09075             ret = SQL_SUCCESS;
09076         }
09077         goto done;
09078     case SQL_DIAG_ROW_COUNT:
09079         if (htype == SQL_HANDLE_STMT) {
09080             SQLULEN count;
09081 
09082             count = s->isselect ? 0 : s->nrows;
09083             *((SQLULEN *) info) = count;
09084             ret = SQL_SUCCESS;
09085         }
09086         goto done;
09087     default:
09088         goto done;
09089     }
09090     if (info && buflen > 0) {
09091         ((char *) info)[0] = '\0';
09092     }
09093     len = strlen(logmsg);
09094     if (len == 0) {
09095         ret = SQL_NO_DATA;
09096         goto done;
09097     }
09098     if (stringlen) {
09099         *stringlen = len;
09100     }
09101     if (strbuf) {
09102         if (len >= buflen) {
09103             if (info && buflen > 0) {
09104                 if (stringlen) {
09105                     *stringlen = buflen - 1;
09106                 }
09107                 strncpy((char *) info, logmsg, buflen);
09108                 ((char *) info)[buflen - 1] = '\0';
09109             }
09110         } else if (info) {
09111             strcpy((char *) info, logmsg);
09112         }
09113     }
09114     if (clrmsg) {
09115         *clrmsg = '\0';
09116     }
09117     ret = SQL_SUCCESS;
09118 done:
09119     switch (htype) {
09120     case SQL_HANDLE_DBC:
09121         HDBC_UNLOCK((SQLHDBC) handle);
09122         break;
09123     case SQL_HANDLE_STMT:
09124         HSTMT_UNLOCK((SQLHSTMT) handle);
09125         break;
09126     }
09127     return ret;
09128 }
09129 
09130 #ifndef WINTERFACE
09131 
09143 SQLRETURN SQL_API
09144 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
09145                 SQLSMALLINT id, SQLPOINTER info,
09146                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
09147 {
09148     return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
09149 }
09150 #endif
09151 
09152 #ifdef WINTERFACE
09153 
09165 SQLRETURN SQL_API
09166 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
09167                  SQLSMALLINT id, SQLPOINTER info,
09168                  SQLSMALLINT buflen, SQLSMALLINT *stringlen)
09169 {
09170     SQLSMALLINT len;
09171     SQLRETURN ret;
09172 
09173     ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
09174     if (ret == SQL_SUCCESS) {
09175         if (info) {
09176             switch (id) {
09177             case SQL_DIAG_CLASS_ORIGIN:
09178             case SQL_DIAG_SUBCLASS_ORIGIN:
09179             case SQL_DIAG_CONNECTION_NAME:
09180             case SQL_DIAG_SERVER_NAME:
09181             case SQL_DIAG_SQLSTATE:
09182             case SQL_DIAG_MESSAGE_TEXT:
09183             case SQL_DIAG_DYNAMIC_FUNCTION:
09184                 if (len > 0) {
09185                     SQLWCHAR *m = NULL;
09186 
09187                     m = uc_from_utf((unsigned char *) info, len);
09188                     if (m) {
09189                         if (buflen) {
09190                             buflen /= sizeof (SQLWCHAR);
09191                             uc_strncpy(info, m, buflen);
09192                             m[len] = 0;
09193                             len = min(buflen, uc_strlen(m));
09194                         } else {
09195                             len = uc_strlen(m);
09196                         }
09197                         uc_free(m);
09198                         len *= sizeof (SQLWCHAR);
09199                     } else {
09200                         len = 0;
09201                     }
09202                 }
09203                 if (len <= 0) {
09204                     len = 0;
09205                     if (buflen > 0) {
09206                         ((SQLWCHAR *) info)[0] = 0;
09207                     }
09208                 }
09209             }
09210         } else {
09211             switch (id) {
09212             case SQL_DIAG_CLASS_ORIGIN:
09213             case SQL_DIAG_SUBCLASS_ORIGIN:
09214             case SQL_DIAG_CONNECTION_NAME:
09215             case SQL_DIAG_SERVER_NAME:
09216             case SQL_DIAG_SQLSTATE:
09217             case SQL_DIAG_MESSAGE_TEXT:
09218             case SQL_DIAG_DYNAMIC_FUNCTION:
09219                 len *= sizeof (SQLWCHAR);
09220                 break;
09221             }
09222         }
09223         if (stringlen) {
09224             *stringlen = len;
09225         }
09226     }
09227     return ret;
09228 }
09229 #endif
09230 
09241 static SQLRETURN
09242 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09243                SQLINTEGER bufmax, SQLINTEGER *buflen)
09244 {
09245     STMT *s = (STMT *) stmt;
09246     SQLULEN *uval = (SQLULEN *) val;
09247     SQLINTEGER dummy;
09248     char dummybuf[16];
09249 
09250     if (!buflen) {
09251         buflen = &dummy;
09252     }
09253     if (!uval) {
09254         uval = (SQLPOINTER) dummybuf;
09255     }
09256     switch (attr) {
09257     case SQL_QUERY_TIMEOUT:
09258         *uval = 0;
09259         *buflen = sizeof (SQLULEN);
09260         return SQL_SUCCESS;
09261     case SQL_ATTR_CURSOR_TYPE:
09262         *uval = s->curtype;
09263         *buflen = sizeof (SQLULEN);
09264         return SQL_SUCCESS;
09265     case SQL_ATTR_CURSOR_SCROLLABLE:
09266         *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
09267             SQL_SCROLLABLE : SQL_NONSCROLLABLE;
09268         *buflen = sizeof (SQLULEN);
09269         return SQL_SUCCESS;
09270 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09271     case SQL_ATTR_CURSOR_SENSITIVITY:
09272         *uval = SQL_UNSPECIFIED;
09273         *buflen = sizeof (SQLULEN);
09274         return SQL_SUCCESS;
09275 #endif
09276     case SQL_ATTR_ROW_NUMBER:
09277         if (s->s3stmt) {
09278             *uval = (s->s3stmt_rownum < 0) ?
09279                     SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09280         } else {
09281             *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09282         }
09283         *buflen = sizeof (SQLULEN);
09284         return SQL_SUCCESS;
09285     case SQL_ATTR_ASYNC_ENABLE:
09286         *uval = SQL_ASYNC_ENABLE_OFF;
09287         *buflen = sizeof (SQLULEN);
09288         return SQL_SUCCESS;
09289     case SQL_CONCURRENCY:
09290         *uval = SQL_CONCUR_LOCK;
09291         *buflen = sizeof (SQLULEN);
09292         return SQL_SUCCESS;
09293     case SQL_ATTR_RETRIEVE_DATA:
09294         *uval = s->retr_data;
09295         *buflen = sizeof (SQLULEN);
09296         return SQL_SUCCESS;
09297     case SQL_ROWSET_SIZE:
09298     case SQL_ATTR_ROW_ARRAY_SIZE:
09299         *uval = s->rowset_size;
09300         *buflen = sizeof (SQLULEN);
09301         return SQL_SUCCESS;
09302     /* Needed for some driver managers, but dummies for now */
09303     case SQL_ATTR_IMP_ROW_DESC:
09304     case SQL_ATTR_APP_ROW_DESC:
09305     case SQL_ATTR_IMP_PARAM_DESC:
09306     case SQL_ATTR_APP_PARAM_DESC:
09307         *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
09308         *buflen = sizeof (SQLHDESC);
09309         return SQL_SUCCESS;
09310     case SQL_ATTR_ROW_STATUS_PTR:
09311         *((SQLUSMALLINT **) uval) = s->row_status;
09312         *buflen = sizeof (SQLUSMALLINT *);
09313         return SQL_SUCCESS;
09314     case SQL_ATTR_ROWS_FETCHED_PTR:
09315         *((SQLULEN **) uval) = s->row_count;
09316         *buflen = sizeof (SQLULEN *);
09317         return SQL_SUCCESS;
09318     case SQL_ATTR_USE_BOOKMARKS: {
09319         STMT *s = (STMT *) stmt;
09320 
09321         *(SQLUINTEGER *) uval = s->bkmrk;
09322         *buflen = sizeof (SQLUINTEGER);
09323         return SQL_SUCCESS;
09324     }
09325     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09326         *(SQLPOINTER *) uval = s->bkmrkptr;
09327         *buflen = sizeof (SQLPOINTER);
09328         return SQL_SUCCESS;
09329     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09330         *((SQLULEN **) uval) = s->parm_bind_offs;
09331         *buflen = sizeof (SQLULEN *);
09332         return SQL_SUCCESS;
09333     case SQL_ATTR_PARAM_BIND_TYPE:
09334         *((SQLULEN *) uval) = s->parm_bind_type;
09335         *buflen = sizeof (SQLULEN);
09336         return SQL_SUCCESS;
09337     case SQL_ATTR_PARAM_OPERATION_PTR:
09338         *((SQLUSMALLINT **) uval) = s->parm_oper;
09339         *buflen = sizeof (SQLUSMALLINT *);
09340         return SQL_SUCCESS;
09341     case SQL_ATTR_PARAM_STATUS_PTR:
09342         *((SQLUSMALLINT **) uval) = s->parm_status;
09343         *buflen = sizeof (SQLUSMALLINT *);
09344         return SQL_SUCCESS;
09345     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09346         *((SQLULEN **) uval) = s->parm_proc;
09347         *buflen = sizeof (SQLULEN *);
09348         return SQL_SUCCESS;
09349     case SQL_ATTR_PARAMSET_SIZE:
09350         *((SQLULEN *) uval) = s->paramset_size;
09351         *buflen = sizeof (SQLULEN);
09352         return SQL_SUCCESS;
09353     case SQL_ATTR_ROW_BIND_TYPE:
09354         *(SQLULEN *) uval = s->bind_type;
09355         *buflen = sizeof (SQLULEN);
09356         return SQL_SUCCESS;
09357     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09358         *((SQLULEN **) uval) = s->bind_offs;
09359         *buflen = sizeof (SQLULEN *);
09360         return SQL_SUCCESS;
09361     case SQL_ATTR_MAX_ROWS:
09362         *((SQLULEN *) uval) = s->max_rows;
09363         *buflen = sizeof (SQLULEN);
09364         return SQL_SUCCESS;
09365     case SQL_ATTR_MAX_LENGTH:
09366         *((SQLULEN *) uval) = 1000000000;
09367         *buflen = sizeof (SQLULEN);
09368         return SQL_SUCCESS;
09369 #ifdef SQL_ATTR_METADATA_ID
09370     case SQL_ATTR_METADATA_ID:
09371         *((SQLULEN *) uval) = SQL_FALSE;
09372         *buflen = sizeof (SQLULEN);
09373         return SQL_SUCCESS;
09374 #endif
09375     }
09376     return drvunimplstmt(stmt);
09377 }
09378 
09379 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09380 
09390 SQLRETURN SQL_API
09391 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09392                SQLINTEGER bufmax, SQLINTEGER *buflen)
09393 {
09394     SQLRETURN ret;
09395 
09396     HSTMT_LOCK(stmt);
09397     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09398     HSTMT_UNLOCK(stmt);
09399     return ret;
09400 }
09401 #endif
09402 
09403 #ifdef WINTERFACE
09404 
09414 SQLRETURN SQL_API
09415 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09416                 SQLINTEGER bufmax, SQLINTEGER *buflen)
09417 {
09418     SQLRETURN ret;
09419 
09420     HSTMT_LOCK(stmt);
09421     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09422     HSTMT_UNLOCK(stmt);
09423     return ret;
09424 }
09425 #endif
09426 
09436 static SQLRETURN
09437 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09438                SQLINTEGER buflen)
09439 {
09440     STMT *s = (STMT *) stmt;
09441 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
09442     SQLBIGINT uval;
09443 
09444     uval = (SQLBIGINT) val;
09445 #else
09446     SQLULEN uval;
09447 
09448     uval = (SQLULEN) val;
09449 #endif
09450     switch (attr) {
09451     case SQL_ATTR_CURSOR_TYPE:
09452         if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
09453             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09454         } else {
09455             s->curtype = SQL_CURSOR_STATIC;
09456         }
09457         if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
09458             val != (SQLPOINTER) SQL_CURSOR_STATIC) {
09459             goto e01s02;
09460         }
09461         return SQL_SUCCESS;
09462     case SQL_ATTR_CURSOR_SCROLLABLE:
09463         if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
09464             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09465         } else {
09466             s->curtype = SQL_CURSOR_STATIC;
09467         }
09468         return SQL_SUCCESS;
09469     case SQL_ATTR_ASYNC_ENABLE:
09470         if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
09471     e01s02:
09472             setstat(s, -1, "option value changed", "01S02");
09473             return SQL_SUCCESS_WITH_INFO;
09474         }
09475         return SQL_SUCCESS;
09476     case SQL_CONCURRENCY:
09477         if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
09478             goto e01s02;
09479         }
09480         return SQL_SUCCESS;
09481 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09482     case SQL_ATTR_CURSOR_SENSITIVITY:
09483         if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
09484             goto e01s02;
09485         }
09486         return SQL_SUCCESS;
09487 #endif
09488     case SQL_ATTR_QUERY_TIMEOUT:
09489         return SQL_SUCCESS;
09490     case SQL_ATTR_RETRIEVE_DATA:
09491         if (val != (SQLPOINTER) SQL_RD_ON &&
09492             val != (SQLPOINTER) SQL_RD_OFF) {
09493             goto e01s02;
09494         }
09495         s->retr_data = uval;
09496         return SQL_SUCCESS;
09497     case SQL_ROWSET_SIZE:
09498     case SQL_ATTR_ROW_ARRAY_SIZE:
09499         if (uval < 1) {
09500             setstat(s, -1, "invalid rowset size", "HY000");
09501             return SQL_ERROR;
09502         } else {
09503             SQLUSMALLINT *rst = &s->row_status1;
09504 
09505             if (uval > 1) {
09506                 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
09507                 if (!rst) {
09508                     return nomem(s);
09509                 }
09510             }
09511             if (s->row_status0 != &s->row_status1) {
09512                 freep(&s->row_status0);
09513             }
09514             s->row_status0 = rst;
09515             s->rowset_size = uval;
09516         }
09517         return SQL_SUCCESS;
09518     case SQL_ATTR_ROW_STATUS_PTR:
09519         s->row_status = (SQLUSMALLINT *) val;
09520         return SQL_SUCCESS;
09521     case SQL_ATTR_ROWS_FETCHED_PTR:
09522         s->row_count = (SQLULEN *) val;
09523         return SQL_SUCCESS;
09524     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09525         s->parm_bind_offs = (SQLULEN *) val;
09526         return SQL_SUCCESS;
09527     case SQL_ATTR_PARAM_BIND_TYPE:
09528         s->parm_bind_type = uval;
09529         return SQL_SUCCESS;
09530     case SQL_ATTR_PARAM_OPERATION_PTR:
09531         s->parm_oper = (SQLUSMALLINT *) val;
09532         return SQL_SUCCESS;
09533     case SQL_ATTR_PARAM_STATUS_PTR:
09534         s->parm_status = (SQLUSMALLINT *) val;
09535         return SQL_SUCCESS;
09536     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09537         s->parm_proc = (SQLULEN *) val;
09538         return SQL_SUCCESS;
09539     case SQL_ATTR_PARAMSET_SIZE:
09540         if (uval < 1) {
09541             goto e01s02;
09542         }
09543         s->paramset_size = uval;
09544         s->paramset_count = 0;
09545         return SQL_SUCCESS;
09546     case SQL_ATTR_ROW_BIND_TYPE:
09547         s->bind_type = uval;
09548         return SQL_SUCCESS;
09549     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09550         s->bind_offs = (SQLULEN *) val;
09551         return SQL_SUCCESS;
09552     case SQL_ATTR_USE_BOOKMARKS:
09553         if (val != (SQLPOINTER) SQL_UB_OFF &&
09554             val != (SQLPOINTER) SQL_UB_ON &&
09555             val != (SQLPOINTER) SQL_UB_VARIABLE) {
09556             goto e01s02;
09557         }
09558         if (*s->ov3 && val == (SQLPOINTER) SQL_UB_VARIABLE) {
09559             s->bkmrk = SQL_UB_VARIABLE;
09560             return SQL_SUCCESS;
09561         }
09562         if (val == (SQLPOINTER) SQL_UB_VARIABLE) {
09563             s->bkmrk = SQL_UB_ON;
09564             goto e01s02;
09565         }
09566         s->bkmrk = (val == (SQLPOINTER) SQL_UB_ON) ? SQL_UB_ON : SQL_UB_OFF;
09567         return SQL_SUCCESS;
09568     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09569         s->bkmrkptr = (SQLINTEGER *) val;
09570         return SQL_SUCCESS;
09571     case SQL_ATTR_MAX_ROWS:
09572         s->max_rows = uval;
09573         return SQL_SUCCESS;
09574     case SQL_ATTR_MAX_LENGTH:
09575         if (val != (SQLPOINTER) 1000000000) {
09576             goto e01s02;
09577         }
09578         return SQL_SUCCESS;
09579 #ifdef SQL_ATTR_METADATA_ID
09580     case SQL_ATTR_METADATA_ID:
09581         if (val != (SQLPOINTER) SQL_FALSE) {
09582             goto e01s02;
09583         }
09584         return SQL_SUCCESS;
09585 #endif
09586     }
09587     return drvunimplstmt(stmt);
09588 }
09589 
09590 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09591 
09600 SQLRETURN SQL_API
09601 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09602                SQLINTEGER buflen)
09603 {
09604     SQLRETURN ret;
09605 
09606     HSTMT_LOCK(stmt);
09607     ret = drvsetstmtattr(stmt, attr, val, buflen);
09608     HSTMT_UNLOCK(stmt);
09609     return ret;
09610 }
09611 #endif
09612 
09613 #ifdef WINTERFACE
09614 
09623 SQLRETURN SQL_API
09624 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09625                 SQLINTEGER buflen)
09626 {
09627     SQLRETURN ret;
09628 
09629     HSTMT_LOCK(stmt);
09630     ret = drvsetstmtattr(stmt, attr, val, buflen);
09631     HSTMT_UNLOCK(stmt);
09632     return ret;
09633 }
09634 #endif
09635 
09644 static SQLRETURN
09645 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09646 {
09647     STMT *s = (STMT *) stmt;
09648     SQLUINTEGER *ret = (SQLUINTEGER *) param;
09649 
09650     switch (opt) {
09651     case SQL_QUERY_TIMEOUT:
09652         *ret = 0;
09653         return SQL_SUCCESS;
09654     case SQL_CURSOR_TYPE:
09655         *ret = s->curtype;
09656         return SQL_SUCCESS;
09657     case SQL_ROW_NUMBER:
09658         if (s->s3stmt) {
09659             *ret = (s->s3stmt_rownum < 0) ?
09660                    SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09661         } else {
09662             *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09663         }
09664         return SQL_SUCCESS;
09665     case SQL_ASYNC_ENABLE:
09666         *ret = SQL_ASYNC_ENABLE_OFF;
09667         return SQL_SUCCESS;
09668     case SQL_CONCURRENCY:
09669         *ret = SQL_CONCUR_LOCK;
09670         return SQL_SUCCESS;
09671     case SQL_ATTR_RETRIEVE_DATA:
09672         *ret = s->retr_data;
09673         return SQL_SUCCESS;
09674     case SQL_ROWSET_SIZE:
09675     case SQL_ATTR_ROW_ARRAY_SIZE:
09676         *ret = s->rowset_size;
09677         return SQL_SUCCESS;
09678     case SQL_ATTR_MAX_ROWS:
09679         *ret = s->max_rows;
09680         return SQL_SUCCESS;
09681     case SQL_ATTR_MAX_LENGTH:
09682         *ret = 1000000000;
09683         return SQL_SUCCESS;
09684     }
09685     return drvunimplstmt(stmt);
09686 }
09687 
09696 SQLRETURN SQL_API
09697 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09698 {
09699     SQLRETURN ret;
09700 
09701     HSTMT_LOCK(stmt);
09702     ret = drvgetstmtoption(stmt, opt, param);
09703     HSTMT_UNLOCK(stmt);
09704     return ret;
09705 }
09706 
09707 #ifdef WINTERFACE
09708 
09716 SQLRETURN SQL_API
09717 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09718 {
09719     SQLRETURN ret;
09720 
09721     HSTMT_LOCK(stmt);
09722     ret = drvgetstmtoption(stmt, opt, param);
09723     HSTMT_UNLOCK(stmt);
09724     return ret;
09725 }
09726 #endif
09727 
09736 static SQLRETURN
09737 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
09738 {
09739     STMT *s = (STMT *) stmt;
09740 
09741     switch (opt) {
09742     case SQL_CURSOR_TYPE:
09743         if (param == SQL_CURSOR_FORWARD_ONLY) {
09744             s->curtype = param;
09745         } else {
09746             s->curtype = SQL_CURSOR_STATIC;
09747         }
09748         if (param != SQL_CURSOR_FORWARD_ONLY &&
09749             param != SQL_CURSOR_STATIC) {
09750             goto e01s02;
09751         }
09752         return SQL_SUCCESS;
09753     case SQL_ASYNC_ENABLE:
09754         if (param != SQL_ASYNC_ENABLE_OFF) {
09755             goto e01s02;
09756         }
09757         return SQL_SUCCESS;
09758     case SQL_CONCURRENCY:
09759         if (param != SQL_CONCUR_LOCK) {
09760             goto e01s02;
09761         }
09762         return SQL_SUCCESS;
09763     case SQL_QUERY_TIMEOUT:
09764         return SQL_SUCCESS;
09765     case SQL_RETRIEVE_DATA:
09766         if (param != SQL_RD_ON && param != SQL_RD_OFF) {
09767     e01s02:
09768             setstat(s, -1, "option value changed", "01S02");
09769             return SQL_SUCCESS_WITH_INFO;
09770         }
09771         s->retr_data = (int) param;
09772         return SQL_SUCCESS;
09773     case SQL_ROWSET_SIZE:
09774     case SQL_ATTR_ROW_ARRAY_SIZE:
09775         if (param < 1) {
09776             setstat(s, -1, "invalid rowset size", "HY000");
09777             return SQL_ERROR;
09778         } else {
09779             SQLUSMALLINT *rst = &s->row_status1;
09780 
09781             if (param > 1) {
09782                 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
09783                 if (!rst) {
09784                     return nomem(s);
09785                 }
09786             }
09787             if (s->row_status0 != &s->row_status1) {
09788                 freep(&s->row_status0);
09789             }
09790             s->row_status0 = rst;
09791             s->rowset_size = param;
09792         }
09793         return SQL_SUCCESS;
09794     case SQL_ATTR_MAX_ROWS:
09795         s->max_rows = param;
09796         return SQL_SUCCESS;
09797     case SQL_ATTR_MAX_LENGTH:
09798         if (param != 1000000000) {
09799             goto e01s02;
09800         }
09801         return SQL_SUCCESS;
09802     }
09803     return drvunimplstmt(stmt);
09804 }
09805 
09814 SQLRETURN SQL_API
09815 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
09816                  SETSTMTOPTION_LAST_ARG_TYPE param)
09817 {
09818     SQLRETURN ret;
09819 
09820     HSTMT_LOCK(stmt);
09821     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09822     HSTMT_UNLOCK(stmt);
09823     return ret;
09824 }
09825 
09826 #ifdef WINTERFACE
09827 
09835 SQLRETURN SQL_API
09836 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
09837                   SETSTMTOPTION_LAST_ARG_TYPE param)
09838 {
09839     SQLRETURN ret;
09840 
09841     HSTMT_LOCK(stmt);
09842     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09843     HSTMT_UNLOCK(stmt);
09844     return ret;
09845 }
09846 #endif
09847 
09854 static SQLRETURN
09855 chkunbound(STMT *s)
09856 {
09857     int i;
09858 
09859     if (!s->bindcols || s->nbindcols < s->ncols) {
09860 unbound:
09861         setstat(s, -1, "unbound columns", (*s->ov3) ? "HY000" : "S1000");
09862         return SQL_ERROR;
09863     }
09864     for (i = 0; i < s->ncols; i++) {
09865         BINDCOL *b = &s->bindcols[i];
09866 
09867         if (b->type == SQL_UNKNOWN_TYPE || !b->valp) {
09868             goto unbound;
09869         }
09870     }
09871     return SQL_SUCCESS;
09872 }
09873 
09885 static SQLRETURN
09886 setposbind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
09887 {
09888     DBC *d = (DBC *) s->dbc;
09889     SQLPOINTER dp = 0;
09890     SQLLEN *lp = 0;
09891     BINDCOL *b = &s->bindcols[i];
09892     COL *c = &s->cols[i];
09893     char strbuf[128], *cp;
09894 
09895     if (b->valp) {
09896         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09897             dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
09898         } else {
09899             dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
09900         }
09901         if (s->bind_offs) {
09902             dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
09903         }
09904     }
09905     if (b->lenp) {
09906         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09907             lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
09908         } else {
09909             lp = b->lenp + rsi;
09910         }
09911         if (s->bind_offs) {
09912             lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
09913         }
09914     }
09915     if (!dp || !lp) {
09916         setstat(s, -1, "unbound column in positional update",
09917                 (*s->ov3) ? "HY000" : "S1000");
09918         return SQL_ERROR;
09919     }
09920     if (*lp == SQL_NULL_DATA) {
09921         sqlite3_bind_null(stmt, si);
09922         if (d->trace) {
09923             fprintf(d->trace, "-- parameter %d: NULL\n", si);
09924             fflush(d->trace);
09925         }
09926         return SQL_SUCCESS;
09927     }
09928     switch (b->type) {
09929     case SQL_C_UTINYINT:
09930     case SQL_C_TINYINT:
09931     case SQL_C_STINYINT:
09932         sqlite3_bind_int(stmt, si, *(SQLCHAR *) dp);
09933         if (d->trace) {
09934             fprintf(d->trace, "-- parameter %d: %d\n", si, *(SQLCHAR *) dp);
09935             fflush(d->trace);
09936         }
09937         break;
09938 #ifdef SQL_BIT
09939     case SQL_C_BIT:
09940         sqlite3_bind_int(stmt, si, (*(SQLCHAR *) dp) ? 1 : 0);
09941         if (d->trace) {
09942             fprintf(d->trace, "-- parameter %d: %d\n", si,
09943                     (*(SQLCHAR *) dp) ? 1 : 0);
09944             fflush(d->trace);
09945         }
09946         break;
09947 #endif
09948     case SQL_C_USHORT:
09949         sqlite3_bind_int(stmt, si, *(SQLUSMALLINT *) dp);
09950         if (d->trace) {
09951             fprintf(d->trace, "-- parameter %d: %d\n", si,
09952                     *(SQLUSMALLINT *) dp);
09953             fflush(d->trace);
09954         }
09955         break;
09956     case SQL_C_SHORT:
09957     case SQL_C_SSHORT:
09958         sqlite3_bind_int(stmt, si, *(SQLSMALLINT *) dp);
09959         if (d->trace) {
09960             fprintf(d->trace, "-- parameter %d: %d\n", si,
09961                     *(SQLSMALLINT *) dp);
09962             fflush(d->trace);
09963         }
09964         break;
09965     case SQL_C_ULONG:
09966         sqlite3_bind_int(stmt, si, *(SQLUINTEGER *) dp);
09967         if (d->trace) {
09968             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09969                     (long) *(SQLUINTEGER *) dp);
09970             fflush(d->trace);
09971         }
09972         break;
09973     case SQL_C_LONG:
09974     case SQL_C_SLONG:
09975         sqlite3_bind_int(stmt, si, *(SQLINTEGER *) dp);
09976         if (d->trace) {
09977             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09978                     (long) *(SQLINTEGER *) dp);
09979             fflush(d->trace);
09980         }
09981         break;
09982 #ifdef SQL_BIGINT
09983     case SQL_C_UBIGINT:
09984     case SQL_C_SBIGINT:
09985         sqlite3_bind_int64(stmt, si, *(SQLBIGINT *) dp);
09986         if (d->trace) {
09987             fprintf(d->trace,
09988 #ifdef _WIN32
09989                     "-- parameter %d: %I64d\n",
09990 #else
09991                     "-- parameter %d: %lld\n",
09992 #endif
09993                     si, (sqlite_int64) *(SQLBIGINT *) dp);
09994             fflush(d->trace);
09995         }
09996         break;
09997 #endif
09998     case SQL_C_FLOAT:
09999         sqlite3_bind_double(stmt, si, *(float *) dp);
10000         if (d->trace) {
10001             fprintf(d->trace, "-- parameter %d: %g\n", si,
10002                     *(float *) dp);
10003             fflush(d->trace);
10004         }
10005         break;
10006     case SQL_C_DOUBLE:
10007         sqlite3_bind_double(stmt, si, *(double *) dp);
10008         if (d->trace) {
10009             fprintf(d->trace, "-- parameter %d: %g\n", si,
10010                     *(double *) dp);
10011             fflush(d->trace);
10012         }
10013         break;
10014     case SQL_C_BINARY:
10015         sqlite3_bind_blob(stmt, si, (char *) dp, *lp, SQLITE_STATIC);
10016         if (d->trace) {
10017             fprintf(d->trace, "-- parameter %d: [BLOB]\n", si);
10018             fflush(d->trace);
10019         }
10020         break;
10021 #ifdef WCHARSUPPORT
10022     case SQL_C_WCHAR:
10023         cp = uc_to_utf((SQLWCHAR *) dp, *lp);
10024         if (!cp) {
10025             return nomem(s);
10026         }
10027         sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
10028         if (d->trace) {
10029             fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
10030             fflush(d->trace);
10031         }
10032         uc_free(cp);
10033         break;
10034 #endif
10035     case SQL_C_CHAR:
10036 #if defined(_WIN32) || defined(_WIN64)
10037         if (*s->oemcp) {
10038             cp = wmb_to_utf((char *) dp, *lp);
10039             if (!cp) {
10040                 return nomem(s);
10041             }
10042             sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
10043             if (d->trace) {
10044                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
10045                 fflush(d->trace);
10046             }
10047             uc_free(cp);
10048         } else
10049 #endif
10050         {
10051             if (*lp == SQL_NTS) {
10052                 sqlite3_bind_text(stmt, si, (char *) dp, -1,
10053                                   SQLITE_STATIC);
10054                 if (d->trace) {
10055                     fprintf(d->trace, "-- parameter %d: '%s'\n", si,
10056                             (char *) dp);
10057                     fflush(d->trace);
10058                 }
10059             } else {
10060                 sqlite3_bind_text(stmt, si, (char *) dp, *lp,
10061                                   SQLITE_STATIC);
10062                 if (d->trace) {
10063                     fprintf(d->trace, "-- parameter %d: '%*s'\n", si,
10064                             (int) *lp, (char *) dp);
10065                     fflush(d->trace);
10066                 }
10067             }
10068         }
10069         break;
10070 #ifdef SQL_C_TYPE_DATE
10071     case SQL_C_TYPE_DATE:
10072 #endif
10073     case SQL_C_DATE:
10074         if (*s->jdconv) {
10075             int a, b, x1, x2, y, m, dd;
10076             double v;
10077 
10078             y = ((DATE_STRUCT *) dp)->year;
10079             m = ((DATE_STRUCT *) dp)->month;
10080             dd = ((DATE_STRUCT *) dp)->day;
10081             if (m <= 2) {
10082                 y--;
10083                 m += 12;
10084             }
10085             a = y / 100;
10086             b = 2 - a + (a / 4);
10087             x1 = 36525 * (y + 4716) / 100;
10088             x2 = 306001 * (m + 1) / 10000;
10089             v = x1 + x2 + dd + b - 1524.5;
10090             sqlite3_bind_double(stmt, si, v);
10091             if (d->trace) {
10092                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10093                 fflush(d->trace);
10094             }
10095         } else {
10096             sprintf(strbuf, "%04d-%02d-%02d",
10097                     ((DATE_STRUCT *) dp)->year,
10098                     ((DATE_STRUCT *) dp)->month,
10099                     ((DATE_STRUCT *) dp)->day);
10100             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10101             if (d->trace) {
10102                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10103                 fflush(d->trace);
10104             }
10105         }
10106         break;
10107 #ifdef SQL_C_TYPE_TIME
10108     case SQL_C_TYPE_TIME:
10109 #endif
10110     case SQL_C_TIME:
10111         if (*s->jdconv) {
10112             double v;
10113 
10114             v = 2451544.5 +
10115                (((TIME_STRUCT *) dp)->hour * 3600000.0 +
10116                 ((TIME_STRUCT *) dp)->minute * 60000.0 +
10117                 ((TIME_STRUCT *) dp)->second * 1000.0) / 86400000.0;
10118             sqlite3_bind_double(stmt, si, v);
10119             if (d->trace) {
10120                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10121                 fflush(d->trace);
10122             }
10123         } else {
10124             sprintf(strbuf, "%02d:%02d:%02d",
10125                     ((TIME_STRUCT *) dp)->hour,
10126                     ((TIME_STRUCT *) dp)->minute,
10127                     ((TIME_STRUCT *) dp)->second);
10128             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10129             if (d->trace) {
10130                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10131                 fflush(d->trace);
10132             }
10133         }
10134         break;
10135 #ifdef SQL_C_TYPE_TIMESTAMP
10136     case SQL_C_TYPE_TIMESTAMP:
10137 #endif
10138     case SQL_C_TIMESTAMP:
10139         if (*s->jdconv) {
10140             int a, b, x1, x2, y, m, dd;
10141             double v;
10142 
10143             y = ((TIMESTAMP_STRUCT *) dp)->year;
10144             m = ((TIMESTAMP_STRUCT *) dp)->month;
10145             dd = ((TIMESTAMP_STRUCT *) dp)->day;
10146             if (m <= 2) {
10147                 y--;
10148                 m += 12;
10149             }
10150             a = y / 100;
10151             b = 2 - a + (a / 4);
10152             x1 = 36525 * (y + 4716) / 100;
10153             x2 = 306001 * (m + 1) / 10000;
10154             v = x1 + x2 + dd + b - 1524.5 +
10155                (((TIMESTAMP_STRUCT *) dp)->hour * 3600000.0 +
10156                 ((TIMESTAMP_STRUCT *) dp)->minute * 60000.0 +
10157                 ((TIMESTAMP_STRUCT *) dp)->second * 1000.0 +
10158                 ((TIMESTAMP_STRUCT *) dp)->fraction / 1.0E6)
10159                / 86400000.0;
10160             sqlite3_bind_double(stmt, si, v);
10161             if (d->trace) {
10162                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10163                 fflush(d->trace);
10164             }
10165         } else {
10166             int frac;
10167 
10168             frac = (int) ((TIMESTAMP_STRUCT *) dp)->fraction;
10169             frac /= 1000000;
10170             frac = frac % 1000;
10171             if (frac < 0) {
10172                 frac = 0;
10173             }
10174             if (c->prec && c->prec <= 16) {
10175                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
10176                         ((TIMESTAMP_STRUCT *) dp)->year,
10177                         ((TIMESTAMP_STRUCT *) dp)->month,
10178                         ((TIMESTAMP_STRUCT *) dp)->day,
10179                         ((TIMESTAMP_STRUCT *) dp)->hour,
10180                         ((TIMESTAMP_STRUCT *) dp)->minute);
10181             } else if (c->prec && c->prec <= 19) {
10182                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
10183                         ((TIMESTAMP_STRUCT *) dp)->year,
10184                         ((TIMESTAMP_STRUCT *) dp)->month,
10185                         ((TIMESTAMP_STRUCT *) dp)->day,
10186                         ((TIMESTAMP_STRUCT *) dp)->hour,
10187                         ((TIMESTAMP_STRUCT *) dp)->minute,
10188                         ((TIMESTAMP_STRUCT *) dp)->second);
10189             } else {
10190                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
10191                         ((TIMESTAMP_STRUCT *) dp)->year,
10192                         ((TIMESTAMP_STRUCT *) dp)->month,
10193                         ((TIMESTAMP_STRUCT *) dp)->day,
10194                         ((TIMESTAMP_STRUCT *) dp)->hour,
10195                         ((TIMESTAMP_STRUCT *) dp)->minute,
10196                         ((TIMESTAMP_STRUCT *) dp)->second,
10197                         frac);
10198             }
10199             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10200             if (d->trace) {
10201                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10202                 fflush(d->trace);
10203             }
10204         }
10205         break;
10206     default:
10207         setstat(s, -1, "unsupported column type in positional update",
10208                 (*s->ov3) ? "HY000" : "S1000");
10209         return SQL_ERROR;
10210     }
10211     return SQL_SUCCESS;
10212 }
10213 
10225 static SQLRETURN
10226 setposibind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
10227 {
10228     DBC *d = (DBC *) s->dbc;
10229     char **data;
10230     int pos;
10231 
10232     pos = s->rowprs;
10233     if (pos < 0) {
10234         setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10235         return SQL_ERROR;
10236     }
10237     pos += rsi;
10238     data = s->rows + s->ncols + (pos * s->ncols) + i;
10239     if (*data == NULL) {
10240         sqlite3_bind_null(stmt, si);
10241         if (d->trace) {
10242             fprintf(d->trace, "-- parameter %d: NULL\n", si);
10243             fflush(d->trace);
10244         }
10245     } else {
10246         sqlite3_bind_text(stmt, si, *data, -1, SQLITE_STATIC);
10247         if (d->trace) {
10248             fprintf(d->trace, "-- parameter %d: '%s'\n", si, *data);
10249             fflush(d->trace);
10250         }
10251     }
10252     return SQL_SUCCESS;
10253 }
10254 
10262 static SQLRETURN
10263 setposrefr(STMT *s, int rsi)
10264 {
10265     int i, withinfo = 0;
10266     SQLRETURN ret = SQL_SUCCESS;
10267 
10268     for (i = 0; s->bindcols && i < s->ncols; i++) {
10269         BINDCOL *b = &s->bindcols[i];
10270         SQLPOINTER dp = 0;
10271         SQLLEN *lp = 0;
10272 
10273         b->offs = 0;
10274         if (b->valp) {
10275             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10276                 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
10277             } else {
10278                 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
10279             }
10280             if (s->bind_offs) {
10281                 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
10282             }
10283         }
10284         if (b->lenp) {
10285             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10286                 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
10287             } else {
10288                 lp = b->lenp + rsi;
10289             }
10290             if (s->bind_offs) {
10291                 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
10292             }
10293         }
10294         if (dp || lp) {
10295             int rowp = s->rowp;
10296 
10297             s->rowp = s->rowprs + rsi;
10298             ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp,
10299                              b->max, lp, 0);
10300             s->rowp = rowp;
10301             if (!SQL_SUCCEEDED(ret)) {
10302                 s->row_status0[rsi] = SQL_ROW_ERROR;
10303                 break;
10304             }
10305             if (ret != SQL_SUCCESS) {
10306                 withinfo = 1;
10307 #ifdef SQL_ROW_SUCCESS_WITH_INFO
10308                 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
10309 #endif
10310             }
10311         }
10312     }
10313     if (SQL_SUCCEEDED(ret)) {
10314         ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10315     }
10316     return ret;
10317 }
10318 
10328 static SQLRETURN
10329 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10330 {
10331     STMT *s = (STMT *) stmt;
10332     DBC *d = (DBC *) s->dbc;
10333     int rowp, i, k, rc, nretry = 0;
10334     dstr *sql = 0;
10335     const char *endp;
10336     sqlite3_stmt *s3stmt = NULL;
10337     SQLRETURN ret;
10338 
10339     if (lock != SQL_LOCK_NO_CHANGE) {
10340         setstat(s, -1, "unsupported locking mode",
10341                 (*s->ov3) ? "HY000" : "S1000");
10342         return SQL_ERROR;
10343     }
10344     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10345         setstat(s, -1, "incompatible statement",
10346                 (*s->ov3) ? "HY000" : "S1000");
10347         return SQL_ERROR;
10348     }
10349     if (op == SQL_ADD) {
10350         if (s->one_tbl <= 0) {
10351             setstat(s, -1, "incompatible rowset",
10352                     (*s->ov3) ? "HY000" : "S1000");
10353             return SQL_ERROR;
10354         }
10355         if (row == 0 || row > s->rowset_size + 1) {
10356             goto rowoor;
10357         }
10358         ret = chkunbound(s);
10359         if (ret != SQL_SUCCESS) {
10360             return ret;
10361         }
10362         sql = dsappend(sql, "INSERT INTO ");
10363         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10364             sql = dsappendq(sql, s->dyncols[0].db);
10365             sql = dsappend(sql, ".");
10366         }
10367         sql = dsappendq(sql, s->dyncols[0].table);
10368         for (i = 0; i < s->ncols; i++) {
10369             sql = dsappend(sql, (i > 0) ? "," : "(");
10370             sql = dsappendq(sql, s->dyncols[i].column);
10371         }
10372         sql = dsappend(sql, ") VALUES ");
10373         for (i = 0; i < s->ncols; i++) {
10374             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10375         }
10376         sql = dsappend(sql, ")");
10377         if (dserr(sql)) {
10378             dsfree(sql);
10379             return nomem(s);
10380         }
10381 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10382         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10383 #else
10384         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10385 #endif
10386         do {
10387             s3stmt = NULL;
10388 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10389             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10390                                     &s3stmt, &endp);
10391 #else
10392             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10393                                  &s3stmt, &endp);
10394 #endif
10395             if (rc != SQLITE_OK) {
10396                 if (s3stmt) {
10397                     sqlite3_finalize(s3stmt);
10398                     s3stmt = NULL;
10399                 }
10400             }
10401         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10402         dbtracerc(d, rc, NULL);
10403         dsfree(sql);
10404         if (rc != SQLITE_OK) {
10405 istmterr:
10406             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10407                     sqlite3_errmsg(d->sqlite), rc);
10408             if (s3stmt) {
10409                 dbtraceapi(d, "sqlite3_finalize", NULL);
10410                 sqlite3_finalize(s3stmt);
10411             }
10412             return SQL_ERROR;
10413         }
10414         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10415             ret = setposbind(s, s3stmt, i, k, row - 1);
10416             if (ret != SQL_SUCCESS) {
10417                 dbtraceapi(d, "sqlite3_finalize", NULL);
10418                 sqlite3_finalize(s3stmt);
10419                 return ret;
10420             }
10421             k++;
10422         }
10423         rc = sqlite3_step(s3stmt);
10424         if (rc != SQLITE_DONE) {
10425             goto istmterr;
10426         }
10427         sqlite3_finalize(s3stmt);
10428         if (sqlite3_changes(d->sqlite) > 0 && row <= s->rowset_size) {
10429             if (s->row_status0) {
10430                 s->row_status0[row - 1] = SQL_ROW_ADDED;
10431             }
10432             if (s->row_status) {
10433                 s->row_status[row - 1] = SQL_ROW_ADDED;
10434             }
10435         }
10436         return SQL_SUCCESS;
10437     } else if (op == SQL_UPDATE || op == SQL_DELETE) {
10438         if (s->one_tbl <= 0 || s->has_pk <= 0) {
10439             setstat(s, -1, "incompatible rowset",
10440                     (*s->ov3) ? "HY000" : "S1000");
10441             return SQL_ERROR;
10442         }
10443         if (row == 0) {
10444             ret = SQL_SUCCESS;
10445             for (i = 1; i <= s->rowset_size; i++) {
10446                 ret = drvsetpos(stmt, i, op, lock);
10447                 if (!SQL_SUCCEEDED(ret)) {
10448                     break;
10449                 }
10450             }
10451             return ret;
10452         }
10453         if (row > s->rowset_size) {
10454             goto rowoor;
10455         }
10456     }
10457     if (op != SQL_POSITION && op != SQL_REFRESH &&
10458         op != SQL_DELETE && op != SQL_UPDATE) {
10459         return drvunimplstmt(stmt);
10460     }
10461     if (op == SQL_POSITION) {
10462         rowp = s->rowp + row - 1;
10463         if (!s->rows || row == 0 || rowp < -1 || rowp >= s->nrows) {
10464 rowoor:
10465             setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10466             return SQL_ERROR;
10467         }
10468         s->rowp = rowp;
10469     } else if (op == SQL_REFRESH) {
10470         if (row > s->rowset_size) {
10471             goto rowoor;
10472         }
10473         if (row == 0) {
10474             ret = SQL_SUCCESS;
10475             for (i = 0; i < s->rowset_size; i++) {
10476                 ret = setposrefr(s, i);
10477                 if (!SQL_SUCCEEDED(ret)) {
10478                     break;
10479                 }
10480             }
10481             return ret;
10482         }
10483         return setposrefr(s, row - 1);
10484     } else if (op == SQL_DELETE) {
10485         sql = dsappend(sql, "DELETE FROM ");
10486         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10487             sql = dsappendq(sql, s->dyncols[0].db);
10488             sql = dsappend(sql, ".");
10489         }
10490         sql = dsappendq(sql, s->dyncols[0].table);
10491         for (i = k = 0; i < s->ncols; i++) {
10492             if (s->dyncols[i].ispk <= 0) {
10493                 continue;
10494             }
10495             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10496             sql = dsappendq(sql, s->dyncols[i].column);
10497             sql = dsappend(sql, " = ?");
10498             k++;
10499         }
10500         if (dserr(sql)) {
10501             dsfree(sql);
10502             return nomem(s);
10503         }
10504 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10505         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10506 #else
10507         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10508 #endif
10509         do {
10510             s3stmt = NULL;
10511 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10512             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10513                                     &s3stmt, &endp);
10514 #else
10515             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10516                                  &s3stmt, &endp);
10517 #endif
10518             if (rc != SQLITE_OK) {
10519                 if (s3stmt) {
10520                     sqlite3_finalize(s3stmt);
10521                     s3stmt = NULL;
10522                 }
10523             }
10524         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10525         dbtracerc(d, rc, NULL);
10526         dsfree(sql);
10527         if (rc != SQLITE_OK) {
10528 dstmterr:
10529             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10530                     sqlite3_errmsg(d->sqlite), rc);
10531             if (s3stmt) {
10532                 dbtraceapi(d, "sqlite3_finalize", NULL);
10533                 sqlite3_finalize(s3stmt);
10534             }
10535             return SQL_ERROR;
10536         }
10537         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10538             if (s->dyncols[i].ispk <= 0) {
10539                 continue;
10540             }
10541             ret = setposibind(s, s3stmt, i, k, row - 1);
10542             if (ret != SQL_SUCCESS) {
10543                 dbtraceapi(d, "sqlite3_finalize", NULL);
10544                 sqlite3_finalize(s3stmt);
10545                 return ret;
10546             }
10547             k++;
10548         }
10549         rc = sqlite3_step(s3stmt);
10550         if (rc != SQLITE_DONE) {
10551             goto dstmterr;
10552         }
10553         sqlite3_finalize(s3stmt);
10554         if (sqlite3_changes(d->sqlite) > 0) {
10555             if (s->row_status0) {
10556                 s->row_status0[row - 1] = SQL_ROW_DELETED;
10557             }
10558             if (s->row_status) {
10559                 s->row_status[row - 1] = SQL_ROW_DELETED;
10560             }
10561         }
10562         return SQL_SUCCESS;
10563     } else if (op == SQL_UPDATE) {
10564         ret = chkunbound(s);
10565         if (ret != SQL_SUCCESS) {
10566             return ret;
10567         }
10568         sql = dsappend(sql, "UPDATE ");
10569         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10570             sql = dsappendq(sql, s->dyncols[0].db);
10571             sql = dsappend(sql, ".");
10572         }
10573         sql = dsappendq(sql, s->dyncols[0].table);
10574         for (i = 0; i < s->ncols; i++) {
10575             sql = dsappend(sql, (i > 0) ? ", " : " SET ");
10576             sql = dsappendq(sql, s->dyncols[i].column);
10577             sql = dsappend(sql, " = ?");
10578         }
10579         for (i = k = 0; i < s->ncols; i++) {
10580             if (s->dyncols[i].ispk <= 0) {
10581                 continue;
10582             }
10583             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10584             sql = dsappendq(sql, s->dyncols[i].column);
10585             sql = dsappend(sql, " = ?");
10586             k++;
10587         }
10588         if (dserr(sql)) {
10589             dsfree(sql);
10590             return nomem(s);
10591         }
10592 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10593         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10594 #else
10595         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10596 #endif
10597         do {
10598             s3stmt = NULL;
10599 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10600             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10601                                     &s3stmt, &endp);
10602 #else
10603             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10604                                  &s3stmt, &endp);
10605 #endif
10606             if (rc != SQLITE_OK) {
10607                 if (s3stmt) {
10608                     sqlite3_finalize(s3stmt);
10609                     s3stmt = NULL;
10610                 }
10611             }
10612         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10613         dbtracerc(d, rc, NULL);
10614         dsfree(sql);
10615         if (rc != SQLITE_OK) {
10616 ustmterr:
10617             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10618                     sqlite3_errmsg(d->sqlite), rc);
10619             if (s3stmt) {
10620                 dbtraceapi(d, "sqlite3_finalize", NULL);
10621                 sqlite3_finalize(s3stmt);
10622             }
10623             return SQL_ERROR;
10624         }
10625         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10626             ret = setposbind(s, s3stmt, i, k, row - 1);
10627             if (ret != SQL_SUCCESS) {
10628                 dbtraceapi(d, "sqlite3_finalize", NULL);
10629                 sqlite3_finalize(s3stmt);
10630                 return ret;
10631             }
10632             k++;
10633         }
10634         for (i = 0; s->bindcols && i < s->ncols; i++) {
10635             if (s->dyncols[i].ispk <= 0) {
10636                 continue;
10637             }
10638             ret = setposibind(s, s3stmt, i, k, row - 1);
10639             if (ret != SQL_SUCCESS) {
10640                 dbtraceapi(d, "sqlite3_finalize", NULL);
10641                 sqlite3_finalize(s3stmt);
10642                 return ret;
10643             }
10644             k++;
10645         }
10646         rc = sqlite3_step(s3stmt);
10647         if (rc != SQLITE_DONE) {
10648             goto ustmterr;
10649         }
10650         sqlite3_finalize(s3stmt);
10651         if (sqlite3_changes(d->sqlite) > 0) {
10652             if (s->row_status0) {
10653                 s->row_status0[row - 1] = SQL_ROW_UPDATED;
10654             }
10655             if (s->row_status) {
10656                 s->row_status[row - 1] = SQL_ROW_UPDATED;
10657             }
10658         }
10659         return SQL_SUCCESS;
10660     }
10661     return SQL_SUCCESS;
10662 }
10663 
10673 SQLRETURN SQL_API
10674 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10675 {
10676     SQLRETURN ret;
10677 
10678     HSTMT_LOCK(stmt);
10679     ret = drvsetpos(stmt, row, op, lock);
10680     HSTMT_UNLOCK(stmt);
10681     return ret;
10682 }
10683 
10691 static SQLRETURN
10692 drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
10693 {
10694     STMT *s = (STMT *) stmt;
10695     DBC *d = (DBC *) s->dbc;
10696     int row, i, k, rc, nretry = 0;
10697     dstr *sql = 0;
10698     const char *endp;
10699     sqlite3_stmt *s3stmt = NULL;
10700     SQLRETURN ret;
10701 
10702     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10703         setstat(s, -1, "incompatible statement",
10704                 (*s->ov3) ? "HY000" : "S1000");
10705         return SQL_ERROR;
10706     }
10707     if (op == SQL_ADD) {
10708         if (s->one_tbl <= 0) {
10709             setstat(s, -1, "incompatible rowset",
10710                     (*s->ov3) ? "HY000" : "S1000");
10711             return SQL_ERROR;
10712         }
10713         ret = chkunbound(s);
10714         if (ret != SQL_SUCCESS) {
10715             return ret;
10716         }
10717         sql = dsappend(sql, "INSERT INTO ");
10718         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10719             sql = dsappendq(sql, s->dyncols[0].db);
10720             sql = dsappend(sql, ".");
10721         }
10722         sql = dsappendq(sql, s->dyncols[0].table);
10723         for (i = 0; i < s->ncols; i++) {
10724             sql = dsappend(sql, (i > 0) ? "," : "(");
10725             sql = dsappendq(sql, s->dyncols[i].column);
10726         }
10727         sql = dsappend(sql, ") VALUES ");
10728         for (i = 0; i < s->ncols; i++) {
10729             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10730         }
10731         sql = dsappend(sql, ")");
10732         if (dserr(sql)) {
10733             dsfree(sql);
10734             return nomem(s);
10735         }
10736 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10737         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10738 #else
10739         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10740 #endif
10741         do {
10742             s3stmt = NULL;
10743 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10744             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10745                                     &s3stmt, &endp);
10746 #else
10747             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10748                                  &s3stmt, &endp);
10749 #endif
10750             if (rc != SQLITE_OK) {
10751                 if (s3stmt) {
10752                     sqlite3_finalize(s3stmt);
10753                     s3stmt = NULL;
10754                 }
10755             }
10756         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10757         dbtracerc(d, rc, NULL);
10758         dsfree(sql);
10759         if (rc != SQLITE_OK) {
10760             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10761                     sqlite3_errmsg(d->sqlite), rc);
10762             if (s3stmt) {
10763                 dbtraceapi(d, "sqlite3_finalize", NULL);
10764                 sqlite3_finalize(s3stmt);
10765             }
10766             return SQL_ERROR;
10767         }
10768         for (row = 0; row < s->rowset_size; row++) {
10769             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10770                 ret = setposbind(s, s3stmt, i, k, row);
10771                 if (ret != SQL_SUCCESS) {
10772 istmterr:
10773                     if (s->row_status0) {
10774                         s->row_status0[row] = SQL_ROW_ERROR;
10775                     }
10776                     if (s->row_status) {
10777                         s->row_status[row] = SQL_ROW_ERROR;
10778                     }
10779                     dbtraceapi(d, "sqlite3_finalize", NULL);
10780                     sqlite3_finalize(s3stmt);
10781                     return ret;
10782                 }
10783                 k++;
10784             }
10785             rc = sqlite3_step(s3stmt);
10786             if (rc != SQLITE_DONE) {
10787                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10788                         sqlite3_errmsg(d->sqlite), rc);
10789                 ret = SQL_ERROR;
10790                 goto istmterr;
10791             }
10792             if (sqlite3_changes(d->sqlite) > 0) {
10793                 if (s->row_status0) {
10794                     s->row_status0[row] = SQL_ROW_ADDED;
10795                 }
10796                 if (s->row_status) {
10797                     s->row_status[row] = SQL_ROW_ADDED;
10798                 }
10799             }
10800             if (s->bkmrk == SQL_UB_VARIABLE &&
10801                 s->bkmrkcol.type == SQL_C_VARBOOKMARK &&
10802                 s->bkmrkcol.valp) {
10803                 SQLPOINTER *val;
10804 
10805                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10806                     val = (SQLPOINTER)
10807                         ((char *) s->bkmrkcol.valp + s->bind_type * row);
10808                 } else {
10809                     val = (SQLPOINTER)
10810                         ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10811                 }
10812                 if (s->bind_offs) {
10813                     val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10814                 }
10815                 *(sqlite_int64 *) val = sqlite3_last_insert_rowid(d->sqlite);
10816                 if (s->bkmrkcol.lenp) {
10817                     SQLLEN *ival;
10818 
10819                     if (s->bind_type != SQL_BIND_BY_COLUMN) {
10820                         ival = (SQLLEN *)
10821                             ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10822                     } else {
10823                         ival = &s->bkmrkcol.lenp[row];
10824                     }
10825                     if (s->bind_offs) {
10826                         ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10827                     }
10828                     *ival = sizeof (sqlite_int64);
10829                 }
10830             }
10831             dbtraceapi(d, "sqlite3_reset", NULL);
10832             sqlite3_reset(s3stmt);
10833         }
10834         dbtraceapi(d, "sqlite3_finalize", NULL);
10835         sqlite3_finalize(s3stmt);
10836         return SQL_SUCCESS;
10837     } else if (op == SQL_DELETE_BY_BOOKMARK) {
10838         if (s->has_rowid < 0 ||
10839             s->bkmrk != SQL_UB_VARIABLE ||
10840             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10841             !s->bkmrkcol.valp) {
10842             setstat(s, -1, "incompatible rowset",
10843                     (*s->ov3) ? "HY000" : "S1000");
10844             return SQL_ERROR;
10845         }
10846         sql = dsappend(sql, "DELETE FROM ");
10847         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10848             sql = dsappendq(sql, s->dyncols[0].db);
10849             sql = dsappend(sql, ".");
10850         }
10851         sql = dsappendq(sql, s->dyncols[0].table);
10852         sql = dsappend(sql, " WHERE ");
10853         sql = dsappendq(sql, s->dyncols[0].column);
10854         sql = dsappend(sql, " = ?");
10855         if (dserr(sql)) {
10856             dsfree(sql);
10857             return nomem(s);
10858         }
10859 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10860         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10861 #else
10862         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10863 #endif
10864         do {
10865             s3stmt = NULL;
10866 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10867             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10868                                     &s3stmt, &endp);
10869 #else
10870             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10871                                  &s3stmt, &endp);
10872 #endif
10873             if (rc != SQLITE_OK) {
10874                 if (s3stmt) {
10875                     sqlite3_finalize(s3stmt);
10876                     s3stmt = NULL;
10877                 }
10878             }
10879         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10880         dbtracerc(d, rc, NULL);
10881         dsfree(sql);
10882         if (rc != SQLITE_OK) {
10883             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10884                     sqlite3_errmsg(d->sqlite), rc);
10885             if (s3stmt) {
10886                 dbtraceapi(d, "sqlite3_finalize", NULL);
10887                 sqlite3_finalize(s3stmt);
10888             }
10889             return SQL_ERROR;
10890         }
10891         for (row = 0; row < s->rowset_size; row++) {
10892             SQLPOINTER *val;
10893             sqlite_int64 rowid;
10894 
10895             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10896                 val = (SQLPOINTER)
10897                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
10898             } else {
10899                 val = (SQLPOINTER)
10900                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10901             }
10902             if (s->bind_offs) {
10903                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10904             }
10905             if (s->bkmrkcol.lenp) {
10906                 SQLLEN *ival;
10907 
10908                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10909                     ival = (SQLLEN *)
10910                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10911                 } else {
10912                     ival = &s->bkmrkcol.lenp[row];
10913                 }
10914                 if (s->bind_offs) {
10915                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10916                 }
10917                 if (*ival != sizeof (sqlite_int64)) {
10918                     continue;
10919                 }
10920             }
10921             rowid = *(sqlite_int64 *) val;
10922             sqlite3_bind_int64(s3stmt, 1, rowid);
10923             if (d->trace) {
10924                 fprintf(d->trace,
10925 #ifdef _WIN32
10926                         "-- parameter 1: %I64d\n",
10927 #else
10928                         "-- parameter 1: %lld\n",
10929 #endif
10930                         rowid);
10931                 fflush(d->trace);
10932             }
10933             rc = sqlite3_step(s3stmt);
10934             if (rc != SQLITE_DONE) {
10935                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10936                         sqlite3_errmsg(d->sqlite), rc);
10937                 if (s->row_status0) {
10938                     s->row_status0[row] = SQL_ROW_ERROR;
10939                 }
10940                 if (s->row_status) {
10941                     s->row_status[row] = SQL_ROW_ERROR;
10942                 }
10943                 dbtraceapi(d, "sqlite3_finalize", NULL);
10944                 sqlite3_finalize(s3stmt);
10945                 return SQL_ERROR;
10946             }
10947             if (sqlite3_changes(d->sqlite) > 0) {
10948                 if (s->row_status0) {
10949                     s->row_status0[row] = SQL_ROW_DELETED;
10950                 }
10951                 if (s->row_status) {
10952                     s->row_status[row] = SQL_ROW_DELETED;
10953                 }
10954             }
10955             dbtraceapi(d, "sqlite3_reset", NULL);
10956             sqlite3_reset(s3stmt);
10957         }
10958         dbtraceapi(d, "sqlite3_finalize", NULL);
10959         sqlite3_finalize(s3stmt);
10960         return SQL_SUCCESS;
10961     } else if (op == SQL_UPDATE_BY_BOOKMARK) {
10962         if (s->has_rowid < 0 ||
10963             s->bkmrk != SQL_UB_VARIABLE ||
10964             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10965             !s->bkmrkcol.valp) {
10966             setstat(s, -1, "incompatible rowset",
10967                     (*s->ov3) ? "HY000" : "S1000");
10968             return SQL_ERROR;
10969         }
10970         ret = chkunbound(s);
10971         if (ret != SQL_SUCCESS) {
10972             return ret;
10973         }
10974         sql = dsappend(sql, "UPDATE ");
10975         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10976             sql = dsappendq(sql, s->dyncols[0].db);
10977             sql = dsappend(sql, ".");
10978         }
10979         sql = dsappendq(sql, s->dyncols[0].table);
10980         for (i = 0, k = 0; i < s->ncols; i++) {
10981             sql = dsappend(sql, (k > 0) ? ", " : " SET ");
10982             sql = dsappendq(sql, s->dyncols[i].column);
10983             sql = dsappend(sql, " = ?");
10984             k++;
10985         }
10986         sql = dsappend(sql, " WHERE ");
10987         sql = dsappendq(sql, s->dyncols[s->has_rowid].column);
10988         sql = dsappend(sql, " = ?");
10989         if (dserr(sql)) {
10990             dsfree(sql);
10991             return nomem(s);
10992         }
10993 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10994         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10995 #else
10996         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10997 #endif
10998         do {
10999             s3stmt = NULL;
11000 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
11001             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
11002                                     &s3stmt, &endp);
11003 #else
11004             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
11005                                  &s3stmt, &endp);
11006 #endif
11007             if (rc != SQLITE_OK) {
11008                 if (s3stmt) {
11009                     sqlite3_finalize(s3stmt);
11010                     s3stmt = NULL;
11011                 }
11012             }
11013         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
11014         dbtracerc(d, rc, NULL);
11015         dsfree(sql);
11016         if (rc != SQLITE_OK) {
11017             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11018                     sqlite3_errmsg(d->sqlite), rc);
11019             if (s3stmt) {
11020                 dbtraceapi(d, "sqlite3_finalize", NULL);
11021                 sqlite3_finalize(s3stmt);
11022             }
11023             return SQL_ERROR;
11024         }
11025         for (row = 0; row < s->rowset_size; row++) {
11026             SQLPOINTER *val;
11027             sqlite_int64 rowid;
11028 
11029             if (s->bind_type != SQL_BIND_BY_COLUMN) {
11030                 val = (SQLPOINTER)
11031                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
11032             } else {
11033                 val = (SQLPOINTER)
11034                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
11035             }
11036             if (s->bind_offs) {
11037                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
11038             }
11039             if (s->bkmrkcol.lenp) {
11040                 SQLLEN *ival;
11041 
11042                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
11043                     ival = (SQLLEN *)
11044                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
11045                 } else {
11046                     ival = &s->bkmrkcol.lenp[row];
11047                 }
11048                 if (s->bind_offs) {
11049                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
11050                 }
11051                 if (*ival != sizeof (sqlite_int64)) {
11052                     continue;
11053                 }
11054             }
11055             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
11056                 ret = setposbind(s, s3stmt, i, k, row);
11057                 if (ret != SQL_SUCCESS) {
11058 ustmterr:
11059                     if (s->row_status0) {
11060                         s->row_status0[row] = SQL_ROW_ERROR;
11061                     }
11062                     if (s->row_status) {
11063                         s->row_status[row] = SQL_ROW_ERROR;
11064                     }
11065                     dbtraceapi(d, "sqlite3_finalize", NULL);
11066                     sqlite3_finalize(s3stmt);
11067                     return ret;
11068                 }
11069                 k++;
11070             }
11071             rowid = *(sqlite_int64 *) val;
11072             sqlite3_bind_int64(s3stmt, k, rowid);
11073             if (d->trace) {
11074                 fprintf(d->trace,
11075 #ifdef _WIN32
11076                         "-- parameter %d: %I64d\n",
11077 #else
11078                         "-- parameter %d: %lld\n",
11079 #endif
11080                         k, rowid);
11081                 fflush(d->trace);
11082             }
11083             rc = sqlite3_step(s3stmt);
11084             if (rc != SQLITE_DONE) {
11085                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11086                         sqlite3_errmsg(d->sqlite), rc);
11087                 ret = SQL_ERROR;
11088                 goto ustmterr;
11089             }
11090             if (sqlite3_changes(d->sqlite) > 0) {
11091                 if (s->row_status0) {
11092                     s->row_status0[row] = SQL_ROW_UPDATED;
11093                 }
11094                 if (s->row_status) {
11095                     s->row_status[row] = SQL_ROW_UPDATED;
11096                 }
11097             }
11098             dbtraceapi(d, "sqlite3_reset", NULL);
11099             sqlite3_reset(s3stmt);
11100         }
11101         dbtraceapi(d, "sqlite3_finalize", NULL);
11102         sqlite3_finalize(s3stmt);
11103         return SQL_SUCCESS;
11104     }
11105     setstat(s, -1, "unsupported operation", (*s->ov3) ? "HY000" : "S1000");
11106     return SQL_ERROR;
11107 }
11108 
11116 SQLRETURN SQL_API
11117 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
11118 {
11119     SQLRETURN ret;
11120 
11121     HSTMT_LOCK(stmt);
11122     ret = drvbulkoperations(stmt, oper);
11123     HSTMT_UNLOCK(stmt);
11124     return ret;
11125 }
11126 
11127 
11132 SQLRETURN SQL_API
11133 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
11134                     SQLUSMALLINT rowset)
11135 {
11136     SQLRETURN ret;
11137 
11138     HSTMT_LOCK(stmt);
11139     ret = drvunimplstmt(stmt);
11140     HSTMT_UNLOCK(stmt);
11141     return ret;
11142 }
11143 
11144 #define strmak(dst, src, max, lenp) { \
11145     int len = strlen(src); \
11146     int cnt = min(len + 1, max); \
11147     strncpy(dst, src, cnt); \
11148     *lenp = (cnt > len) ? len : cnt; \
11149 }
11150 
11161 static SQLRETURN
11162 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11163            SQLSMALLINT *valLen)
11164 {
11165     DBC *d;
11166     char dummyc[301];
11167     SQLSMALLINT dummy;
11168 #if defined(_WIN32) || defined(_WIN64)
11169     char pathbuf[301], *drvname;
11170 #else
11171     static char drvname[] = "sqlite3odbc.so";
11172 #endif
11173 
11174     if (dbc == SQL_NULL_HDBC) {
11175         return SQL_INVALID_HANDLE;
11176     }
11177     d = (DBC *) dbc;
11178     if (valMax) {
11179         valMax--;
11180     }
11181     if (!valLen) {
11182         valLen = &dummy;
11183     }
11184     if (!val) {
11185         val = dummyc;
11186         valMax = sizeof (dummyc) - 1;
11187     }
11188     switch (type) {
11189     case SQL_MAX_USER_NAME_LEN:
11190         *((SQLSMALLINT *) val) = 16;
11191         *valLen = sizeof (SQLSMALLINT);
11192         break;
11193     case SQL_USER_NAME:
11194         strmak(val, "", valMax, valLen);
11195         break;
11196     case SQL_DRIVER_ODBC_VER:
11197 #if 0
11198         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11199 #else
11200         strmak(val, "03.00", valMax, valLen);
11201 #endif
11202         break;
11203     case SQL_ACTIVE_CONNECTIONS:
11204     case SQL_ACTIVE_STATEMENTS:
11205         *((SQLSMALLINT *) val) = 0;
11206         *valLen = sizeof (SQLSMALLINT);
11207         break;
11208 #ifdef SQL_ASYNC_MODE
11209     case SQL_ASYNC_MODE:
11210         *((SQLUINTEGER *) val) = SQL_AM_NONE;
11211         *valLen = sizeof (SQLUINTEGER);
11212         break;
11213 #endif
11214 #ifdef SQL_CREATE_TABLE
11215     case SQL_CREATE_TABLE:
11216         *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
11217                                  SQL_CT_COLUMN_DEFAULT |
11218                                  SQL_CT_COLUMN_CONSTRAINT |
11219                                  SQL_CT_CONSTRAINT_NON_DEFERRABLE;
11220         *valLen = sizeof (SQLUINTEGER);
11221         break;
11222 #endif
11223 #ifdef SQL_CREATE_VIEW
11224     case SQL_CREATE_VIEW:
11225         *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
11226         *valLen = sizeof (SQLUINTEGER);
11227         break;
11228 #endif
11229 #ifdef SQL_DDL_INDEX
11230     case SQL_DDL_INDEX:
11231         *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
11232         *valLen = sizeof (SQLUINTEGER);
11233         break;
11234 #endif
11235 #ifdef SQL_DROP_TABLE
11236     case SQL_DROP_TABLE:
11237         *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
11238         *valLen = sizeof (SQLUINTEGER);
11239         break;
11240 #endif
11241 #ifdef SQL_DROP_VIEW
11242     case SQL_DROP_VIEW:
11243         *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
11244         *valLen = sizeof (SQLUINTEGER);
11245         break;
11246 #endif
11247 #ifdef SQL_INDEX_KEYWORDS
11248     case SQL_INDEX_KEYWORDS:
11249         *((SQLUINTEGER *) val) = SQL_IK_ALL;
11250         *valLen = sizeof (SQLUINTEGER);
11251         break;
11252 #endif
11253     case SQL_DATA_SOURCE_NAME:
11254         strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
11255         break;
11256     case SQL_DRIVER_NAME:
11257 #if defined(_WIN32) || defined(_WIN64)
11258         GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
11259         drvname = strrchr(pathbuf, '\\');
11260         if (drvname == NULL) {
11261             drvname = strrchr(pathbuf, '/');
11262         }
11263         if (drvname == NULL) {
11264             drvname = pathbuf;
11265         } else {
11266             drvname++;
11267         }
11268 #endif
11269         strmak(val, drvname, valMax, valLen);
11270         break;
11271     case SQL_DRIVER_VER:
11272         strmak(val, DRIVER_VER_INFO, valMax, valLen);
11273         break;
11274     case SQL_FETCH_DIRECTION:
11275         *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
11276             SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
11277         *valLen = sizeof (SQLUINTEGER);
11278         break;
11279     case SQL_ODBC_VER:
11280         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11281         break;
11282     case SQL_ODBC_SAG_CLI_CONFORMANCE:
11283         *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
11284         *valLen = sizeof (SQLSMALLINT);
11285         break;
11286     case SQL_STANDARD_CLI_CONFORMANCE:
11287         *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
11288         *valLen = sizeof (SQLUINTEGER);
11289         break;
11290     case SQL_SQL_CONFORMANCE:
11291         *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
11292         *valLen = sizeof (SQLUINTEGER);
11293         break;
11294     case SQL_SERVER_NAME:
11295     case SQL_DATABASE_NAME:
11296         strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
11297         break;
11298     case SQL_SEARCH_PATTERN_ESCAPE:
11299         strmak(val, "\\", valMax, valLen);
11300         break;
11301     case SQL_ODBC_SQL_CONFORMANCE:
11302         *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
11303         *valLen = sizeof (SQLSMALLINT);
11304         break;
11305     case SQL_ODBC_API_CONFORMANCE:
11306         *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
11307         *valLen = sizeof (SQLSMALLINT);
11308         break;
11309     case SQL_DBMS_NAME:
11310         strmak(val, "SQLite", valMax, valLen);
11311         break;
11312     case SQL_DBMS_VER:
11313         strmak(val, SQLITE_VERSION, valMax, valLen);
11314         break;
11315     case SQL_COLUMN_ALIAS:
11316     case SQL_NEED_LONG_DATA_LEN:
11317     case SQL_OUTER_JOINS:
11318         strmak(val, "Y", valMax, valLen);
11319         break;
11320     case SQL_ROW_UPDATES:
11321     case SQL_ACCESSIBLE_PROCEDURES:
11322     case SQL_PROCEDURES:
11323     case SQL_EXPRESSIONS_IN_ORDERBY:
11324     case SQL_ODBC_SQL_OPT_IEF:
11325     case SQL_LIKE_ESCAPE_CLAUSE:
11326     case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11327     case SQL_ACCESSIBLE_TABLES:
11328     case SQL_MULT_RESULT_SETS:
11329     case SQL_MULTIPLE_ACTIVE_TXN:
11330     case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11331         strmak(val, "N", valMax, valLen);
11332         break;
11333 #ifdef SQL_CATALOG_NAME
11334     case SQL_CATALOG_NAME:
11335 #if defined(_WIN32) || defined(_WIN64)
11336         strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
11337 #else
11338         strmak(val, "N", valMax, valLen);
11339 #endif
11340         break;
11341 #endif
11342     case SQL_DATA_SOURCE_READ_ONLY:
11343         strmak(val, "N", valMax, valLen);
11344         break;
11345 #ifdef SQL_OJ_CAPABILITIES
11346     case SQL_OJ_CAPABILITIES:
11347         *((SQLUINTEGER *) val) = SQL_OJ_LEFT;
11348         *valLen = sizeof (SQLUINTEGER);
11349         break;
11350 #endif
11351 #ifdef SQL_MAX_IDENTIFIER_LEN
11352     case SQL_MAX_IDENTIFIER_LEN:
11353         *((SQLUSMALLINT *) val) = 255;
11354         *valLen = sizeof (SQLUSMALLINT);
11355         break;
11356 #endif
11357     case SQL_CONCAT_NULL_BEHAVIOR:
11358         *((SQLSMALLINT *) val) = SQL_CB_NULL;
11359         *valLen = sizeof (SQLSMALLINT);
11360         break;
11361     case SQL_CURSOR_COMMIT_BEHAVIOR:
11362     case SQL_CURSOR_ROLLBACK_BEHAVIOR:
11363         *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
11364         *valLen = sizeof (SQLSMALLINT);
11365         break;
11366 #ifdef SQL_CURSOR_SENSITIVITY
11367     case SQL_CURSOR_SENSITIVITY:
11368         *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
11369         *valLen = sizeof (SQLUINTEGER);
11370         break;
11371 #endif
11372     case SQL_DEFAULT_TXN_ISOLATION:
11373         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11374         *valLen = sizeof (SQLUINTEGER);
11375         break;
11376 #ifdef SQL_DESCRIBE_PARAMETER
11377     case SQL_DESCRIBE_PARAMETER:
11378         strmak(val, "Y", valMax, valLen);
11379         break;
11380 #endif
11381     case SQL_TXN_ISOLATION_OPTION:
11382         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11383         *valLen = sizeof (SQLUINTEGER);
11384         break;
11385     case SQL_IDENTIFIER_CASE:
11386         *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
11387         *valLen = sizeof (SQLSMALLINT);
11388         break;
11389     case SQL_IDENTIFIER_QUOTE_CHAR:
11390         strmak(val, "\"", valMax, valLen);
11391         break;
11392     case SQL_MAX_TABLE_NAME_LEN:
11393     case SQL_MAX_COLUMN_NAME_LEN:
11394         *((SQLSMALLINT *) val) = 255;
11395         *valLen = sizeof (SQLSMALLINT);
11396         break;
11397     case SQL_MAX_CURSOR_NAME_LEN:
11398         *((SQLSMALLINT *) val) = 255;
11399         *valLen = sizeof (SQLSMALLINT);
11400         break;
11401     case SQL_MAX_PROCEDURE_NAME_LEN:
11402         *((SQLSMALLINT *) val) = 0;
11403         break;
11404     case SQL_MAX_QUALIFIER_NAME_LEN:
11405     case SQL_MAX_OWNER_NAME_LEN:
11406         *((SQLSMALLINT *) val) = 255;
11407         break;
11408     case SQL_OWNER_TERM:
11409         strmak(val, "", valMax, valLen);
11410         break;
11411     case SQL_PROCEDURE_TERM:
11412         strmak(val, "PROCEDURE", valMax, valLen);
11413         break;
11414     case SQL_QUALIFIER_NAME_SEPARATOR:
11415         strmak(val, ".", valMax, valLen);
11416         break;
11417     case SQL_QUALIFIER_TERM:
11418 #if defined(_WIN32) || defined(_WIN64)
11419         strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
11420 #else
11421         strmak(val, "", valMax, valLen);
11422 #endif
11423         break;
11424     case SQL_QUALIFIER_USAGE:
11425 #if defined(_WIN32) || defined(_WIN64)
11426         *((SQLUINTEGER *) val) = d->xcelqrx ?
11427             (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
11428              SQL_CU_TABLE_DEFINITION) : 0;
11429 #else
11430         *((SQLUINTEGER *) val) = 0;
11431 #endif
11432         *valLen = sizeof (SQLUINTEGER);
11433         break;
11434     case SQL_SCROLL_CONCURRENCY:
11435         *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
11436         *valLen = sizeof (SQLUINTEGER);
11437         break;
11438     case SQL_SCROLL_OPTIONS:
11439         *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
11440         *valLen = sizeof (SQLUINTEGER);
11441         break;
11442     case SQL_TABLE_TERM:
11443         strmak(val, "TABLE", valMax, valLen);
11444         break;
11445     case SQL_TXN_CAPABLE:
11446         *((SQLSMALLINT *) val) = SQL_TC_ALL;
11447         *valLen = sizeof (SQLSMALLINT);
11448         break;
11449     case SQL_CONVERT_FUNCTIONS:
11450         *((SQLUINTEGER *) val) = 0;
11451         *valLen = sizeof (SQLUINTEGER);
11452        break;
11453     case SQL_SYSTEM_FUNCTIONS:
11454     case SQL_NUMERIC_FUNCTIONS:
11455     case SQL_STRING_FUNCTIONS:
11456     case SQL_TIMEDATE_FUNCTIONS:
11457         *((SQLUINTEGER *) val) = 0;
11458         *valLen = sizeof (SQLUINTEGER);
11459         break;
11460     case SQL_CONVERT_BIGINT:
11461     case SQL_CONVERT_BIT:
11462     case SQL_CONVERT_CHAR:
11463     case SQL_CONVERT_DATE:
11464     case SQL_CONVERT_DECIMAL:
11465     case SQL_CONVERT_DOUBLE:
11466     case SQL_CONVERT_FLOAT:
11467     case SQL_CONVERT_INTEGER:
11468     case SQL_CONVERT_LONGVARCHAR:
11469     case SQL_CONVERT_NUMERIC:
11470     case SQL_CONVERT_REAL:
11471     case SQL_CONVERT_SMALLINT:
11472     case SQL_CONVERT_TIME:
11473     case SQL_CONVERT_TIMESTAMP:
11474     case SQL_CONVERT_TINYINT:
11475     case SQL_CONVERT_VARCHAR:
11476         *((SQLUINTEGER *) val) =
11477             SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
11478             SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
11479             SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
11480             SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
11481             SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
11482         *valLen = sizeof (SQLUINTEGER);
11483         break;
11484     case SQL_CONVERT_BINARY:
11485     case SQL_CONVERT_VARBINARY:
11486     case SQL_CONVERT_LONGVARBINARY:
11487         *((SQLUINTEGER *) val) = 0;
11488         *valLen = sizeof (SQLUINTEGER);
11489         break;
11490     case SQL_POSITIONED_STATEMENTS:
11491         *((SQLUINTEGER *) val) = 0;
11492         *valLen = sizeof (SQLUINTEGER);
11493         break;
11494     case SQL_LOCK_TYPES:
11495         *((SQLUINTEGER *) val) = SQL_LCK_NO_CHANGE;
11496         *valLen = sizeof (SQLUINTEGER);
11497         break;
11498     case SQL_BOOKMARK_PERSISTENCE:
11499         *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
11500         *valLen = sizeof (SQLUINTEGER);
11501         break;
11502     case SQL_UNION:
11503         *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
11504         *valLen = sizeof (SQLUINTEGER);
11505         break;
11506     case SQL_OWNER_USAGE:
11507     case SQL_SUBQUERIES:
11508     case SQL_TIMEDATE_ADD_INTERVALS:
11509     case SQL_TIMEDATE_DIFF_INTERVALS:
11510         *((SQLUINTEGER *) val) = 0;
11511         *valLen = sizeof (SQLUINTEGER);
11512         break;
11513     case SQL_QUOTED_IDENTIFIER_CASE:
11514         *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
11515         *valLen = sizeof (SQLUSMALLINT);
11516         break;
11517     case SQL_POS_OPERATIONS:
11518         *((SQLUINTEGER *) val) = SQL_POS_POSITION | SQL_POS_UPDATE |
11519             SQL_POS_DELETE | SQL_POS_ADD | SQL_POS_REFRESH;
11520         *valLen = sizeof (SQLUINTEGER);
11521         break;
11522     case SQL_ALTER_TABLE:
11523         *((SQLUINTEGER *) val) = 0;
11524         *valLen = sizeof (SQLUINTEGER);
11525         break;
11526     case SQL_CORRELATION_NAME:
11527         *((SQLSMALLINT *) val) = SQL_CN_ANY;
11528         *valLen = sizeof (SQLSMALLINT);
11529         break;
11530     case SQL_NON_NULLABLE_COLUMNS:
11531         *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
11532         *valLen = sizeof (SQLSMALLINT);
11533         break;
11534     case SQL_NULL_COLLATION:
11535         *((SQLSMALLINT *) val) = SQL_NC_START;
11536         *valLen = sizeof (SQLSMALLINT);
11537         break;
11538     case SQL_MAX_COLUMNS_IN_GROUP_BY:
11539     case SQL_MAX_COLUMNS_IN_ORDER_BY:
11540     case SQL_MAX_COLUMNS_IN_SELECT:
11541     case SQL_MAX_COLUMNS_IN_TABLE:
11542     case SQL_MAX_ROW_SIZE:
11543     case SQL_MAX_TABLES_IN_SELECT:
11544         *((SQLSMALLINT *) val) = 0;
11545         *valLen = sizeof (SQLSMALLINT);
11546         break;
11547     case SQL_MAX_BINARY_LITERAL_LEN:
11548     case SQL_MAX_CHAR_LITERAL_LEN:
11549         *((SQLUINTEGER *) val) = 0;
11550         *valLen = sizeof (SQLUINTEGER);
11551         break;
11552     case SQL_MAX_COLUMNS_IN_INDEX:
11553         *((SQLSMALLINT *) val) = 0;
11554         *valLen = sizeof (SQLSMALLINT);
11555         break;
11556     case SQL_MAX_INDEX_SIZE:
11557         *((SQLUINTEGER *) val) = 0;
11558         *valLen = sizeof (SQLUINTEGER);
11559         break;
11560 #ifdef SQL_MAX_IDENTIFIER_LENGTH
11561     case SQL_MAX_IDENTIFIER_LENGTH:
11562         *((SQLUINTEGER *) val) = 255;
11563         *valLen = sizeof (SQLUINTEGER);
11564         break;
11565 #endif
11566     case SQL_MAX_STATEMENT_LEN:
11567         *((SQLUINTEGER *) val) = 16384;
11568         *valLen = sizeof (SQLUINTEGER);
11569         break;
11570     case SQL_QUALIFIER_LOCATION:
11571         *((SQLSMALLINT *) val) = SQL_QL_START;
11572         *valLen = sizeof (SQLSMALLINT);
11573         break;
11574     case SQL_GETDATA_EXTENSIONS:
11575         *((SQLUINTEGER *) val) =
11576             SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
11577         *valLen = sizeof (SQLUINTEGER);
11578         break;
11579     case SQL_STATIC_SENSITIVITY:
11580         *((SQLUINTEGER *) val) = 0;
11581         *valLen = sizeof (SQLUINTEGER);
11582         break;
11583     case SQL_FILE_USAGE:
11584 #if defined(_WIN32) || defined(_WIN64)
11585         *((SQLSMALLINT *) val) =
11586             d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
11587 #else
11588         *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
11589 #endif
11590         *valLen = sizeof (SQLSMALLINT);
11591         break;
11592     case SQL_GROUP_BY:
11593         *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
11594         *valLen = sizeof (SQLSMALLINT);
11595         break;
11596     case SQL_KEYWORDS:
11597         strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
11598                "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
11599                valMax, valLen);
11600         break;
11601     case SQL_SPECIAL_CHARACTERS:
11602 #ifdef SQL_COLLATION_SEQ
11603     case SQL_COLLATION_SEQ:
11604 #endif
11605         strmak(val, "", valMax, valLen);
11606         break;
11607     case SQL_BATCH_SUPPORT:
11608     case SQL_BATCH_ROW_COUNT:
11609     case SQL_PARAM_ARRAY_ROW_COUNTS:
11610         *((SQLUINTEGER *) val) = 0;
11611         *valLen = sizeof (SQLUINTEGER);
11612         break;
11613     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
11614         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
11615         *valLen = sizeof (SQLUINTEGER);
11616         break;
11617     case SQL_STATIC_CURSOR_ATTRIBUTES1:
11618         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
11619             SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_POS_POSITION |
11620             SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_REFRESH |
11621             SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_BULK_ADD |
11622             SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK;
11623         *valLen = sizeof (SQLUINTEGER);
11624         break;
11625     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
11626     case SQL_STATIC_CURSOR_ATTRIBUTES2:
11627         *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
11628             SQL_CA2_LOCK_CONCURRENCY;
11629         *valLen = sizeof (SQLUINTEGER);
11630         break;
11631     case SQL_KEYSET_CURSOR_ATTRIBUTES1:
11632     case SQL_KEYSET_CURSOR_ATTRIBUTES2:
11633     case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
11634     case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
11635         *((SQLUINTEGER *) val) = 0;
11636         *valLen = sizeof (SQLUINTEGER);
11637         break;
11638     case SQL_ODBC_INTERFACE_CONFORMANCE:
11639         *((SQLUINTEGER *) val) = SQL_OIC_CORE;
11640         *valLen = sizeof (SQLUINTEGER);
11641         break;
11642     default:
11643         setstatd(d, -1, "unsupported info option %d",
11644                  (*d->ov3) ? "HYC00" : "S1C00", type);
11645         return SQL_ERROR;
11646     }
11647     return SQL_SUCCESS;
11648 }
11649 
11650 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
11651 
11661 SQLRETURN SQL_API
11662 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11663            SQLSMALLINT *valLen)
11664 {
11665     SQLRETURN ret;
11666 
11667     HDBC_LOCK(dbc);
11668     ret = drvgetinfo(dbc, type, val, valMax, valLen);
11669     HDBC_UNLOCK(dbc);
11670     return ret;
11671 }
11672 #endif
11673 
11674 #ifdef WINTERFACE
11675 
11685 SQLRETURN SQL_API
11686 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11687             SQLSMALLINT *valLen)
11688 {
11689     SQLRETURN ret;
11690     SQLSMALLINT len = 0;
11691 
11692     HDBC_LOCK(dbc);
11693     ret = drvgetinfo(dbc, type, val, valMax, &len);
11694     HDBC_UNLOCK(dbc);
11695     if (ret == SQL_SUCCESS) {
11696         SQLWCHAR *v = NULL;
11697 
11698         switch (type) {
11699         case SQL_USER_NAME:
11700         case SQL_DRIVER_ODBC_VER:
11701         case SQL_DATA_SOURCE_NAME:
11702         case SQL_DRIVER_NAME:
11703         case SQL_DRIVER_VER:
11704         case SQL_ODBC_VER:
11705         case SQL_SERVER_NAME:
11706         case SQL_DATABASE_NAME:
11707         case SQL_SEARCH_PATTERN_ESCAPE:
11708         case SQL_DBMS_NAME:
11709         case SQL_DBMS_VER:
11710         case SQL_NEED_LONG_DATA_LEN:
11711         case SQL_ROW_UPDATES:
11712         case SQL_ACCESSIBLE_PROCEDURES:
11713         case SQL_PROCEDURES:
11714         case SQL_EXPRESSIONS_IN_ORDERBY:
11715         case SQL_ODBC_SQL_OPT_IEF:
11716         case SQL_LIKE_ESCAPE_CLAUSE:
11717         case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11718         case SQL_OUTER_JOINS:
11719         case SQL_COLUMN_ALIAS:
11720         case SQL_ACCESSIBLE_TABLES:
11721         case SQL_MULT_RESULT_SETS:
11722         case SQL_MULTIPLE_ACTIVE_TXN:
11723         case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11724         case SQL_DATA_SOURCE_READ_ONLY:
11725 #ifdef SQL_DESCRIBE_PARAMETER
11726         case SQL_DESCRIBE_PARAMETER:
11727 #endif
11728         case SQL_IDENTIFIER_QUOTE_CHAR:
11729         case SQL_OWNER_TERM:
11730         case SQL_PROCEDURE_TERM:
11731         case SQL_QUALIFIER_NAME_SEPARATOR:
11732         case SQL_QUALIFIER_TERM:
11733         case SQL_TABLE_TERM:
11734         case SQL_KEYWORDS:
11735         case SQL_SPECIAL_CHARACTERS:
11736 #ifdef SQL_CATALOG_NAME
11737         case SQL_CATALOG_NAME:
11738 #endif
11739 #ifdef SQL_COLLATION_SEQ
11740         case SQL_COLLATION_SEQ:
11741 #endif
11742             if (val) {
11743                 if (len > 0) {
11744                     v = uc_from_utf((SQLCHAR *) val, len);
11745                     if (v) {
11746                         int vmax = valMax / sizeof (SQLWCHAR);
11747 
11748                         uc_strncpy(val, v, vmax);
11749                         if (len < vmax) {
11750                             len = min(vmax, uc_strlen(v));
11751                             v[len] = 0;
11752                         } else {
11753                             len = vmax;
11754                         }
11755                         uc_free(v);
11756                         len *= sizeof (SQLWCHAR);
11757                     } else {
11758                         len = 0;
11759                     }
11760                 }
11761                 if (len <= 0) {
11762                     len = 0;
11763                     if (valMax >= sizeof (SQLWCHAR)) {
11764                         *((SQLWCHAR *)val) = 0;
11765                     }
11766                 }
11767             } else {
11768                 len *= sizeof (SQLWCHAR);
11769             }
11770             break;
11771         }
11772         if (valLen) {
11773             *valLen = len;
11774         }
11775     }
11776     return ret;
11777 }
11778 #endif
11779 
11788 SQLRETURN SQL_API
11789 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
11790                 SQLUSMALLINT *flags)
11791 {
11792     int i;
11793     SQLUSMALLINT exists[100];
11794 
11795     if (dbc == SQL_NULL_HDBC) {
11796         return SQL_INVALID_HANDLE;
11797     }
11798     for (i = 0; i < array_size(exists); i++) {
11799         exists[i] = SQL_FALSE;
11800     }
11801     exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
11802     exists[SQL_API_SQLFETCH] = SQL_TRUE;
11803     exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
11804     exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
11805     exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
11806     exists[SQL_API_SQLFREEENV] = SQL_TRUE;
11807     exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
11808     exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
11809     exists[SQL_API_SQLCANCEL] = SQL_TRUE;
11810     exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
11811     exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
11812     exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
11813     exists[SQL_API_SQLCONNECT] = SQL_TRUE;
11814     exists[SQL_API_SQLPREPARE] = SQL_TRUE;
11815     exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
11816     exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
11817     exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
11818     exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
11819     exists[SQL_API_SQLERROR] = SQL_TRUE;
11820     exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
11821     exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
11822     exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
11823     exists[SQL_API_SQLBULKOPERATIONS] = SQL_TRUE;
11824     exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
11825     exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
11826     exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
11827     exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
11828     exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
11829     exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
11830     exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
11831     exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
11832     exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
11833     exists[SQL_API_SQLGETDATA] = SQL_TRUE;
11834     exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
11835     exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
11836     exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
11837     exists[SQL_API_SQLGETINFO] = SQL_TRUE;
11838     exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
11839     exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
11840     exists[SQL_API_SQLTABLES] = SQL_TRUE;
11841     exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
11842     exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
11843     exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
11844     exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
11845     exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
11846     exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
11847     exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
11848     exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
11849     exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
11850     exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
11851     exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
11852     exists[SQL_API_SQLSETPOS] = SQL_TRUE;
11853     exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
11854     exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
11855     exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
11856     exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
11857     exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
11858     if (func == SQL_API_ALL_FUNCTIONS) {
11859         memcpy(flags, exists, sizeof (exists));
11860     } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
11861         int i;
11862 #define SET_EXISTS(x) \
11863         flags[(x) >> 4] |= (1 << ((x) & 0xF))
11864 #define CLR_EXISTS(x) \
11865         flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
11866 
11867         memset(flags, 0,
11868                sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
11869         for (i = 0; i < array_size(exists); i++) {
11870             if (exists[i]) {
11871                 flags[i >> 4] |= (1 << (i & 0xF));
11872             }
11873         }
11874         SET_EXISTS(SQL_API_SQLALLOCHANDLE);
11875         SET_EXISTS(SQL_API_SQLFREEHANDLE);
11876         SET_EXISTS(SQL_API_SQLGETSTMTATTR);
11877         SET_EXISTS(SQL_API_SQLSETSTMTATTR);
11878         SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
11879         SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
11880         SET_EXISTS(SQL_API_SQLGETENVATTR);
11881         SET_EXISTS(SQL_API_SQLSETENVATTR);
11882         SET_EXISTS(SQL_API_SQLCLOSECURSOR);
11883         SET_EXISTS(SQL_API_SQLBINDPARAM);
11884 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11885         /*
11886          * Some unixODBC versions have problems with
11887          * SQLError() vs. SQLGetDiagRec() with loss
11888          * of error/warning messages.
11889          */
11890         SET_EXISTS(SQL_API_SQLGETDIAGREC);
11891 #endif
11892         SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
11893         SET_EXISTS(SQL_API_SQLFETCHSCROLL);
11894         SET_EXISTS(SQL_API_SQLENDTRAN);
11895     } else {
11896         if (func < array_size(exists)) {
11897             *flags = exists[func];
11898         } else {
11899             switch (func) {
11900             case SQL_API_SQLALLOCHANDLE:
11901             case SQL_API_SQLFREEHANDLE:
11902             case SQL_API_SQLGETSTMTATTR:
11903             case SQL_API_SQLSETSTMTATTR:
11904             case SQL_API_SQLGETCONNECTATTR:
11905             case SQL_API_SQLSETCONNECTATTR:
11906             case SQL_API_SQLGETENVATTR:
11907             case SQL_API_SQLSETENVATTR:
11908             case SQL_API_SQLCLOSECURSOR:
11909             case SQL_API_SQLBINDPARAM:
11910 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11911             /*
11912              * Some unixODBC versions have problems with
11913              * SQLError() vs. SQLGetDiagRec() with loss
11914              * of error/warning messages.
11915              */
11916             case SQL_API_SQLGETDIAGREC:
11917 #endif
11918             case SQL_API_SQLGETDIAGFIELD:
11919             case SQL_API_SQLFETCHSCROLL:
11920             case SQL_API_SQLENDTRAN:
11921                 *flags = SQL_TRUE;
11922                 break;
11923             default:
11924                 *flags = SQL_FALSE;
11925             }
11926         }
11927     }
11928     return SQL_SUCCESS;
11929 }
11930 
11937 static SQLRETURN
11938 drvallocenv(SQLHENV *env)
11939 {
11940     ENV *e;
11941 
11942     if (env == NULL) {
11943         return SQL_INVALID_HANDLE;
11944     }
11945     e = (ENV *) xmalloc(sizeof (ENV));
11946     if (e == NULL) {
11947         *env = SQL_NULL_HENV;
11948         return SQL_ERROR;
11949     }
11950     e->magic = ENV_MAGIC;
11951     e->ov3 = 0;
11952     e->pool = 0;
11953 #if defined(_WIN32) || defined(_WIN64)
11954     InitializeCriticalSection(&e->cs);
11955 #else
11956 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
11957     nvfs_init();
11958 #endif
11959 #endif
11960     e->dbcs = NULL;
11961     *env = (SQLHENV) e;
11962     return SQL_SUCCESS;
11963 }
11964 
11971 SQLRETURN SQL_API
11972 SQLAllocEnv(SQLHENV *env)
11973 {
11974     return drvallocenv(env);
11975 }
11976 
11983 static SQLRETURN
11984 drvfreeenv(SQLHENV env)
11985 {
11986     ENV *e;
11987 
11988     if (env == SQL_NULL_HENV) {
11989         return SQL_INVALID_HANDLE;
11990     }
11991     e = (ENV *) env;
11992     if (e->magic != ENV_MAGIC) {
11993         return SQL_SUCCESS;
11994     }
11995 #if defined(_WIN32) || defined(_WIN64)
11996     EnterCriticalSection(&e->cs);
11997 #endif
11998     if (e->dbcs) {
11999 #if defined(_WIN32) || defined(_WIN64)
12000         LeaveCriticalSection(&e->cs);
12001 #endif
12002         return SQL_ERROR;
12003     }
12004     e->magic = DEAD_MAGIC;
12005 #if defined(_WIN32) || defined(_WIN64)
12006     LeaveCriticalSection(&e->cs);
12007     DeleteCriticalSection(&e->cs);
12008 #endif
12009     xfree(e);
12010     return SQL_SUCCESS;
12011 }
12012 
12019 SQLRETURN SQL_API
12020 SQLFreeEnv(SQLHENV env)
12021 {
12022     return drvfreeenv(env);
12023 }
12024 
12032 static SQLRETURN
12033 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
12034 {
12035     DBC *d;
12036     ENV *e;
12037     const char *verstr;
12038     int maj = 0, min = 0, lev = 0;
12039 
12040     if (dbc == NULL) {
12041         return SQL_ERROR;
12042     }
12043     d = (DBC *) xmalloc(sizeof (DBC));
12044     if (d == NULL) {
12045         *dbc = SQL_NULL_HDBC;
12046         return SQL_ERROR;
12047     }
12048     memset(d, 0, sizeof (DBC));
12049     d->curtype = SQL_CURSOR_STATIC;
12050     d->ov3 = &d->ov3val;
12051     verstr = sqlite3_libversion();
12052     sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
12053     d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
12054     e = (ENV *) env;
12055 #if defined(_WIN32) || defined(_WIN64)
12056     if (e->magic == ENV_MAGIC) {
12057         EnterCriticalSection(&e->cs);
12058     }
12059 #endif
12060     if (e->magic == ENV_MAGIC) {
12061         DBC *n, *p;
12062 
12063         d->env = e;
12064         d->ov3 = &e->ov3;
12065         p = NULL;
12066         n = e->dbcs;
12067         while (n) {
12068             p = n;
12069             n = n->next;
12070         }
12071         if (p) {
12072             p->next = d;
12073         } else {
12074             e->dbcs = d;
12075         }
12076     }
12077 #if defined(_WIN32) || defined(_WIN64)
12078     InitializeCriticalSection(&d->cs);
12079     d->owner = 0;
12080     if (e->magic == ENV_MAGIC) {
12081         LeaveCriticalSection(&e->cs);
12082     }
12083     d->oemcp = 1;
12084 #endif
12085     d->autocommit = 1;
12086     d->magic = DBC_MAGIC;
12087     *dbc = (SQLHDBC) d;
12088     drvgetgpps(d);
12089     return SQL_SUCCESS;
12090 }
12091 
12099 SQLRETURN SQL_API
12100 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
12101 {
12102     return drvallocconnect(env, dbc);
12103 }
12104 
12111 static SQLRETURN
12112 drvfreeconnect(SQLHDBC dbc)
12113 {
12114     DBC *d;
12115     ENV *e;
12116     SQLRETURN ret = SQL_ERROR;
12117 
12118     if (dbc == SQL_NULL_HDBC) {
12119         return SQL_INVALID_HANDLE;
12120     }
12121     d = (DBC *) dbc;
12122     if (d->magic != DBC_MAGIC) {
12123         return SQL_INVALID_HANDLE;
12124     }
12125     e = d->env;
12126     if (e && e->magic == ENV_MAGIC) {
12127 #if defined(_WIN32) || defined(_WIN64)
12128         EnterCriticalSection(&e->cs);
12129 #endif
12130     } else {
12131         e = NULL;
12132     }
12133     HDBC_LOCK(dbc);
12134     if (d->sqlite) {
12135         setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
12136         HDBC_UNLOCK(dbc);
12137         goto done;
12138     }
12139     while (d->stmt) {
12140         freestmt((HSTMT) d->stmt);
12141     }
12142     if (e && e->magic == ENV_MAGIC) {
12143         DBC *n, *p;
12144 
12145         p = NULL;
12146         n = e->dbcs;
12147         while (n) {
12148             if (n == d) {
12149                 break;
12150             }
12151             p = n;
12152             n = n->next;
12153         }
12154         if (n) {
12155             if (p) {
12156                 p->next = d->next;
12157             } else {
12158                 e->dbcs = d->next;
12159             }
12160         }
12161     }
12162     drvrelgpps(d);
12163     d->magic = DEAD_MAGIC;
12164     if (d->trace) {
12165         fclose(d->trace);
12166     }
12167 #if defined(_WIN32) || defined(_WIN64)
12168     d->owner = 0;
12169     LeaveCriticalSection(&d->cs);
12170     DeleteCriticalSection(&d->cs);
12171 #endif
12172     xfree(d);
12173     ret = SQL_SUCCESS;
12174 done:
12175 #if defined(_WIN32) || defined(_WIN64)
12176     if (e) {
12177         LeaveCriticalSection(&e->cs);
12178     }
12179 #endif
12180     return ret;
12181 }
12182 
12189 SQLRETURN SQL_API
12190 SQLFreeConnect(SQLHDBC dbc)
12191 {
12192     return drvfreeconnect(dbc);
12193 }
12194 
12205 static SQLRETURN
12206 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12207                   SQLINTEGER bufmax, SQLINTEGER *buflen)
12208 {
12209     DBC *d;
12210     SQLINTEGER dummy;
12211 
12212     if (dbc == SQL_NULL_HDBC) {
12213         return SQL_INVALID_HANDLE;
12214     }
12215     d = (DBC *) dbc;
12216     if (!val) {
12217         val = (SQLPOINTER) &dummy;
12218     }
12219     if (!buflen) {
12220         buflen = &dummy;
12221     }
12222     switch (attr) {
12223     case SQL_ATTR_CONNECTION_DEAD:
12224         *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
12225         *buflen = sizeof (SQLINTEGER);
12226         break;
12227     case SQL_ATTR_ACCESS_MODE:
12228         *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
12229         *buflen = sizeof (SQLINTEGER);
12230         break;
12231     case SQL_ATTR_AUTOCOMMIT:
12232         *((SQLINTEGER *) val) =
12233             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12234         *buflen = sizeof (SQLINTEGER);
12235         break;
12236     case SQL_ATTR_LOGIN_TIMEOUT:
12237         *((SQLINTEGER *) val) = 100;
12238         *buflen = sizeof (SQLINTEGER);
12239         break;
12240     case SQL_ATTR_ODBC_CURSORS:
12241         *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
12242         *buflen = sizeof (SQLINTEGER);
12243         break;
12244     case SQL_ATTR_PACKET_SIZE:
12245         *((SQLINTEGER *) val) = 16384;
12246         *buflen = sizeof (SQLINTEGER);
12247         break;
12248     case SQL_ATTR_TXN_ISOLATION:
12249         *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
12250         *buflen = sizeof (SQLINTEGER);
12251         break;
12252     case SQL_ATTR_TRACEFILE:
12253     case SQL_ATTR_TRANSLATE_LIB:
12254         *((SQLCHAR *) val) = 0;
12255         *buflen = 0;
12256         break;
12257     case SQL_ATTR_CURRENT_CATALOG:
12258 #if defined(_WIN32) || defined(_WIN64)
12259         if (d->xcelqrx) {
12260             if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
12261                 strcpy((char *) val, "main");
12262                 *buflen = 4;
12263                 break;
12264             }
12265         }
12266 #endif
12267         *((SQLCHAR *) val) = 0;
12268         *buflen = 0;
12269         break;
12270     case SQL_ATTR_TRACE:
12271     case SQL_ATTR_QUIET_MODE:
12272     case SQL_ATTR_TRANSLATE_OPTION:
12273     case SQL_ATTR_KEYSET_SIZE:
12274     case SQL_ATTR_QUERY_TIMEOUT:
12275         *((SQLINTEGER *) val) = 0;
12276         *buflen = sizeof (SQLINTEGER);
12277         break;
12278     case SQL_ATTR_PARAM_BIND_TYPE:
12279         *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
12280         *buflen = sizeof (SQLUINTEGER);
12281         break;
12282     case SQL_ATTR_ROW_BIND_TYPE:
12283         *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
12284         *buflen = sizeof (SQLULEN);
12285         break;
12286     case SQL_ATTR_USE_BOOKMARKS:
12287         *((SQLINTEGER *) val) = SQL_UB_OFF;
12288         *buflen = sizeof (SQLINTEGER);
12289         break;
12290     case SQL_ATTR_ASYNC_ENABLE:
12291         *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
12292         *buflen = sizeof (SQLINTEGER);
12293         break;
12294     case SQL_ATTR_NOSCAN:
12295         *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
12296         *buflen = sizeof (SQLINTEGER);
12297         break;
12298     case SQL_ATTR_CONCURRENCY:
12299         *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
12300         *buflen = sizeof (SQLINTEGER);
12301         break;
12302 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
12303     case SQL_ATTR_CURSOR_SENSITIVITY:
12304         *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
12305         *buflen = sizeof (SQLINTEGER);
12306         break;
12307 #endif
12308     case SQL_ATTR_SIMULATE_CURSOR:
12309         *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
12310         *buflen = sizeof (SQLINTEGER);
12311         break;
12312     case SQL_ATTR_MAX_ROWS:
12313         *((SQLINTEGER *) val) = 0;
12314         *buflen = sizeof (SQLINTEGER);
12315     case SQL_ATTR_MAX_LENGTH:
12316         *((SQLINTEGER *) val) = 1000000000;
12317         *buflen = sizeof (SQLINTEGER);
12318         break;
12319     case SQL_ATTR_CURSOR_TYPE:
12320         *((SQLINTEGER *) val) = d->curtype;
12321         *buflen = sizeof (SQLINTEGER);
12322         break;
12323     case SQL_ATTR_RETRIEVE_DATA:
12324         *((SQLINTEGER *) val) = SQL_RD_ON;
12325         *buflen = sizeof (SQLINTEGER);
12326         break;
12327 #ifdef SQL_ATTR_METADATA_ID
12328     case SQL_ATTR_METADATA_ID:
12329         *((SQLULEN *) val) = SQL_FALSE;
12330         return SQL_SUCCESS;
12331 #endif
12332     default:
12333         *((SQLINTEGER *) val) = 0;
12334         *buflen = sizeof (SQLINTEGER);
12335         setstatd(d, -1, "unsupported connect attribute %d",
12336                  (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
12337         return SQL_ERROR;
12338     }
12339     return SQL_SUCCESS;
12340 }
12341 
12342 #ifndef WINTERFACE
12343 
12353 SQLRETURN SQL_API
12354 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12355                   SQLINTEGER bufmax, SQLINTEGER *buflen)
12356 {
12357     SQLRETURN ret;
12358 
12359     HDBC_LOCK(dbc);
12360     ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
12361     HDBC_UNLOCK(dbc);
12362     return ret;
12363 }
12364 #endif
12365 
12366 #ifdef WINTERFACE
12367 
12377 SQLRETURN SQL_API
12378 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12379                    SQLINTEGER bufmax, SQLINTEGER *buflen)
12380 {
12381     SQLRETURN ret;
12382     SQLINTEGER len = 0;
12383 
12384     HDBC_LOCK(dbc);
12385     ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
12386     if (ret == SQL_SUCCESS) {
12387         SQLWCHAR *v = NULL;
12388 
12389         switch (attr) {
12390         case SQL_ATTR_TRACEFILE:
12391         case SQL_ATTR_CURRENT_CATALOG:
12392         case SQL_ATTR_TRANSLATE_LIB:
12393             if (val) {
12394                 if (len > 0) {
12395                     v = uc_from_utf((SQLCHAR *) val, len);
12396                     if (v) {
12397                         int vmax = bufmax / sizeof (SQLWCHAR);
12398 
12399                         uc_strncpy(val, v, vmax);
12400                         if (len < vmax) {
12401                             len = min(vmax, uc_strlen(v));
12402                             v[len] = 0;
12403                         } else {
12404                             len = vmax;
12405                         }
12406                         uc_free(v);
12407                         len *= sizeof (SQLWCHAR);
12408                     } else {
12409                         len = 0;
12410                     }
12411                 }
12412                 if (len <= 0) {
12413                     len = 0;
12414                     if (bufmax >= sizeof (SQLWCHAR)) {
12415                         *((SQLWCHAR *)val) = 0;
12416                     }
12417                 }
12418             } else {
12419                 len *= sizeof (SQLWCHAR);
12420             }
12421             break;
12422         }
12423         if (buflen) {
12424             *buflen = len;
12425         }
12426     }
12427     HDBC_UNLOCK(dbc);
12428     return ret;
12429 }
12430 #endif
12431 
12441 static SQLRETURN
12442 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12443                   SQLINTEGER len)
12444 {
12445     DBC *d;
12446 
12447     if (dbc == SQL_NULL_HDBC) {
12448         return SQL_INVALID_HANDLE;
12449     }
12450     d = (DBC *) dbc;
12451     switch (attr) {
12452     case SQL_AUTOCOMMIT:
12453         d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
12454         if (d->autocommit && d->intrans) {
12455             return endtran(d, SQL_COMMIT, 1);
12456         } else if (!d->autocommit) {
12457             s3stmt_end(d->cur_s3stmt);
12458         }
12459         break;
12460 #ifdef SQL_ATTR_METADATA_ID
12461     case SQL_ATTR_METADATA_ID:
12462         if (val == (SQLPOINTER) SQL_FALSE) {
12463             break;
12464         }
12465         /* fall through */
12466 #endif
12467     default:
12468         setstatd(d, -1, "option value changed", "01S02");
12469         return SQL_SUCCESS_WITH_INFO;
12470     }
12471     return SQL_SUCCESS;
12472 }
12473 
12474 #ifndef WINTERFACE
12475 
12484 SQLRETURN SQL_API
12485 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12486                   SQLINTEGER len)
12487 {
12488     SQLRETURN ret;
12489 
12490     HDBC_LOCK(dbc);
12491     ret = drvsetconnectattr(dbc, attr, val, len);
12492     HDBC_UNLOCK(dbc);
12493     return ret;
12494 }
12495 #endif
12496 
12497 #ifdef WINTERFACE
12498 
12507 SQLRETURN SQL_API
12508 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12509                    SQLINTEGER len)
12510 {
12511     SQLRETURN ret;
12512 
12513     HDBC_LOCK(dbc);
12514     ret = drvsetconnectattr(dbc, attr, val, len);
12515     HDBC_UNLOCK(dbc);
12516     return ret;
12517 }
12518 #endif
12519 
12528 static SQLRETURN
12529 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12530 {
12531     DBC *d;
12532     SQLINTEGER dummy;
12533 
12534     if (dbc == SQL_NULL_HDBC) {
12535         return SQL_INVALID_HANDLE;
12536     }
12537     d = (DBC *) dbc;
12538     if (!param) {
12539         param = (SQLPOINTER) &dummy;
12540     }
12541     switch (opt) {
12542     case SQL_ACCESS_MODE:
12543         *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
12544         break;
12545     case SQL_AUTOCOMMIT:
12546         *((SQLINTEGER *) param) =
12547             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12548         break;
12549     case SQL_LOGIN_TIMEOUT:
12550         *((SQLINTEGER *) param) = 100;
12551         break;
12552     case SQL_ODBC_CURSORS:
12553         *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
12554         break;
12555     case SQL_PACKET_SIZE:
12556         *((SQLINTEGER *) param) = 16384;
12557         break;
12558     case SQL_TXN_ISOLATION:
12559         *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
12560         break;
12561     case SQL_OPT_TRACE:
12562     case SQL_OPT_TRACEFILE:
12563     case SQL_QUIET_MODE:
12564     case SQL_TRANSLATE_DLL:
12565     case SQL_TRANSLATE_OPTION:
12566     case SQL_KEYSET_SIZE:
12567     case SQL_QUERY_TIMEOUT:
12568     case SQL_BIND_TYPE:
12569     case SQL_CURRENT_QUALIFIER:
12570         *((SQLINTEGER *) param) = 0;
12571         break;
12572     case SQL_USE_BOOKMARKS:
12573         *((SQLINTEGER *) param) = SQL_UB_OFF;
12574         break;
12575     case SQL_ASYNC_ENABLE:
12576         *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
12577         break;
12578     case SQL_NOSCAN:
12579         *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
12580         break;
12581     case SQL_CONCURRENCY:
12582         *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
12583         break;
12584     case SQL_SIMULATE_CURSOR:
12585         *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
12586         break;
12587     case SQL_MAX_ROWS:
12588         *((SQLINTEGER *) param) = 0;
12589         break;
12590     case SQL_ROWSET_SIZE:
12591     case SQL_MAX_LENGTH:
12592         *((SQLINTEGER *) param) = 1000000000;
12593         break;
12594     case SQL_CURSOR_TYPE:
12595         *((SQLINTEGER *) param) = d->curtype;
12596         break;
12597     case SQL_RETRIEVE_DATA:
12598         *((SQLINTEGER *) param) = SQL_RD_ON;
12599         break;
12600     default:
12601         *((SQLINTEGER *) param) = 0;
12602         setstatd(d, -1, "unsupported connect option %d",
12603                  (*d->ov3) ? "HYC00" : "S1C00", opt);
12604         return SQL_ERROR;
12605     }
12606     return SQL_SUCCESS;
12607 }
12608 
12609 #ifndef WINTERFACE
12610 
12618 SQLRETURN SQL_API
12619 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12620 {
12621     SQLRETURN ret;
12622 
12623     HDBC_LOCK(dbc);
12624     ret = drvgetconnectoption(dbc, opt, param);
12625     HDBC_UNLOCK(dbc);
12626     return ret;
12627 }
12628 #endif
12629 
12630 #ifdef WINTERFACE
12631 
12639 SQLRETURN SQL_API
12640 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12641 {
12642     SQLRETURN ret;
12643 
12644     HDBC_LOCK(dbc);
12645     ret = drvgetconnectoption(dbc, opt, param);
12646     if (SQL_SUCCEEDED(ret)) {
12647         switch (opt) {
12648         case SQL_OPT_TRACEFILE:
12649         case SQL_CURRENT_QUALIFIER:
12650         case SQL_TRANSLATE_DLL:
12651             if (param) {
12652                 *(SQLWCHAR *) param = 0;
12653             }
12654             break;
12655         }
12656     }
12657     HDBC_UNLOCK(dbc);
12658     return ret;
12659 }
12660 #endif
12661 
12670 static SQLRETURN
12671 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
12672 {
12673     DBC *d;
12674 
12675     if (dbc == SQL_NULL_HDBC) {
12676         return SQL_INVALID_HANDLE;
12677     }
12678     d = (DBC *) dbc;
12679     switch (opt) {
12680     case SQL_AUTOCOMMIT:
12681         d->autocommit = param == SQL_AUTOCOMMIT_ON;
12682         if (d->autocommit && d->intrans) {
12683             return endtran(d, SQL_COMMIT, 1);
12684         } else if (!d->autocommit) {
12685             s3stmt_end(d->cur_s3stmt);
12686         }
12687         break;
12688     default:
12689         setstatd(d, -1, "option value changed", "01S02");
12690         return SQL_SUCCESS_WITH_INFO;
12691     }
12692     return SQL_SUCCESS;
12693 }
12694 
12695 #ifndef WINTERFACE
12696 
12704 SQLRETURN SQL_API
12705 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12706 {
12707     SQLRETURN ret;
12708 
12709     HDBC_LOCK(dbc);
12710     ret = drvsetconnectoption(dbc, opt, param);
12711     HDBC_UNLOCK(dbc);
12712     return ret;
12713 }
12714 #endif
12715 
12716 #ifdef WINTERFACE
12717 
12725 SQLRETURN SQL_API
12726 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12727 {
12728     SQLRETURN ret;
12729 
12730     HDBC_LOCK(dbc);
12731     ret = drvsetconnectoption(dbc, opt, param);
12732     HDBC_UNLOCK(dbc);
12733     return ret;
12734 }
12735 #endif
12736 
12737 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12738 
12749 static int
12750 getdsnattr(char *dsn, char *attr, char *out, int outLen)
12751 {
12752     char *str = dsn, *start;
12753     int len = strlen(attr);
12754 
12755     while (*str) {
12756         while (*str && *str == ';') {
12757             ++str;
12758         }
12759         start = str;
12760         if ((str = strchr(str, '=')) == NULL) {
12761             return 0;
12762         }
12763         if (str - start == len && strncasecmp(start, attr, len) == 0) {
12764             start = ++str;
12765             while (*str && *str != ';') {
12766                 ++str;
12767             }
12768             len = min(outLen - 1, str - start);
12769             strncpy(out, start, len);
12770             out[len] = '\0';
12771             return 1;
12772         }
12773         while (*str && *str != ';') {
12774             ++str;
12775         }
12776     }
12777     return 0;
12778 }
12779 #endif
12780 
12792 static SQLRETURN
12793 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
12794            int pwdLen, int isu)
12795 {
12796     DBC *d;
12797     int len;
12798     SQLRETURN ret;
12799     char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12800     char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
12801     char loadext[SQL_MAX_MESSAGE_LENGTH], attas[SQL_MAX_MESSAGE_LENGTH];
12802     char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
12803     char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
12804     char jdflag[32], ilflag[32];
12805 #if defined(_WIN32) || defined(_WIN64)
12806     char oemcp[32];
12807 #endif
12808 
12809     if (dbc == SQL_NULL_HDBC) {
12810         return SQL_INVALID_HANDLE;
12811     }
12812     d = (DBC *) dbc;
12813     if (d->magic != DBC_MAGIC) {
12814         return SQL_INVALID_HANDLE;
12815     }
12816     if (d->sqlite != NULL) {
12817         setstatd(d, -1, "connection already established", "08002");
12818         return SQL_ERROR;
12819     }
12820     buf[0] = '\0';
12821     if (dsnLen == SQL_NTS) {
12822         len = sizeof (buf) - 1;
12823     } else {
12824         len = min(sizeof (buf) - 1, dsnLen);
12825     }
12826     if (dsn != NULL) {
12827         strncpy(buf, (char *) dsn, len);
12828     }
12829     buf[len] = '\0';
12830     if (buf[0] == '\0') {
12831         setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
12832         return SQL_ERROR;
12833     }
12834 #if defined(_WIN32) || defined(_WIN64)
12835     /*
12836      * When DSN is in UTF it must be converted to ANSI
12837      * here for ANSI SQLGetPrivateProfileString()
12838      */
12839     if (isu) {
12840         char *cdsn = utf_to_wmb(buf, len);
12841 
12842         if (!cdsn) {
12843             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12844             return SQL_ERROR;
12845         }
12846         strcpy(buf, cdsn);
12847         uc_free(cdsn);
12848     }
12849 #endif
12850     busy[0] = '\0';
12851     dbname[0] = '\0';
12852 #ifdef WITHOUT_DRIVERMGR
12853     getdsnattr(buf, "database", dbname, sizeof (dbname));
12854     if (dbname[0] == '\0') {
12855         strncpy(dbname, buf, sizeof (dbname));
12856         dbname[sizeof (dbname) - 1] = '\0';
12857     }
12858     getdsnattr(buf, "timeout", busy, sizeof (busy));
12859     sflag[0] = '\0';
12860     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12861     spflag[0] = '\0';
12862     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12863     ntflag[0] = '\0';
12864     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12865     nwflag[0] = '\0';
12866     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12867     snflag[0] = '\0';
12868     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12869     lnflag[0] = '\0';
12870     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12871     ncflag[0] = '\0';
12872     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12873     fkflag[0] = '\0';
12874     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12875     loadext[0] = '\0';
12876     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12877     jmode[0] = '\0';
12878     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12879     jdflag[0] = '\0';
12880     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
12881 #if defined(_WIN32) || defined(_WIN64)
12882     oemcp[0] = '\0';
12883     getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
12884 #endif
12885     biflag[0] = '\0';
12886     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12887     attas[0] = '\0';
12888     getdsnattr(buf, "attachas", attas, sizeof (attas));
12889     ilflag[0] = '\0';
12890     getdsnattr(buf, "ilike", ilflag, sizeof (ilflag));
12891 #else
12892     SQLGetPrivateProfileString(buf, "timeout", "100000",
12893                                busy, sizeof (busy), ODBC_INI);
12894     SQLGetPrivateProfileString(buf, "database", "",
12895                                dbname, sizeof (dbname), ODBC_INI);
12896 #if defined(_WIN32) || defined(_WIN64)
12897     /* database name read from registry is not UTF8 !!! */
12898     isu = 0;
12899 #endif
12900     SQLGetPrivateProfileString(buf, "stepapi", "",
12901                                sflag, sizeof (sflag), ODBC_INI);
12902     SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
12903                                spflag, sizeof (spflag), ODBC_INI);
12904     SQLGetPrivateProfileString(buf, "notxn", "",
12905                                ntflag, sizeof (ntflag), ODBC_INI);
12906     SQLGetPrivateProfileString(buf, "nowchar", "",
12907                                nwflag, sizeof (nwflag), ODBC_INI);
12908     SQLGetPrivateProfileString(buf, "shortnames", "",
12909                                snflag, sizeof (snflag), ODBC_INI);
12910     SQLGetPrivateProfileString(buf, "longnames", "",
12911                                lnflag, sizeof (lnflag), ODBC_INI);
12912     SQLGetPrivateProfileString(buf, "nocreat", "",
12913                                ncflag, sizeof (ncflag), ODBC_INI);
12914     SQLGetPrivateProfileString(buf, "fksupport", "",
12915                                fkflag, sizeof (fkflag), ODBC_INI);
12916     SQLGetPrivateProfileString(buf, "loadext", "",
12917                                loadext, sizeof (loadext), ODBC_INI);
12918     SQLGetPrivateProfileString(buf, "journalmode", "",
12919                                jmode, sizeof (jmode), ODBC_INI);
12920     SQLGetPrivateProfileString(buf, "jdconv", "",
12921                                jdflag, sizeof (jdflag), ODBC_INI);
12922 #if defined(_WIN32) || defined(_WIN64)
12923     SQLGetPrivateProfileString(buf, "oemcp", "1",
12924                                oemcp, sizeof (oemcp), ODBC_INI);
12925 #endif
12926     SQLGetPrivateProfileString(buf, "bigint", "",
12927                                biflag, sizeof (biflag), ODBC_INI);
12928     SQLGetPrivateProfileString(buf, "attachas", "",
12929                                attas, sizeof (attas), ODBC_INI);
12930     SQLGetPrivateProfileString(buf, "ilike", "",
12931                                ilflag, sizeof (ilflag), ODBC_INI);
12932 #endif
12933     tracef[0] = '\0';
12934 #ifdef WITHOUT_DRIVERMGR
12935     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12936 #else
12937     SQLGetPrivateProfileString(buf, "tracefile", "",
12938                                tracef, sizeof (tracef), ODBC_INI);
12939 #endif
12940     if (tracef[0] != '\0') {
12941         d->trace = fopen(tracef, "a");
12942     }
12943     d->nowchar = getbool(nwflag);
12944     d->shortnames = getbool(snflag);
12945     d->longnames = getbool(lnflag);
12946     d->nocreat = getbool(ncflag);
12947     d->fksupport = getbool(fkflag);
12948     d->jdconv = getbool(jdflag);
12949     d->ilike = getbool(ilflag);
12950 #if defined(_WIN32) || defined(_WIN64)
12951     d->oemcp = getbool(oemcp);
12952 #else
12953     d->oemcp = 0;
12954 #endif
12955     d->dobigint = getbool(biflag);
12956     d->pwd = pwd;
12957     d->pwdLen = 0;
12958     if (d->pwd) {
12959         d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
12960     }
12961     ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
12962                   jmode, busy);
12963     if (ret == SQL_SUCCESS) {
12964         dbloadext(d, loadext);
12965         dbattas(d, attas);
12966     }
12967     return ret;
12968 }
12969 
12970 #ifndef WINTERFACE
12971 
12983 SQLRETURN SQL_API
12984 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
12985            SQLCHAR *uid, SQLSMALLINT uidLen,
12986            SQLCHAR *pwd, SQLSMALLINT pwdLen)
12987 {
12988     SQLRETURN ret;
12989 
12990     HDBC_LOCK(dbc);
12991     ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
12992     HDBC_UNLOCK(dbc);
12993     return ret;
12994 }
12995 #endif
12996 
12997 #ifdef WINTERFACE
12998 
13010 SQLRETURN SQL_API
13011 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
13012             SQLWCHAR *uid, SQLSMALLINT uidLen,
13013             SQLWCHAR *pwd, SQLSMALLINT pwdLen)
13014 {
13015     char *dsna = NULL;
13016     char *pwda = NULL;
13017     SQLRETURN ret;
13018 
13019     HDBC_LOCK(dbc);
13020     if (dsn) {
13021         dsna = uc_to_utf_c(dsn, dsnLen);
13022         if (!dsna) {
13023             DBC *d = (DBC *) dbc;
13024 
13025             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
13026             ret = SQL_ERROR;
13027             goto done;
13028         }
13029     }
13030     if (pwd) {
13031         pwda = uc_to_utf_c(pwd, pwdLen);
13032         if (!pwda) {
13033             DBC *d = (DBC *) dbc;
13034 
13035             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
13036             ret = SQL_ERROR;
13037             goto done;
13038         }
13039     }
13040     ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
13041 done:
13042     HDBC_UNLOCK(dbc);
13043     uc_free(dsna);
13044     uc_free(pwda);
13045     return ret;
13046 }
13047 #endif
13048 
13055 static SQLRETURN
13056 drvdisconnect(SQLHDBC dbc)
13057 {
13058     DBC *d;
13059     int rc;
13060 
13061     if (dbc == SQL_NULL_HDBC) {
13062         return SQL_INVALID_HANDLE;
13063     }
13064     d = (DBC *) dbc;
13065     if (d->magic != DBC_MAGIC) {
13066         return SQL_INVALID_HANDLE;
13067     }
13068     if (d->intrans) {
13069         setstatd(d, -1, "incomplete transaction", "25000");
13070         return SQL_ERROR;
13071     }
13072     if (d->cur_s3stmt) {
13073         s3stmt_end(d->cur_s3stmt);
13074     }
13075     if (d->sqlite) {
13076         if (d->trace) {
13077             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
13078                     d->dbname);
13079             fflush(d->trace);
13080         }
13081         rc = sqlite3_close(d->sqlite);
13082         if (rc == SQLITE_BUSY) {
13083             setstatd(d, -1, "unfinished statements", "25000");
13084             return SQL_ERROR;
13085         }
13086         d->sqlite = NULL;
13087     }
13088     freep(&d->dbname);
13089     freep(&d->dsn);
13090     return SQL_SUCCESS;
13091 }
13092 
13099 SQLRETURN SQL_API
13100 SQLDisconnect(SQLHDBC dbc)
13101 {
13102     SQLRETURN ret;
13103 
13104     HDBC_LOCK(dbc);
13105     ret = drvdisconnect(dbc);
13106     HDBC_UNLOCK(dbc);
13107     return ret;
13108 }
13109 
13110 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
13111 
13125 static SQLRETURN
13126 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
13127                  SQLCHAR *connIn, SQLSMALLINT connInLen,
13128                  SQLCHAR *connOut, SQLSMALLINT connOutMax,
13129                  SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
13130 {
13131     DBC *d;
13132     int len;
13133     SQLRETURN ret;
13134     char buf[SQL_MAX_MESSAGE_LENGTH * 8], dbname[SQL_MAX_MESSAGE_LENGTH];
13135     char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
13136     char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
13137     char pwd[SQL_MAX_MESSAGE_LENGTH], attas[SQL_MAX_MESSAGE_LENGTH];
13138     char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
13139     char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
13140     char jdflag[32], ilflag[32];
13141 
13142     if (dbc == SQL_NULL_HDBC) {
13143         return SQL_INVALID_HANDLE;
13144     }
13145     if (drvcompl != SQL_DRIVER_COMPLETE &&
13146         drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
13147         drvcompl != SQL_DRIVER_PROMPT &&
13148         drvcompl != SQL_DRIVER_NOPROMPT) {
13149         return SQL_NO_DATA;
13150     }
13151     d = (DBC *) dbc;
13152     if (d->sqlite) {
13153         setstatd(d, -1, "connection already established", "08002");
13154         return SQL_ERROR;
13155     }
13156     buf[0] = '\0';
13157     if (connInLen == SQL_NTS) {
13158         len = sizeof (buf) - 1;
13159     } else {
13160         len = min(connInLen, sizeof (buf) - 1);
13161     }
13162     if (connIn != NULL) {
13163         strncpy(buf, (char *) connIn, len);
13164     }
13165     buf[len] = '\0';
13166     if (!buf[0]) {
13167         setstatd(d, -1, "invalid connect attributes",
13168                  (*d->ov3) ? "HY090" : "S1090");
13169         return SQL_ERROR;
13170     }
13171     dsn[0] = '\0';
13172     getdsnattr(buf, "DSN", dsn, sizeof (dsn));
13173 
13174     /* special case: connIn is sole DSN value without keywords */
13175     if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
13176         strncpy(dsn, buf, sizeof (dsn) - 1);
13177         dsn[sizeof (dsn) - 1] = '\0';
13178     }
13179 
13180     busy[0] = '\0';
13181     getdsnattr(buf, "timeout", busy, sizeof (busy));
13182 #ifndef WITHOUT_DRIVERMGR
13183     if (dsn[0] && !busy[0]) {
13184         SQLGetPrivateProfileString(dsn, "timeout", "100000",
13185                                    busy, sizeof (busy), ODBC_INI);
13186     }
13187 #endif
13188     dbname[0] = '\0';
13189     getdsnattr(buf, "database", dbname, sizeof (dbname));
13190 #ifndef WITHOUT_DRIVERMGR
13191     if (dsn[0] && !dbname[0]) {
13192         SQLGetPrivateProfileString(dsn, "database", "",
13193                                    dbname, sizeof (dbname), ODBC_INI);
13194     }
13195 #endif
13196     sflag[0] = '\0';
13197     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
13198 #ifndef WITHOUT_DRIVERMGR
13199     if (dsn[0] && !sflag[0]) {
13200         SQLGetPrivateProfileString(dsn, "stepapi", "",
13201                                    sflag, sizeof (sflag), ODBC_INI);
13202     }
13203 #endif
13204     spflag[0] = '\0';
13205     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
13206 #ifndef WITHOUT_DRIVERMGR
13207     if (dsn[0] && !spflag[0]) {
13208         SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
13209                                    spflag, sizeof (spflag), ODBC_INI);
13210     }
13211 #endif
13212     ntflag[0] = '\0';
13213     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
13214 #ifndef WITHOUT_DRIVERMGR
13215     if (dsn[0] && !ntflag[0]) {
13216         SQLGetPrivateProfileString(dsn, "notxn", "",
13217                                    ntflag, sizeof (ntflag), ODBC_INI);
13218     }
13219 #endif
13220     snflag[0] = '\0';
13221     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
13222 #ifndef WITHOUT_DRIVERMGR
13223     if (dsn[0] && !snflag[0]) {
13224         SQLGetPrivateProfileString(dsn, "shortnames", "",
13225                                    snflag, sizeof (snflag), ODBC_INI);
13226     }
13227 #endif
13228     lnflag[0] = '\0';
13229     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
13230 #ifndef WITHOUT_DRIVERMGR
13231     if (dsn[0] && !lnflag[0]) {
13232         SQLGetPrivateProfileString(dsn, "longnames", "",
13233                                    lnflag, sizeof (lnflag), ODBC_INI);
13234     }
13235 #endif
13236     ncflag[0] = '\0';
13237     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
13238 #ifndef WITHOUT_DRIVERMGR
13239     if (dsn[0] && !ncflag[0]) {
13240         SQLGetPrivateProfileString(dsn, "nocreat", "",
13241                                    ncflag, sizeof (ncflag), ODBC_INI);
13242     }
13243 #endif
13244     nwflag[0] = '\0';
13245     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
13246 #ifndef WITHOUT_DRIVERMGR
13247     if (dsn[0] && !nwflag[0]) {
13248         SQLGetPrivateProfileString(dsn, "nowchar", "",
13249                                    nwflag, sizeof (nwflag), ODBC_INI);
13250     }
13251 #endif
13252     fkflag[0] = '\0';
13253     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
13254 #ifndef WITHOUT_DRIVERMGR
13255     if (dsn[0] && !fkflag[0]) {
13256         SQLGetPrivateProfileString(dsn, "fksupport", "",
13257                                    fkflag, sizeof (fkflag), ODBC_INI);
13258     }
13259 #endif
13260     loadext[0] = '\0';
13261     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
13262 #ifndef WITHOUT_DRIVERMGR
13263     if (dsn[0] && !loadext[0]) {
13264         SQLGetPrivateProfileString(dsn, "loadext", "",
13265                                    loadext, sizeof (loadext), ODBC_INI);
13266     }
13267 #endif
13268     jmode[0] = '\0';
13269     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
13270 #ifndef WITHOUT_DRIVERMGR
13271     if (dsn[0] && !jmode[0]) {
13272         SQLGetPrivateProfileString(dsn, "journalmode", "",
13273                                    jmode, sizeof (jmode), ODBC_INI);
13274     }
13275 #endif
13276     biflag[0] = '\0';
13277     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
13278 #ifndef WITHOUT_DRIVERMGR
13279     if (dsn[0] && !biflag[0]) {
13280         SQLGetPrivateProfileString(dsn, "bigint", "",
13281                                    biflag, sizeof (biflag), ODBC_INI);
13282     }
13283 #endif
13284     jdflag[0] = '\0';
13285     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
13286 #ifndef WITHOUT_DRIVERMGR
13287     if (dsn[0] && !jdflag[0]) {
13288         SQLGetPrivateProfileString(dsn, "jdconv", "",
13289                                    jdflag, sizeof (jdflag), ODBC_INI);
13290     }
13291 #endif
13292     pwd[0] = '\0';
13293     getdsnattr(buf, "pwd", pwd, sizeof (pwd));
13294 #ifndef WITHOUT_DRIVERMGR
13295     if (dsn[0] && !pwd[0]) {
13296         SQLGetPrivateProfileString(dsn, "pwd", "",
13297                                    pwd, sizeof (pwd), ODBC_INI);
13298     }
13299 #endif
13300     attas[0] = '\0';
13301     getdsnattr(buf, "attachas", attas, sizeof (attas));
13302 #ifndef WITHOUT_DRIVERMGR
13303     if (dsn[0] && !attas[0]) {
13304         SQLGetPrivateProfileString(dsn, "attachas", "",
13305                                    attas, sizeof (attas), ODBC_INI);
13306     }
13307 #endif
13308     ilflag[0] = '\0';
13309     getdsnattr(buf, "ilike", ilflag, sizeof (ilflag));
13310 #ifndef WITHOUT_DRIVERMGR
13311     if (dsn[0] && !ilflag[0]) {
13312         SQLGetPrivateProfileString(dsn, "ilike", "",
13313                                    ilflag, sizeof (ilflag), ODBC_INI);
13314     }
13315 #endif
13316 
13317     if (!dbname[0] && !dsn[0]) {
13318         strcpy(dsn, "SQLite");
13319         strncpy(dbname, buf, sizeof (dbname));
13320         dbname[sizeof (dbname) - 1] = '\0';
13321     }
13322     tracef[0] = '\0';
13323     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
13324 #ifndef WITHOUT_DRIVERMGR
13325     if (dsn[0] && !tracef[0]) {
13326         SQLGetPrivateProfileString(dsn, "tracefile", "",
13327                                    tracef, sizeof (tracef), ODBC_INI);
13328     }
13329 #endif
13330     if (connOut || connOutLen) {
13331         int count;
13332 
13333         buf[0] = '\0';
13334         count = snprintf(buf, sizeof (buf),
13335                          "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
13336                          "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
13337                          "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
13338                          "JournalMode=%s;LoadExt=%s;BigInt=%s;JDConv=%s;"
13339                          "PWD=%s;AttachAs=%s;ILike=%s",
13340                          dsn, dbname, sflag, busy, spflag, ntflag,
13341                          snflag, lnflag, ncflag, nwflag, fkflag, tracef,
13342                          jmode, loadext, biflag, jdflag, pwd, attas, ilflag);
13343         if (count < 0) {
13344             buf[sizeof (buf) - 1] = '\0';
13345         }
13346         len = min(connOutMax - 1, strlen(buf));
13347         if (connOut) {
13348             strncpy((char *) connOut, buf, len);
13349             connOut[len] = '\0';
13350         }
13351         if (connOutLen) {
13352             *connOutLen = len;
13353         }
13354     }
13355     if (tracef[0] != '\0') {
13356         d->trace = fopen(tracef, "a");
13357     }
13358     d->shortnames = getbool(snflag);
13359     d->longnames = getbool(lnflag);
13360     d->nocreat = getbool(ncflag);
13361     d->nowchar = getbool(nwflag);
13362     d->fksupport = getbool(fkflag);
13363     d->dobigint = getbool(biflag);
13364     d->jdconv = getbool(jdflag);
13365     d->ilike = getbool(ilflag);
13366     d->oemcp = 0;
13367     d->pwdLen = strlen(pwd);
13368     d->pwd = (d->pwdLen > 0) ? pwd : NULL;
13369     ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
13370     memset(pwd, 0, sizeof (pwd));
13371     if (ret == SQL_SUCCESS) {
13372         dbloadext(d, loadext);
13373         dbattas(d, attas);
13374     }
13375     return ret;
13376 }
13377 #endif
13378 
13385 static SQLRETURN
13386 freestmt(SQLHSTMT stmt)
13387 {
13388     STMT *s;
13389     DBC *d;
13390 
13391     if (stmt == SQL_NULL_HSTMT) {
13392         return SQL_INVALID_HANDLE;
13393     }
13394     s = (STMT *) stmt;
13395     s3stmt_drop(s);
13396     freeresult(s, 1);
13397     freep(&s->query);
13398     d = (DBC *) s->dbc;
13399     if (d && d->magic == DBC_MAGIC) {
13400         STMT *p, *n;
13401 
13402         p = NULL;
13403         n = d->stmt;
13404         while (n) {
13405             if (n == s) {
13406                 break;
13407             }
13408             p = n;
13409             n = n->next;
13410         }
13411         if (n) {
13412             if (p) {
13413                 p->next = s->next;
13414             } else {
13415                 d->stmt = s->next;
13416             }
13417         }
13418     }
13419     freeparams(s);
13420     freep(&s->bindparms);
13421     if (s->row_status0 != &s->row_status1) {
13422         freep(&s->row_status0);
13423         s->rowset_size = 1;
13424         s->row_status0 = &s->row_status1;
13425     }
13426     xfree(s);
13427     return SQL_SUCCESS;
13428 }
13429 
13437 static SQLRETURN
13438 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
13439 {
13440     DBC *d;
13441     STMT *s, *sl, *pl;
13442 
13443     if (dbc == SQL_NULL_HDBC) {
13444         return SQL_INVALID_HANDLE;
13445     }
13446     d = (DBC *) dbc;
13447     if (d->magic != DBC_MAGIC || stmt == NULL) {
13448         return SQL_INVALID_HANDLE;
13449     }
13450     s = (STMT *) xmalloc(sizeof (STMT));
13451     if (s == NULL) {
13452         *stmt = SQL_NULL_HSTMT;
13453         return SQL_ERROR;
13454     }
13455     *stmt = (SQLHSTMT) s;
13456     memset(s, 0, sizeof (STMT));
13457     s->dbc = dbc;
13458     s->ov3 = d->ov3;
13459     s->bkmrk = SQL_UB_OFF;
13460     s->bkmrkptr = 0;
13461     s->oemcp = &d->oemcp;
13462     s->jdconv = &d->jdconv;
13463     s->ilike = &d->ilike;
13464     s->nowchar[0] = d->nowchar;
13465     s->nowchar[1] = 0;
13466     s->dobigint = d->dobigint;
13467     s->curtype = d->curtype;
13468     s->row_status0 = &s->row_status1;
13469     s->rowset_size = 1;
13470     s->longnames = d->longnames;
13471     s->retr_data = SQL_RD_ON;
13472     s->max_rows = 0;
13473     s->bind_type = SQL_BIND_BY_COLUMN;
13474     s->bind_offs = NULL;
13475     s->paramset_size = 1;
13476     s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
13477     s->one_tbl = -1;
13478     s->has_pk = -1;
13479     s->has_rowid = -1;
13480 #ifdef _WIN64
13481     sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
13482 #else
13483     sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
13484 #endif
13485     sl = d->stmt;
13486     pl = NULL;
13487     while (sl) {
13488         pl = sl;
13489         sl = sl->next;
13490     }
13491     if (pl) {
13492         pl->next = s;
13493     } else {
13494         d->stmt = s;
13495     }
13496     return SQL_SUCCESS;
13497 }
13498 
13506 SQLRETURN SQL_API
13507 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
13508 {
13509     SQLRETURN ret;
13510 
13511     HDBC_LOCK(dbc);
13512     ret = drvallocstmt(dbc, stmt);
13513     HDBC_UNLOCK(dbc);
13514     return ret;
13515 }
13516 
13524 static SQLRETURN
13525 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13526 {
13527     STMT *s;
13528     SQLRETURN ret = SQL_SUCCESS;
13529     SQLHDBC dbc;
13530 
13531     if (stmt == SQL_NULL_HSTMT) {
13532         return SQL_INVALID_HANDLE;
13533     }
13534     HSTMT_LOCK(stmt);
13535     s = (STMT *) stmt;
13536     dbc = s->dbc;
13537     switch (opt) {
13538     case SQL_RESET_PARAMS:
13539         freeparams(s);
13540         break;
13541     case SQL_UNBIND:
13542         unbindcols(s);
13543         break;
13544     case SQL_CLOSE:
13545         s3stmt_end_if(s);
13546         freeresult(s, 0);
13547         break;
13548     case SQL_DROP:
13549         s3stmt_end_if(s);
13550         ret = freestmt(stmt);
13551         break;
13552     default:
13553         setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
13554         ret = SQL_ERROR;
13555         break;
13556     }
13557     HDBC_UNLOCK(dbc);
13558     return ret;
13559 }
13560 
13568 SQLRETURN SQL_API
13569 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13570 {
13571     return drvfreestmt(stmt, opt);
13572 }
13573 
13580 SQLRETURN SQL_API
13581 SQLCancel(SQLHSTMT stmt)
13582 {
13583     if (stmt != SQL_NULL_HSTMT) {
13584         DBC *d = (DBC *) ((STMT *) stmt)->dbc;
13585 #if defined(_WIN32) || defined(_WIN64)
13586         /* interrupt when other thread owns critical section */
13587         if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
13588             d->owner != 0) {
13589             d->busyint = 1;
13590             sqlite3_interrupt(d->sqlite);
13591             return SQL_SUCCESS;
13592         }
13593 #else
13594         if (d->magic == DBC_MAGIC) {
13595             d->busyint = 1;
13596             sqlite3_interrupt(d->sqlite);
13597         }
13598 #endif
13599     }
13600     return drvfreestmt(stmt, SQL_CLOSE);
13601 }
13602 
13612 static SQLRETURN
13613 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13614                  SQLSMALLINT *lenp)
13615 {
13616     STMT *s;
13617 
13618     if (stmt == SQL_NULL_HSTMT) {
13619         return SQL_INVALID_HANDLE;
13620     }
13621     s = (STMT *) stmt;
13622     if (lenp && !cursor) {
13623         *lenp = strlen((char *) s->cursorname);
13624         return SQL_SUCCESS;
13625     }
13626     if (cursor) {
13627         if (buflen > 0) {
13628             strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
13629             cursor[buflen - 1] = '\0';
13630         }
13631         if (lenp) {
13632             *lenp = min(strlen((char *) s->cursorname), buflen - 1);
13633         }
13634     }
13635     return SQL_SUCCESS;
13636 }
13637 
13638 #ifndef WINTERFACE
13639 
13648 SQLRETURN SQL_API
13649 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13650                  SQLSMALLINT *lenp)
13651 {
13652     SQLRETURN ret;
13653 #if defined(_WIN32) || defined(_WIN64)
13654     SQLSMALLINT len = 0;
13655 #endif
13656 
13657     HSTMT_LOCK(stmt);
13658 #if defined(_WIN32) || defined(_WIN64)
13659     if (!((STMT *) stmt)->oemcp[0]) {
13660         ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13661         goto done;
13662     }
13663     ret = drvgetcursorname(stmt, cursor, buflen, &len);
13664     if (ret == SQL_SUCCESS) {
13665         char *c = NULL;
13666 
13667         if (cursor) {
13668             c = utf_to_wmb((char *) cursor, len);
13669             if (!c) {
13670                 ret = nomem((STMT *) stmt);
13671                 goto done;
13672             }
13673             c[len] = 0;
13674             len = strlen(c);
13675             if (buflen > 0) {
13676                 strncpy((char *) cursor, c, buflen - 1);
13677                 cursor[buflen - 1] = 0;
13678             }
13679             uc_free(c);
13680         }
13681         if (lenp) {
13682             *lenp = min(len, buflen - 1);
13683         }
13684     }
13685 done:
13686     ;
13687 #else
13688     ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13689 #endif
13690     HSTMT_UNLOCK(stmt);
13691     return ret;
13692 }
13693 #endif
13694 
13695 #ifdef WINTERFACE
13696 
13705 SQLRETURN SQL_API
13706 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
13707                   SQLSMALLINT *lenp)
13708 {
13709     SQLRETURN ret;
13710     SQLSMALLINT len = 0;
13711 
13712     HSTMT_LOCK(stmt);
13713     ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
13714     if (ret == SQL_SUCCESS) {
13715         SQLWCHAR *c = NULL;
13716 
13717         if (cursor) {
13718             c = uc_from_utf((SQLCHAR *) cursor, len);
13719             if (!c) {
13720                 ret = nomem((STMT *) stmt);
13721                 goto done;
13722             }
13723             c[len] = 0;
13724             len = uc_strlen(c);
13725             if (buflen > 0) {
13726                 uc_strncpy(cursor, c, buflen - 1);
13727                 cursor[buflen - 1] = 0;
13728             }
13729             uc_free(c);
13730         }
13731         if (lenp) {
13732             *lenp = min(len, buflen - 1);
13733         }
13734     }
13735 done:
13736     HSTMT_UNLOCK(stmt);
13737     return ret;
13738 }
13739 #endif
13740 
13749 static SQLRETURN
13750 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13751 {
13752     STMT *s;
13753 
13754     if (stmt == SQL_NULL_HSTMT) {
13755         return SQL_INVALID_HANDLE;
13756     }
13757     s = (STMT *) stmt;
13758     if (!cursor ||
13759         !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
13760           (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
13761         setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
13762         return SQL_ERROR;
13763     }
13764     if (len == SQL_NTS) {
13765         len = sizeof (s->cursorname) - 1;
13766     } else {
13767         len = min(sizeof (s->cursorname) - 1, len);
13768     }
13769     strncpy((char *) s->cursorname, (char *) cursor, len);
13770     s->cursorname[len] = '\0';
13771     return SQL_SUCCESS;
13772 }
13773 
13774 #ifndef WINTERFACE
13775 
13783 SQLRETURN SQL_API
13784 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13785 {
13786 #if defined(_WIN32) || defined(_WIN64)
13787     char *c = NULL;
13788 #endif
13789     SQLRETURN ret;
13790 
13791     HSTMT_LOCK(stmt);
13792 #if defined(_WIN32) || defined(_WIN64)
13793     if (!((STMT *) stmt)->oemcp[0]) {
13794         ret = drvsetcursorname(stmt, cursor, len);
13795         goto done2;
13796     }
13797     if (cursor) {
13798         c = wmb_to_utf_c((char *) cursor, len);
13799         if (!c) {
13800             ret = nomem((STMT *) stmt);
13801             goto done;
13802         }
13803     }
13804     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13805 #else
13806     ret = drvsetcursorname(stmt, cursor, len);
13807 #endif
13808 #if defined(_WIN32) || defined(_WIN64)
13809 done:
13810     uc_free(c);
13811 done2:
13812     ;
13813 #endif
13814     HSTMT_UNLOCK(stmt);
13815     return ret;
13816 }
13817 #endif
13818 
13819 #ifdef WINTERFACE
13820 
13828 SQLRETURN SQL_API
13829 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
13830 {
13831     char *c = NULL;
13832     SQLRETURN ret;
13833 
13834     HSTMT_LOCK(stmt);
13835     if (cursor) {
13836         c = uc_to_utf_c(cursor, len);
13837         if (!c) {
13838             ret = nomem((STMT *) stmt);
13839             goto done;
13840         }
13841     }
13842     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13843 done:
13844     uc_free(c);
13845     HSTMT_UNLOCK(stmt);
13846     return ret;
13847 }
13848 #endif
13849 
13856 SQLRETURN SQL_API
13857 SQLCloseCursor(SQLHSTMT stmt)
13858 {
13859     return drvfreestmt(stmt, SQL_CLOSE);
13860 }
13861 
13870 SQLRETURN SQL_API
13871 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
13872 {
13873     SQLRETURN ret;
13874 
13875     switch (type) {
13876     case SQL_HANDLE_ENV:
13877         ret = drvallocenv((SQLHENV *) output);
13878         if (ret == SQL_SUCCESS) {
13879             ENV *e = (ENV *) *output;
13880 
13881             if (e && e->magic == ENV_MAGIC) {
13882                 e->ov3 = 1;
13883             }
13884         }
13885         return ret;
13886     case SQL_HANDLE_DBC:
13887         return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
13888     case SQL_HANDLE_STMT:
13889         HDBC_LOCK((SQLHDBC) input);
13890         ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
13891         HDBC_UNLOCK((SQLHDBC) input);
13892         return ret;
13893     }
13894     return SQL_ERROR;
13895 }
13896 
13904 SQLRETURN SQL_API
13905 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
13906 {
13907     switch (type) {
13908     case SQL_HANDLE_ENV:
13909         return drvfreeenv((SQLHENV) h);
13910     case SQL_HANDLE_DBC:
13911         return drvfreeconnect((SQLHDBC) h);
13912     case SQL_HANDLE_STMT:
13913         return drvfreestmt((SQLHSTMT) h, SQL_DROP);
13914     }
13915     return SQL_ERROR;
13916 }
13917 
13923 static void
13924 freedyncols(STMT *s)
13925 {
13926     if (s->dyncols) {
13927         int i;
13928 
13929         for (i = 0; i < s->dcols; i++) {
13930             freep(&s->dyncols[i].typename);
13931         }
13932         if (s->cols == s->dyncols) {
13933             s->cols = NULL;
13934             s->ncols = 0;
13935         }
13936         freep(&s->dyncols);
13937     }
13938     s->dcols = 0;
13939 }
13940 
13952 static void
13953 freeresult(STMT *s, int clrcols)
13954 {
13955     freep(&s->bincache);
13956     s->bincell = NULL;
13957     s->binlen = 0;
13958     if (s->rows) {
13959         if (s->rowfree) {
13960             s->rowfree(s->rows);
13961             s->rowfree = NULL;
13962         }
13963         s->rows = NULL;
13964     }
13965     s->nrows = -1;
13966     if (clrcols > 0) {
13967         freep(&s->bindcols);
13968         s->nbindcols = 0;
13969     }
13970     if (clrcols) {
13971         freedyncols(s);
13972         s->cols = NULL;
13973         s->ncols = 0;
13974         s->nowchar[1] = 0;
13975         s->one_tbl = -1;
13976         s->has_pk = -1;
13977         s->has_rowid = -1;
13978     }
13979 }
13980 
13986 static void
13987 unbindcols(STMT *s)
13988 {
13989     int i;
13990 
13991     for (i = 0; s->bindcols && i < s->nbindcols; i++) {
13992         s->bindcols[i].type = SQL_UNKNOWN_TYPE;
13993         s->bindcols[i].max = 0;
13994         s->bindcols[i].lenp = NULL;
13995         s->bindcols[i].valp = NULL;
13996         s->bindcols[i].index = i;
13997         s->bindcols[i].offs = 0;
13998     }
13999 }
14000 
14008 static SQLRETURN
14009 mkbindcols(STMT *s, int ncols)
14010 {
14011     if (s->bindcols) {
14012         if (s->nbindcols < ncols) {
14013             int i;
14014             BINDCOL *bindcols =
14015                 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
14016 
14017             if (!bindcols) {
14018                 return nomem(s);
14019             }
14020             for (i = s->nbindcols; i < ncols; i++) {
14021                 bindcols[i].type = SQL_UNKNOWN_TYPE;
14022                 bindcols[i].max = 0;
14023                 bindcols[i].lenp = NULL;
14024                 bindcols[i].valp = NULL;
14025                 bindcols[i].index = i;
14026                 bindcols[i].offs = 0;
14027             }
14028             s->bindcols = bindcols;
14029             s->nbindcols = ncols;
14030         }
14031     } else if (ncols > 0) {
14032         s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
14033         if (!s->bindcols) {
14034             return nomem(s);
14035         }
14036         s->nbindcols = ncols;
14037         unbindcols(s);
14038     }
14039     return SQL_SUCCESS;
14040 }
14041 
14055 static SQLRETURN
14056 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
14057            SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
14058 {
14059     char **data, valdummy[16];
14060     SQLLEN dummy;
14061     SQLINTEGER *ilenp = NULL;
14062     int valnull = 0;
14063     int type = otype;
14064     SQLRETURN sret = SQL_NO_DATA;
14065 
14066     if (!lenp) {
14067         lenp = &dummy;
14068     }
14069     /* workaround for JDK 1.7.0 on x86_64 */
14070     if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
14071         ilenp = (SQLINTEGER *) lenp;
14072         lenp = &dummy;
14073     }
14074     if (col >= s->ncols) {
14075         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14076         return SQL_ERROR;
14077     }
14078     if (s->retr_data != SQL_RD_ON) {
14079         return SQL_SUCCESS;
14080     }
14081     if (!s->rows) {
14082         *lenp = SQL_NULL_DATA;
14083         goto done;
14084     }
14085     if (s->rowp < 0 || s->rowp >= s->nrows) {
14086         *lenp = SQL_NULL_DATA;
14087         goto done;
14088     }
14089     type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
14090                       s->nowchar[0]);
14091 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14092     /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
14093     if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
14094         type = SQL_C_CHAR;
14095     }
14096 #endif
14097     data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
14098     if (!val) {
14099         valnull = 1;
14100         val = (SQLPOINTER) valdummy;
14101     }
14102     if (*data == NULL) {
14103         *lenp = SQL_NULL_DATA;
14104         switch (type) {
14105         case SQL_C_UTINYINT:
14106         case SQL_C_TINYINT:
14107         case SQL_C_STINYINT:
14108 #ifdef SQL_BIT
14109         case SQL_C_BIT:
14110 #endif
14111             *((SQLCHAR *) val) = 0;
14112             break;
14113         case SQL_C_USHORT:
14114         case SQL_C_SHORT:
14115         case SQL_C_SSHORT:
14116             *((SQLSMALLINT *) val) = 0;
14117             break;
14118         case SQL_C_ULONG:
14119         case SQL_C_LONG:
14120         case SQL_C_SLONG:
14121             *((SQLINTEGER *) val) = 0;
14122             break;
14123 #ifdef SQL_BIGINT
14124         case SQL_C_SBIGINT:
14125         case SQL_C_UBIGINT:
14126             *((SQLBIGINT *) val) = 0;
14127             break;
14128 #endif
14129         case SQL_C_FLOAT:
14130             *((float *) val) = 0;
14131             break;
14132         case SQL_C_DOUBLE:
14133             *((double *) val) = 0;
14134             break;
14135         case SQL_C_BINARY:
14136         case SQL_C_CHAR:
14137             if (len > 0) {
14138                 *((SQLCHAR *) val) = '\0';
14139             }
14140             break;
14141 #ifdef WCHARSUPPORT
14142         case SQL_C_WCHAR:
14143             if (len > 0) {
14144                 *((SQLWCHAR *) val) = '\0';
14145             }
14146             break;
14147 #endif
14148 #ifdef SQL_C_TYPE_DATE
14149         case SQL_C_TYPE_DATE:
14150 #endif
14151         case SQL_C_DATE:
14152             memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
14153             break;
14154 #ifdef SQL_C_TYPE_TIME
14155         case SQL_C_TYPE_TIME:
14156 #endif
14157         case SQL_C_TIME:
14158             memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
14159             break;
14160 #ifdef SQL_C_TYPE_TIMESTAMP
14161         case SQL_C_TYPE_TIMESTAMP:
14162 #endif
14163         case SQL_C_TIMESTAMP:
14164             memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
14165             break;
14166         default:
14167             return SQL_ERROR;
14168         }
14169     } else {
14170         char *endp = NULL;
14171 #if defined(_WIN32) || defined(_WIN64)
14172 #ifdef SQL_BIGINT
14173         char endc;
14174 #endif
14175 #endif
14176 
14177         switch (type) {
14178         case SQL_C_UTINYINT:
14179         case SQL_C_TINYINT:
14180         case SQL_C_STINYINT:
14181             *((SQLCHAR *) val) = strtol(*data, &endp, 0);
14182             if (endp && endp == *data) {
14183                 *lenp = SQL_NULL_DATA;
14184             } else {
14185                 *lenp = sizeof (SQLCHAR);
14186             }
14187             break;
14188 #ifdef SQL_BIT
14189         case SQL_C_BIT:
14190             *((SQLCHAR *) val) = getbool(*data);
14191             *lenp = sizeof (SQLCHAR);
14192             break;
14193 #endif
14194         case SQL_C_USHORT:
14195         case SQL_C_SHORT:
14196         case SQL_C_SSHORT:
14197             *((SQLSMALLINT *) val) = strtol(*data, &endp, 0);
14198             if (endp && endp == *data) {
14199                 *lenp = SQL_NULL_DATA;
14200             } else {
14201                 *lenp = sizeof (SQLSMALLINT);
14202             }
14203             break;
14204         case SQL_C_ULONG:
14205         case SQL_C_LONG:
14206         case SQL_C_SLONG:
14207             *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
14208             if (endp && endp == *data) {
14209                 *lenp = SQL_NULL_DATA;
14210             } else {
14211                 *lenp = sizeof (SQLINTEGER);
14212             }
14213             break;
14214 #ifdef SQL_BIGINT
14215         case SQL_C_UBIGINT:
14216 #if defined(_WIN32) || defined(_WIN64)
14217             if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
14218                 *lenp = SQL_NULL_DATA;
14219             } else {
14220                 *lenp = sizeof (SQLUBIGINT);
14221             }
14222 #else
14223 #ifdef __osf__
14224             *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
14225 #else
14226             *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
14227 #endif
14228             if (endp && endp == *data) {
14229                 *lenp = SQL_NULL_DATA;
14230             } else {
14231                 *lenp = sizeof (SQLUBIGINT);
14232             }
14233 #endif
14234             break;
14235         case SQL_C_SBIGINT:
14236 #if defined(_WIN32) || defined(_WIN64)
14237             if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
14238                 *lenp = SQL_NULL_DATA;
14239             } else {
14240                 *lenp = sizeof (SQLBIGINT);
14241             }
14242 #else
14243 #ifdef __osf__
14244             *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
14245 #else
14246             *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
14247 #endif
14248             if (endp && endp == *data) {
14249                 *lenp = SQL_NULL_DATA;
14250             } else {
14251                 *lenp = sizeof (SQLBIGINT);
14252             }
14253 #endif
14254             break;
14255 #endif
14256         case SQL_C_FLOAT:
14257             *((float *) val) = ln_strtod(*data, &endp);
14258             if (endp && endp == *data) {
14259                 *lenp = SQL_NULL_DATA;
14260             } else {
14261                 *lenp = sizeof (float);
14262             }
14263             break;
14264         case SQL_C_DOUBLE:
14265             *((double *) val) = ln_strtod(*data, &endp);
14266             if (endp && endp == *data) {
14267                 *lenp = SQL_NULL_DATA;
14268             } else {
14269                 *lenp = sizeof (double);
14270             }
14271             break;
14272         case SQL_C_BINARY: {
14273             int dlen, offs = 0;
14274             char *bin;
14275 
14276             if (valnull) {
14277                 freep(&s->bincache);
14278                 s->binlen = 0;
14279                 goto doCHAR;
14280             }
14281             if (*data == s->bincell) {
14282                 if (s->bincache) {
14283                     bin = s->bincache;
14284                     dlen = s->binlen;
14285                 } else {
14286                     goto doCHAR;
14287                 }
14288             } else {
14289                 char *dp;
14290                 int i;
14291 
14292                 freep(&s->bincache);
14293                 dp = *data;
14294                 dlen = strlen(dp);
14295                 s->bincell = dp;
14296                 s->binlen = 0;
14297                 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
14298                     dp[dlen - 1] != '\'') {
14299                     goto doCHAR;
14300                 }
14301                 dlen -= 2;
14302                 dp += 2;
14303                 dlen = dlen / 2;
14304                 s->bincache = bin = xmalloc(dlen + 1);
14305                 if (!bin) {
14306                     return nomem(s);
14307                 }
14308                 s->binlen = dlen;
14309                 memset(bin, 0, dlen);
14310                 bin[dlen] = '\0';       /* terminator, just in case */
14311                 for (i = 0; i < dlen; i++) {
14312                     char *x;
14313                     int v;
14314 
14315                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14316                         goto converr;
14317                     }
14318                     v = x - xdigits;
14319                     bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
14320                     ++dp;
14321                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14322 converr:
14323                         freep(&s->bincache);
14324                         s->binlen = 0;
14325                         setstat(s, -1, "conversion error",
14326                                 (*s->ov3) ? "HY000" : "S1000");
14327                         return SQL_ERROR;
14328                     }
14329                     v = x - xdigits;
14330                     bin[i] |= (v >= 16) ? (v - 6) : v;
14331                     ++dp;
14332                 }
14333                 bin = s->bincache;
14334             }
14335             if (partial && len && s->bindcols) {
14336                 if (s->bindcols[col].offs >= dlen) {
14337                     *lenp = 0;
14338                     if (!dlen && s->bindcols[col].offs == dlen) {
14339                         s->bindcols[col].offs = 1;
14340                         sret = SQL_SUCCESS;
14341                         goto done;
14342                     }
14343                     s->bindcols[col].offs = 0;
14344                     sret = SQL_NO_DATA;
14345                     goto done;
14346                 }
14347                 offs = s->bindcols[col].offs;
14348                 dlen -= offs;
14349             }
14350             if (val && len) {
14351                 memcpy(val, bin + offs, min(len, dlen));
14352             }
14353             if (len < 1) {
14354                 *lenp = dlen;
14355             } else {
14356                 *lenp = min(len, dlen);
14357                 if (*lenp == len && *lenp != dlen) {
14358                     *lenp = SQL_NO_TOTAL;
14359                 }
14360             }
14361             if (partial && len && s->bindcols) {
14362                 if (*lenp == SQL_NO_TOTAL) {
14363                     *lenp = dlen;
14364                     s->bindcols[col].offs += len;
14365                     setstat(s, -1, "data right truncated", "01004");
14366                     if (s->bindcols[col].lenp) {
14367                         *s->bindcols[col].lenp = dlen;
14368                     }
14369                     sret = SQL_SUCCESS_WITH_INFO;
14370                     goto done;
14371                 }
14372                 s->bindcols[col].offs += *lenp;
14373             }
14374             if (*lenp == SQL_NO_TOTAL) {
14375                 *lenp = dlen;
14376                 setstat(s, -1, "data right truncated", "01004");
14377                 sret = SQL_SUCCESS_WITH_INFO;
14378                 goto done;
14379             }
14380             break;
14381         }
14382         doCHAR:
14383 #ifdef WCHARSUPPORT
14384         case SQL_C_WCHAR:
14385 #endif
14386         case SQL_C_CHAR: {
14387             int doz, zlen = len - 1;
14388             int dlen = strlen(*data);
14389             int offs = 0;
14390 #ifdef WCHARSUPPORT
14391             SQLWCHAR *ucdata = NULL;
14392             SQLCHAR *cdata = (SQLCHAR *) *data;
14393 #endif
14394 
14395 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14396             /* MS Access hack part 2 (reserved error -7748) */
14397             if (!valnull &&
14398                 (s->cols == statSpec2P || s->cols == statSpec3P) &&
14399                 type == SQL_C_WCHAR) {
14400                 if (len > 0 && len <= sizeof (SQLWCHAR)) {
14401                     ((char *) val)[0] = data[0][0];
14402                     memset((char *) val + 1, 0, len - 1);
14403                     *lenp = 1;
14404                     sret = SQL_SUCCESS;
14405                     goto done;
14406                 }
14407             }
14408 #endif
14409 
14410 #ifdef WCHARSUPPORT
14411             switch (type) {
14412             case SQL_C_CHAR:
14413                 doz = 1;
14414                 break;
14415             case SQL_C_WCHAR:
14416                 doz = sizeof (SQLWCHAR);
14417                 break;
14418             default:
14419                 doz = 0;
14420                 break;
14421             }
14422             if (type == SQL_C_WCHAR) {
14423                 ucdata = uc_from_utf(cdata, dlen);
14424                 if (!ucdata) {
14425                     return nomem(s);
14426                 }
14427                 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
14428             }
14429 #if defined(_WIN32) || defined(_WIN64)
14430             else if (*s->oemcp && type == SQL_C_CHAR) {
14431                 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
14432                 if (!ucdata) {
14433                     return nomem(s);
14434                 }
14435                 cdata = (SQLCHAR *) ucdata;
14436                 dlen = strlen((char *) cdata);
14437             }
14438 #endif
14439 #else
14440             doz = (type == SQL_C_CHAR) ? 1 : 0;
14441 #endif
14442             if (partial && len && s->bindcols) {
14443                 if (s->bindcols[col].offs >= dlen) {
14444 #ifdef WCHARSUPPORT
14445                     uc_free(ucdata);
14446 #endif
14447                     *lenp = 0;
14448                     if (doz && val) {
14449 #ifdef WCHARSUPPORT
14450                         if (type == SQL_C_WCHAR) {
14451                             ((SQLWCHAR *) val)[0] = 0;
14452                         } else {
14453                             ((char *) val)[0] = '\0';
14454                         }
14455 #else
14456                         ((char *) val)[0] = '\0';
14457 #endif
14458                     }
14459                     if (!dlen && s->bindcols[col].offs == dlen) {
14460                         s->bindcols[col].offs = 1;
14461                         sret = SQL_SUCCESS;
14462                         goto done;
14463                     }
14464                     s->bindcols[col].offs = 0;
14465                     sret = SQL_NO_DATA;
14466                     goto done;
14467                 }
14468                 offs = s->bindcols[col].offs;
14469                 dlen -= offs;
14470             }
14471             if (val && !valnull && len) {
14472 #ifdef WCHARSUPPORT
14473                 if (type == SQL_C_WCHAR) {
14474                     uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
14475                                (len - doz) / sizeof (SQLWCHAR));
14476                 } else {
14477                     strncpy(val, (char *) cdata + offs, len - doz);
14478                 }
14479 #else
14480                 strncpy(val, *data + offs, len - doz);
14481 #endif
14482             }
14483             if (valnull || len < 1) {
14484                 *lenp = dlen;
14485             } else {
14486                 *lenp = min(len - doz, dlen);
14487                 if (*lenp == len - doz && *lenp != dlen) {
14488                     *lenp = SQL_NO_TOTAL;
14489                 } else if (*lenp < zlen) {
14490                     zlen = *lenp;
14491                 }
14492             }
14493             if (len && !valnull && doz) {
14494 #ifdef WCHARSUPPORT
14495                 if (type == SQL_C_WCHAR) {
14496                     ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
14497                 } else {
14498                     ((char *) val)[zlen] = '\0';
14499                 }
14500 #else
14501                 ((char *) val)[zlen] = '\0';
14502 #endif
14503             }
14504 #ifdef WCHARSUPPORT
14505             uc_free(ucdata);
14506 #endif
14507             if (partial && len && s->bindcols) {
14508                 if (*lenp == SQL_NO_TOTAL) {
14509                     *lenp = dlen;
14510                     s->bindcols[col].offs += len - doz;
14511                     setstat(s, -1, "data right truncated", "01004");
14512                     if (s->bindcols[col].lenp) {
14513                         *s->bindcols[col].lenp = dlen;
14514                     }
14515                     sret = SQL_SUCCESS_WITH_INFO;
14516                     goto done;
14517                 }
14518                 s->bindcols[col].offs += *lenp;
14519             }
14520             if (*lenp == SQL_NO_TOTAL) {
14521                 *lenp = dlen;
14522                 setstat(s, -1, "data right truncated", "01004");
14523                 sret = SQL_SUCCESS_WITH_INFO;
14524                 goto done;
14525             }
14526             break;
14527         }
14528 #ifdef SQL_C_TYPE_DATE
14529         case SQL_C_TYPE_DATE:
14530 #endif
14531         case SQL_C_DATE:
14532             if (str2date(*s->jdconv, *data, (DATE_STRUCT *) val) < 0) {
14533                 *lenp = SQL_NULL_DATA;
14534             } else {
14535                 *lenp = sizeof (DATE_STRUCT);
14536             }
14537             break;
14538 #ifdef SQL_C_TYPE_TIME
14539         case SQL_C_TYPE_TIME:
14540 #endif
14541         case SQL_C_TIME:
14542             if (str2time(*s->jdconv, *data, (TIME_STRUCT *) val) < 0) {
14543                 *lenp = SQL_NULL_DATA;
14544             } else {
14545                 *lenp = sizeof (TIME_STRUCT);
14546             }
14547             break;
14548 #ifdef SQL_C_TYPE_TIMESTAMP
14549         case SQL_C_TYPE_TIMESTAMP:
14550 #endif
14551         case SQL_C_TIMESTAMP:
14552             if (str2timestamp(*s->jdconv, *data,
14553                               (TIMESTAMP_STRUCT *) val) < 0) {
14554                 *lenp = SQL_NULL_DATA;
14555             } else {
14556                 *lenp = sizeof (TIMESTAMP_STRUCT);
14557             }
14558             switch (s->cols[col].prec) {
14559             case 0:
14560                 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
14561                 break;
14562             case 1:
14563                 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
14564                 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
14565                 break;
14566             case 2:
14567                 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
14568                 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
14569                 break;
14570             }
14571             break;
14572         default:
14573             return SQL_ERROR;
14574         }
14575     }
14576     sret = SQL_SUCCESS;
14577 done:
14578     if (ilenp) {
14579         *ilenp = *lenp;
14580     }
14581     return sret;
14582 }
14583 
14595 static SQLRETURN
14596 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14597            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14598 {
14599     STMT *s;
14600     int sz = 0;
14601 
14602     if (stmt == SQL_NULL_HSTMT) {
14603         return SQL_INVALID_HANDLE;
14604     }
14605     s = (STMT *) stmt;
14606     if (col < 1) {
14607         if (col == 0 && s->bkmrk == SQL_UB_ON &&
14608             type == SQL_C_BOOKMARK) {
14609             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14610             s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
14611             s->bkmrkcol.lenp = val ? lenp : 0;
14612             s->bkmrkcol.valp = val;
14613             s->bkmrkcol.offs = 0;
14614             if (val && lenp) {
14615                 *lenp = 0;
14616             }
14617             return SQL_SUCCESS;
14618         } else if (col == 0 && s->bkmrk == SQL_UB_VARIABLE &&
14619                    type == SQL_C_VARBOOKMARK &&
14620                    max >= sizeof (sqlite_int64)) {
14621             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14622             s->bkmrkcol.max = val ? max : 0;
14623             s->bkmrkcol.lenp = val ? lenp : 0;
14624             s->bkmrkcol.valp = val;
14625             s->bkmrkcol.offs = 0;
14626             if (val && lenp) {
14627                 *lenp = 0;
14628             }
14629             return SQL_SUCCESS;
14630         }
14631         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14632         return SQL_ERROR;
14633     }
14634     if (mkbindcols(s, col) != SQL_SUCCESS) {
14635         return SQL_ERROR;
14636     }
14637     --col;
14638     if (type == SQL_C_DEFAULT) {
14639         type = mapdeftype(type, s->cols[col].type, 0,
14640                           s->nowchar[0] || s->nowchar[1]);
14641     }
14642     switch (type) {
14643     case SQL_C_LONG:
14644     case SQL_C_ULONG:
14645     case SQL_C_SLONG:
14646         sz = sizeof (SQLINTEGER);
14647         break;
14648     case SQL_C_TINYINT:
14649     case SQL_C_UTINYINT:
14650     case SQL_C_STINYINT:
14651         sz = sizeof (SQLCHAR);
14652         break;
14653     case SQL_C_SHORT:
14654     case SQL_C_USHORT:
14655     case SQL_C_SSHORT:
14656         sz = sizeof (SQLSMALLINT);
14657         break;
14658     case SQL_C_FLOAT:
14659         sz = sizeof (SQLFLOAT);
14660         break;
14661     case SQL_C_DOUBLE:
14662         sz = sizeof (SQLDOUBLE);
14663         break;
14664     case SQL_C_TIMESTAMP:
14665         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14666         break;
14667     case SQL_C_TIME:
14668         sz = sizeof (SQL_TIME_STRUCT);
14669         break;
14670     case SQL_C_DATE:
14671         sz = sizeof (SQL_DATE_STRUCT);
14672         break;
14673     case SQL_C_CHAR:
14674         break;
14675 #ifdef WCHARSUPPORT
14676     case SQL_C_WCHAR:
14677         break;
14678 #endif
14679 #ifdef SQL_C_TYPE_DATE
14680     case SQL_C_TYPE_DATE:
14681         sz = sizeof (SQL_DATE_STRUCT);
14682         break;
14683 #endif
14684 #ifdef SQL_C_TYPE_TIME
14685     case SQL_C_TYPE_TIME:
14686         sz = sizeof (SQL_TIME_STRUCT);
14687         break;
14688 #endif
14689 #ifdef SQL_C_TYPE_TIMESTAMP
14690     case SQL_C_TYPE_TIMESTAMP:
14691         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14692         break;
14693 #endif
14694 #ifdef SQL_BIT
14695     case SQL_C_BIT:
14696         sz = sizeof (SQLCHAR);
14697         break;
14698 #endif
14699     case SQL_C_BINARY:
14700         break;
14701 #ifdef SQL_BIGINT
14702     case SQL_C_SBIGINT:
14703     case SQL_C_UBIGINT:
14704         sz = sizeof (SQLBIGINT);
14705         break;
14706 #endif
14707     default:
14708         if (val == NULL) {
14709             /* fall through, unbinding column */
14710             break;
14711         }
14712         setstat(s, -1, "invalid type %d", "HY003", type);
14713         return SQL_ERROR;
14714     }
14715     if (val == NULL) {
14716         /* unbind column */
14717         s->bindcols[col].type = SQL_UNKNOWN_TYPE;
14718         s->bindcols[col].max = 0;
14719         s->bindcols[col].lenp = NULL;
14720         s->bindcols[col].valp = NULL;
14721         s->bindcols[col].offs = 0;
14722     } else {
14723         if (sz == 0 && max < 0) {
14724             setstat(s, -1, "invalid length", "HY090");
14725             return SQL_ERROR;
14726         }
14727         s->bindcols[col].type = type;
14728         s->bindcols[col].max = (sz == 0) ? max : sz;
14729         s->bindcols[col].lenp = lenp;
14730         s->bindcols[col].valp = val;
14731         s->bindcols[col].offs = 0;
14732         if (lenp) {
14733             *lenp = 0;
14734         }
14735     }
14736     return SQL_SUCCESS;
14737 }
14738 
14750 SQLRETURN SQL_API
14751 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14752            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14753 {
14754     SQLRETURN ret;
14755 
14756     HSTMT_LOCK(stmt);
14757     ret = drvbindcol(stmt, col, type, val, max, lenp);
14758     HSTMT_UNLOCK(stmt);
14759     return ret;
14760 }
14761 
14766 static COL tableSpec2[] = {
14767     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14768     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14769     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14770     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14771     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14772 };
14773 
14774 static COL tableSpec3[] = {
14775     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14776     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14777     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14778     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14779     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14780 };
14781 
14796 static SQLRETURN
14797 drvtables(SQLHSTMT stmt,
14798           SQLCHAR *cat, SQLSMALLINT catLen,
14799           SQLCHAR *schema, SQLSMALLINT schemaLen,
14800           SQLCHAR *table, SQLSMALLINT tableLen,
14801           SQLCHAR *type, SQLSMALLINT typeLen)
14802 {
14803     SQLRETURN ret;
14804     STMT *s;
14805     DBC *d;
14806     int ncols, asize, rc, size, npatt;
14807     char *errp = NULL, *sql, tname[512];
14808     char *where = "(type = 'table' or type = 'view')";
14809 
14810     ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
14811                       tableSpec3, array_size(tableSpec3), &asize);
14812     if (ret != SQL_SUCCESS) {
14813         return ret;
14814     }
14815     s = (STMT *) stmt;
14816     d = (DBC *) s->dbc;
14817     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
14818         int size = 3 * asize;
14819 
14820         s->rows = xmalloc(size * sizeof (char *));
14821         if (!s->rows) {
14822             s->nrows = 0;
14823             return nomem(s);
14824         }
14825         memset(s->rows, 0, sizeof (char *) * size);
14826         s->ncols = asize;
14827         s->rows[s->ncols + 0] = "";
14828         s->rows[s->ncols + 1] = "";
14829         s->rows[s->ncols + 2] = "";
14830         s->rows[s->ncols + 3] = "TABLE";
14831         s->rows[s->ncols + 5] = "";
14832         s->rows[s->ncols + 6] = "";
14833         s->rows[s->ncols + 7] = "";
14834         s->rows[s->ncols + 8] = "VIEW";
14835 #ifdef MEMORY_DEBUG
14836         s->rowfree = xfree__;
14837 #else
14838         s->rowfree = sqlite3_free;
14839 #endif
14840         s->nrows = 2;
14841         s->rowp = s->rowprs = -1;
14842         return SQL_SUCCESS;
14843     }
14844     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
14845         table = NULL;
14846         goto doit;
14847     }
14848     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
14849         schema[0] == '%') {
14850         if ((!cat || catLen == 0 || !cat[0]) &&
14851             (!table || tableLen == 0 || !table[0])) {
14852             table = NULL;
14853             goto doit;
14854         }
14855     }
14856     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
14857         char tmp[256], *t;
14858         int with_view = 0, with_table = 0;
14859 
14860         if (typeLen == SQL_NTS) {
14861             strncpy(tmp, (char *) type, sizeof (tmp));
14862             tmp[sizeof (tmp) - 1] = '\0';
14863         } else {
14864             int len = min(sizeof (tmp) - 1, typeLen);
14865 
14866             strncpy(tmp, (char *) type, len);
14867             tmp[len] = '\0';
14868         }
14869         t = tmp;
14870         while (*t) {
14871             *t = TOLOWER(*t);
14872             t++;
14873         }
14874         t = tmp;
14875         unescpat(t);
14876         while (t) {
14877             if (t[0] == '\'') {
14878                 ++t;
14879             }
14880             if (strncmp(t, "table", 5) == 0) {
14881                 with_table++;
14882             } else if (strncmp(t, "view", 4) == 0) {
14883                 with_view++;
14884             }
14885             t = strchr(t, ',');
14886             if (t) {
14887                 ++t;
14888             }
14889         }
14890         if (with_view && with_table) {
14891             /* where is already preset */
14892         } else if (with_view && !with_table) {
14893             where = "type = 'view'";
14894         } else if (!with_view && with_table) {
14895             where = "type = 'table'";
14896         } else {
14897             return SQL_SUCCESS;
14898         }
14899     }
14900 doit:
14901     if (!table) {
14902         size = 1;
14903         tname[0] = '%';
14904     } else {
14905         if (tableLen == SQL_NTS) {
14906             size = sizeof (tname) - 1;
14907         } else {
14908             size = min(sizeof (tname) - 1, tableLen);
14909         }
14910         strncpy(tname, (char *) table, size);
14911     }
14912     tname[size] = '\0';
14913     npatt = unescpat(tname);
14914 #if defined(_WIN32) || defined(_WIN64)
14915     if (npatt) {
14916         sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14917                               "%s as 'TABLE_SCHEM', "
14918                               "tbl_name as 'TABLE_NAME', "
14919                               "upper(type) as 'TABLE_TYPE', "
14920                               "NULL as 'REMARKS' "
14921                               "from sqlite_master where %s "
14922                               "and tbl_name like %Q",
14923                               d->xcelqrx ? "'main'" : "NULL",
14924                               d->xcelqrx ? "''" : "NULL",
14925                               where, tname);
14926     } else {
14927         sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14928                               "%s as 'TABLE_SCHEM', "
14929                               "tbl_name as 'TABLE_NAME', "
14930                               "upper(type) as 'TABLE_TYPE', "
14931                               "NULL as 'REMARKS' "
14932                               "from sqlite_master where %s "
14933                               "and lower(tbl_name) = lower(%Q)",
14934                               d->xcelqrx ? "'main'" : "NULL",
14935                               d->xcelqrx ? "''" : "NULL",
14936                               where, tname);
14937     }
14938 #else
14939     if (npatt) {
14940         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14941                               "NULL as 'TABLE_OWNER', "
14942                               "tbl_name as 'TABLE_NAME', "
14943                               "upper(type) as 'TABLE_TYPE', "
14944                               "NULL as 'REMARKS' "
14945                               "from sqlite_master where %s "
14946                               "and tbl_name like %Q",
14947                               where, tname);
14948     } else {
14949         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14950                               "NULL as 'TABLE_OWNER', "
14951                               "tbl_name as 'TABLE_NAME', "
14952                               "upper(type) as 'TABLE_TYPE', "
14953                               "NULL as 'REMARKS' "
14954                               "from sqlite_master where %s "
14955                               "and lower(tbl_name) = lower(%Q)",
14956                               where, tname);
14957     }
14958 #endif
14959     if (!sql) {
14960         return nomem(s);
14961     }
14962     ret = starttran(s);
14963     if (ret != SQL_SUCCESS) {
14964         sqlite3_free(sql);
14965         return ret;
14966     }
14967     dbtraceapi(d, "sqlite3_get_table", sql);
14968     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
14969     sqlite3_free(sql);
14970     if (rc == SQLITE_OK) {
14971         if (ncols != s->ncols) {
14972             freeresult(s, 0);
14973             s->nrows = 0;
14974         } else {
14975             s->rowfree = sqlite3_free_table;
14976         }
14977     } else {
14978         s->nrows = 0;
14979         s->rows = NULL;
14980         s->rowfree = NULL;
14981     }
14982     if (errp) {
14983         sqlite3_free(errp);
14984         errp = NULL;
14985     }
14986     s->rowp = s->rowprs = -1;
14987     return SQL_SUCCESS;
14988 }
14989 
14990 #ifndef WINTERFACE
14991 
15005 SQLRETURN SQL_API
15006 SQLTables(SQLHSTMT stmt,
15007           SQLCHAR *cat, SQLSMALLINT catLen,
15008           SQLCHAR *schema, SQLSMALLINT schemaLen,
15009           SQLCHAR *table, SQLSMALLINT tableLen,
15010           SQLCHAR *type, SQLSMALLINT typeLen)
15011 {
15012 #if defined(_WIN32) || defined(_WIN64)
15013     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
15014 #endif
15015     SQLRETURN ret;
15016 
15017     HSTMT_LOCK(stmt);
15018 #if defined(_WIN32) || defined(_WIN64)
15019     if (!((STMT *) stmt)->oemcp[0]) {
15020         ret = drvtables(stmt, cat, catLen, schema, schemaLen,
15021                         table, tableLen, type, typeLen);
15022         goto done2;
15023     }
15024     if (cat) {
15025         c = wmb_to_utf_c((char *) cat, catLen);
15026         if (!c) {
15027             ret = nomem((STMT *) stmt);
15028             goto done;
15029         }
15030     }
15031     if (schema) {
15032         s = wmb_to_utf_c((char *) schema, schemaLen);
15033         if (!s) {
15034             ret = nomem((STMT *) stmt);
15035             goto done;
15036         }
15037     }
15038     if (table) {
15039         t = wmb_to_utf_c((char *) table, tableLen);
15040         if (!t) {
15041             ret = nomem((STMT *) stmt);
15042             goto done;
15043         }
15044     }
15045     if (type) {
15046         y = wmb_to_utf_c((char *) type, typeLen);
15047         if (!y) {
15048             ret = nomem((STMT *) stmt);
15049             goto done;
15050         }
15051     }
15052     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15053                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
15054 #else
15055     ret = drvtables(stmt, cat, catLen, schema, schemaLen,
15056                     table, tableLen, type, typeLen);
15057 #endif
15058 #if defined(_WIN32) || defined(_WIN64)
15059 done:
15060     uc_free(y);
15061     uc_free(t);
15062     uc_free(s);
15063     uc_free(c);
15064 done2:
15065     ;
15066 #endif
15067     HSTMT_UNLOCK(stmt);
15068     return ret;
15069 }
15070 #endif
15071 
15072 #ifdef WINTERFACE
15073 
15087 SQLRETURN SQL_API
15088 SQLTablesW(SQLHSTMT stmt,
15089            SQLWCHAR *cat, SQLSMALLINT catLen,
15090            SQLWCHAR *schema, SQLSMALLINT schemaLen,
15091            SQLWCHAR *table, SQLSMALLINT tableLen,
15092            SQLWCHAR *type, SQLSMALLINT typeLen)
15093 {
15094     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
15095     SQLRETURN ret;
15096 
15097     HSTMT_LOCK(stmt);
15098     if (cat) {
15099         c = uc_to_utf_c(cat, catLen);
15100         if (!c) {
15101             ret = nomem((STMT *) stmt);
15102             goto done;
15103         }
15104     }
15105     if (schema) {
15106         s = uc_to_utf_c(schema, schemaLen);
15107         if (!s) {
15108             ret = nomem((STMT *) stmt);
15109             goto done;
15110         }
15111     }
15112     if (table) {
15113         t = uc_to_utf_c(table, tableLen);
15114         if (!t) {
15115             ret = nomem((STMT *) stmt);
15116             goto done;
15117         }
15118     }
15119     if (type) {
15120         y = uc_to_utf_c(type, typeLen);
15121         if (!y) {
15122             ret = nomem((STMT *) stmt);
15123             goto done;
15124         }
15125     }
15126     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15127                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
15128 done:
15129     uc_free(y);
15130     uc_free(t);
15131     uc_free(s);
15132     uc_free(c);
15133     HSTMT_UNLOCK(stmt);
15134     return ret;
15135 }
15136 #endif
15137 
15142 static COL colSpec2[] = {
15143     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
15144     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
15145     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15146     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15147     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15148     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15149     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
15150     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
15151     { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
15152     { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
15153     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15154     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15155     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15156     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15157     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15158     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15159     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15160     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15161 };
15162 
15163 static COL colSpec3[] = {
15164     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
15165     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
15166     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15167     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15168     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15169     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15170     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
15171     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
15172     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
15173     { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
15174     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15175     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15176     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15177     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15178     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15179     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15180     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15181     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15182 };
15183 
15198 static SQLRETURN
15199 drvcolumns(SQLHSTMT stmt,
15200            SQLCHAR *cat, SQLSMALLINT catLen,
15201            SQLCHAR *schema, SQLSMALLINT schemaLen,
15202            SQLCHAR *table, SQLSMALLINT tableLen,
15203            SQLCHAR *col, SQLSMALLINT colLen)
15204 {
15205     SQLRETURN sret;
15206     STMT *s;
15207     DBC *d;
15208     int ret, nrows, ncols, asize, i, k, roffs, namec;
15209     int tnrows, tncols, npatt;
15210     PTRDIFF_T size;
15211     char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
15212 
15213     sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
15214                        colSpec3, array_size(colSpec3), &asize);
15215     if (sret != SQL_SUCCESS) {
15216         return sret;
15217     }
15218     s = (STMT *) stmt;
15219     d = (DBC *) s->dbc;
15220     if (!table) {
15221         size = 1;
15222         tname[0] = '%';
15223     } else {
15224         if (tableLen == SQL_NTS) {
15225             size = sizeof (tname) - 1;
15226         } else {
15227             size = min(sizeof (tname) - 1, tableLen);
15228         }
15229         strncpy(tname, (char *) table, size);
15230     }
15231     tname[size] = '\0';
15232     npatt = unescpat(tname);
15233     size = 0;
15234     if (col) {
15235         if (colLen == SQL_NTS) {
15236             size = sizeof (cname) - 1;
15237         } else {
15238             size = min(sizeof (cname) - 1, colLen);
15239         }
15240         strncpy(cname, (char *) col, size);
15241     }
15242     cname[size] = '\0';
15243     if (!strcmp(cname, "%")) {
15244         cname[0] = '\0';
15245     }
15246     if (npatt) {
15247         sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15248                               "(type = 'table' or type = 'view') "
15249                               "and tbl_name like %Q", tname);
15250     } else {
15251         sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15252                               "(type = 'table' or type = 'view') "
15253                               "and lower(tbl_name) = lower(%Q)", tname);
15254     }
15255     if (!sql) {
15256         return nomem(s);
15257     }
15258     sret = starttran(s);
15259     if (sret != SQL_SUCCESS) {
15260         sqlite3_free(sql);
15261         return sret;
15262     }
15263     dbtraceapi(d, "sqlite3_get_table", sql);
15264     ret = sqlite3_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
15265     sqlite3_free(sql);
15266     if (ret != SQLITE_OK) {
15267         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15268                 errp ? errp : "unknown error", ret);
15269         if (errp) {
15270             sqlite3_free(errp);
15271             errp = NULL;
15272         }
15273         return SQL_ERROR;
15274     }
15275     if (errp) {
15276         sqlite3_free(errp);
15277         errp = NULL;
15278     }
15279     /* pass 1: compute number of rows of result set */
15280     if (tncols * tnrows <= 0) {
15281         sqlite3_free_table(trows);
15282         return SQL_SUCCESS;
15283     }
15284     size = 0;
15285     for (i = 1; i <= tnrows; i++) {
15286         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15287         if (!sql) {
15288             sqlite3_free_table(trows);
15289             return nomem(s);
15290         }
15291         dbtraceapi(d, "sqlite3_get_table", sql);
15292         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15293         sqlite3_free(sql);
15294         if (ret != SQLITE_OK) {
15295             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15296                     errp ? errp : "unknown error", ret);
15297             if (errp) {
15298                 sqlite3_free(errp);
15299                 errp = NULL;
15300             }
15301             sqlite3_free_table(trows);
15302             return SQL_ERROR;
15303         }
15304         if (errp) {
15305             sqlite3_free(errp);
15306             errp = NULL;
15307         }
15308         if (ncols * nrows > 0) {
15309             namec = -1;
15310             for (k = 0; k < ncols; k++) {
15311                 if (strcmp(rowp[k], "name") == 0) {
15312                     namec = k;
15313                     break;
15314                 }
15315             }
15316             if (cname[0]) {
15317                 if (namec >= 0) {
15318                     for (k = 1; k <= nrows; k++) {
15319                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15320                             size++;
15321                         }
15322                     }
15323                 }
15324             } else {
15325                 size += nrows;
15326             }
15327         }
15328         sqlite3_free_table(rowp);
15329     }
15330     /* pass 2: fill result set */
15331     if (size <= 0) {
15332         sqlite3_free_table(trows);
15333         return SQL_SUCCESS;
15334     }
15335     s->nrows = size;
15336     size = (size + 1) * asize;
15337     s->rows = xmalloc((size + 1) * sizeof (char *));
15338     if (!s->rows) {
15339         s->nrows = 0;
15340         sqlite3_free_table(trows);
15341         return nomem(s);
15342     }
15343     s->rows[0] = (char *) size;
15344     s->rows += 1;
15345     memset(s->rows, 0, sizeof (char *) * size);
15346     s->rowfree = freerows;
15347     roffs = 1;
15348     for (i = 1; i <= tnrows; i++) {
15349         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15350         if (!sql) {
15351             sqlite3_free_table(trows);
15352             return nomem(s);
15353         }
15354         dbtraceapi(d, "sqlite3_get_table", sql);
15355         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15356         sqlite3_free(sql);
15357         if (ret != SQLITE_OK) {
15358             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15359                     errp ? errp : "unknown error", ret);
15360             if (errp) {
15361                 sqlite3_free(errp);
15362                 errp = NULL;
15363             }
15364             sqlite3_free_table(trows);
15365             return SQL_ERROR;
15366         }
15367         if (errp) {
15368             sqlite3_free(errp);
15369             errp = NULL;
15370         }
15371         if (ncols * nrows > 0) {
15372             int m, mr, nr = nrows;
15373 
15374             namec = -1;
15375             for (k = 0; k < ncols; k++) {
15376                 if (strcmp(rowp[k], "name") == 0) {
15377                     namec = k;
15378                     break;
15379                 }
15380             }
15381             if (cname[0]) {
15382                 nr = 0;
15383                 if (namec >= 0) {
15384                     for (k = 1; k <= nrows; k++) {
15385                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15386                             nr++;
15387                         }
15388                     }
15389                 }
15390             }
15391             for (k = 0; k < nr; k++) {
15392                 m = asize * (roffs + k);
15393 #if defined(_WIN32) || defined(_WIN64)
15394                 s->rows[m + 0] = xstrdup(d->xcelqrx ? "main" : "");
15395                 s->rows[m + 1] = xstrdup("");
15396 #else
15397                 s->rows[m + 0] = xstrdup("");
15398                 s->rows[m + 1] = xstrdup("");
15399 #endif
15400                 s->rows[m + 2] = xstrdup(trows[i]);
15401                 s->rows[m + 8] = xstrdup("10");
15402                 s->rows[m + 9] = xstrdup("0");
15403                 s->rows[m + 15] = xstrdup("16384");
15404             }
15405             for (k = 0; nr && k < ncols; k++) {
15406                 if (strcmp(rowp[k], "cid") == 0) {
15407                     for (mr = 0, m = 1; m <= nrows; m++) {
15408                         char buf[256];
15409                         int ir, coln = k;
15410 
15411                         if (cname[0] &&
15412                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15413                             continue;
15414                         }
15415                         ir = asize * (roffs + mr);
15416                         sscanf(rowp[m * ncols + k], "%d", &coln);
15417                         sprintf(buf, "%d", coln + 1);
15418                         s->rows[ir + 16] = xstrdup(buf);
15419                         ++mr;
15420                     }
15421                 } else if (k == namec) {
15422                     for (mr = 0, m = 1; m <= nrows; m++) {
15423                         int ir;
15424 
15425                         if (cname[0] &&
15426                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15427                             continue;
15428                         }
15429                         ir = asize * (roffs + mr);
15430                         s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
15431                         ++mr;
15432                     }
15433                 } else if (strcmp(rowp[k], "notnull") == 0) {
15434                     for (mr = 0, m = 1; m <= nrows; m++) {
15435                         int ir;
15436 
15437                         if (cname[0] &&
15438                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15439                             continue;
15440                         }
15441                         ir = asize * (roffs + mr);
15442                         if (*rowp[m * ncols + k] != '0') {
15443                             s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
15444                         } else {
15445                             s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
15446                         }
15447                         s->rows[ir + 17] =
15448                             xstrdup((*rowp[m * ncols + k] != '0') ?
15449                                     "NO" : "YES");
15450                         ++mr;
15451                     }
15452                 } else if (strcmp(rowp[k], "dflt_value") == 0) {
15453                     for (mr = 0, m = 1; m <= nrows; m++) {
15454                         char *dflt = unquote(rowp[m * ncols + k]);
15455                         int ir;
15456 
15457                         if (cname[0] &&
15458                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15459                             continue;
15460                         }
15461                         ir = asize * (roffs + mr);
15462                         s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
15463                         ++mr;
15464                     }
15465                 } else if (strcmp(rowp[k], "type") == 0) {
15466                     for (mr = 0, m = 1; m <= nrows; m++) {
15467                         char *typename = rowp[m * ncols + k];
15468                         int sqltype, mm, dd, ir;
15469                         char buf[256];
15470 
15471                         if (cname[0] &&
15472                             !namematch(rowp[m * ncols + namec], cname, 1)) {
15473                             continue;
15474                         }
15475                         ir = asize * (roffs + mr);
15476                         s->rows[ir + 5] = xstrdup(typename);
15477                         sqltype = mapsqltype(typename, NULL, *s->ov3,
15478                                              s->nowchar[0], s->dobigint);
15479                         getmd(typename, sqltype, &mm, &dd);
15480 #ifdef SQL_LONGVARCHAR
15481                         if (sqltype == SQL_VARCHAR && mm > 255) {
15482                             sqltype = SQL_LONGVARCHAR;
15483                         }
15484 #endif
15485 #ifdef WINTERFACE
15486 #ifdef SQL_WLONGVARCHAR
15487                         if (sqltype == SQL_WVARCHAR && mm > 255) {
15488                             sqltype = SQL_WLONGVARCHAR;
15489                         }
15490 #endif
15491 #endif
15492                         if (sqltype == SQL_VARBINARY && mm > 255) {
15493                             sqltype = SQL_LONGVARBINARY;
15494                         }
15495                         sprintf(buf, "%d", sqltype);
15496                         s->rows[ir + 4] = xstrdup(buf);
15497                         s->rows[ir + 13] = xstrdup(buf);
15498                         sprintf(buf, "%d", mm);
15499                         s->rows[ir + 7] = xstrdup(buf);
15500                         sprintf(buf, "%d", dd);
15501                         s->rows[ir + 6] = xstrdup(buf);
15502                         ++mr;
15503                     }
15504                 }
15505             }
15506             roffs += nr;
15507         }
15508         sqlite3_free_table(rowp);
15509     }
15510     sqlite3_free_table(trows);
15511     return SQL_SUCCESS;
15512 }
15513 
15514 #ifndef WINTERFACE
15515 
15529 SQLRETURN SQL_API
15530 SQLColumns(SQLHSTMT stmt,
15531            SQLCHAR *cat, SQLSMALLINT catLen,
15532            SQLCHAR *schema, SQLSMALLINT schemaLen,
15533            SQLCHAR *table, SQLSMALLINT tableLen,
15534            SQLCHAR *col, SQLSMALLINT colLen)
15535 {
15536 #if defined(_WIN32) || defined(_WIN64)
15537     char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15538 #endif
15539     SQLRETURN ret;
15540 
15541     HSTMT_LOCK(stmt);
15542 #if defined(_WIN32) || defined(_WIN64)
15543     if (!((STMT *) stmt)->oemcp[0]) {
15544         ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15545                          table, tableLen, col, colLen);
15546         goto done2;
15547     }
15548     if (cat) {
15549         c = wmb_to_utf_c((char *) cat, catLen);
15550         if (!c) {
15551             ret = nomem((STMT *) stmt);
15552             goto done;
15553         }
15554     }
15555     if (schema) {
15556         s = wmb_to_utf_c((char *) schema, schemaLen);
15557         if (!s) {
15558             ret = nomem((STMT *) stmt);
15559             goto done;
15560         }
15561     }
15562     if (table) {
15563         t = wmb_to_utf_c((char *) table, tableLen);
15564         if (!t) {
15565             ret = nomem((STMT *) stmt);
15566             goto done;
15567         }
15568     }
15569     if (col) {
15570         k = wmb_to_utf_c((char *) col, colLen);
15571         if (!k) {
15572             ret = nomem((STMT *) stmt);
15573             goto done;
15574         }
15575     }
15576     ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15577                      (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
15578 #else
15579     ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15580                      table, tableLen, col, colLen);
15581 #endif
15582 #if defined(_WIN32) || defined(_WIN64)
15583 done:
15584     uc_free(k);
15585     uc_free(t);
15586     uc_free(s);
15587     uc_free(c);
15588 done2:
15589     ;
15590 #endif
15591     HSTMT_UNLOCK(stmt);
15592     return ret;
15593 }
15594 #endif
15595 
15596 #ifdef WINTERFACE
15597 
15611 SQLRETURN SQL_API
15612 SQLColumnsW(SQLHSTMT stmt,
15613             SQLWCHAR *cat, SQLSMALLINT catLen,
15614             SQLWCHAR *schema, SQLSMALLINT schemaLen,
15615             SQLWCHAR *table, SQLSMALLINT tableLen,
15616             SQLWCHAR *col, SQLSMALLINT colLen)
15617 {
15618     char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15619     SQLRETURN ret;
15620 
15621     HSTMT_LOCK(stmt);
15622     if (cat) {
15623         c = uc_to_utf_c(cat, catLen);
15624         if (!c) {
15625             ret = nomem((STMT *) stmt);
15626             goto done;
15627         }
15628     }
15629     if (schema) {
15630         s = uc_to_utf_c(schema, schemaLen);
15631         if (!s) {
15632             ret = nomem((STMT *) stmt);
15633             goto done;
15634         }
15635     }
15636     if (table) {
15637         t = uc_to_utf_c(table, tableLen);
15638         if (!t) {
15639             ret = nomem((STMT *) stmt);
15640             goto done;
15641         }
15642     }
15643     if (col) {
15644         k = uc_to_utf_c(col, colLen);
15645         if (!k) {
15646             ret = nomem((STMT *) stmt);
15647             goto done;
15648         }
15649     }
15650     ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15651                      (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
15652 done:
15653     uc_free(k);
15654     uc_free(t);
15655     uc_free(s);
15656     uc_free(c);
15657     HSTMT_UNLOCK(stmt);
15658     return ret;
15659 
15660 }
15661 #endif
15662 
15667 static COL typeSpec2[] = {
15668     { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
15669     { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
15670     { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 9 },
15671     { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
15672     { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
15673     { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
15674     { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
15675     { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
15676     { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
15677     { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
15678     { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
15679     { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
15680     { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
15681     { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
15682     { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
15683 };
15684 
15685 static COL typeSpec3[] = {
15686     { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
15687     { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
15688     { "SYSTEM", "TYPE", "COLUMN_SIZE", SQL_INTEGER, 9 },
15689     { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
15690     { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
15691     { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
15692     { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
15693     { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
15694     { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
15695     { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
15696     { "SYSTEM", "TYPE", "FIXED_PREC_SCALE", SQL_SMALLINT, 2 },
15697     { "SYSTEM", "TYPE", "AUTO_UNIQUE_VALUE", SQL_SMALLINT, 2 },
15698     { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
15699     { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
15700     { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 },
15701     { "SYSTEM", "TYPE", "SQL_DATA_TYPE", SQL_SMALLINT, 2 },
15702     { "SYSTEM", "TYPE", "SQL_DATETIME_SUB", SQL_SMALLINT, 2 },
15703     { "SYSTEM", "TYPE", "NUM_PREC_RADIX", SQL_INTEGER, 4 },
15704     { "SYSTEM", "TYPE", "INTERVAL_PRECISION", SQL_SMALLINT, 2 }
15705 };
15706 
15717 static void
15718 mktypeinfo(STMT *s, int row, int asize, char *typename, int type, int tind)
15719 {
15720     int offs = row * asize;
15721     char *tcode, *crpar = NULL, *sign = stringify(SQL_FALSE);
15722     char *quote[2] = { NULL, NULL };
15723     static char tcodes[32 * 32];
15724 
15725     if (tind <= 0) {
15726         tind = row;
15727     }
15728     tcode = tcodes + tind * 32;
15729     sprintf(tcode, "%d", type);
15730     s->rows[offs + 0] = typename;
15731     s->rows[offs + 1] = tcode;
15732     if (asize >= 17) {
15733         s->rows[offs + 15] = tcode;
15734         s->rows[offs + 16] = "0";
15735     }
15736     switch (type) {
15737     default:
15738 #ifdef SQL_LONGVARCHAR
15739     case SQL_LONGVARCHAR:
15740 #ifdef WINTERFACE
15741     case SQL_WLONGVARCHAR:
15742 #endif
15743         crpar = "length";
15744         quote[0] = quote[1] = "'";
15745         sign = NULL;
15746         s->rows[offs + 2] = "65536";
15747         break;
15748 #endif
15749 #ifdef SQL_BIT
15750     case SQL_BIT:
15751         sign = NULL;
15752         s->rows[offs + 2] = "1";
15753         break;
15754 #endif
15755     case SQL_CHAR:
15756     case SQL_VARCHAR:
15757 #ifdef WINTERFACE
15758     case SQL_WCHAR:
15759     case SQL_WVARCHAR:
15760 #endif
15761         s->rows[offs + 2] = "255";
15762         crpar = "length";
15763         quote[0] = quote[1] = "'";
15764         sign = NULL;
15765         break;
15766     case SQL_TINYINT:
15767         s->rows[offs + 2] = "3";
15768         break;
15769     case SQL_SMALLINT:
15770         s->rows[offs + 2] = "5";
15771         break;
15772     case SQL_INTEGER:
15773         s->rows[offs + 2] = "9";
15774         break;
15775 #ifdef SQL_BIGINT
15776     case SQL_BIGINT:
15777         s->rows[offs + 2] = "19";
15778         break;
15779 #endif
15780     case SQL_FLOAT:
15781         s->rows[offs + 2] = "7";
15782         break;
15783     case SQL_DOUBLE:
15784         s->rows[offs + 2] = "15";
15785         break;
15786 #ifdef SQL_TYPE_DATE
15787     case SQL_TYPE_DATE:
15788 #endif
15789     case SQL_DATE:
15790         s->rows[offs + 2] = "10";
15791         quote[0] = quote[1] = "'";
15792         sign = NULL;
15793         break;
15794 #ifdef SQL_TYPE_TIME
15795     case SQL_TYPE_TIME:
15796 #endif
15797     case SQL_TIME:
15798         s->rows[offs + 2] = "8";
15799         quote[0] = quote[1] = "'";
15800         sign = NULL;
15801         break;
15802 #ifdef SQL_TYPE_TIMESTAMP
15803     case SQL_TYPE_TIMESTAMP:
15804 #endif
15805     case SQL_TIMESTAMP:
15806         s->rows[offs + 2] = "32";
15807         quote[0] = quote[1] = "'";
15808         sign = NULL;
15809         break;
15810     case SQL_VARBINARY:
15811         quote[0] = "0x";
15812         sign = NULL;
15813         s->rows[offs + 2] = "255";
15814         break;
15815     case SQL_LONGVARBINARY:
15816         quote[0] = "0x";
15817         sign = NULL;
15818         s->rows[offs + 2] = "65536";
15819         break;
15820     }
15821     s->rows[offs + 3] = quote[0];
15822     s->rows[offs + 4] = quote[1];
15823     s->rows[offs + 5] = crpar;
15824     s->rows[offs + 6] = stringify(SQL_NULLABLE);
15825     s->rows[offs + 7] = stringify(SQL_FALSE);
15826     s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
15827     s->rows[offs + 9] = sign;
15828     s->rows[offs + 10] = stringify(SQL_FALSE);
15829     s->rows[offs + 11] = stringify(SQL_FALSE);
15830     s->rows[offs + 12] = typename;
15831     switch (type) {
15832     case SQL_DATE:
15833     case SQL_TIME:
15834         s->rows[offs + 13] = "0";
15835         s->rows[offs + 14] = "0";
15836         break;
15837 #ifdef SQL_TYPE_TIMESTAMP
15838     case SQL_TYPE_TIMESTAMP:
15839 #endif
15840     case SQL_TIMESTAMP:
15841         s->rows[offs + 13] = "0";
15842         s->rows[offs + 14] = "3";
15843         break;
15844     default:
15845         s->rows[offs + 13] = NULL;
15846         s->rows[offs + 14] = NULL;
15847         break;
15848     }
15849 }
15850 
15859 static int
15860 typeinfosort(const void *a, const void *b)
15861 {
15862     char **pa = (char **) a;
15863     char **pb = (char **) b;
15864     int na, nb;
15865 
15866     na = strtol(pa[1], NULL, 0);
15867     nb = strtol(pb[1], NULL, 0);
15868     return na - nb;
15869 }
15870 
15878 static SQLRETURN
15879 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
15880 {
15881     SQLRETURN ret;
15882     STMT *s;
15883     int asize;
15884 
15885     ret = mkresultset(stmt, typeSpec2, array_size(typeSpec2),
15886                       typeSpec3, array_size(typeSpec3), &asize);
15887     if (ret != SQL_SUCCESS) {
15888         return ret;
15889     }
15890     s = (STMT *) stmt;
15891 #ifdef SQL_LONGVARCHAR
15892     s->nrows = (sqltype == SQL_ALL_TYPES) ? 13 : 1;
15893 #else
15894     s->nrows = (sqltype == SQL_ALL_TYPES) ? 12 : 1;
15895 #endif
15896     if (sqltype == SQL_ALL_TYPES) {
15897 #ifdef WINTERFACE
15898         s->nrows += 2;
15899 #ifdef SQL_WLONGVARCHAR
15900         s->nrows += 2;
15901 #endif
15902 #endif
15903     }
15904     if (sqltype == SQL_ALL_TYPES) {
15905         s->nrows += 2;
15906 #ifdef SQL_BIT
15907         s->nrows += 1;
15908 #endif
15909 #ifdef SQL_BIGINT
15910         s->nrows += 1;
15911 #endif
15912     }
15913     s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1) * asize);
15914     if (!s->rows) {
15915         s->nrows = 0;
15916         return nomem(s);
15917     }
15918 #ifdef MEMORY_DEBUG
15919     s->rowfree = xfree__;
15920 #else
15921     s->rowfree = sqlite3_free;
15922 #endif
15923     memset(s->rows, 0, sizeof (char *) * (s->nrows + 1) * asize);
15924     if (sqltype == SQL_ALL_TYPES) {
15925         int cc = 1;
15926 
15927         mktypeinfo(s, cc++, asize, "varchar", SQL_VARCHAR, 0);
15928         mktypeinfo(s, cc++, asize, "tinyint", SQL_TINYINT, 0);
15929         mktypeinfo(s, cc++, asize, "smallint", SQL_SMALLINT, 0);
15930         mktypeinfo(s, cc++, asize, "integer", SQL_INTEGER, 0);
15931         mktypeinfo(s, cc++, asize, "float", SQL_FLOAT, 0);
15932         mktypeinfo(s, cc++, asize, "double", SQL_DOUBLE, 0);
15933 #ifdef SQL_TYPE_DATE
15934         mktypeinfo(s, cc++, asize, "date",
15935                    (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
15936 #else
15937         mktypeinfo(s, cc++, asize, "date", SQL_DATE, 0);
15938 #endif
15939 #ifdef SQL_TYPE_TIME
15940         mktypeinfo(s, cc++, asize, "time",
15941                    (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
15942 #else
15943         mktypeinfo(s, cc++, asize, "time", SQL_TIME, 0);
15944 #endif
15945 #ifdef SQL_TYPE_TIMESTAMP
15946         mktypeinfo(s, cc++, asize, "timestamp",
15947                    (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
15948 #else
15949         mktypeinfo(s, cc++, asize, "timestamp", SQL_TIMESTAMP, 0);
15950 #endif
15951         mktypeinfo(s, cc++, asize, "char", SQL_CHAR, 0);
15952         mktypeinfo(s, cc++, asize, "numeric", SQL_DOUBLE, 0);
15953 #ifdef SQL_LONGVARCHAR
15954         mktypeinfo(s, cc++, asize, "text", SQL_LONGVARCHAR, 0);
15955         mktypeinfo(s, cc++, asize, "longvarchar", SQL_LONGVARCHAR, 0);
15956 #else
15957         mktypeinfo(s, cc++, asize, "text", SQL_VARCHAR, 0);
15958 #endif
15959         mktypeinfo(s, cc++, asize, "varbinary", SQL_VARBINARY, 0);
15960         mktypeinfo(s, cc++, asize, "longvarbinary", SQL_LONGVARBINARY, 0);
15961 #ifdef SQL_BIT
15962         mktypeinfo(s, cc++, asize, "bit", SQL_BIT, 0);
15963 #endif
15964 #ifdef SQL_BIGINT
15965         mktypeinfo(s, cc++, asize, "bigint", SQL_BIGINT, 0);
15966 #endif
15967 #ifdef WINTERFACE
15968         mktypeinfo(s, cc++, asize, "wvarchar", SQL_WVARCHAR, 0);
15969         mktypeinfo(s, cc++, asize, "wchar", SQL_WCHAR, 0);
15970 #ifdef SQL_WLONGVARCHAR
15971         mktypeinfo(s, cc++, asize, "wtext", SQL_WLONGVARCHAR, 0);
15972         mktypeinfo(s, cc++, asize, "longwvarchar", SQL_WLONGVARCHAR, 0);
15973 #endif
15974 #endif
15975         qsort(s->rows + asize, s->nrows, sizeof (char *) * asize,
15976               typeinfosort);
15977     } else {
15978         switch (sqltype) {
15979         case SQL_CHAR:
15980             mktypeinfo(s, 1, asize, "char", SQL_CHAR, 10);
15981             break;
15982         case SQL_VARCHAR:
15983             mktypeinfo(s, 1, asize, "varchar", SQL_VARCHAR, 1);
15984             break;
15985         case SQL_TINYINT:
15986             mktypeinfo(s, 1, asize, "tinyint", SQL_TINYINT, 2);
15987             break;
15988         case SQL_SMALLINT:
15989             mktypeinfo(s, 1, asize, "smallint", SQL_SMALLINT, 3);
15990             break;
15991         case SQL_INTEGER:
15992             mktypeinfo(s, 1, asize, "integer", SQL_INTEGER, 4);
15993             break;
15994         case SQL_FLOAT:
15995             mktypeinfo(s, 1, asize, "float", SQL_FLOAT, 5);
15996             break;
15997         case SQL_DOUBLE:
15998             mktypeinfo(s, 1, asize, "double", SQL_DOUBLE, 6);
15999             break;
16000 #ifdef SQL_TYPE_DATE
16001         case SQL_TYPE_DATE:
16002             mktypeinfo(s, 1, asize, "date", SQL_TYPE_DATE, 25);
16003             break;
16004 #endif
16005         case SQL_DATE:
16006             mktypeinfo(s, 1, asize, "date", SQL_DATE, 7);
16007             break;
16008 #ifdef SQL_TYPE_TIME
16009         case SQL_TYPE_TIME:
16010             mktypeinfo(s, 1, asize, "time", SQL_TYPE_TIME, 26);
16011             break;
16012 #endif
16013         case SQL_TIME:
16014             mktypeinfo(s, 1, asize, "time", SQL_TIME, 8);
16015             break;
16016 #ifdef SQL_TYPE_TIMESTAMP
16017         case SQL_TYPE_TIMESTAMP:
16018             mktypeinfo(s, 1, asize, "timestamp", SQL_TYPE_TIMESTAMP, 27);
16019             break;
16020 #endif
16021         case SQL_TIMESTAMP:
16022             mktypeinfo(s, 1, asize, "timestamp", SQL_TIMESTAMP, 9);
16023             break;
16024 #ifdef SQL_LONGVARCHAR
16025         case SQL_LONGVARCHAR:
16026             mktypeinfo(s, 1, asize, "longvarchar", SQL_LONGVARCHAR, 12);
16027             break;
16028 #endif
16029         case SQL_VARBINARY:
16030             mktypeinfo(s, 1, asize, "varbinary", SQL_VARBINARY, 30);
16031             break;
16032         case SQL_LONGVARBINARY:
16033             mktypeinfo(s, 1, asize, "longvarbinary", SQL_LONGVARBINARY, 31);
16034             break;
16035 #ifdef SQL_BIT
16036         case SQL_BIT:
16037             mktypeinfo(s, 1, asize, "bit", SQL_BIT, 29);
16038             break;
16039 #endif
16040 #ifdef SQL_BIGINT
16041         case SQL_BIGINT:
16042             mktypeinfo(s, 1, asize, "bigint", SQL_BIGINT, 28);
16043             break;
16044 #endif
16045 #ifdef WINTERFACE
16046 #ifdef SQL_WCHAR
16047         case SQL_WCHAR:
16048             mktypeinfo(s, 1, asize, "wchar", SQL_WCHAR, 18);
16049             break;
16050 #endif
16051 #ifdef SQL_WVARCHAR
16052         case SQL_WVARCHAR:
16053             mktypeinfo(s, 1, asize, "wvarchar", SQL_WVARCHAR, 19);
16054             break;
16055 #endif
16056 #ifdef SQL_WLONGVARCHAR
16057         case SQL_WLONGVARCHAR:
16058             mktypeinfo(s, 1, asize, "longwvarchar", SQL_WLONGVARCHAR, 20);
16059             break;
16060 #endif
16061 #endif
16062         default:
16063             s->nrows = 0;
16064         }
16065     }
16066     return SQL_SUCCESS;
16067 }
16068 
16069 #ifndef WINTERFACE
16070 
16077 SQLRETURN SQL_API
16078 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
16079 {
16080     SQLRETURN ret;
16081 
16082     HSTMT_LOCK(stmt);
16083     ret = drvgettypeinfo(stmt, sqltype);
16084     HSTMT_UNLOCK(stmt);
16085     return ret;
16086 }
16087 #endif
16088 
16089 #ifdef WINTERFACE
16090 
16097 SQLRETURN SQL_API
16098 SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
16099 {
16100     SQLRETURN ret;
16101 
16102     HSTMT_LOCK(stmt);
16103     ret = drvgettypeinfo(stmt, sqltype);
16104     HSTMT_UNLOCK(stmt);
16105     return ret;
16106 }
16107 #endif
16108 
16113 static COL statSpec2[] = {
16114     { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
16115     { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
16116     { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
16117     { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
16118     { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
16119     { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
16120     { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
16121     { "SYSTEM", "STATISTICS", "SEQ_IN_INDEX", SQL_SMALLINT, 50 },
16122     { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
16123     { "SYSTEM", "STATISTICS", "COLLATION", SCOL_CHAR, 1 },
16124     { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
16125     { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
16126     { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
16127 };
16128 
16129 static COL statSpec3[] = {
16130     { "SYSTEM", "STATISTICS", "TABLE_CAT", SCOL_VARCHAR, 50 },
16131     { "SYSTEM", "STATISTICS", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
16132     { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
16133     { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
16134     { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
16135     { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
16136     { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
16137     { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
16138     { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
16139     { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
16140     { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
16141     { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
16142     { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
16143 };
16144 
16159 static SQLRETURN
16160 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
16161               SQLCHAR *schema, SQLSMALLINT schemaLen,
16162               SQLCHAR *table, SQLSMALLINT tableLen,
16163               SQLUSMALLINT itype, SQLUSMALLINT resv)
16164 {
16165     SQLRETURN sret;
16166     STMT *s;
16167     DBC *d;
16168     int i, asize, ret, nrows, ncols, offs, namec, uniquec, addipk = 0;
16169     PTRDIFF_T size;
16170     char **rowp, *errp = NULL, *sql, tname[512];
16171 
16172     sret = mkresultset(stmt, statSpec2, array_size(statSpec2),
16173                        statSpec3, array_size(statSpec3), &asize);
16174     if (sret != SQL_SUCCESS) {
16175         return sret;
16176     }
16177     s = (STMT *) stmt;
16178     d = (DBC *) s->dbc;
16179     if (!table || table[0] == '\0' || table[0] == '%') {
16180         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
16181         return SQL_ERROR;
16182     }
16183     if (tableLen == SQL_NTS) {
16184         size = sizeof (tname) - 1;
16185     } else {
16186         size = min(sizeof (tname) - 1, tableLen);
16187     }
16188     strncpy(tname, (char *) table, size);
16189     tname[size] = '\0';
16190     unescpat(tname);
16191     sret = starttran(s);
16192     if (sret != SQL_SUCCESS) {
16193         return sret;
16194     }
16195     /*
16196      * Try integer primary key (autoincrement) first
16197      */
16198     if (itype == SQL_INDEX_UNIQUE || itype == SQL_INDEX_ALL) {
16199         rowp = 0;
16200         ret = SQLITE_ERROR;
16201         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
16202         if (sql) {
16203             dbtraceapi(d, "sqlite3_get_table", sql);
16204             ret = sqlite3_get_table(d->sqlite, sql, &rowp,
16205                                     &nrows, &ncols, NULL);
16206             sqlite3_free(sql);
16207         }
16208         if (ret == SQLITE_OK) {
16209             int colid, typec, npk = 0, npkint = 0;
16210 
16211             namec = findcol(rowp, ncols, "name");
16212             uniquec = findcol(rowp, ncols, "pk");
16213             typec = findcol(rowp, ncols, "type");
16214             colid = findcol(rowp, ncols, "cid");
16215             if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
16216                 goto noipk;
16217             }
16218             for (i = 1; i <= nrows; i++) {
16219                 if (*rowp[i * ncols + uniquec] != '0') {
16220                     npk++;
16221                     if (strlen(rowp[i * ncols + typec]) == 7 &&
16222                         strncasecmp(rowp[i * ncols + typec], "integer", 7)
16223                         == 0) {
16224                         npkint++;
16225                     }
16226                 }
16227             }
16228             if (npkint == 1 && npk == npkint) {
16229                 addipk = 1;
16230             }
16231         }
16232 noipk:
16233         sqlite3_free_table(rowp);
16234     }
16235     sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
16236     if (!sql) {
16237         return nomem(s);
16238     }
16239     dbtraceapi(d, "sqlite3_get_table", sql);
16240     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
16241     sqlite3_free(sql);
16242     if (ret != SQLITE_OK) {
16243         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
16244                 errp ? errp : "unknown error", ret);
16245         if (errp) {
16246             sqlite3_free(errp);
16247             errp = NULL;
16248         }
16249         return SQL_ERROR;
16250     }
16251     if (errp) {
16252         sqlite3_free(errp);
16253         errp = NULL;
16254     }
16255     size = 0;
16256     namec = findcol(rowp, ncols, "name");
16257     uniquec = findcol(rowp, ncols, "unique");
16258     if (namec < 0 || uniquec < 0) {
16259         goto nodata;
16260     }
16261     for (i = 1; i <= nrows; i++) {
16262         int nnrows, nncols;
16263         char **rowpp;
16264         int isuniq;
16265 
16266         isuniq = *rowp[i * ncols + uniquec] != '0';
16267         if (isuniq || itype == SQL_INDEX_ALL) {
16268             ret = SQLITE_ERROR;
16269             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
16270                                   rowp[i * ncols + namec]);
16271             if (sql) {
16272                 dbtraceapi(d, "sqlite3_get_table", sql);
16273                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16274                                         &nnrows, &nncols, NULL);
16275                 sqlite3_free(sql);
16276             }
16277             if (ret == SQLITE_OK) {
16278                 size += nnrows;
16279                 sqlite3_free_table(rowpp);
16280             }
16281         }
16282     }
16283 nodata:
16284     if (addipk) {
16285         size++;
16286     }
16287     if (size == 0) {
16288         sqlite3_free_table(rowp);
16289         return SQL_SUCCESS;
16290     }
16291     s->nrows = size;
16292     size = (size + 1) * asize;
16293     s->rows = xmalloc((size + 1) * sizeof (char *));
16294     if (!s->rows) {
16295         s->nrows = 0;
16296         return nomem(s);
16297     }
16298     s->rows[0] = (char *) size;
16299     s->rows += 1;
16300     memset(s->rows, 0, sizeof (char *) * size);
16301     s->rowfree = freerows;
16302     offs = 0;
16303     if (addipk) {
16304         char **rowpp = 0;
16305         int nrows2, ncols2;
16306 
16307         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
16308         if (sql) {
16309             dbtraceapi(d, "sqlite3_get_table", sql);
16310             ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16311                                     &nrows2, &ncols2, NULL);
16312             sqlite3_free(sql);
16313         }
16314         if (ret == SQLITE_OK) {
16315             int colid, typec, roffs, namecc, uniquecc;
16316 
16317             namecc = findcol(rowpp, ncols2, "name");
16318             uniquecc = findcol(rowpp, ncols2, "pk");
16319             typec = findcol(rowpp, ncols2, "type");
16320             colid = findcol(rowpp, ncols2, "cid");
16321             if (namecc < 0 || uniquecc < 0 || typec < 0 || colid < 0) {
16322                 addipk = 0;
16323                 s->nrows--;
16324                 goto nodata2;
16325             }
16326             for (i = 1; i <= nrows2; i++) {
16327                 if (*rowpp[i * ncols2 + uniquecc] != '0' &&
16328                     strlen(rowpp[i * ncols2 + typec]) == 7 &&
16329                     strncasecmp(rowpp[i * ncols2 + typec], "integer", 7)
16330                     == 0) {
16331                     break;
16332                 }
16333             }
16334             if (i > nrows2) {
16335                 addipk = 0;
16336                 s->nrows--;
16337                 goto nodata2;
16338             }
16339             roffs = s->ncols;
16340 #if defined(_WIN32) || defined(_WIN64)
16341             s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
16342             s->rows[roffs + 1] = xstrdup("");
16343 #else
16344             s->rows[roffs + 0] = xstrdup("");
16345             s->rows[roffs + 1] = xstrdup("");
16346 #endif
16347             s->rows[roffs + 2] = xstrdup(tname);
16348             s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
16349             s->rows[roffs + 5] = xstrdup("sqlite_autoindex_0");
16350             s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
16351             s->rows[roffs + 7] = xstrdup("1");
16352             s->rows[roffs + 8] = xstrdup(rowpp[i * ncols2 + namecc]);
16353             s->rows[roffs + 9] = xstrdup("A");
16354         }
16355 nodata2:
16356         sqlite3_free_table(rowpp);
16357     }
16358     for (i = 1; i <= nrows; i++) {
16359         int nnrows, nncols;
16360         char **rowpp = 0;
16361 
16362         if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
16363             int k;
16364 
16365             ret = SQLITE_ERROR;
16366             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
16367                                   rowp[i * ncols + namec]);
16368             if (sql) {
16369                 dbtraceapi(d, "sqlite3_get_table", sql);
16370                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16371                                         &nnrows, &nncols, NULL);
16372                 sqlite3_free(sql);
16373             }
16374             if (ret != SQLITE_OK) {
16375                 continue;
16376             }
16377             for (k = 0; nnrows && k < nncols; k++) {
16378                 if (strcmp(rowpp[k], "name") == 0) {
16379                     int m;
16380 
16381                     for (m = 1; m <= nnrows; m++) {
16382                         int roffs = (offs + addipk + m) * s->ncols;
16383                         int isuniq;
16384 
16385                         isuniq = *rowp[i * ncols + uniquec] != '0';
16386                         s->rows[roffs + 0] = xstrdup("");
16387                         s->rows[roffs + 1] = xstrdup("");
16388                         s->rows[roffs + 2] = xstrdup(tname);
16389                         if (isuniq) {
16390                             s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
16391                         } else {
16392                             s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
16393                         }
16394                         s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
16395                         s->rows[roffs + 6] =
16396                             xstrdup(stringify(SQL_INDEX_OTHER));
16397                         s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
16398                         s->rows[roffs + 9] = xstrdup("A");
16399                     }
16400                 } else if (strcmp(rowpp[k], "seqno") == 0) {
16401                     int m;
16402 
16403                     for (m = 1; m <= nnrows; m++) {
16404                         int roffs = (offs + addipk + m) * s->ncols;
16405                         int pos = m - 1;
16406                         char buf[32];
16407 
16408                         sscanf(rowpp[m * nncols + k], "%d", &pos);
16409                         sprintf(buf, "%d", pos + 1);
16410                         s->rows[roffs + 7] = xstrdup(buf);
16411                     }
16412                 }
16413             }
16414             offs += nnrows;
16415             sqlite3_free_table(rowpp);
16416         }
16417     }
16418     sqlite3_free_table(rowp);
16419     return SQL_SUCCESS;
16420 }
16421 
16422 #ifndef WINTERFACE
16423 
16437 SQLRETURN SQL_API
16438 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
16439               SQLCHAR *schema, SQLSMALLINT schemaLen,
16440               SQLCHAR *table, SQLSMALLINT tableLen,
16441               SQLUSMALLINT itype, SQLUSMALLINT resv)
16442 {
16443 #if defined(_WIN32) || defined(_WIN64)
16444     char *c = NULL, *s = NULL, *t = NULL;
16445 #endif
16446     SQLRETURN ret;
16447 
16448     HSTMT_LOCK(stmt);
16449 #if defined(_WIN32) || defined(_WIN64)
16450     if (!((STMT *) stmt)->oemcp[0]) {
16451         ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
16452                             table, tableLen, itype, resv);
16453         goto done2;
16454     }
16455     if (cat) {
16456         c = wmb_to_utf_c((char *) cat, catLen);
16457         if (!c) {
16458             ret = nomem((STMT *) stmt);
16459             goto done;
16460         }
16461     }
16462     if (schema) {
16463         s = wmb_to_utf_c((char *) schema, schemaLen);
16464         if (!s) {
16465             ret = nomem((STMT *) stmt);
16466             goto done;
16467         }
16468     }
16469     if (table) {
16470         t = wmb_to_utf_c((char *) table, tableLen);
16471         if (!t) {
16472             ret = nomem((STMT *) stmt);
16473             goto done;
16474         }
16475     }
16476     ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
16477                         (SQLCHAR *) t, SQL_NTS, itype, resv);
16478 #else
16479     ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
16480                         table, tableLen, itype, resv);
16481 #endif
16482 #if defined(_WIN32) || defined(_WIN64)
16483 done:
16484     uc_free(t);
16485     uc_free(s);
16486     uc_free(c);
16487 done2:
16488     ;
16489 #endif
16490     HSTMT_UNLOCK(stmt);
16491     return ret;
16492 }
16493 #endif
16494 
16495 #ifdef WINTERFACE
16496 
16510 SQLRETURN SQL_API
16511 SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen,
16512                SQLWCHAR *schema, SQLSMALLINT schemaLen,
16513                SQLWCHAR *table, SQLSMALLINT tableLen,
16514                SQLUSMALLINT itype, SQLUSMALLINT resv)
16515 {
16516     char *c = NULL, *s = NULL, *t = NULL;
16517     SQLRETURN ret;
16518 
16519     HSTMT_LOCK(stmt);
16520     if (cat) {
16521         c = uc_to_utf_c(cat, catLen);
16522         if (!c) {
16523             ret = nomem((STMT *) stmt);
16524             goto done;
16525         }
16526     }
16527     if (schema) {
16528         s = uc_to_utf_c(schema, schemaLen);
16529         if (!s) {
16530             ret = nomem((STMT *) stmt);
16531             goto done;
16532         }
16533     }
16534     if (table) {
16535         t = uc_to_utf_c(table, tableLen);
16536         if (!t) {
16537             ret = nomem((STMT *) stmt);
16538             goto done;
16539         }
16540     }
16541     ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
16542                         (SQLCHAR *) t, SQL_NTS, itype, resv);
16543 done:
16544     uc_free(t);
16545     uc_free(s);
16546     uc_free(c);
16547     HSTMT_UNLOCK(stmt);
16548     return ret;
16549 }
16550 #endif
16551 
16563 SQLRETURN SQL_API
16564 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
16565            SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
16566 {
16567     STMT *s;
16568     SQLRETURN ret = SQL_ERROR;
16569 
16570     HSTMT_LOCK(stmt);
16571     if (stmt == SQL_NULL_HSTMT) {
16572         return SQL_INVALID_HANDLE;
16573     }
16574     s = (STMT *) stmt;
16575     if (col == 0 && s->bkmrk != SQL_UB_OFF) {
16576         if (s->bkmrk == SQL_UB_ON && type == SQL_C_BOOKMARK) {
16577             *((SQLINTEGER *) val) = s->rowp;
16578             if (lenp) {
16579                 *lenp = sizeof (SQLINTEGER);
16580             }
16581             ret = SQL_SUCCESS;
16582             goto done;
16583         } else if (s->bkmrk == SQL_UB_VARIABLE && type == SQL_C_VARBOOKMARK) {
16584             if (s->has_rowid >= 0) {
16585                 char **data, *endp = 0;
16586 
16587                 data = s->rows + s->ncols + (s->rowp * s->ncols)
16588                      + s->has_rowid;
16589 #ifdef __osf__
16590                 *((sqlite_int64 *) val) = strtol(*data, &endp, 0);
16591 #else
16592                 *((sqlite_int64 *) val) = strtoll(*data, &endp, 0);
16593 #endif
16594             } else {
16595                 *((sqlite_int64 *) val) = s->rowp;
16596             }
16597             if (lenp) {
16598                 *lenp = sizeof (sqlite_int64);
16599             }
16600             ret = SQL_SUCCESS;
16601             goto done;
16602         }
16603     }
16604     if (col < 1 || col > s->ncols) {
16605         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
16606         goto done;
16607     }
16608     --col;
16609     ret = getrowdata(s, col, type, val, len, lenp, 1);
16610 done:
16611     HSTMT_UNLOCK(stmt);
16612     return ret;
16613 }
16614 
16622 static SQLRETURN
16623 dofetchbind(STMT *s, int rsi)
16624 {
16625     int ret, i, withinfo = 0;
16626 
16627     s->row_status0[rsi] = SQL_ROW_SUCCESS;
16628     if (s->bkmrk != SQL_UB_OFF && s->bkmrkcol.valp) {
16629         int bsize = sizeof (SQLINTEGER);
16630 
16631         if (s->bkmrkcol.type == SQL_C_VARBOOKMARK) {
16632             SQLPOINTER *val;
16633 
16634             if (s->bind_type != SQL_BIND_BY_COLUMN) {
16635                 val = (SQLPOINTER)
16636                     ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
16637             } else {
16638                 val = (SQLPOINTER)
16639                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * rsi);
16640             }
16641             if (s->bind_offs) {
16642                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
16643             }
16644             if (s->has_rowid >= 0) {
16645                 char **data, *endp = 0;
16646 
16647                 data = s->rows + s->ncols + (s->rowp * s->ncols)
16648                      + s->has_rowid;
16649 #ifdef __osf__
16650                 *(sqlite_int64 *) val = strtol(*data, &endp, 0);
16651 #else
16652                 *(sqlite_int64 *) val = strtoll(*data, &endp, 0);
16653 #endif
16654             } else {
16655                 *(sqlite_int64 *) val = s->rowp;
16656             }
16657             bsize = sizeof (sqlite_int64);
16658         } else {
16659             SQLINTEGER *val;
16660 
16661             if (s->bind_type != SQL_BIND_BY_COLUMN) {
16662                 val = (SQLINTEGER *)
16663                     ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
16664             } else {
16665                 val = (SQLINTEGER *) s->bkmrkcol.valp + rsi;
16666             }
16667             if (s->bind_offs) {
16668                 val = (SQLINTEGER *) ((char *) val + *s->bind_offs);
16669             }
16670             *val = s->rowp;
16671         }
16672         if (s->bkmrkcol.lenp) {
16673             SQLLEN *ival;
16674 
16675             if (s->bind_type != SQL_BIND_BY_COLUMN) {
16676                 ival = (SQLLEN *)
16677                     ((char *) s->bkmrkcol.lenp + s->bind_type * rsi);
16678             } else {
16679                 ival = &s->bkmrkcol.lenp[rsi];
16680             }
16681             if (s->bind_offs) {
16682                 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
16683             }
16684             *ival = bsize;
16685         }
16686     }
16687     ret = SQL_SUCCESS;
16688     for (i = 0; s->bindcols && i < s->ncols; i++) {
16689         BINDCOL *b = &s->bindcols[i];
16690         SQLPOINTER dp = 0;
16691         SQLLEN *lp = 0;
16692 
16693         b->offs = 0;
16694         if (b->valp) {
16695             if (s->bind_type != SQL_BIND_BY_COLUMN) {
16696                 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
16697             } else {
16698                 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
16699             }
16700             if (s->bind_offs) {
16701                 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
16702             }
16703         }
16704         if (b->lenp) {
16705             if (s->bind_type != SQL_BIND_BY_COLUMN) {
16706                 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
16707             } else {
16708                 lp = b->lenp + rsi;
16709             }
16710             if (s->bind_offs) {
16711                 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
16712             }
16713         }
16714         if (dp || lp) {
16715             ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
16716             if (!SQL_SUCCEEDED(ret)) {
16717                 s->row_status0[rsi] = SQL_ROW_ERROR;
16718                 break;
16719             }
16720             if (ret != SQL_SUCCESS) {
16721                 withinfo = 1;
16722 #ifdef SQL_ROW_SUCCESS_WITH_INFO
16723                 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
16724 #endif
16725             }
16726         }
16727     }
16728     if (SQL_SUCCEEDED(ret)) {
16729         ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
16730     }
16731     return ret;
16732 }
16733 
16742 static SQLRETURN
16743 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
16744 {
16745     STMT *s;
16746     int i, withinfo = 0;
16747     SQLRETURN ret;
16748 
16749     if (stmt == SQL_NULL_HSTMT) {
16750         return SQL_INVALID_HANDLE;
16751     }
16752     s = (STMT *) stmt;
16753     for (i = 0; i < s->rowset_size; i++) {
16754         s->row_status0[i] = SQL_ROW_NOROW;
16755     }
16756     if (s->row_status) {
16757         memcpy(s->row_status, s->row_status0,
16758                sizeof (SQLUSMALLINT) * s->rowset_size);
16759     }
16760     s->row_count0 = 0;
16761     if (s->row_count) {
16762         *s->row_count = s->row_count0;
16763     }
16764     if (!s->bindcols) {
16765         for (i = 0; i < s->rowset_size; i++) {
16766             s->row_status0[i] = SQL_ROW_ERROR;
16767         }
16768         ret = SQL_ERROR;
16769         i = 0;
16770         goto done2;
16771     }
16772     if (s->isselect != 1 && s->isselect != -1) {
16773         if (s->isselect != 0 || s->ncols <= 0) {
16774             setstat(s, -1, "no result set available", "24000");
16775             ret = SQL_ERROR;
16776             i = s->nrows;
16777             goto done2;
16778         } else {
16779             /* INSERT/UPDATE/DELETE ... RETURNING ... has columns */
16780         }
16781     }
16782     if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
16783         setstat(s, -1, "wrong fetch direction", "01000");
16784         ret = SQL_ERROR;
16785         i = 0;
16786         goto done2;
16787     }
16788     ret = SQL_SUCCESS;
16789     i = 0;
16790     if (((DBC *) (s->dbc))->cur_s3stmt == s && s->s3stmt) {
16791         s->rowp = s->rowprs = 0;
16792         for (; i < s->rowset_size; i++) {
16793             if (s->max_rows && s->s3stmt_rownum + 1 >= s->max_rows) {
16794                 ret = (i == 0) ? SQL_NO_DATA : SQL_SUCCESS;
16795                 break;
16796             }
16797             ret = s3stmt_step(s);
16798             if (ret != SQL_SUCCESS) {
16799                 s->row_status0[i] = SQL_ROW_ERROR;
16800                 break;
16801             }
16802             if (s->nrows < 1) {
16803                 break;
16804             }
16805             ret = dofetchbind(s, i);
16806             if (!SQL_SUCCEEDED(ret)) {
16807                 break;
16808             } else if (ret == SQL_SUCCESS_WITH_INFO) {
16809                 withinfo = 1;
16810             }
16811         }
16812     } else if (s->rows) {
16813         switch (orient) {
16814         case SQL_FETCH_NEXT:
16815             if (s->nrows < 1) {
16816                 return SQL_NO_DATA;
16817             }
16818             if (s->rowp < 0) {
16819                 s->rowp = -1;
16820             }
16821             if (s->rowp >= s->nrows) {
16822                 s->rowp = s->rowprs = s->nrows;
16823                 return SQL_NO_DATA;
16824             }
16825             break;
16826         case SQL_FETCH_PRIOR:
16827             if (s->nrows < 1 || s->rowp <= 0) {
16828                 s->rowp = s->rowprs = -1;
16829                 return SQL_NO_DATA;
16830             }
16831             s->rowp -= s->rowset_size + 1;
16832             if (s->rowp < -1) {
16833                 s->rowp = s->rowprs = -1;
16834                 return SQL_NO_DATA;
16835             }
16836             break;
16837         case SQL_FETCH_FIRST:
16838             if (s->nrows < 1) {
16839                 return SQL_NO_DATA;
16840             }
16841             s->rowp = -1;
16842             break;
16843         case SQL_FETCH_LAST:
16844             if (s->nrows < 1) {
16845                 return SQL_NO_DATA;
16846             }
16847             s->rowp = s->nrows - s->rowset_size;
16848             if (--s->rowp < -1) {
16849                 s->rowp = -1;
16850             }
16851             break;
16852         case SQL_FETCH_ABSOLUTE:
16853             if (offset == 0) {
16854                 s->rowp = s->rowprs = -1;
16855                 return SQL_NO_DATA;
16856             } else if (offset < 0) {
16857                 if (0 - offset <= s->nrows) {
16858                     s->rowp = s->nrows + offset - 1;
16859                     break;
16860                 }
16861                 s->rowp = s->rowprs = -1;
16862                 return SQL_NO_DATA;
16863             } else if (offset > s->nrows) {
16864                 s->rowp = s->rowprs = s->nrows;
16865                 return SQL_NO_DATA;
16866             }
16867             s->rowp = offset - 1 - 1;
16868             break;
16869         case SQL_FETCH_RELATIVE:
16870             if (offset >= 0) {
16871                 s->rowp += offset * s->rowset_size - 1;
16872                 if (s->rowp >= s->nrows) {
16873                     s->rowp = s->rowprs = s->nrows;
16874                     return SQL_NO_DATA;
16875                 }
16876             } else {
16877                 s->rowp += offset * s->rowset_size - 1;
16878                 if (s->rowp < -1) {
16879                     s->rowp = s->rowprs = -1;
16880                     return SQL_NO_DATA;
16881                 }
16882             }
16883             break;
16884         case SQL_FETCH_BOOKMARK:
16885             if (s->bkmrk == SQL_UB_ON && !s->bkmrkptr) {
16886                 if (offset < 0 || offset >= s->nrows) {
16887                     return SQL_NO_DATA;
16888                 }
16889                 s->rowp = offset - 1;
16890                 break;
16891             }
16892             if (s->bkmrk != SQL_UB_OFF && s->bkmrkptr) {
16893                 int rowp;
16894 
16895                 if (s->bkmrk == SQL_UB_VARIABLE) {
16896                     if (s->has_rowid >= 0) {
16897                         sqlite_int64 bkmrk, rowid;
16898 
16899                         bkmrk = *(sqlite_int64 *) s->bkmrkptr;
16900                         for (rowp = 0; rowp < s->nrows; rowp++) {
16901                             char **data, *endp = 0;
16902 
16903                             data = s->rows + s->ncols + (rowp * s->ncols)
16904                                  + s->has_rowid;
16905 #ifdef __osf__
16906                             rowid = strtol(*data, &endp, 0);
16907 #else
16908                             rowid = strtoll(*data, &endp, 0);
16909 #endif
16910                             if (rowid == bkmrk) {
16911                                 break;
16912                             }
16913                         }
16914                     } else {
16915                         rowp = *(sqlite_int64 *) s->bkmrkptr;
16916                     }
16917                 } else {
16918                     rowp = *(int *) s->bkmrkptr;
16919                 }
16920                 if (rowp + offset < 0 || rowp + offset >= s->nrows) {
16921                     return SQL_NO_DATA;
16922                 }
16923                 s->rowp = rowp + offset - 1;
16924                 break;
16925             }
16926             /* fall through */
16927         default:
16928             s->row_status0[0] = SQL_ROW_ERROR;
16929             ret = SQL_ERROR;
16930             goto done;
16931         }
16932         s->rowprs = s->rowp + 1;
16933         for (; i < s->rowset_size; i++) {
16934             ++s->rowp;
16935             if (s->rowp < 0 || s->rowp >= s->nrows) {
16936                 break;
16937             }
16938             ret = dofetchbind(s, i);
16939             if (!SQL_SUCCEEDED(ret)) {
16940                 break;
16941             } else if (ret == SQL_SUCCESS_WITH_INFO) {
16942                 withinfo = 1;
16943             }
16944         }
16945     }
16946 done:
16947     if (i == 0) {
16948         if (SQL_SUCCEEDED(ret)) {
16949             return SQL_NO_DATA;
16950         }
16951         return ret;
16952     }
16953     if (SQL_SUCCEEDED(ret)) {
16954         ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
16955     }
16956 done2:
16957     if (s->row_status) {
16958         memcpy(s->row_status, s->row_status0,
16959                sizeof (SQLUSMALLINT) * s->rowset_size);
16960     }
16961     s->row_count0 = i;
16962     if (s->row_count) {
16963         *s->row_count = s->row_count0;
16964     }
16965     return ret;
16966 }
16967 
16974 SQLRETURN SQL_API
16975 SQLFetch(SQLHSTMT stmt)
16976 {
16977     SQLRETURN ret;
16978 
16979     HSTMT_LOCK(stmt);
16980     ret = drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
16981     HSTMT_UNLOCK(stmt);
16982     return ret;
16983 }
16984 
16993 SQLRETURN SQL_API
16994 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
16995 {
16996     SQLRETURN ret;
16997 
16998     HSTMT_LOCK(stmt);
16999     ret = drvfetchscroll(stmt, orient, offset);
17000     HSTMT_UNLOCK(stmt);
17001     return ret;
17002 }
17003 
17014 SQLRETURN SQL_API
17015 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLROWOFFSET offset,
17016                  SQLROWSETSIZE *rowcount, SQLUSMALLINT *rowstatus)
17017 {
17018     STMT *s;
17019     SQLRETURN ret;
17020     SQLUSMALLINT *rst;
17021     SQLINTEGER *bkmrkptr;
17022 
17023     HSTMT_LOCK(stmt);
17024     if (stmt == SQL_NULL_HSTMT) {
17025         return SQL_INVALID_HANDLE;
17026     }
17027     s = (STMT *) stmt;
17028     /* temporarily turn off SQL_ATTR_ROW_STATUS_PTR */
17029     rst = s->row_status;
17030     s->row_status = 0;
17031     bkmrkptr = s->bkmrkptr;
17032     s->bkmrkptr = 0;
17033     ret = drvfetchscroll(stmt, orient, offset);
17034     s->row_status = rst;
17035     s->bkmrkptr = bkmrkptr;
17036     if (rowstatus) {
17037         memcpy(rowstatus, s->row_status0,
17038                sizeof (SQLUSMALLINT) * s->rowset_size);
17039     }
17040     if (rowcount) {
17041         *rowcount = s->row_count0;
17042     }
17043     HSTMT_UNLOCK(stmt);
17044     return ret;
17045 }
17046 
17054 SQLRETURN SQL_API
17055 SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
17056 {
17057     STMT *s;
17058 
17059     HSTMT_LOCK(stmt);
17060     if (stmt == SQL_NULL_HSTMT) {
17061         return SQL_INVALID_HANDLE;
17062     }
17063     s = (STMT *) stmt;
17064     if (nrows) {
17065         *nrows = s->isselect ? 0 : s->nrows;
17066     }
17067     HSTMT_UNLOCK(stmt);
17068     return SQL_SUCCESS;
17069 }
17070 
17078 SQLRETURN SQL_API
17079 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
17080 {
17081     STMT *s;
17082 
17083     HSTMT_LOCK(stmt);
17084     if (stmt == SQL_NULL_HSTMT) {
17085         return SQL_INVALID_HANDLE;
17086     }
17087     s = (STMT *) stmt;
17088     if (ncols) {
17089         *ncols = s->ncols;
17090     }
17091     HSTMT_UNLOCK(stmt);
17092     return SQL_SUCCESS;
17093 }
17094 
17109 static SQLRETURN
17110 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
17111                SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17112                SQLSMALLINT *type, SQLULEN *size,
17113                SQLSMALLINT *digits, SQLSMALLINT *nullable)
17114 {
17115     STMT *s;
17116     COL *c;
17117     int didname = 0;
17118 
17119     if (stmt == SQL_NULL_HSTMT) {
17120         return SQL_INVALID_HANDLE;
17121     }
17122     s = (STMT *) stmt;
17123     if (!s->cols) {
17124         setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
17125         return SQL_ERROR;
17126     }
17127     if (col < 1 || col > s->ncols) {
17128         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
17129         return SQL_ERROR;
17130     }
17131     c = s->cols + col - 1;
17132     if (name && nameMax > 0) {
17133         strncpy((char *) name, c->column, nameMax);
17134         name[nameMax - 1] = '\0';
17135         didname = 1;
17136     }
17137     if (nameLen) {
17138         if (didname) {
17139             *nameLen = strlen((char *) name);
17140         } else {
17141             *nameLen = strlen(c->column);
17142         }
17143     }
17144     if (type) {
17145         *type = c->type;
17146 #ifdef WINTERFACE
17147         if (s->nowchar[0] || s->nowchar[1]) {
17148             switch (c->type) {
17149             case SQL_WCHAR:
17150                 *type = SQL_CHAR;
17151                 break;
17152             case SQL_WVARCHAR:
17153                 *type = SQL_VARCHAR;
17154                 break;
17155 #ifdef SQL_LONGVARCHAR
17156             case SQL_WLONGVARCHAR:
17157                 *type = SQL_LONGVARCHAR;
17158                 break;
17159 #endif
17160             }
17161         }
17162 #endif
17163     }
17164     if (size) {
17165         *size = c->size;
17166     }
17167     if (digits) {
17168         *digits = 0;
17169     }
17170     if (nullable) {
17171         *nullable = 1;
17172     }
17173     return SQL_SUCCESS;
17174 }
17175 
17176 #ifndef WINTERFACE
17177 
17191 SQLRETURN SQL_API
17192 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
17193                SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17194                SQLSMALLINT *type, SQLULEN *size,
17195                SQLSMALLINT *digits, SQLSMALLINT *nullable)
17196 {
17197 #if defined(_WIN32) || defined(_WIN64)
17198     SQLSMALLINT len = 0;
17199 #endif
17200     SQLRETURN ret;
17201 
17202     HSTMT_LOCK(stmt);
17203 #if defined(_WIN32) || defined(_WIN64)
17204     if (!((STMT *) stmt)->oemcp[0]) {
17205         ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
17206                              type, size, digits, nullable);
17207         goto done;
17208     }
17209     ret = drvdescribecol(stmt, col, name, nameMax,
17210                          &len, type, size, digits, nullable);
17211     if (ret == SQL_SUCCESS) {
17212         if (name) {
17213             if (len > 0) {
17214                 SQLCHAR *n = NULL;
17215 
17216                 n = (SQLCHAR *) utf_to_wmb((char *) name, len);
17217                 if (n) {
17218                     strncpy((char *) name, (char *) n, nameMax);
17219                     n[len] = 0;
17220                     len = min(nameMax, strlen((char *) n));
17221                     uc_free(n);
17222                 } else {
17223                     len = 0;
17224                 }
17225             }
17226             if (len <= 0) {
17227                 len = 0;
17228                 if (nameMax > 0) {
17229                     name[0] = 0;
17230                 }
17231             }
17232         } else {
17233             STMT *s = (STMT *) stmt;
17234             COL *c = s->cols + col - 1;
17235 
17236             len = 0;
17237             if (c->column) {
17238                 len = strlen(c->column);
17239             }
17240         }
17241         if (nameLen) {
17242             *nameLen = len;
17243         }
17244     }
17245 done:
17246     ;
17247 #else
17248     ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
17249                          type, size, digits, nullable);
17250 #endif
17251     HSTMT_UNLOCK(stmt);
17252     return ret;
17253 }
17254 #endif
17255 
17256 #ifdef WINTERFACE
17257 
17271 SQLRETURN SQL_API
17272 SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name,
17273                 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17274                 SQLSMALLINT *type, SQLULEN *size,
17275                 SQLSMALLINT *digits, SQLSMALLINT *nullable)
17276 {
17277     SQLRETURN ret;
17278     SQLSMALLINT len = 0;
17279 
17280     HSTMT_LOCK(stmt);
17281     ret = drvdescribecol(stmt, col, (SQLCHAR *) name,
17282                          (SQLSMALLINT) (nameMax * sizeof (SQLWCHAR)),
17283                          &len, type, size, digits, nullable);
17284     if (ret == SQL_SUCCESS) {
17285         if (name) {
17286             if (len > 0) {
17287                 SQLWCHAR *n = NULL;
17288 
17289                 n = uc_from_utf((SQLCHAR *) name, len);
17290                 if (n) {
17291                     uc_strncpy(name, n, nameMax);
17292                     n[len] = 0;
17293                     len = min(nameMax, uc_strlen(n));
17294                     uc_free(n);
17295                 } else {
17296                     len = 0;
17297                 }
17298             }
17299             if (len <= 0) {
17300                 len = 0;
17301                 if (nameMax > 0) {
17302                     name[0] = 0;
17303                 }
17304             }
17305         } else {
17306             STMT *s = (STMT *) stmt;
17307             COL *c = s->cols + col - 1;
17308 
17309             len = 0;
17310             if (c->column) {
17311                 len = strlen(c->column);
17312             }
17313         }
17314         if (nameLen) {
17315             *nameLen = len;
17316         }
17317     }
17318     HSTMT_UNLOCK(stmt);
17319     return ret;
17320 }
17321 #endif
17322 
17335 static SQLRETURN
17336 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17337                  SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17338                  SQLLEN *val2)
17339 {
17340     STMT *s;
17341     COL *c;
17342     SQLSMALLINT dummy;
17343     char *valc = (char *) val;
17344 
17345     if (stmt == SQL_NULL_HSTMT) {
17346         return SQL_INVALID_HANDLE;
17347     }
17348     s = (STMT *) stmt;
17349     if (!s->cols) {
17350         return SQL_ERROR;
17351     }
17352     if (!valLen) {
17353         valLen = &dummy;
17354     }
17355     if (id == SQL_COLUMN_COUNT) {
17356         if (val2) {
17357             *val2 = s->ncols;
17358         }
17359         *valLen = sizeof (int);
17360         return SQL_SUCCESS;
17361     }
17362     if (id == SQL_COLUMN_TYPE && col == 0) {
17363         if (val2) {
17364             *val2 = SQL_INTEGER;
17365         }
17366         *valLen = sizeof (int);
17367         return SQL_SUCCESS;
17368     }
17369 #ifdef SQL_DESC_OCTET_LENGTH
17370     if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
17371         if (val2) {
17372             *val2 = 4;
17373         }
17374         *valLen = sizeof (int);
17375         return SQL_SUCCESS;
17376     }
17377 #endif
17378     if (col < 1 || col > s->ncols) {
17379         setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
17380         return SQL_ERROR;
17381     }
17382     c = s->cols + col - 1;
17383 
17384     switch (id) {
17385     case SQL_COLUMN_LABEL:
17386         if (c->label) {
17387             if (valc && valMax > 0) {
17388                 strncpy(valc, c->label, valMax);
17389                 valc[valMax - 1] = '\0';
17390             }
17391             *valLen = strlen(c->label);
17392             goto checkLen;
17393         }
17394         /* fall through */
17395     case SQL_COLUMN_NAME:
17396     case SQL_DESC_NAME:
17397         if (valc && valMax > 0) {
17398             strncpy(valc, c->column, valMax);
17399             valc[valMax - 1] = '\0';
17400         }
17401         *valLen = strlen(c->column);
17402 checkLen:
17403         if (*valLen >= valMax) {
17404             setstat(s, -1, "data right truncated", "01004");
17405             return SQL_SUCCESS_WITH_INFO;
17406         }
17407         return SQL_SUCCESS;
17408 #ifdef SQL_DESC_BASE_COLUMN_NAME
17409      case SQL_DESC_BASE_COLUMN_NAME:
17410         if (strchr(c->column, '(') || strchr(c->column, ')')) {
17411             if (valc && valMax > 0) {
17412                 valc[0] = '\0';
17413             }
17414             *valLen = 0;
17415         } else if (valc && valMax > 0) {
17416             strncpy(valc, c->column, valMax);
17417             valc[valMax - 1] = '\0';
17418             *valLen = strlen(c->column);
17419         }
17420         goto checkLen;
17421 #endif
17422     case SQL_COLUMN_TYPE:
17423     case SQL_DESC_TYPE:
17424 #ifdef WINTERFACE
17425         {
17426             int type = c->type;
17427 
17428             if (s->nowchar[0] || s->nowchar[1]) {
17429                 switch (type) {
17430                 case SQL_WCHAR:
17431                     type = SQL_CHAR;
17432                     break;
17433                 case SQL_WVARCHAR:
17434                     type = SQL_VARCHAR;
17435                     break;
17436 #ifdef SQL_LONGVARCHAR
17437                 case SQL_WLONGVARCHAR:
17438                     type = SQL_LONGVARCHAR;
17439                     break;
17440                 }
17441             }
17442             if (val2) {
17443                 *val2 = type;
17444             }
17445 #endif
17446         }
17447 #else
17448         if (val2) {
17449             *val2 = c->type;
17450         }
17451 #endif
17452         *valLen = sizeof (int);
17453         return SQL_SUCCESS;
17454     case SQL_COLUMN_DISPLAY_SIZE:
17455         if (val2) {
17456             *val2 = c->size;
17457         }
17458         *valLen = sizeof (int);
17459         return SQL_SUCCESS;
17460     case SQL_COLUMN_UNSIGNED:
17461         if (val2) {
17462             *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
17463         }
17464         *valLen = sizeof (int);
17465         return SQL_SUCCESS;
17466     case SQL_COLUMN_SCALE:
17467     case SQL_DESC_SCALE:
17468         if (val2) {
17469             *val2 = c->scale;
17470         }
17471         *valLen = sizeof (int);
17472         return SQL_SUCCESS;
17473     case SQL_COLUMN_PRECISION:
17474     case SQL_DESC_PRECISION:
17475         if (val2) {
17476             switch (c->type) {
17477             case SQL_SMALLINT:
17478                 *val2 = 5;
17479                 break;
17480             case SQL_INTEGER:
17481                 *val2 = 10;
17482                 break;
17483             case SQL_FLOAT:
17484             case SQL_REAL:
17485             case SQL_DOUBLE:
17486                 *val2 = 15;
17487                 break;
17488             case SQL_DATE:
17489                 *val2 = 0;
17490                 break;
17491             case SQL_TIME:
17492                 *val2 = 0;
17493                 break;
17494 #ifdef SQL_TYPE_TIMESTAMP
17495             case SQL_TYPE_TIMESTAMP:
17496 #endif
17497             case SQL_TIMESTAMP:
17498                 *val2 = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
17499                 break;
17500             default:
17501                 *val2 = c->prec;
17502                 break;
17503             }
17504         }
17505         *valLen = sizeof (int);
17506         return SQL_SUCCESS;
17507     case SQL_COLUMN_MONEY:
17508         if (val2) {
17509             *val2 = SQL_FALSE;
17510         }
17511         *valLen = sizeof (int);
17512         return SQL_SUCCESS;
17513     case SQL_COLUMN_AUTO_INCREMENT:
17514         if (val2) {
17515             *val2 = c->autoinc;
17516         }
17517         *valLen = sizeof (int);
17518         return SQL_SUCCESS;
17519     case SQL_COLUMN_LENGTH:
17520     case SQL_DESC_LENGTH:
17521         if (val2) {
17522             *val2 = c->size;
17523         }
17524         *valLen = sizeof (int);
17525         return SQL_SUCCESS;
17526     case SQL_COLUMN_NULLABLE:
17527     case SQL_DESC_NULLABLE:
17528         if (val2) {
17529             *val2 = c->notnull;
17530         }
17531         *valLen = sizeof (int);
17532         return SQL_SUCCESS;
17533     case SQL_COLUMN_SEARCHABLE:
17534         if (val2) {
17535             *val2 = SQL_SEARCHABLE;
17536         }
17537         *valLen = sizeof (int);
17538         return SQL_SUCCESS;
17539     case SQL_COLUMN_CASE_SENSITIVE:
17540         if (val2) {
17541             *val2 = SQL_TRUE;
17542         }
17543         *valLen = sizeof (int);
17544         return SQL_SUCCESS;
17545     case SQL_COLUMN_UPDATABLE:
17546         if (val2) {
17547             *val2 = SQL_TRUE;
17548         }
17549         *valLen = sizeof (int);
17550         return SQL_SUCCESS;
17551     case SQL_DESC_COUNT:
17552         if (val2) {
17553             *val2 = s->ncols;
17554         }
17555         *valLen = sizeof (int);
17556         return SQL_SUCCESS;
17557     case SQL_COLUMN_TYPE_NAME: {
17558         char *p = NULL, *tn = c->typename ? c->typename : "varchar";
17559 
17560 #ifdef WINTERFACE
17561         if (c->type == SQL_WCHAR ||
17562             c->type == SQL_WVARCHAR ||
17563             c->type == SQL_WLONGVARCHAR) {
17564             if (!(s->nowchar[0] || s->nowchar[1])) {
17565                 if (strcasecmp(tn, "varchar") == 0) {
17566                     tn = "wvarchar";
17567                 }
17568             }
17569         }
17570 #endif
17571         if (valc && valMax > 0) {
17572             strncpy(valc, tn, valMax);
17573             valc[valMax - 1] = '\0';
17574             p = strchr(valc, '(');
17575             if (p) {
17576                 *p = '\0';
17577                 while (p > valc && ISSPACE(p[-1])) {
17578                     --p;
17579                     *p = '\0';
17580                 }
17581             }
17582             *valLen = strlen(valc);
17583         } else {
17584             *valLen = strlen(tn);
17585             p = strchr(tn, '(');
17586             if (p) {
17587                 *valLen = p - tn;
17588                 while (p > tn && ISSPACE(p[-1])) {
17589                     --p;
17590                     *valLen -= 1;
17591                 }
17592             }
17593         }
17594         goto checkLen;
17595     }
17596     case SQL_COLUMN_OWNER_NAME:
17597     case SQL_COLUMN_QUALIFIER_NAME: {
17598         char *z = "";
17599 
17600         if (valc && valMax > 0) {
17601             strncpy(valc, z, valMax);
17602             valc[valMax - 1] = '\0';
17603         }
17604         *valLen = strlen(z);
17605         goto checkLen;
17606     }
17607     case SQL_COLUMN_TABLE_NAME:
17608 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17609     case SQL_DESC_TABLE_NAME:
17610 #endif
17611 #ifdef SQL_DESC_BASE_TABLE_NAME
17612     case SQL_DESC_BASE_TABLE_NAME:
17613 #endif
17614         if (valc && valMax > 0) {
17615             strncpy(valc, c->table, valMax);
17616             valc[valMax - 1] = '\0';
17617         }
17618         *valLen = strlen(c->table);
17619         goto checkLen;
17620 #ifdef SQL_DESC_NUM_PREC_RADIX
17621     case SQL_DESC_NUM_PREC_RADIX:
17622         if (val2) {
17623             switch (c->type) {
17624 #ifdef WINTERFACE
17625             case SQL_WCHAR:
17626             case SQL_WVARCHAR:
17627 #ifdef SQL_LONGVARCHAR
17628             case SQL_WLONGVARCHAR:
17629 #endif
17630 #endif
17631             case SQL_CHAR:
17632             case SQL_VARCHAR:
17633 #ifdef SQL_LONGVARCHAR
17634             case SQL_LONGVARCHAR:
17635 #endif
17636             case SQL_BINARY:
17637             case SQL_VARBINARY:
17638             case SQL_LONGVARBINARY:
17639                 *val2 = 0;
17640                 break;
17641             default:
17642                 *val2 = 2;
17643             }
17644         }
17645         *valLen = sizeof (int);
17646         return SQL_SUCCESS;
17647 #endif
17648     }
17649     setstat(s, -1, "unsupported column attributes %d", "HY091", id);
17650     return SQL_ERROR;
17651 }
17652 
17653 #ifndef WINTERFACE
17654 
17666 SQLRETURN SQL_API
17667 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17668                  SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17669                  SQLLEN *val2)
17670 {
17671 #if defined(_WIN32) || defined(_WIN64)
17672     SQLSMALLINT len = 0;
17673 #endif
17674     SQLRETURN ret;
17675 
17676     HSTMT_LOCK(stmt);
17677 #if defined(_WIN32) || defined(_WIN64)
17678     if (!((STMT *) stmt)->oemcp[0]) {
17679         ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
17680         goto done;
17681     }
17682     ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
17683     if (SQL_SUCCEEDED(ret)) {
17684         char *v = NULL;
17685 
17686         switch (id) {
17687         case SQL_COLUMN_LABEL:
17688         case SQL_COLUMN_NAME:
17689         case SQL_DESC_NAME:
17690         case SQL_COLUMN_TYPE_NAME:
17691         case SQL_COLUMN_OWNER_NAME:
17692         case SQL_COLUMN_QUALIFIER_NAME:
17693         case SQL_COLUMN_TABLE_NAME:
17694 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17695         case SQL_DESC_TABLE_NAME:
17696 #endif
17697 #ifdef SQL_DESC_BASE_COLUMN_NAME
17698         case SQL_DESC_BASE_COLUMN_NAME:
17699 #endif
17700 #ifdef SQL_DESC_BASE_TABLE_NAME
17701     case SQL_DESC_BASE_TABLE_NAME:
17702 #endif
17703             if (val && valMax > 0) {
17704                 int vmax = valMax;
17705 
17706                 v = utf_to_wmb((char *) val, SQL_NTS);
17707                 if (v) {
17708                     strncpy(val, v, vmax);
17709                     len = min(vmax, strlen(v));
17710                     uc_free(v);
17711                 }
17712                 if (vmax > 0) {
17713                     v = (char *) val;
17714                     v[vmax - 1] = '\0';
17715                 }
17716             }
17717             if (len <= 0) {
17718                 len = 0;
17719             }
17720             break;
17721         }
17722         if (valLen) {
17723             *valLen = len;
17724         }
17725     }
17726 done:
17727     ;
17728 #else
17729     ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
17730 #endif
17731     HSTMT_UNLOCK(stmt);
17732     return ret;
17733 }
17734 #endif
17735 
17736 #ifdef WINTERFACE
17737 
17749 SQLRETURN SQL_API
17750 SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17751                   SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17752                   SQLLEN *val2)
17753 {
17754     SQLRETURN ret;
17755     SQLSMALLINT len = 0;
17756 
17757     HSTMT_LOCK(stmt);
17758     ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
17759     if (SQL_SUCCEEDED(ret)) {
17760         SQLWCHAR *v = NULL;
17761 
17762         switch (id) {
17763         case SQL_COLUMN_LABEL:
17764         case SQL_COLUMN_NAME:
17765         case SQL_DESC_NAME:
17766         case SQL_COLUMN_TYPE_NAME:
17767         case SQL_COLUMN_OWNER_NAME:
17768         case SQL_COLUMN_QUALIFIER_NAME:
17769         case SQL_COLUMN_TABLE_NAME:
17770 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17771         case SQL_DESC_TABLE_NAME:
17772 #endif
17773 #ifdef SQL_DESC_BASE_COLUMN_NAME
17774         case SQL_DESC_BASE_COLUMN_NAME:
17775 #endif
17776 #ifdef SQL_DESC_BASE_TABLE_NAME
17777     case SQL_DESC_BASE_TABLE_NAME:
17778 #endif
17779             if (val && valMax > 0) {
17780                 int vmax = valMax / sizeof (SQLWCHAR);
17781 
17782                 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
17783                 if (v) {
17784                     uc_strncpy(val, v, vmax);
17785                     len = min(vmax, uc_strlen(v));
17786                     uc_free(v);
17787                     len *= sizeof (SQLWCHAR);
17788                 }
17789                 if (vmax > 0) {
17790                     v = (SQLWCHAR *) val;
17791                     v[vmax - 1] = '\0';
17792                 }
17793             }
17794             if (len <= 0) {
17795                 len = 0;
17796             }
17797             break;
17798         }
17799         if (valLen) {
17800             *valLen = len;
17801         }
17802     }
17803     HSTMT_UNLOCK(stmt);
17804     return ret;
17805 }
17806 #endif
17807 
17820 static SQLRETURN
17821 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17822                 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17823                 SQLPOINTER val2)
17824 {
17825     STMT *s;
17826     COL *c;
17827     int v = 0;
17828     char *valc = (char *) val;
17829     SQLSMALLINT dummy;
17830 
17831     if (stmt == SQL_NULL_HSTMT) {
17832         return SQL_INVALID_HANDLE;
17833     }
17834     s = (STMT *) stmt;
17835     if (!s->cols) {
17836         return SQL_ERROR;
17837     }
17838     if (col < 1 || col > s->ncols) {
17839         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
17840         return SQL_ERROR;
17841     }
17842     if (!valLen) {
17843         valLen = &dummy;
17844     }
17845     c = s->cols + col - 1;
17846     switch (id) {
17847     case SQL_DESC_COUNT:
17848         v = s->ncols;
17849         break;
17850     case SQL_DESC_CATALOG_NAME:
17851         if (valc && valMax > 0) {
17852             strncpy(valc, c->db, valMax);
17853             valc[valMax - 1] = '\0';
17854         }
17855         *valLen = strlen(c->db);
17856 checkLen:
17857         if (*valLen >= valMax) {
17858             setstat(s, -1, "data right truncated", "01004");
17859             return SQL_SUCCESS_WITH_INFO;
17860         }
17861         break;
17862     case SQL_COLUMN_LENGTH:
17863     case SQL_DESC_LENGTH:
17864         v = c->size;
17865         break;
17866     case SQL_COLUMN_LABEL:
17867         if (c->label) {
17868             if (valc && valMax > 0) {
17869                 strncpy(valc, c->label, valMax);
17870                 valc[valMax - 1] = '\0';
17871             }
17872             *valLen = strlen(c->label);
17873             goto checkLen;
17874         }
17875         /* fall through */
17876     case SQL_COLUMN_NAME:
17877     case SQL_DESC_NAME:
17878         if (valc && valMax > 0) {
17879             strncpy(valc, c->column, valMax);
17880             valc[valMax - 1] = '\0';
17881         }
17882         *valLen = strlen(c->column);
17883         goto checkLen;
17884     case SQL_DESC_SCHEMA_NAME: {
17885         char *z = "";
17886 
17887         if (valc && valMax > 0) {
17888             strncpy(valc, z, valMax);
17889             valc[valMax - 1] = '\0';
17890         }
17891         *valLen = strlen(z);
17892         goto checkLen;
17893     }
17894 #ifdef SQL_DESC_BASE_COLUMN_NAME
17895     case SQL_DESC_BASE_COLUMN_NAME:
17896         if (strchr(c->column, '(') || strchr(c->column, ')')) {
17897             valc[0] = '\0';
17898             *valLen = 0;
17899         } else if (valc && valMax > 0) {
17900             strncpy(valc, c->column, valMax);
17901             valc[valMax - 1] = '\0';
17902             *valLen = strlen(c->column);
17903         }
17904         goto checkLen;
17905 #endif
17906     case SQL_DESC_TYPE_NAME: {
17907         char *p = NULL, *tn = c->typename ? c->typename : "varchar";
17908 
17909 #ifdef WINTERFACE
17910         if (c->type == SQL_WCHAR ||
17911             c->type == SQL_WVARCHAR ||
17912             c->type == SQL_WLONGVARCHAR) {
17913             if (!(s->nowchar[0] || s->nowchar[1])) {
17914                 if (strcasecmp(tn, "varchar") == 0) {
17915                     tn = "wvarchar";
17916                 }
17917             }
17918         }
17919 #endif
17920         if (valc && valMax > 0) {
17921             strncpy(valc, tn, valMax);
17922             valc[valMax - 1] = '\0';
17923             p = strchr(valc, '(');
17924             if (p) {
17925                 *p = '\0';
17926                 while (p > valc && ISSPACE(p[-1])) {
17927                     --p;
17928                     *p = '\0';
17929                 }
17930             }
17931             *valLen = strlen(valc);
17932         } else {
17933             *valLen = strlen(tn);
17934             p = strchr(tn, '(');
17935             if (p) {
17936                 *valLen = p - tn;
17937                 while (p > tn && ISSPACE(p[-1])) {
17938                     --p;
17939                     *valLen -= 1;
17940                 }
17941             }
17942         }
17943         goto checkLen;
17944     }
17945     case SQL_DESC_OCTET_LENGTH:
17946         v = c->size;
17947 #ifdef WINTERFACE
17948         if (c->type == SQL_WCHAR ||
17949             c->type == SQL_WVARCHAR ||
17950             c->type == SQL_WLONGVARCHAR) {
17951             if (!(s->nowchar[0] || s->nowchar[1])) {
17952                 v *= sizeof (SQLWCHAR);
17953             }
17954         }
17955 #endif
17956         break;
17957 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17958     case SQL_COLUMN_TABLE_NAME:
17959 #endif
17960 #ifdef SQL_DESC_BASE_TABLE_NAME
17961     case SQL_DESC_BASE_TABLE_NAME:
17962 #endif
17963     case SQL_DESC_TABLE_NAME:
17964         if (valc && valMax > 0) {
17965             strncpy(valc, c->table, valMax);
17966             valc[valMax - 1] = '\0';
17967         }
17968         *valLen = strlen(c->table);
17969         goto checkLen;
17970     case SQL_DESC_TYPE:
17971         v = c->type;
17972 #ifdef WINTERFACE
17973         if (s->nowchar[0] || s->nowchar[1]) {
17974             switch (v) {
17975             case SQL_WCHAR:
17976                 v = SQL_CHAR;
17977                 break;
17978             case SQL_WVARCHAR:
17979                 v = SQL_VARCHAR;
17980                 break;
17981 #ifdef SQL_LONGVARCHAR
17982             case SQL_WLONGVARCHAR:
17983                 v = SQL_LONGVARCHAR;
17984                 break;
17985 #endif
17986             }
17987         }
17988 #endif
17989         break;
17990     case SQL_DESC_CONCISE_TYPE:
17991         switch (c->type) {
17992         case SQL_INTEGER:
17993             v = SQL_C_LONG;
17994             break;
17995         case SQL_TINYINT:
17996             v = SQL_C_TINYINT;
17997             break;
17998         case SQL_SMALLINT:
17999             v = SQL_C_SHORT;
18000             break;
18001         case SQL_FLOAT:
18002             v = SQL_C_FLOAT;
18003             break;
18004         case SQL_DOUBLE:
18005             v = SQL_C_DOUBLE;
18006             break;
18007         case SQL_TIMESTAMP:
18008             v = SQL_C_TIMESTAMP;
18009             break;
18010         case SQL_TIME:
18011             v = SQL_C_TIME;
18012             break;
18013         case SQL_DATE:
18014             v = SQL_C_DATE;
18015             break;
18016 #ifdef SQL_C_TYPE_TIMESTAMP
18017         case SQL_TYPE_TIMESTAMP:
18018             v = SQL_C_TYPE_TIMESTAMP;
18019             break;
18020 #endif
18021 #ifdef SQL_C_TYPE_TIME
18022         case SQL_TYPE_TIME:
18023             v = SQL_C_TYPE_TIME;
18024             break;
18025 #endif
18026 #ifdef SQL_C_TYPE_DATE
18027         case SQL_TYPE_DATE:
18028             v = SQL_C_TYPE_DATE;
18029             break;
18030 #endif
18031 #ifdef SQL_BIT
18032         case SQL_BIT:
18033             v = SQL_C_BIT;
18034             break;
18035 #endif
18036 #ifdef SQL_BIGINT
18037         case SQL_BIGINT:
18038             v = SQL_C_SBIGINT;
18039             break;
18040 #endif
18041         default:
18042 #ifdef WINTERFACE
18043             v = (s->nowchar[0] || s->nowchar[1]) ? SQL_C_CHAR : SQL_C_WCHAR;
18044 #else
18045             v = SQL_C_CHAR;
18046 #endif
18047             break;
18048         }
18049         break;
18050     case SQL_DESC_UPDATABLE:
18051         v = SQL_TRUE;
18052         break;
18053     case SQL_COLUMN_DISPLAY_SIZE:
18054         v = c->size;
18055         break;
18056     case SQL_COLUMN_UNSIGNED:
18057         v = c->nosign ? SQL_TRUE : SQL_FALSE;
18058         break;
18059     case SQL_COLUMN_SEARCHABLE:
18060         v = SQL_SEARCHABLE;
18061         break;
18062     case SQL_COLUMN_SCALE:
18063     case SQL_DESC_SCALE:
18064         v = c->scale;
18065         break;
18066     case SQL_COLUMN_PRECISION:
18067     case SQL_DESC_PRECISION:
18068         switch (c->type) {
18069         case SQL_SMALLINT:
18070             v = 5;
18071             break;
18072         case SQL_INTEGER:
18073             v = 10;
18074             break;
18075         case SQL_FLOAT:
18076         case SQL_REAL:
18077         case SQL_DOUBLE:
18078             v = 15;
18079             break;
18080         case SQL_DATE:
18081             v = 0;
18082             break;
18083         case SQL_TIME:
18084             v = 0;
18085             break;
18086 #ifdef SQL_TYPE_TIMESTAMP
18087         case SQL_TYPE_TIMESTAMP:
18088 #endif
18089         case SQL_TIMESTAMP:
18090             v = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
18091             break;
18092         default:
18093             v = c->prec;
18094             break;
18095         }
18096         break;
18097     case SQL_COLUMN_MONEY:
18098         v = SQL_FALSE;
18099         break;
18100     case SQL_COLUMN_AUTO_INCREMENT:
18101         v = c->autoinc;
18102         break;
18103     case SQL_DESC_NULLABLE:
18104         v = c->notnull;
18105         break;
18106 #ifdef SQL_DESC_NUM_PREC_RADIX
18107     case SQL_DESC_NUM_PREC_RADIX:
18108         switch (c->type) {
18109 #ifdef WINTERFACE
18110         case SQL_WCHAR:
18111         case SQL_WVARCHAR:
18112 #ifdef SQL_LONGVARCHAR
18113         case SQL_WLONGVARCHAR:
18114 #endif
18115 #endif
18116         case SQL_CHAR:
18117         case SQL_VARCHAR:
18118 #ifdef SQL_LONGVARCHAR
18119         case SQL_LONGVARCHAR:
18120 #endif
18121         case SQL_BINARY:
18122         case SQL_VARBINARY:
18123         case SQL_LONGVARBINARY:
18124             v = 0;
18125             break;
18126         default:
18127             v = 2;
18128         }
18129         break;
18130 #endif
18131     default:
18132         setstat(s, -1, "unsupported column attribute %d", "HY091", id);
18133         return SQL_ERROR;
18134     }
18135     if (val2) {
18136         *(SQLLEN *) val2 = v;
18137     }
18138     return SQL_SUCCESS;
18139 }
18140 
18141 #ifndef WINTERFACE
18142 
18154 SQLRETURN SQL_API
18155 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
18156                 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
18157                 COLATTRIBUTE_LAST_ARG_TYPE val2)
18158 {
18159 #if defined(_WIN32) || defined(_WIN64)
18160     SQLSMALLINT len = 0;
18161 #endif
18162     SQLRETURN ret;
18163 
18164     HSTMT_LOCK(stmt);
18165 #if defined(_WIN32) || defined(_WIN64)
18166     if (!((STMT *) stmt)->oemcp[0]) {
18167         ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
18168                               (SQLPOINTER) val2);
18169         goto done;
18170     }
18171     ret = drvcolattribute(stmt, col, id, val, valMax, &len,
18172                           (SQLPOINTER) val2);
18173     if (SQL_SUCCEEDED(ret)) {
18174         char *v = NULL;
18175 
18176         switch (id) {
18177         case SQL_DESC_SCHEMA_NAME:
18178         case SQL_DESC_CATALOG_NAME:
18179         case SQL_COLUMN_LABEL:
18180         case SQL_DESC_NAME:
18181         case SQL_DESC_TABLE_NAME:
18182 #ifdef SQL_DESC_BASE_TABLE_NAME
18183         case SQL_DESC_BASE_TABLE_NAME:
18184 #endif
18185 #ifdef SQL_DESC_BASE_COLUMN_NAME
18186         case SQL_DESC_BASE_COLUMN_NAME:
18187 #endif
18188         case SQL_DESC_TYPE_NAME:
18189             if (val && valMax > 0) {
18190                 int vmax = valMax;
18191 
18192                 v = utf_to_wmb((char *) val, SQL_NTS);
18193                 if (v) {
18194                     strncpy(val, v, vmax);
18195                     len = min(vmax, strlen(v));
18196                     uc_free(v);
18197                 }
18198                 if (vmax > 0) {
18199                     v = (char *) val;
18200                     v[vmax - 1] = '\0';
18201                 }
18202             }
18203             if (len <= 0) {
18204                 len = 0;
18205             }
18206             break;
18207         }
18208         if (valLen) {
18209             *valLen = len;
18210         }
18211     }
18212 done:
18213     ;
18214 #else
18215     ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
18216                           (SQLPOINTER) val2);
18217 #endif
18218     HSTMT_UNLOCK(stmt);
18219     return ret;
18220 }
18221 #endif
18222 
18223 #ifdef WINTERFACE
18224 
18236 SQLRETURN SQL_API
18237 SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
18238                  SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
18239                  COLATTRIBUTE_LAST_ARG_TYPE val2)
18240 {
18241     SQLRETURN ret;
18242     SQLSMALLINT len = 0;
18243 
18244     HSTMT_LOCK(stmt);
18245     ret = drvcolattribute(stmt, col, id, val, valMax, &len,
18246                           (SQLPOINTER) val2);
18247     if (SQL_SUCCEEDED(ret)) {
18248         SQLWCHAR *v = NULL;
18249 
18250         switch (id) {
18251         case SQL_DESC_SCHEMA_NAME:
18252         case SQL_DESC_CATALOG_NAME:
18253         case SQL_COLUMN_LABEL:
18254         case SQL_DESC_NAME:
18255         case SQL_DESC_TABLE_NAME:
18256 #ifdef SQL_DESC_BASE_TABLE_NAME
18257         case SQL_DESC_BASE_TABLE_NAME:
18258 #endif
18259 #ifdef SQL_DESC_BASE_COLUMN_NAME
18260         case SQL_DESC_BASE_COLUMN_NAME:
18261 #endif
18262         case SQL_DESC_TYPE_NAME:
18263             if (val && valMax > 0) {
18264                 int vmax = valMax / sizeof (SQLWCHAR);
18265 
18266                 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
18267                 if (v) {
18268                     uc_strncpy(val, v, vmax);
18269                     len = min(vmax, uc_strlen(v));
18270                     uc_free(v);
18271                     len *= sizeof (SQLWCHAR);
18272                 }
18273                 if (vmax > 0) {
18274                     v = (SQLWCHAR *) val;
18275                     v[vmax - 1] = '\0';
18276                 }
18277             }
18278             if (len <= 0) {
18279                 len = 0;
18280             }
18281             break;
18282         }
18283         if (valLen) {
18284             *valLen = len;
18285         }
18286     }
18287     HSTMT_UNLOCK(stmt);
18288     return ret;
18289 }
18290 #endif
18291 
18305 static SQLRETURN
18306 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18307          SQLCHAR *sqlState, SQLINTEGER *nativeErr,
18308          SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18309 {
18310     SQLCHAR dummy0[6];
18311     SQLINTEGER dummy1;
18312     SQLSMALLINT dummy2;
18313 
18314     if (env == SQL_NULL_HENV &&
18315         dbc == SQL_NULL_HDBC &&
18316         stmt == SQL_NULL_HSTMT) {
18317         return SQL_INVALID_HANDLE;
18318     }
18319     if (sqlState) {
18320         sqlState[0] = '\0';
18321     } else {
18322         sqlState = dummy0;
18323     }
18324     if (!nativeErr) {
18325         nativeErr = &dummy1;
18326     }
18327     *nativeErr = 0;
18328     if (!errlen) {
18329         errlen = &dummy2;
18330     }
18331     *errlen = 0;
18332     if (errmsg) {
18333         if (errmax > 0) {
18334             errmsg[0] = '\0';
18335         }
18336     } else {
18337         errmsg = dummy0;
18338         errmax = 0;
18339     }
18340     if (stmt) {
18341         STMT *s = (STMT *) stmt;
18342 
18343         HSTMT_LOCK(stmt);
18344         if (s->logmsg[0] == '\0') {
18345             HSTMT_UNLOCK(stmt);
18346             goto noerr;
18347         }
18348         *nativeErr = s->naterr;
18349         strcpy((char *) sqlState, s->sqlstate);
18350         if (errmax == SQL_NTS) {
18351             strcpy((char *) errmsg, "[SQLite]");
18352             strcat((char *) errmsg, (char *) s->logmsg);
18353             *errlen = strlen((char *) errmsg);
18354         } else {
18355             strncpy((char *) errmsg, "[SQLite]", errmax);
18356             if (errmax - 8 > 0) {
18357                 strncpy((char *) errmsg + 8, (char *) s->logmsg, errmax - 8);
18358             }
18359             *errlen = min(strlen((char *) s->logmsg) + 8, errmax);
18360         }
18361         s->logmsg[0] = '\0';
18362         HSTMT_UNLOCK(stmt);
18363         return SQL_SUCCESS;
18364     }
18365     if (dbc) {
18366         DBC *d = (DBC *) dbc;
18367 
18368         HDBC_LOCK(dbc);
18369         if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
18370             HDBC_UNLOCK(dbc);
18371             goto noerr;
18372         }
18373         *nativeErr = d->naterr;
18374         strcpy((char *) sqlState, d->sqlstate);
18375         if (errmax == SQL_NTS) {
18376             strcpy((char *) errmsg, "[SQLite]");
18377             strcat((char *) errmsg, (char *) d->logmsg);
18378             *errlen = strlen((char *) errmsg);
18379         } else {
18380             strncpy((char *) errmsg, "[SQLite]", errmax);
18381             if (errmax - 8 > 0) {
18382                 strncpy((char *) errmsg + 8, (char *) d->logmsg, errmax - 8);
18383             }
18384             *errlen = min(strlen((char *) d->logmsg) + 8, errmax);
18385         }
18386         d->logmsg[0] = '\0';
18387         HDBC_UNLOCK(dbc);
18388         return SQL_SUCCESS;
18389     }
18390 noerr:
18391     sqlState[0] = '\0';
18392     errmsg[0] = '\0';
18393     *nativeErr = 0;
18394     *errlen = 0;
18395     return SQL_NO_DATA;
18396 }
18397 
18398 #ifndef WINTERFACE
18399 
18412 SQLRETURN SQL_API
18413 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18414          SQLCHAR *sqlState, SQLINTEGER *nativeErr,
18415          SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18416 {
18417     return drverror(env, dbc, stmt, sqlState, nativeErr,
18418                     errmsg, errmax, errlen);
18419 }
18420 #endif
18421 
18422 #ifdef WINTERFACE
18423 
18436 SQLRETURN SQL_API
18437 SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18438           SQLWCHAR *sqlState, SQLINTEGER *nativeErr,
18439           SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18440 {
18441     char state[16];
18442     SQLSMALLINT len = 0;
18443     SQLRETURN ret;
18444 
18445     ret = drverror(env, dbc, stmt, (SQLCHAR *) state, nativeErr,
18446                    (SQLCHAR *) errmsg, errmax, &len);
18447     if (ret == SQL_SUCCESS) {
18448         if (sqlState) {
18449             uc_from_utf_buf((SQLCHAR *) state, -1, sqlState,
18450                             6 * sizeof (SQLWCHAR));
18451         }
18452         if (errmsg) {
18453             if (len > 0) {
18454                 SQLWCHAR *e = NULL;
18455 
18456                 e = uc_from_utf((SQLCHAR *) errmsg, len);
18457                 if (e) {
18458                     if (errmax > 0) {
18459                         uc_strncpy(errmsg, e, errmax);
18460                         e[len] = 0;
18461                         len = min(errmax, uc_strlen(e));
18462                     } else {
18463                         len = uc_strlen(e);
18464                     }
18465                     uc_free(e);
18466                 } else {
18467                     len = 0;
18468                 }
18469             }
18470             if (len <= 0) {
18471                 len = 0;
18472                 if (errmax > 0) {
18473                     errmsg[0] = 0;
18474                 }
18475             }
18476         } else {
18477             len = 0;
18478         }
18479         if (errlen) {
18480             *errlen = len;
18481         }
18482     } else if (ret == SQL_NO_DATA) {
18483         if (sqlState) {
18484             sqlState[0] = 0;
18485         }
18486         if (errmsg) {
18487             if (errmax > 0) {
18488                 errmsg[0] = 0;
18489             }
18490         }
18491         if (errlen) {
18492             *errlen = 0;
18493         }
18494     }
18495     return ret;
18496 }
18497 #endif
18498 
18505 SQLRETURN SQL_API
18506 SQLMoreResults(SQLHSTMT stmt)
18507 {
18508     HSTMT_LOCK(stmt);
18509     if (stmt == SQL_NULL_HSTMT) {
18510         return SQL_INVALID_HANDLE;
18511     }
18512     HSTMT_UNLOCK(stmt);
18513     return SQL_NO_DATA;
18514 }
18515 
18524 static SQLRETURN
18525 setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp)
18526 {
18527     int ncols = *ncolsp, guessed_types = 0;
18528     SQLRETURN ret = SQL_SUCCESS;
18529 
18530     if (ncols > 0) {
18531         int i;
18532         PTRDIFF_T size;
18533         char *p;
18534         COL *dyncols;
18535         DBC *d = (DBC *) s->dbc;
18536         const char *colname, *typename;
18537 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18538         char *tblname;
18539 #endif
18540 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18541         char *dbname;
18542 #endif
18543 
18544         for (i = size = 0; i < ncols; i++) {
18545             colname = sqlite3_column_name(s3stmt, i);
18546             size += 3 + 3 * strlen(colname);
18547         }
18548 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18549         tblname = (char *) size;
18550         for (i = 0; i < ncols; i++) {
18551             p = (char *) sqlite3_column_table_name(s3stmt, i);
18552             size += 2 + (p ? strlen(p) : 0);
18553         }
18554 #endif
18555 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18556         dbname = (char *) size;
18557         for (i = 0; i < ncols; i++) {
18558             p = (char *) sqlite3_column_database_name(s3stmt, i);
18559             size += 2 + (p ? strlen(p) : 0);
18560         }
18561 #endif
18562         dyncols = xmalloc(ncols * sizeof (COL) + size);
18563         if (!dyncols) {
18564             freedyncols(s);
18565             *ncolsp = 0;
18566             ret = SQL_ERROR;
18567         } else {
18568             p = (char *) (dyncols + ncols);
18569 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18570             tblname = p + (PTRDIFF_T) tblname;
18571 #endif
18572 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18573             dbname = p + (PTRDIFF_T) dbname;
18574 #endif
18575             for (i = 0; i < ncols; i++) {
18576                 char *q;
18577 
18578                 colname = sqlite3_column_name(s3stmt, i);
18579                 if (d->trace) {
18580                     fprintf(d->trace, "-- column %d name: '%s'\n",
18581                             i + 1, colname);
18582                     fflush(d->trace);
18583                 }
18584 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18585                 q = (char *) sqlite3_column_table_name(s3stmt, i);
18586                 strcpy(tblname, q ? q : "");
18587                 if (d->trace) {
18588                     fprintf(d->trace, "-- table %d name: '%s'\n",
18589                             i + 1, tblname);
18590                     fflush(d->trace);
18591                 }
18592                 dyncols[i].table = tblname;
18593                 tblname += strlen(tblname) + 1;
18594 #endif
18595 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18596                 q = (char *) sqlite3_column_database_name(s3stmt, i);
18597                 strcpy(dbname, q ? q : "");
18598                 if (d->trace) {
18599                     fprintf(d->trace, "-- database %d name: '%s'\n",
18600                             i + 1, dbname);
18601                     fflush(d->trace);
18602                 }
18603                 dyncols[i].db = dbname;
18604                 dbname += strlen(dbname) + 1;
18605 #else
18606                 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
18607 #endif
18608                 typename = s3stmt_coltype(s3stmt, i, d, &guessed_types);
18609                 strcpy(p, colname);
18610                 dyncols[i].label = p;
18611                 p += strlen(p) + 1;
18612                 q = strchr(colname, '.');
18613                 if (q) {
18614                     char *q2 = strchr(q + 1, '.');
18615 
18616                     /* SQLite 3.3.4 produces view.table.column sometimes */
18617                     if (q2) {
18618                         q = q2;
18619                     }
18620                 }
18621                 if (q) {
18622 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
18623                     dyncols[i].table = p;
18624 #endif
18625                     strncpy(p, colname, q - colname);
18626                     p[q - colname] = '\0';
18627                     p += strlen(p) + 1;
18628                     strcpy(p, q + 1);
18629                     dyncols[i].column = p;
18630                     p += strlen(p) + 1;
18631                 } else {
18632 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
18633                     dyncols[i].table = "";
18634 #endif
18635                     strcpy(p, colname);
18636                     dyncols[i].column = p;
18637                     p += strlen(p) + 1;
18638                 }
18639                 if (s->longnames) {
18640                     dyncols[i].column = dyncols[i].label;
18641                 }
18642 #ifdef SQL_LONGVARCHAR
18643                 dyncols[i].type = SQL_LONGVARCHAR;
18644                 dyncols[i].size = 65535;
18645 #else
18646                 dyncols[i].type = SQL_VARCHAR;
18647                 dyncols[i].size = 255;
18648 #endif
18649                 dyncols[i].index = i;
18650                 dyncols[i].scale = 0;
18651                 dyncols[i].prec = 0;
18652                 dyncols[i].nosign = 1;
18653                 dyncols[i].autoinc = SQL_FALSE;
18654                 dyncols[i].notnull = SQL_NULLABLE;
18655                 dyncols[i].ispk = -1;
18656                 dyncols[i].isrowid = -1;
18657 #ifdef FULL_METADATA
18658                 s3stmt_addmeta(s3stmt, i, d, &dyncols[i]);
18659 #endif
18660                 dyncols[i].typename = xstrdup(typename);
18661             }
18662             freedyncols(s);
18663             s->dyncols = s->cols = dyncols;
18664             s->dcols = ncols;
18665             fixupdyncols(s, d);
18666             s->guessed_types = guessed_types;
18667         }
18668     }
18669     return ret;
18670 }
18671 
18680 static SQLRETURN
18681 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
18682 {
18683     STMT *s;
18684     DBC *d;
18685     char *errp = NULL;
18686     SQLRETURN sret;
18687 
18688     if (stmt == SQL_NULL_HSTMT) {
18689         return SQL_INVALID_HANDLE;
18690     }
18691     s = (STMT *) stmt;
18692     if (s->dbc == SQL_NULL_HDBC) {
18693 noconn:
18694         return noconn(s);
18695     }
18696     d = s->dbc;
18697     if (!d->sqlite) {
18698         goto noconn;
18699     }
18700     s3stmt_end(s);
18701     s3stmt_drop(s);
18702     sret = starttran(s);
18703     if (sret != SQL_SUCCESS) {
18704         return sret;
18705     }
18706     freep(&s->query);
18707     s->query = (SQLCHAR *) fixupsql((char *) query, queryLen,
18708                                     (d->version >= 0x030805),
18709                                     &s->nparams, &s->isselect, &errp);
18710     if (!s->query) {
18711         if (errp) {
18712             setstat(s, -1, "%s", (*s->ov3) ? "HY000" : "S1000", errp);
18713             return SQL_ERROR;
18714         }
18715         return nomem(s);
18716     }
18717     if (*s->ilike) {
18718         replilike((char *) s->query);
18719     }
18720     errp = NULL;
18721     freeresult(s, -1);
18722     if (s->isselect == 1) {
18723         int ret, ncols, nretry = 0;
18724         const char *rest;
18725         sqlite3_stmt *s3stmt = NULL;
18726 
18727 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
18728         dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
18729 #else
18730         dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
18731 #endif
18732         do {
18733             s3stmt = NULL;
18734 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
18735             ret = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
18736                                      &s3stmt, &rest);
18737 #else
18738             ret = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
18739                                   &s3stmt, &rest);
18740 #endif
18741             if (ret != SQLITE_OK) {
18742                 if (s3stmt) {
18743                     sqlite3_finalize(s3stmt);
18744                     s3stmt = NULL;
18745                 }
18746             }
18747         } while (ret == SQLITE_SCHEMA && (++nretry) < 2);
18748         dbtracerc(d, ret, NULL);
18749         if (ret != SQLITE_OK) {
18750             if (s3stmt) {
18751                 dbtraceapi(d, "sqlite3_finalize", 0);
18752                 sqlite3_finalize(s3stmt);
18753             }
18754             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
18755                     sqlite3_errmsg(d->sqlite), ret);
18756             return SQL_ERROR;
18757         }
18758         if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
18759             dbtraceapi(d, "sqlite3_finalize", 0);
18760             sqlite3_finalize(s3stmt);
18761             setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
18762                     (*s->ov3) ? "HY000" : "S1000");
18763             return SQL_ERROR;
18764         }
18765         ncols = sqlite3_column_count(s3stmt);
18766         s->guessed_types = 0;
18767         setupdyncols(s, s3stmt, &ncols);
18768         s->ncols = ncols;
18769         s->s3stmt = s3stmt;
18770     } else {
18771         s->guessed_types = 1;
18772     }
18773     mkbindcols(s, s->ncols);
18774     s->paramset_count = 0;
18775     return SQL_SUCCESS;
18776 }
18777 
18785 static SQLRETURN
18786 drvexecute(SQLHSTMT stmt, int initial)
18787 {
18788     STMT *s;
18789     DBC *d;
18790     char *errp = NULL;
18791     int rc, i, ncols = 0, nrows = 0, busy_count;
18792     SQLRETURN ret;
18793 
18794     if (stmt == SQL_NULL_HSTMT) {
18795         return SQL_INVALID_HANDLE;
18796     }
18797     s = (STMT *) stmt;
18798     if (s->dbc == SQL_NULL_HDBC) {
18799 noconn:
18800         return noconn(s);
18801     }
18802     d = (DBC *) s->dbc;
18803     if (!d->sqlite) {
18804         goto noconn;
18805     }
18806     if (!s->query) {
18807         setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
18808         return SQL_ERROR;
18809     }
18810     if (s->nbindparms < s->nparams) {
18811 unbound:
18812         setstat(s, -1, "unbound parameters in query",
18813                 (*s->ov3) ? "HY000" : "S1000");
18814         return SQL_ERROR;
18815     }
18816     for (i = 0; i < s->nparams; i++) {
18817         BINDPARM *p = &s->bindparms[i];
18818 
18819         if (!p->bound) {
18820             goto unbound;
18821         }
18822         if (initial) {
18823             SQLLEN *lenp = p->lenp;
18824 
18825             if (lenp && *lenp < 0 && *lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18826                 *lenp != SQL_NTS && *lenp != SQL_NULL_DATA &&
18827                 *lenp != SQL_DATA_AT_EXEC) {
18828                 setstat(s, -1, "invalid length reference", "HY009");
18829                 return SQL_ERROR;
18830             }
18831             if (lenp && (*lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18832                          *lenp == SQL_DATA_AT_EXEC)) {
18833                 p->need = 1;
18834                 p->offs = 0;
18835                 p->len = 0;
18836             }
18837         }
18838     }
18839     ret = starttran(s);
18840     if (ret != SQL_SUCCESS) {
18841         goto cleanup;
18842     }
18843     busy_count = 0;
18844 again:
18845     s3stmt_end(s);
18846     if (initial) {
18847         /* fixup data-at-execution parameters and alloc'ed blobs */
18848         s->pdcount = -1;
18849         for (i = 0; i < s->nparams; i++) {
18850             BINDPARM *p = &s->bindparms[i];
18851 
18852             if (p->param == p->parbuf) {
18853                 p->param = NULL;
18854             }
18855             freep(&p->parbuf);
18856             if (p->need <= 0 &&
18857                 p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18858                             *p->lenp == SQL_DATA_AT_EXEC)) {
18859                 p->need = 1;
18860                 p->offs = 0;
18861                 p->len = 0;
18862             }
18863         }
18864     }
18865     if (s->nparams) {
18866         for (i = 0; i < s->nparams; i++) {
18867             ret = setupparam(s, (char *) s->query, i);
18868             if (ret != SQL_SUCCESS) {
18869                 goto cleanup;
18870             }
18871         }
18872     }
18873     freeresult(s, 0);
18874     if (s->isselect == 1 && !d->intrans &&
18875         s->curtype == SQL_CURSOR_FORWARD_ONLY &&
18876         d->step_enable && s->nparams == 0 && d->cur_s3stmt == NULL) {
18877         s->nrows = -1;
18878         ret = s3stmt_start(s);
18879         if (ret == SQL_SUCCESS) {
18880             goto done2;
18881         }
18882     }
18883     rc = drvgettable(s, s->s3stmt ? NULL : (char *) s->query, &s->rows,
18884                      &s->nrows, &ncols, &errp, s->nparams, s->bindparms);
18885     dbtracerc(d, rc, errp);
18886     if (rc == SQLITE_BUSY) {
18887         if (busy_handler((void *) d, ++busy_count)) {
18888             if (errp) {
18889                 sqlite3_free(errp);
18890                 errp = NULL;
18891             }
18892             for (i = 0; i < s->nparams; i++) {
18893                 BINDPARM *p = &s->bindparms[i];
18894 
18895                 if (p->param == p->parbuf) {
18896                     p->param = NULL;
18897                 }
18898                 freep(&p->parbuf);
18899                 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18900                                  *p->lenp != SQL_DATA_AT_EXEC)) {
18901                     p->param = p->param0;
18902                 }
18903                 p->lenp = p->lenp0;
18904             }
18905             s->nrows = 0;
18906             goto again;
18907         }
18908     }
18909     if (rc != SQLITE_OK) {
18910         setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
18911                 errp ? errp : "unknown error", rc);
18912         if (errp) {
18913             sqlite3_free(errp);
18914             errp = NULL;
18915         }
18916         ret = SQL_ERROR;
18917         goto cleanup;
18918     }
18919     if (errp) {
18920         sqlite3_free(errp);
18921         errp = NULL;
18922     }
18923     s->rowfree = freerows;
18924     if (s->isselect <= 0 || s->isselect > 1) {
18925         /*
18926          * DDL results are immediately released.
18927          * INSERT/UPDATE/DELETE depends on number of columns in
18928          * result set, if zero, result is immediately released.
18929          */
18930         if (s->isselect != 0 || ncols == 0) {
18931             freeresult(s, -1);
18932             nrows += sqlite3_changes(d->sqlite);
18933             s->nrows = nrows;
18934         } else {
18935             s->ncols = ncols;
18936         }
18937         goto done;
18938     }
18939     if (s->ncols != ncols) {
18940         /*
18941          * Weird result.
18942          */
18943         setstat(s, -1, "broken result set %d/%d",
18944                 (*s->ov3) ? "HY000" : "S1000", s->ncols, ncols);
18945         ret = SQL_ERROR;
18946         goto cleanup;
18947     }
18948 done:
18949     mkbindcols(s, s->ncols);
18950 done2:
18951     ret = SQL_SUCCESS;
18952     s->rowp = s->rowprs = -1;
18953     s->paramset_count++;
18954     s->paramset_nrows = s->nrows;
18955     if (s->paramset_count < s->paramset_size) {
18956         for (i = 0; i < s->nparams; i++) {
18957             BINDPARM *p = &s->bindparms[i];
18958 
18959             if (p->param == p->parbuf) {
18960                 p->param = NULL;
18961             }
18962             freep(&p->parbuf);
18963             if (p->lenp0 &&
18964                 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18965                 p->lenp = (SQLLEN *) ((char *) p->lenp0 +
18966                                       s->paramset_count * s->parm_bind_type);
18967             } else if (p->lenp0 && p->inc > 0) {
18968                 p->lenp = p->lenp0 + s->paramset_count;
18969             }
18970             if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18971                              *p->lenp != SQL_DATA_AT_EXEC)) {
18972                 if (p->param0 &&
18973                     s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18974                     p->param = (char *) p->param0 +
18975                         s->paramset_count * s->parm_bind_type;
18976                 } else if (p->param0 && p->inc > 0) {
18977                     p->param = (char *) p->param0 +
18978                         s->paramset_count * p->inc;
18979                 }
18980             } else if (p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18981                                    *p->lenp == SQL_DATA_AT_EXEC)) {
18982                 p->need = 1;
18983                 p->offs = 0;
18984                 p->len = 0;
18985             }
18986         }
18987         goto again;
18988     }
18989 cleanup:
18990     if (ret != SQL_NEED_DATA) {
18991         for (i = 0; i < s->nparams; i++) {
18992             BINDPARM *p = &s->bindparms[i];
18993 
18994             if (p->param == p->parbuf) {
18995                 p->param = NULL;
18996             }
18997             freep(&p->parbuf);
18998             if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18999                              *p->lenp != SQL_DATA_AT_EXEC)) {
19000                 p->param = p->param0;
19001             }
19002             p->lenp = p->lenp0;
19003         }
19004         s->nrows = s->paramset_nrows;
19005         if (s->parm_proc) {
19006             *s->parm_proc = s->paramset_count;
19007         }
19008         s->paramset_count = 0;
19009         s->paramset_nrows = 0;
19010     }
19011     /*
19012      * For INSERT/UPDATE/DELETE statements change the return code
19013      * to SQL_NO_DATA if the number of rows affected was 0.
19014      */
19015     if (*s->ov3 && s->isselect == 0 &&
19016         ret == SQL_SUCCESS && nrows == 0) {
19017         ret = SQL_NO_DATA;
19018     }
19019     return ret;
19020 }
19021 
19022 #ifndef WINTERFACE
19023 
19031 SQLRETURN SQL_API
19032 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
19033 {
19034     SQLRETURN ret;
19035 #if defined(_WIN32) || defined(_WIN64)
19036     char *q;
19037 #endif
19038 
19039     HSTMT_LOCK(stmt);
19040 #if defined(_WIN32) || defined(_WIN64)
19041     if (!((STMT *) stmt)->oemcp[0]) {
19042         ret = drvprepare(stmt, query, queryLen);
19043         goto done;
19044     }
19045     q = wmb_to_utf_c((char *) query, queryLen);
19046     if (!q) {
19047         ret = nomem((STMT *) stmt);
19048         goto done;
19049     }
19050     query = (SQLCHAR *) q;
19051     queryLen = SQL_NTS;
19052 #endif
19053     ret = drvprepare(stmt, query, queryLen);
19054 #if defined(_WIN32) || defined(_WIN64)
19055     uc_free(q);
19056 done:
19057     ;
19058 #endif
19059     HSTMT_UNLOCK(stmt);
19060     return ret;
19061 }
19062 #endif
19063 
19064 #ifdef WINTERFACE
19065 
19073 SQLRETURN SQL_API
19074 SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
19075 {
19076     SQLRETURN ret;
19077     char *q = uc_to_utf_c(query, queryLen);
19078 
19079     HSTMT_LOCK(stmt);
19080     if (!q) {
19081         ret = nomem((STMT *) stmt);
19082         goto done;
19083     }
19084     ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
19085     uc_free(q);
19086 done:
19087     HSTMT_UNLOCK(stmt);
19088     return ret;
19089 }
19090 #endif
19091 
19098 SQLRETURN SQL_API
19099 SQLExecute(SQLHSTMT stmt)
19100 {
19101     SQLRETURN ret;
19102 
19103     HSTMT_LOCK(stmt);
19104     ret = drvexecute(stmt, 1);
19105     HSTMT_UNLOCK(stmt);
19106     return ret;
19107 }
19108 
19109 #ifndef WINTERFACE
19110 
19118 SQLRETURN SQL_API
19119 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
19120 {
19121     SQLRETURN ret;
19122 #if defined(_WIN32) || defined(_WIN64)
19123     char *q;
19124 #endif
19125 
19126     HSTMT_LOCK(stmt);
19127 #if defined(_WIN32) || defined(_WIN64)
19128     if (!((STMT *) stmt)->oemcp[0]) {
19129         ret = drvprepare(stmt, query, queryLen);
19130         if (ret == SQL_SUCCESS) {
19131             ret = drvexecute(stmt, 1);
19132         }
19133         goto done;
19134     }
19135     q = wmb_to_utf_c((char *) query, queryLen);
19136     if (!q) {
19137         ret = nomem((STMT *) stmt);
19138         goto done;
19139     }
19140     query = (SQLCHAR *) q;
19141     queryLen = SQL_NTS;
19142 #endif
19143     ret = drvprepare(stmt, query, queryLen);
19144     if (ret == SQL_SUCCESS) {
19145         ret = drvexecute(stmt, 1);
19146     }
19147 #if defined(_WIN32) || defined(_WIN64)
19148     uc_free(q);
19149 done:
19150     ;
19151 #endif
19152     HSTMT_UNLOCK(stmt);
19153     return ret;
19154 }
19155 #endif
19156 
19157 #ifdef WINTERFACE
19158 
19166 SQLRETURN SQL_API
19167 SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
19168 {
19169     SQLRETURN ret;
19170     char *q = uc_to_utf_c(query, queryLen);
19171 
19172     HSTMT_LOCK(stmt);
19173     if (!q) {
19174         ret = nomem((STMT *) stmt);
19175         goto done;
19176     }
19177     ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
19178     uc_free(q);
19179     if (ret == SQL_SUCCESS) {
19180         ret = drvexecute(stmt, 1);
19181     }
19182 done:
19183     HSTMT_UNLOCK(stmt);
19184     return ret;
19185 }
19186 #endif
19187 
19188 
19189 #if defined(_WIN32) || defined(_WIN64)
19190 #ifndef WITHOUT_DRIVERMGR
19191 
19192 /*
19193  * Windows configuration dialog stuff.
19194  */
19195 
19196 #include <windowsx.h>
19197 #include <winuser.h>
19198 
19199 #define MAXPATHLEN      (259+1)         /* Max path length */
19200 #define MAXKEYLEN       (15+1)          /* Max keyword length */
19201 #define MAXDESC         (255+1)         /* Max description length */
19202 #define MAXDSNAME       (255+1)         /* Max data source name length */
19203 #define MAXTONAME       (32+1)          /* Max timeout length */
19204 #define MAXDBNAME       MAXPATHLEN
19205 
19206 /* Attribute key indexes into an array of Attr structs, see below */
19207 
19208 #define KEY_DSN                 0
19209 #define KEY_DESC                1
19210 #define KEY_DBNAME              2
19211 #define KEY_BUSY                3
19212 #define KEY_DRIVER              4
19213 #define KEY_STEPAPI             5
19214 #define KEY_SYNCP               6
19215 #define KEY_NOTXN               7
19216 #define KEY_SHORTNAM            8
19217 #define KEY_LONGNAM             9
19218 #define KEY_NOCREAT            10
19219 #define KEY_NOWCHAR            11
19220 #define KEY_LOADEXT            12
19221 #define KEY_JMODE              13
19222 #define KEY_FKSUPPORT          14
19223 #define KEY_OEMCP              15
19224 #define KEY_BIGINT             16
19225 #define KEY_PASSWD             17
19226 #define KEY_JDCONV             18
19227 #define KEY_ATTAS              19
19228 #define KEY_ILIKE              20
19229 #define NUMOFKEYS              21
19230 
19231 typedef struct {
19232     BOOL supplied;
19233     char attr[MAXPATHLEN*4];
19234 } ATTR;
19235 
19236 typedef struct {
19237     SQLHWND parent;
19238     LPCSTR  driver;
19239     ATTR    attr[NUMOFKEYS];
19240     char    DSN[MAXDSNAME];
19241     BOOL    newDSN;
19242     BOOL    defDSN;
19243 } SETUPDLG;
19244 
19245 static struct {
19246     char *key;
19247     int ikey;
19248 } attrLookup[] = {
19249     { "DSN", KEY_DSN },
19250     { "DESC", KEY_DESC },
19251     { "Description", KEY_DESC},
19252     { "Database", KEY_DBNAME },
19253     { "Timeout", KEY_BUSY },
19254     { "Driver", KEY_DRIVER },
19255     { "StepAPI", KEY_STEPAPI },
19256     { "SyncPragma", KEY_SYNCP },
19257     { "NoTXN", KEY_NOTXN },
19258     { "ShortNames", KEY_SHORTNAM },
19259     { "LongNames", KEY_LONGNAM },
19260     { "NoCreat", KEY_NOCREAT },
19261     { "NoWCHAR", KEY_NOWCHAR },
19262     { "LoadExt", KEY_LOADEXT },
19263     { "JournalMode", KEY_JMODE },
19264     { "FKSupport", KEY_FKSUPPORT },
19265     { "OEMCP", KEY_OEMCP },
19266     { "BigInt", KEY_BIGINT },
19267     { "PWD", KEY_PASSWD },
19268     { "JDConv", KEY_JDCONV },
19269     { "AttachAs", KEY_ATTAS },
19270     { "ILike", KEY_ILIKE },
19271     { NULL, 0 }
19272 };
19273 
19280 static void
19281 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
19282 {
19283     char *str = (char *) attribs, *start, key[MAXKEYLEN];
19284     int elem, nkey;
19285 
19286     while (*str) {
19287         start = str;
19288         if ((str = strchr(str, '=')) == NULL) {
19289             return;
19290         }
19291         elem = -1;
19292         nkey = str - start;
19293         if (nkey < sizeof (key)) {
19294             int i;
19295 
19296             memcpy(key, start, nkey);
19297             key[nkey] = '\0';
19298             for (i = 0; attrLookup[i].key; i++) {
19299                 if (strcasecmp(attrLookup[i].key, key) == 0) {
19300                     elem = attrLookup[i].ikey;
19301                     break;
19302                 }
19303             }
19304         }
19305         start = ++str;
19306         while (*str && *str != ';') {
19307             ++str;
19308         }
19309         if (elem >= 0) {
19310             int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
19311 
19312             setupdlg->attr[elem].supplied = TRUE;
19313             memcpy(setupdlg->attr[elem].attr, start, end);
19314             setupdlg->attr[elem].attr[end] = '\0';
19315         }
19316         ++str;
19317     }
19318 }
19319 
19327 static BOOL
19328 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
19329 {
19330     char *dsn = setupdlg->attr[KEY_DSN].attr;
19331 
19332     if (setupdlg->newDSN && strlen(dsn) == 0) {
19333         return FALSE;
19334     }
19335     if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
19336         if (parent) {
19337             char buf[MAXPATHLEN], msg[MAXPATHLEN];
19338 
19339             LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
19340             wsprintf(msg, buf, dsn);
19341             LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
19342             MessageBox(parent, msg, buf,
19343                        MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
19344                        MB_SETFOREGROUND);
19345         }
19346         return FALSE;
19347     }
19348     if (parent || setupdlg->attr[KEY_DESC].supplied) {
19349         SQLWritePrivateProfileString(dsn, "Description",
19350                                      setupdlg->attr[KEY_DESC].attr,
19351                                      ODBC_INI);
19352     }
19353     if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
19354         SQLWritePrivateProfileString(dsn, "Database",
19355                                      setupdlg->attr[KEY_DBNAME].attr,
19356                                      ODBC_INI);
19357     }
19358     if (parent || setupdlg->attr[KEY_BUSY].supplied) {
19359         SQLWritePrivateProfileString(dsn, "Timeout",
19360                                      setupdlg->attr[KEY_BUSY].attr,
19361                                      ODBC_INI);
19362     }
19363     if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
19364         SQLWritePrivateProfileString(dsn, "StepAPI",
19365                                      setupdlg->attr[KEY_STEPAPI].attr,
19366                                      ODBC_INI);
19367     }
19368     if (parent || setupdlg->attr[KEY_SYNCP].supplied) {
19369         SQLWritePrivateProfileString(dsn, "SyncPragma",
19370                                      setupdlg->attr[KEY_SYNCP].attr,
19371                                      ODBC_INI);
19372     }
19373     if (parent || setupdlg->attr[KEY_NOTXN].supplied) {
19374         SQLWritePrivateProfileString(dsn, "NoTXN",
19375                                      setupdlg->attr[KEY_NOTXN].attr,
19376                                      ODBC_INI);
19377     }
19378     if (parent || setupdlg->attr[KEY_SHORTNAM].supplied) {
19379         SQLWritePrivateProfileString(dsn, "ShortNames",
19380                                      setupdlg->attr[KEY_SHORTNAM].attr,
19381                                      ODBC_INI);
19382     }
19383     if (parent || setupdlg->attr[KEY_LONGNAM].supplied) {
19384         SQLWritePrivateProfileString(dsn, "LongNames",
19385                                      setupdlg->attr[KEY_LONGNAM].attr,
19386                                      ODBC_INI);
19387     }
19388     if (parent || setupdlg->attr[KEY_NOCREAT].supplied) {
19389         SQLWritePrivateProfileString(dsn, "NoCreat",
19390                                      setupdlg->attr[KEY_NOCREAT].attr,
19391                                      ODBC_INI);
19392     }
19393     if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) {
19394         SQLWritePrivateProfileString(dsn, "NoWCHAR",
19395                                      setupdlg->attr[KEY_NOWCHAR].attr,
19396                                      ODBC_INI);
19397     }
19398     if (parent || setupdlg->attr[KEY_FKSUPPORT].supplied) {
19399         SQLWritePrivateProfileString(dsn, "FKSupport",
19400                                      setupdlg->attr[KEY_FKSUPPORT].attr,
19401                                      ODBC_INI);
19402     }
19403     if (parent || setupdlg->attr[KEY_OEMCP].supplied) {
19404         SQLWritePrivateProfileString(dsn, "OEMCP",
19405                                      setupdlg->attr[KEY_OEMCP].attr,
19406                                      ODBC_INI);
19407     }
19408     if (parent || setupdlg->attr[KEY_LOADEXT].supplied) {
19409         SQLWritePrivateProfileString(dsn, "LoadExt",
19410                                      setupdlg->attr[KEY_LOADEXT].attr,
19411                                      ODBC_INI);
19412     }
19413     if (parent || setupdlg->attr[KEY_BIGINT].supplied) {
19414         SQLWritePrivateProfileString(dsn, "BigInt",
19415                                      setupdlg->attr[KEY_BIGINT].attr,
19416                                      ODBC_INI);
19417     }
19418     if (parent || setupdlg->attr[KEY_JDCONV].supplied) {
19419         SQLWritePrivateProfileString(dsn, "JDConv",
19420                                      setupdlg->attr[KEY_JDCONV].attr,
19421                                      ODBC_INI);
19422     }
19423     if (parent || setupdlg->attr[KEY_ATTAS].supplied) {
19424         SQLWritePrivateProfileString(dsn, "AttachAs",
19425                                      setupdlg->attr[KEY_ATTAS].attr,
19426                                      ODBC_INI);
19427     }
19428     if (parent || setupdlg->attr[KEY_ILIKE].supplied) {
19429         SQLWritePrivateProfileString(dsn, "ILike",
19430                                      setupdlg->attr[KEY_ILIKE].attr,
19431                                      ODBC_INI);
19432     }
19433     if (parent || setupdlg->attr[KEY_PASSWD].supplied) {
19434         SQLWritePrivateProfileString(dsn, "PWD",
19435                                      setupdlg->attr[KEY_PASSWD].attr,
19436                                      ODBC_INI);
19437     }
19438     if (setupdlg->attr[KEY_DSN].supplied &&
19439         strcasecmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
19440         SQLRemoveDSNFromIni(setupdlg->DSN);
19441     }
19442     return TRUE;
19443 }
19444 
19450 static void
19451 GetAttributes(SETUPDLG *setupdlg)
19452 {
19453     char *dsn = setupdlg->attr[KEY_DSN].attr;
19454 
19455     if (!setupdlg->attr[KEY_DESC].supplied) {
19456         SQLGetPrivateProfileString(dsn, "Description", "",
19457                                    setupdlg->attr[KEY_DESC].attr,
19458                                    sizeof (setupdlg->attr[KEY_DESC].attr),
19459                                    ODBC_INI);
19460     }
19461     if (!setupdlg->attr[KEY_DBNAME].supplied) {
19462         SQLGetPrivateProfileString(dsn, "Database", "",
19463                                    setupdlg->attr[KEY_DBNAME].attr,
19464                                    sizeof (setupdlg->attr[KEY_DBNAME].attr),
19465                                    ODBC_INI);
19466     }
19467     if (!setupdlg->attr[KEY_BUSY].supplied) {
19468         SQLGetPrivateProfileString(dsn, "Timeout", "100000",
19469                                    setupdlg->attr[KEY_BUSY].attr,
19470                                    sizeof (setupdlg->attr[KEY_BUSY].attr),
19471                                    ODBC_INI);
19472     }
19473     if (!setupdlg->attr[KEY_STEPAPI].supplied) {
19474         SQLGetPrivateProfileString(dsn, "StepAPI", "0",
19475                                    setupdlg->attr[KEY_STEPAPI].attr,
19476                                    sizeof (setupdlg->attr[KEY_STEPAPI].attr),
19477                                    ODBC_INI);
19478     }
19479     if (!setupdlg->attr[KEY_SYNCP].supplied) {
19480         SQLGetPrivateProfileString(dsn, "SyncPragma", "NORMAL",
19481                                    setupdlg->attr[KEY_SYNCP].attr,
19482                                    sizeof (setupdlg->attr[KEY_SYNCP].attr),
19483                                    ODBC_INI);
19484     }
19485     if (!setupdlg->attr[KEY_NOTXN].supplied) {
19486         SQLGetPrivateProfileString(dsn, "NoTXN", "",
19487                                    setupdlg->attr[KEY_NOTXN].attr,
19488                                    sizeof (setupdlg->attr[KEY_NOTXN].attr),
19489                                    ODBC_INI);
19490     }
19491     if (!setupdlg->attr[KEY_SHORTNAM].supplied) {
19492         SQLGetPrivateProfileString(dsn, "ShortNames", "",
19493                                    setupdlg->attr[KEY_SHORTNAM].attr,
19494                                    sizeof (setupdlg->attr[KEY_SHORTNAM].attr),
19495                                    ODBC_INI);
19496     }
19497     if (!setupdlg->attr[KEY_LONGNAM].supplied) {
19498         SQLGetPrivateProfileString(dsn, "LongNames", "",
19499                                    setupdlg->attr[KEY_LONGNAM].attr,
19500                                    sizeof (setupdlg->attr[KEY_LONGNAM].attr),
19501                                    ODBC_INI);
19502     }
19503     if (!setupdlg->attr[KEY_NOCREAT].supplied) {
19504         SQLGetPrivateProfileString(dsn, "NoCreat", "",
19505                                    setupdlg->attr[KEY_NOCREAT].attr,
19506                                    sizeof (setupdlg->attr[KEY_NOCREAT].attr),
19507                                    ODBC_INI);
19508     }
19509     if (!setupdlg->attr[KEY_NOWCHAR].supplied) {
19510         SQLGetPrivateProfileString(dsn, "NoWCHAR", "",
19511                                    setupdlg->attr[KEY_NOWCHAR].attr,
19512                                    sizeof (setupdlg->attr[KEY_NOWCHAR].attr),
19513                                    ODBC_INI);
19514     }
19515     if (!setupdlg->attr[KEY_FKSUPPORT].supplied) {
19516         SQLGetPrivateProfileString(dsn, "FKSupport", "",
19517                                    setupdlg->attr[KEY_FKSUPPORT].attr,
19518                                    sizeof (setupdlg->attr[KEY_FKSUPPORT].attr),
19519                                    ODBC_INI);
19520     }
19521     if (!setupdlg->attr[KEY_OEMCP].supplied) {
19522         SQLGetPrivateProfileString(dsn, "OEMCP", "",
19523                                    setupdlg->attr[KEY_OEMCP].attr,
19524                                    sizeof (setupdlg->attr[KEY_OEMCP].attr),
19525                                    ODBC_INI);
19526     }
19527     if (!setupdlg->attr[KEY_LOADEXT].supplied) {
19528         SQLGetPrivateProfileString(dsn, "LoadExt", "",
19529                                    setupdlg->attr[KEY_LOADEXT].attr,
19530                                    sizeof (setupdlg->attr[KEY_LOADEXT].attr),
19531                                    ODBC_INI);
19532     }
19533     if (!setupdlg->attr[KEY_JMODE].supplied) {
19534         SQLGetPrivateProfileString(dsn, "JournalMode", "",
19535                                    setupdlg->attr[KEY_JMODE].attr,
19536                                    sizeof (setupdlg->attr[KEY_JMODE].attr),
19537                                    ODBC_INI);
19538     }
19539     if (!setupdlg->attr[KEY_BIGINT].supplied) {
19540         SQLGetPrivateProfileString(dsn, "BigInt", "",
19541                                    setupdlg->attr[KEY_BIGINT].attr,
19542                                    sizeof (setupdlg->attr[KEY_BIGINT].attr),
19543                                    ODBC_INI);
19544     }
19545     if (!setupdlg->attr[KEY_PASSWD].supplied) {
19546         SQLGetPrivateProfileString(dsn, "PWD", "",
19547                                    setupdlg->attr[KEY_PASSWD].attr,
19548                                    sizeof (setupdlg->attr[KEY_PASSWD].attr),
19549                                    ODBC_INI);
19550     }
19551     if (!setupdlg->attr[KEY_JDCONV].supplied) {
19552         SQLGetPrivateProfileString(dsn, "JDConv", "",
19553                                    setupdlg->attr[KEY_JDCONV].attr,
19554                                    sizeof (setupdlg->attr[KEY_JDCONV].attr),
19555                                    ODBC_INI);
19556     }
19557     if (!setupdlg->attr[KEY_ATTAS].supplied) {
19558         SQLGetPrivateProfileString(dsn, "AttachAs", "",
19559                                    setupdlg->attr[KEY_ATTAS].attr,
19560                                    sizeof (setupdlg->attr[KEY_ATTAS].attr),
19561                                    ODBC_INI);
19562     }
19563     if (!setupdlg->attr[KEY_ILIKE].supplied) {
19564         SQLGetPrivateProfileString(dsn, "ILike", "",
19565                                    setupdlg->attr[KEY_ILIKE].attr,
19566                                    sizeof (setupdlg->attr[KEY_ILIKE].attr),
19567                                    ODBC_INI);
19568     }
19569 }
19570 
19576 static void
19577 GetDBFile(HWND hdlg)
19578 {
19579 #ifdef _WIN64
19580     SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19581 #else
19582     SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19583 #endif
19584     OPENFILENAME ofn;
19585 
19586     memset(&ofn, 0, sizeof (ofn));
19587     ofn.lStructSize = sizeof (ofn);
19588     ofn.hwndOwner = hdlg;
19589 #ifdef _WIN64
19590     ofn.hInstance = (HINSTANCE) GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
19591 #else
19592     ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
19593 #endif
19594     ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
19595     ofn.nMaxFile = MAXPATHLEN;
19596     ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
19597                 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
19598     if (GetOpenFileName(&ofn)) {
19599         SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19600         setupdlg->attr[KEY_DBNAME].supplied = TRUE;
19601     }
19602 }
19603 
19613 static BOOL CALLBACK
19614 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
19615 {
19616     SETUPDLG *setupdlg = NULL;
19617     WORD index;
19618 
19619     switch (wmsg) {
19620     case WM_INITDIALOG:
19621 #ifdef _WIN64
19622         SetWindowLongPtr(hdlg, DWLP_USER, lparam);
19623 #else
19624         SetWindowLong(hdlg, DWL_USER, lparam);
19625 #endif
19626         setupdlg = (SETUPDLG *) lparam;
19627         GetAttributes(setupdlg);
19628         SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
19629         SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
19630         SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19631         SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
19632         SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
19633         SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
19634                            (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
19635         SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
19636                            (WPARAM) (MAXDESC - 1), (LPARAM) 0);
19637         SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
19638                            (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
19639         SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
19640                            (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
19641         SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
19642                            (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
19643         CheckDlgButton(hdlg, IDC_STEPAPI,
19644                        getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
19645                        BST_CHECKED : BST_UNCHECKED);
19646         CheckDlgButton(hdlg, IDC_NOTXN,
19647                        getbool(setupdlg->attr[KEY_NOTXN].attr) ?
19648                        BST_CHECKED : BST_UNCHECKED);
19649         CheckDlgButton(hdlg, IDC_SHORTNAM,
19650                        getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
19651                        BST_CHECKED : BST_UNCHECKED);
19652         CheckDlgButton(hdlg, IDC_LONGNAM,
19653                        getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
19654                        BST_CHECKED : BST_UNCHECKED);
19655         CheckDlgButton(hdlg, IDC_NOCREAT,
19656                        getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
19657                        BST_CHECKED : BST_UNCHECKED);
19658         CheckDlgButton(hdlg, IDC_NOWCHAR,
19659                        getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
19660                        BST_CHECKED : BST_UNCHECKED);
19661         CheckDlgButton(hdlg, IDC_FKSUPPORT,
19662                        getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
19663                        BST_CHECKED : BST_UNCHECKED);
19664         CheckDlgButton(hdlg, IDC_OEMCP,
19665                        getbool(setupdlg->attr[KEY_OEMCP].attr) ?
19666                        BST_CHECKED : BST_UNCHECKED);
19667         CheckDlgButton(hdlg, IDC_BIGINT,
19668                        getbool(setupdlg->attr[KEY_BIGINT].attr) ?
19669                        BST_CHECKED : BST_UNCHECKED);
19670         CheckDlgButton(hdlg, IDC_JDCONV,
19671                        getbool(setupdlg->attr[KEY_JDCONV].attr) ?
19672                        BST_CHECKED : BST_UNCHECKED);
19673         SetDlgItemText(hdlg, IDC_ATTAS, setupdlg->attr[KEY_ATTAS].attr);
19674         CheckDlgButton(hdlg, IDC_ILIKE,
19675                        getbool(setupdlg->attr[KEY_ILIKE].attr) ?
19676                        BST_CHECKED : BST_UNCHECKED);
19677         SendDlgItemMessage(hdlg, IDC_SYNCP,
19678                            CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
19679         SendDlgItemMessage(hdlg, IDC_SYNCP,
19680                            CB_ADDSTRING, 0, (LPARAM) "NORMAL");
19681         SendDlgItemMessage(hdlg, IDC_SYNCP,
19682                            CB_ADDSTRING, 0, (LPARAM) "OFF");
19683         SendDlgItemMessage(hdlg, IDC_SYNCP,
19684                            CB_ADDSTRING, 0, (LPARAM) "FULL");
19685         SendDlgItemMessage(hdlg, IDC_SYNCP,
19686                            CB_SELECTSTRING, (WPARAM) -1,
19687                            (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19688         if (setupdlg->defDSN) {
19689             EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
19690             EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
19691         }
19692         return TRUE;
19693     case WM_COMMAND:
19694         switch (GET_WM_COMMAND_ID(wparam, lparam)) {
19695         case IDC_DSNAME:
19696             if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
19697                 char item[MAXDSNAME];
19698 
19699                 EnableWindow(GetDlgItem(hdlg, IDOK),
19700                              GetDlgItemText(hdlg, IDC_DSNAME,
19701                                             item, sizeof (item)));
19702                 return TRUE;
19703             }
19704             break;
19705         case IDC_BROWSE:
19706             GetDBFile(hdlg);
19707             break;
19708         case IDOK:
19709 #ifdef _WIN64
19710             setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19711 #else
19712             setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19713 #endif
19714             if (!setupdlg->defDSN) {
19715                 GetDlgItemText(hdlg, IDC_DSNAME,
19716                                setupdlg->attr[KEY_DSN].attr,
19717                                sizeof (setupdlg->attr[KEY_DSN].attr));
19718             }
19719             GetDlgItemText(hdlg, IDC_DESC,
19720                            setupdlg->attr[KEY_DESC].attr,
19721                            sizeof (setupdlg->attr[KEY_DESC].attr));
19722             GetDlgItemText(hdlg, IDC_DBNAME,
19723                            setupdlg->attr[KEY_DBNAME].attr,
19724                            sizeof (setupdlg->attr[KEY_DBNAME].attr));
19725             GetDlgItemText(hdlg, IDC_TONAME,
19726                            setupdlg->attr[KEY_BUSY].attr,
19727                            sizeof (setupdlg->attr[KEY_BUSY].attr));
19728             GetDlgItemText(hdlg, IDC_LOADEXT,
19729                            setupdlg->attr[KEY_LOADEXT].attr,
19730                            sizeof (setupdlg->attr[KEY_LOADEXT].attr));
19731             index = SendDlgItemMessage(hdlg, IDC_SYNCP,
19732                                        CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
19733             if (index != (WORD) CB_ERR) {
19734                 SendDlgItemMessage(hdlg, IDC_SYNCP,
19735                                    CB_GETLBTEXT, index,
19736                                    (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19737             }
19738             strcpy(setupdlg->attr[KEY_STEPAPI].attr,
19739                    (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
19740                    "1" : "0");
19741             strcpy(setupdlg->attr[KEY_NOTXN].attr,
19742                    (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
19743                    "1" : "0");
19744             strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
19745                    (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
19746                    "1" : "0");
19747             strcpy(setupdlg->attr[KEY_LONGNAM].attr,
19748                    (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
19749                    "1" : "0");
19750             strcpy(setupdlg->attr[KEY_NOCREAT].attr,
19751                    (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
19752                    "1" : "0");
19753             strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
19754                    (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
19755                    "1" : "0");
19756             strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
19757                    (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
19758                    "1" : "0");
19759             strcpy(setupdlg->attr[KEY_OEMCP].attr,
19760                    (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
19761                    "1" : "0");
19762             strcpy(setupdlg->attr[KEY_BIGINT].attr,
19763                    (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
19764                    "1" : "0");
19765             strcpy(setupdlg->attr[KEY_JDCONV].attr,
19766                    (IsDlgButtonChecked(hdlg, IDC_JDCONV) == BST_CHECKED) ?
19767                    "1" : "0");
19768             GetDlgItemText(hdlg, IDC_ATTAS,
19769                            setupdlg->attr[KEY_ATTAS].attr,
19770                            sizeof (setupdlg->attr[KEY_ATTAS].attr));
19771             strcpy(setupdlg->attr[KEY_ILIKE].attr,
19772                    (IsDlgButtonChecked(hdlg, IDC_ILIKE) == BST_CHECKED) ?
19773                    "1" : "0");
19774             SetDSNAttributes(hdlg, setupdlg);
19775             /* FALL THROUGH */
19776         case IDCANCEL:
19777             EndDialog(hdlg, wparam);
19778             return TRUE;
19779         }
19780         break;
19781     }
19782     return FALSE;
19783 }
19784 
19794 BOOL INSTAPI
19795 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
19796 {
19797     BOOL success;
19798     SETUPDLG *setupdlg;
19799 
19800     setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
19801     if (setupdlg == NULL) {
19802         return FALSE;
19803     }
19804     memset(setupdlg, 0, sizeof (SETUPDLG));
19805     if (attribs) {
19806         ParseAttributes(attribs, setupdlg);
19807     }
19808     if (setupdlg->attr[KEY_DSN].supplied) {
19809         strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
19810     } else {
19811         setupdlg->DSN[0] = '\0';
19812     }
19813     if (request == ODBC_REMOVE_DSN) {
19814         if (!setupdlg->attr[KEY_DSN].supplied) {
19815             success = FALSE;
19816         } else {
19817             success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
19818         }
19819     } else {
19820         setupdlg->parent = hwnd;
19821         setupdlg->driver = driver;
19822         setupdlg->newDSN = request == ODBC_ADD_DSN;
19823         setupdlg->defDSN = strcasecmp(setupdlg->attr[KEY_DSN].attr,
19824                                       "Default") == 0;
19825         if (hwnd) {
19826             success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
19827                                      hwnd, (DLGPROC) ConfigDlgProc,
19828                                      (LPARAM) setupdlg) == IDOK;
19829         } else if (setupdlg->attr[KEY_DSN].supplied) {
19830             success = SetDSNAttributes(hwnd, setupdlg);
19831         } else {
19832             success = FALSE;
19833         }
19834     }
19835     xfree(setupdlg);
19836     return success;
19837 }
19838 
19848 static BOOL CALLBACK
19849 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
19850 {
19851     SETUPDLG *setupdlg;
19852     WORD index;
19853 
19854     switch (wmsg) {
19855     case WM_INITDIALOG:
19856 #ifdef _WIN64
19857         SetWindowLongPtr(hdlg, DWLP_USER, lparam);
19858 #else
19859         SetWindowLong(hdlg, DWL_USER, lparam);
19860 #endif
19861         setupdlg = (SETUPDLG *) lparam;
19862         SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
19863         SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
19864         SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19865         SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
19866         SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
19867         SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
19868                            (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
19869         SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
19870                            (WPARAM) (MAXDESC - 1), (LPARAM) 0);
19871         SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
19872                            (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
19873         SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
19874                            (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
19875         SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
19876                            (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
19877         CheckDlgButton(hdlg, IDC_STEPAPI,
19878                        getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
19879                        BST_CHECKED : BST_UNCHECKED);
19880         CheckDlgButton(hdlg, IDC_NOTXN,
19881                        getbool(setupdlg->attr[KEY_NOTXN].attr) ?
19882                        BST_CHECKED : BST_UNCHECKED);
19883         CheckDlgButton(hdlg, IDC_SHORTNAM,
19884                        getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
19885                        BST_CHECKED : BST_UNCHECKED);
19886         CheckDlgButton(hdlg, IDC_LONGNAM,
19887                        getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
19888                        BST_CHECKED : BST_UNCHECKED);
19889         CheckDlgButton(hdlg, IDC_NOCREAT,
19890                        getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
19891                        BST_CHECKED : BST_UNCHECKED);
19892         CheckDlgButton(hdlg, IDC_NOWCHAR,
19893                        getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
19894                        BST_CHECKED : BST_UNCHECKED);
19895         CheckDlgButton(hdlg, IDC_FKSUPPORT,
19896                        getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
19897                        BST_CHECKED : BST_UNCHECKED);
19898         CheckDlgButton(hdlg, IDC_OEMCP,
19899                        getbool(setupdlg->attr[KEY_OEMCP].attr) ?
19900                        BST_CHECKED : BST_UNCHECKED);
19901         CheckDlgButton(hdlg, IDC_BIGINT,
19902                        getbool(setupdlg->attr[KEY_BIGINT].attr) ?
19903                        BST_CHECKED : BST_UNCHECKED);
19904         CheckDlgButton(hdlg, IDC_JDCONV,
19905                        getbool(setupdlg->attr[KEY_JDCONV].attr) ?
19906                        BST_CHECKED : BST_UNCHECKED);
19907         SendDlgItemMessage(hdlg, IDC_SYNCP,
19908                            CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
19909         SendDlgItemMessage(hdlg, IDC_SYNCP,
19910                            CB_ADDSTRING, 0, (LPARAM) "NORMAL");
19911         SendDlgItemMessage(hdlg, IDC_SYNCP,
19912                            CB_ADDSTRING, 0, (LPARAM) "OFF");
19913         SendDlgItemMessage(hdlg, IDC_SYNCP,
19914                            CB_ADDSTRING, 0, (LPARAM) "FULL");
19915         SendDlgItemMessage(hdlg, IDC_SYNCP,
19916                            CB_SELECTSTRING, (WORD) -1,
19917                            (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19918         if (setupdlg->defDSN) {
19919             EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
19920             EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
19921         }
19922         SetDlgItemText(hdlg, IDC_ATTAS, setupdlg->attr[KEY_ATTAS].attr);
19923         CheckDlgButton(hdlg, IDC_ILIKE,
19924                        getbool(setupdlg->attr[KEY_ILIKE].attr) ?
19925                        BST_CHECKED : BST_UNCHECKED);
19926         return TRUE;
19927     case WM_COMMAND:
19928         switch (GET_WM_COMMAND_ID(wparam, lparam)) {
19929         case IDC_BROWSE:
19930             GetDBFile(hdlg);
19931             break;
19932         case IDOK:
19933 #ifdef _WIN64
19934             setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19935 #else
19936             setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19937 #endif
19938             GetDlgItemText(hdlg, IDC_DSNAME,
19939                            setupdlg->attr[KEY_DSN].attr,
19940                            sizeof (setupdlg->attr[KEY_DSN].attr));
19941             GetDlgItemText(hdlg, IDC_DBNAME,
19942                            setupdlg->attr[KEY_DBNAME].attr,
19943                            sizeof (setupdlg->attr[KEY_DBNAME].attr));
19944             GetDlgItemText(hdlg, IDC_TONAME,
19945                            setupdlg->attr[KEY_BUSY].attr,
19946                            sizeof (setupdlg->attr[KEY_BUSY].attr));
19947             GetDlgItemText(hdlg, IDC_LOADEXT,
19948                            setupdlg->attr[KEY_LOADEXT].attr,
19949                            sizeof (setupdlg->attr[KEY_LOADEXT].attr));
19950             index = SendDlgItemMessage(hdlg, IDC_SYNCP,
19951                                        CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
19952             if (index != (WORD) CB_ERR) {
19953                 SendDlgItemMessage(hdlg, IDC_SYNCP,
19954                                    CB_GETLBTEXT, index,
19955                                    (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19956             }
19957             strcpy(setupdlg->attr[KEY_STEPAPI].attr,
19958                    (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
19959                    "1" : "0");
19960             strcpy(setupdlg->attr[KEY_NOTXN].attr,
19961                    (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
19962                    "1" : "0");
19963             strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
19964                    (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
19965                    "1" : "0");
19966             strcpy(setupdlg->attr[KEY_LONGNAM].attr,
19967                    (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
19968                    "1" : "0");
19969             strcpy(setupdlg->attr[KEY_NOCREAT].attr,
19970                    (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
19971                    "1" : "0");
19972             strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
19973                    (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
19974                    "1" : "0");
19975             strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
19976                    (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
19977                    "1" : "0");
19978             strcpy(setupdlg->attr[KEY_OEMCP].attr,
19979                    (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
19980                    "1" : "0");
19981             strcpy(setupdlg->attr[KEY_BIGINT].attr,
19982                    (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
19983                    "1" : "0");
19984             strcpy(setupdlg->attr[KEY_JDCONV].attr,
19985                    (IsDlgButtonChecked(hdlg, IDC_JDCONV) == BST_CHECKED) ?
19986                    "1" : "0");
19987             GetDlgItemText(hdlg, IDC_ATTAS,
19988                            setupdlg->attr[KEY_ATTAS].attr,
19989                            sizeof (setupdlg->attr[KEY_ATTAS].attr));
19990             strcpy(setupdlg->attr[KEY_ILIKE].attr,
19991                    (IsDlgButtonChecked(hdlg, IDC_ILIKE) == BST_CHECKED) ?
19992                    "1" : "0");
19993             /* FALL THROUGH */
19994         case IDCANCEL:
19995             EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
19996             return TRUE;
19997         }
19998     }
19999     return FALSE;
20000 }
20001 
20015 static SQLRETURN
20016 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
20017                  SQLCHAR *connIn, SQLSMALLINT connInLen,
20018                  SQLCHAR *connOut, SQLSMALLINT connOutMax,
20019                  SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
20020 {
20021     BOOL maybeprompt, prompt = FALSE, defaultdsn = FALSE;
20022     DBC *d;
20023     SETUPDLG *setupdlg;
20024     SQLRETURN ret;
20025     char *dsn = NULL, *driver = NULL, *dbname = NULL;
20026 
20027     if (dbc == SQL_NULL_HDBC) {
20028         return SQL_INVALID_HANDLE;
20029     }
20030     d = (DBC *) dbc;
20031     if (d->sqlite) {
20032         setstatd(d, -1, "connection already established", "08002");
20033         return SQL_ERROR;
20034     }
20035     setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
20036     if (setupdlg == NULL) {
20037         return SQL_ERROR;
20038     }
20039     memset(setupdlg, 0, sizeof (SETUPDLG));
20040     maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
20041         drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
20042     if (connIn == NULL || !connInLen ||
20043         (connInLen == SQL_NTS && !connIn[0])) {
20044         prompt = TRUE;
20045     } else {
20046         ParseAttributes((LPCSTR) connIn, setupdlg);
20047         if (!setupdlg->attr[KEY_DSN].attr[0] &&
20048             drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
20049             strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
20050             defaultdsn = TRUE;
20051         }
20052         GetAttributes(setupdlg);
20053         if (drvcompl == SQL_DRIVER_PROMPT ||
20054             (maybeprompt &&
20055              !setupdlg->attr[KEY_DBNAME].attr[0])) {
20056             prompt = TRUE;
20057         }
20058     }
20059 retry:
20060     if (prompt) {
20061         short dlgret;
20062 
20063         setupdlg->defDSN = setupdlg->attr[KEY_DRIVER].attr[0] != '\0';
20064         dlgret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
20065                                 hwnd, (DLGPROC) DriverConnectProc,
20066                                 (LPARAM) setupdlg);
20067 
20068         if (!dlgret || dlgret == -1) {
20069             xfree(setupdlg);
20070             return SQL_NO_DATA;
20071         }
20072     }
20073     dsn = setupdlg->attr[KEY_DSN].attr;
20074     driver = setupdlg->attr[KEY_DRIVER].attr;
20075     dbname = setupdlg->attr[KEY_DBNAME].attr;
20076     if (connOut || connOutLen) {
20077         char buf[SQL_MAX_MESSAGE_LENGTH * 8];
20078         int len, count;
20079         char dsn_0 = (dsn && !defaultdsn) ? dsn[0] : '\0';
20080         char drv_0 = driver ? driver[0] : '\0';
20081 
20082         buf[0] = '\0';
20083         count = snprintf(buf, sizeof (buf),
20084                          "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
20085                          "SyncPragma=%s;NoTXN=%s;Timeout=%s;"
20086                          "ShortNames=%s;LongNames=%s;"
20087                          "NoCreat=%s;NoWCHAR=%s;"
20088                          "FKSupport=%s;JournalMode=%s;OEMCP=%s;LoadExt=%s;"
20089                          "BigInt=%s;JDConv=%s;PWD=%s;AttachAs=%s;ILike=%s",
20090                          dsn_0 ? "DSN=" : "",
20091                          dsn_0 ? dsn : "",
20092                          dsn_0 ? ";" : "",
20093                          drv_0 ? "Driver=" : "",
20094                          drv_0 ? driver : "",
20095                          drv_0 ? ";" : "",
20096                          dbname ? dbname : "",
20097                          setupdlg->attr[KEY_STEPAPI].attr,
20098                          setupdlg->attr[KEY_SYNCP].attr,
20099                          setupdlg->attr[KEY_NOTXN].attr,
20100                          setupdlg->attr[KEY_BUSY].attr,
20101                          setupdlg->attr[KEY_SHORTNAM].attr,
20102                          setupdlg->attr[KEY_LONGNAM].attr,
20103                          setupdlg->attr[KEY_NOCREAT].attr,
20104                          setupdlg->attr[KEY_NOWCHAR].attr,
20105                          setupdlg->attr[KEY_FKSUPPORT].attr,
20106                          setupdlg->attr[KEY_JMODE].attr,
20107                          setupdlg->attr[KEY_OEMCP].attr,
20108                          setupdlg->attr[KEY_LOADEXT].attr,
20109                          setupdlg->attr[KEY_BIGINT].attr,
20110                          setupdlg->attr[KEY_JDCONV].attr,
20111                          setupdlg->attr[KEY_PASSWD].attr,
20112                          setupdlg->attr[KEY_ATTAS].attr,
20113                          setupdlg->attr[KEY_ILIKE].attr);
20114         if (count < 0) {
20115             buf[sizeof (buf) - 1] = '\0';
20116         }
20117         len = min(connOutMax - 1, strlen(buf));
20118         if (connOut) {
20119             strncpy((char *) connOut, buf, len);
20120             connOut[len] = '\0';
20121         }
20122         if (connOutLen) {
20123             *connOutLen = len;
20124         }
20125     }
20126     if (dsn[0]) {
20127         char tracef[SQL_MAX_MESSAGE_LENGTH];
20128 
20129         tracef[0] = '\0';
20130         SQLGetPrivateProfileString(setupdlg->attr[KEY_DSN].attr,
20131                                    "tracefile", "", tracef,
20132                                    sizeof (tracef), ODBC_INI);
20133         if (tracef[0] != '\0') {
20134             d->trace = fopen(tracef, "a");
20135         }
20136     }
20137     d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr);
20138     d->shortnames = getbool(setupdlg->attr[KEY_SHORTNAM].attr);
20139     d->longnames = getbool(setupdlg->attr[KEY_LONGNAM].attr);
20140     d->nocreat = getbool(setupdlg->attr[KEY_NOCREAT].attr);
20141     d->fksupport = getbool(setupdlg->attr[KEY_FKSUPPORT].attr);
20142     d->oemcp = getbool(setupdlg->attr[KEY_OEMCP].attr);
20143     d->dobigint = getbool(setupdlg->attr[KEY_BIGINT].attr);
20144     d->jdconv = getbool(setupdlg->attr[KEY_JDCONV].attr);
20145     d->ilike = getbool(setupdlg->attr[KEY_ILIKE].attr);
20146     d->pwdLen = strlen(setupdlg->attr[KEY_PASSWD].attr);
20147     d->pwd = (d->pwdLen > 0) ? setupdlg->attr[KEY_PASSWD].attr : NULL;
20148     ret = dbopen(d, dbname ? dbname : "", 0,
20149                  dsn ? dsn : "",
20150                  setupdlg->attr[KEY_STEPAPI].attr,
20151                  setupdlg->attr[KEY_SYNCP].attr,
20152                  setupdlg->attr[KEY_NOTXN].attr,
20153                  setupdlg->attr[KEY_JMODE].attr,
20154                  setupdlg->attr[KEY_BUSY].attr);
20155     if (ret != SQL_SUCCESS) {
20156         if (maybeprompt && !prompt) {
20157             prompt = TRUE;
20158             goto retry;
20159         }
20160     }
20161     memset(setupdlg->attr[KEY_PASSWD].attr, 0,
20162            sizeof (setupdlg->attr[KEY_PASSWD].attr));
20163     if (ret == SQL_SUCCESS) {
20164         dbloadext(d, setupdlg->attr[KEY_LOADEXT].attr);
20165         dbattas(d, setupdlg->attr[KEY_ATTAS].attr);
20166     }
20167     xfree(setupdlg);
20168     return ret;
20169 }
20170 
20171 #endif /* WITHOUT_DRIVERMGR */
20172 #endif /* _WIN32 || _WIN64 */
20173 
20174 #ifndef WINTERFACE
20175 
20188 SQLRETURN SQL_API
20189 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
20190                  SQLCHAR *connIn, SQLSMALLINT connInLen,
20191                  SQLCHAR *connOut, SQLSMALLINT connOutMax,
20192                  SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
20193 {
20194     SQLRETURN ret;
20195 
20196     HDBC_LOCK(dbc);
20197     ret = drvdriverconnect(dbc, hwnd, connIn, connInLen,
20198                            connOut, connOutMax, connOutLen, drvcompl);
20199     HDBC_UNLOCK(dbc);
20200     return ret;
20201 }
20202 #endif
20203 
20204 #ifdef WINTERFACE
20205 
20218 SQLRETURN SQL_API
20219 SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd,
20220                   SQLWCHAR *connIn, SQLSMALLINT connInLen,
20221                   SQLWCHAR *connOut, SQLSMALLINT connOutMax,
20222                   SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
20223 {
20224     SQLRETURN ret;
20225     char *ci = NULL;
20226     SQLSMALLINT len = 0;
20227 
20228     HDBC_LOCK(dbc);
20229     if (connIn) {
20230 #if defined(_WIN32) || defined(_WIN64)
20231         if (connInLen == SQL_NTS) {
20232             connInLen = -1;
20233         }
20234         ci = uc_to_wmb(connIn, connInLen);
20235 #else
20236         ci = uc_to_utf(connIn, connInLen);
20237 #endif
20238         if (!ci) {
20239             DBC *d = (DBC *) dbc;
20240 
20241             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
20242             HDBC_UNLOCK(dbc);
20243             return SQL_ERROR;
20244         }
20245     }
20246     ret = drvdriverconnect(dbc, hwnd, (SQLCHAR *) ci, SQL_NTS,
20247                            (SQLCHAR *) connOut, connOutMax, &len, drvcompl);
20248     HDBC_UNLOCK(dbc);
20249     uc_free(ci);
20250     if (ret == SQL_SUCCESS) {
20251         SQLWCHAR *co = NULL;
20252 
20253         if (connOut) {
20254             if (len > 0) {
20255 #if defined(_WIN32) || defined(_WIN64)
20256                 co = wmb_to_uc((char *) connOut, len);
20257 #else
20258                 co = uc_from_utf((SQLCHAR *) connOut, len);
20259 #endif
20260                 if (co) {
20261                     uc_strncpy(connOut, co, connOutMax / sizeof (SQLWCHAR));
20262                     len = min(connOutMax / sizeof (SQLWCHAR), uc_strlen(co));
20263                     uc_free(co);
20264                 } else {
20265                     len = 0;
20266                 }
20267             }
20268             if (len <= 0) {
20269                 len = 0;
20270                 connOut[0] = 0;
20271             }
20272         } else {
20273             len = 0;
20274         }
20275         if (connOutLen) {
20276             *connOutLen = len;
20277         }
20278     }
20279     return ret;
20280 }
20281 #endif
20282 
20283 #if defined(_WIN32) || defined(_WIN64)
20284 
20293 BOOL APIENTRY
20294 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
20295 {
20296     static int initialized = 0;
20297 
20298     switch (reason) {
20299     case DLL_PROCESS_ATTACH:
20300         if (!initialized++) {
20301             hModule = hinst;
20302 #ifdef WINTERFACE
20303             /* MS Access hack part 1 (reserved error -7748) */
20304             statSpec2P = statSpec2;
20305             statSpec3P = statSpec3;
20306 #endif
20307 #ifdef SQLITE_DYNLOAD
20308             dls_init();
20309 #endif
20310 #ifdef SQLITE_HAS_CODEC
20311             sqlite3_activate_see(SQLITE_ACTIVATION_KEY);
20312 #endif
20313         }
20314 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
20315         nvfs_init();
20316 #endif
20317         break;
20318     case DLL_THREAD_ATTACH:
20319         break;
20320     case DLL_PROCESS_DETACH:
20321         if (--initialized <= 0) {
20322 #ifdef SQLITE_DYNLOAD
20323             dls_fini();
20324 #endif
20325         }
20326         break;
20327     case DLL_THREAD_DETACH:
20328         break;
20329     default:
20330         break;
20331     }
20332     return TRUE;
20333 }
20334 
20343 int __stdcall
20344 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
20345 {
20346     return LibMain(hinst, reason, reserved);
20347 }
20348 
20349 #ifndef WITHOUT_INSTALLER
20350 
20357 static BOOL
20358 InUnError(char *name)
20359 {
20360     WORD err = 1;
20361     DWORD code;
20362     char errmsg[301];
20363     WORD errlen, errmax = sizeof (errmsg) - 1;
20364     int sqlret;
20365     BOOL ret = FALSE;
20366 
20367     do {
20368         errmsg[0] = '\0';
20369         sqlret = SQLInstallerError(err, &code, errmsg, errmax, &errlen);
20370         if (SQL_SUCCEEDED(sqlret)) {
20371             MessageBox(NULL, errmsg, name,
20372                        MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
20373             ret = TRUE;
20374         }
20375         err++;
20376     } while (sqlret != SQL_NO_DATA);
20377     return ret;
20378 }
20379 
20386 static BOOL
20387 InUn(int remove, char *cmdline)
20388 {
20389 #ifdef SQLITE_HAS_CODEC
20390     static char *drivername = "SQLite3 ODBC Driver (SEE)";
20391     static char *dsname = "SQLite3 SEE Datasource";
20392 #else
20393     static char *drivername = "SQLite3 ODBC Driver";
20394     static char *dsname = "SQLite3 Datasource";
20395 #endif
20396     char *dllname, *p;
20397     char dllbuf[301], path[301], driver[300], attr[300], inst[400];
20398     WORD pathmax = sizeof (path) - 1, pathlen;
20399     DWORD usecnt, mincnt;
20400     int quiet = 0;
20401 
20402     dllbuf[0] = '\0';
20403     GetModuleFileName(hModule, dllbuf, sizeof (dllbuf));
20404     p = strrchr(dllbuf, '\\');
20405     dllname = p ? (p + 1) : dllbuf;
20406     quiet = cmdline && strstr(cmdline, "quiet");
20407     if (SQLInstallDriverManager(path, pathmax, &pathlen)) {
20408         sprintf(driver, "%s;Driver=%s;Setup=%s;",
20409                 drivername, dllname, dllname);
20410         p = driver;
20411         while (*p) {
20412             if (*p == ';') {
20413                 *p = '\0';
20414             }
20415             ++p;
20416         }
20417         usecnt = 0;
20418         path[0] = '\0';
20419         SQLInstallDriverEx(driver, NULL, path, pathmax, NULL,
20420                            ODBC_INSTALL_INQUIRY, &usecnt);
20421         pathlen = strlen(path);
20422         while (pathlen > 0 && path[pathlen - 1] == '\\') {
20423             --pathlen;
20424             path[pathlen] = '\0';
20425         }
20426         sprintf(driver, "%s;Driver=%s\\%s;Setup=%s\\%s;",
20427                 drivername, path, dllname, path, dllname);
20428         p = driver;
20429         while (*p) {
20430             if (*p == ';') {
20431                 *p = '\0';
20432             }
20433             ++p;
20434         }
20435         sprintf(inst, "%s\\%s", path, dllname);
20436         if (!remove && usecnt > 0) {
20437             /* first install try: copy over driver dll, keeping DSNs */
20438             if (GetFileAttributesA(dllbuf) != INVALID_FILE_ATTRIBUTES &&
20439                 CopyFile(dllbuf, inst, 0)) {
20440                 if (!quiet) {
20441                     char buf[512];
20442 
20443                     sprintf(buf, "%s replaced.", drivername);
20444                     MessageBox(NULL, buf, "Info",
20445                                MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
20446                                MB_SETFOREGROUND);
20447                 }
20448                 return TRUE;
20449             }
20450         }
20451         mincnt = remove ? 1 : 0;
20452         while (usecnt != mincnt) {
20453             if (!SQLRemoveDriver(driver, TRUE, &usecnt)) {
20454                 break;
20455             }
20456         }
20457         if (remove) {
20458             if (usecnt && !SQLRemoveDriver(driver, TRUE, &usecnt)) {
20459                 InUnError("SQLRemoveDriver");
20460                 return FALSE;
20461             }
20462             if (!usecnt) {
20463                 char buf[512];
20464 
20465                 DeleteFile(inst);
20466                 if (!quiet) {
20467                     sprintf(buf, "%s uninstalled.", drivername);
20468                     MessageBox(NULL, buf, "Info",
20469                                MB_ICONINFORMATION |MB_OK | MB_TASKMODAL |
20470                                MB_SETFOREGROUND);
20471                 }
20472             }
20473             sprintf(attr, "DSN=%s;Database=;", dsname);
20474             p = attr;
20475             while (*p) {
20476                 if (*p == ';') {
20477                     *p = '\0';
20478                 }
20479                 ++p;
20480             }
20481             SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
20482             return TRUE;
20483         }
20484         if (GetFileAttributesA(dllbuf) == INVALID_FILE_ATTRIBUTES) {
20485             return FALSE;
20486         }
20487         if (strcasecmp(dllbuf, inst) != 0 && !CopyFile(dllbuf, inst, 0)) {
20488             char buf[512];
20489 
20490             sprintf(buf, "Copy %s to %s failed.", dllbuf, inst);
20491             MessageBox(NULL, buf, "CopyFile",
20492                        MB_ICONSTOP |MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
20493             return FALSE;
20494         }
20495         if (!SQLInstallDriverEx(driver, path, path, pathmax, &pathlen,
20496                                 ODBC_INSTALL_COMPLETE, &usecnt)) {
20497             InUnError("SQLInstallDriverEx");
20498             return FALSE;
20499         }
20500         sprintf(attr, "DSN=%s;Database=;", dsname);
20501         p = attr;
20502         while (*p) {
20503             if (*p == ';') {
20504                 *p = '\0';
20505             }
20506             ++p;
20507         }
20508         SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
20509         if (!SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, drivername, attr)) {
20510             InUnError("SQLConfigDataSource");
20511             return FALSE;
20512         }
20513         if (!quiet) {
20514             char buf[512];
20515 
20516             sprintf(buf, "%s installed.", drivername);
20517             MessageBox(NULL, buf, "Info",
20518                        MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
20519                        MB_SETFOREGROUND);
20520         }
20521     } else {
20522         InUnError("SQLInstallDriverManager");
20523         return FALSE;
20524     }
20525     return TRUE;
20526 }
20527 
20536 void CALLBACK
20537 install(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20538 {
20539     InUn(0, lpszCmdLine);
20540 }
20541 
20550 void CALLBACK
20551 uninstall(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20552 {
20553     InUn(1, lpszCmdLine);
20554 }
20555 
20556 #endif /* WITHOUT_INSTALLER */
20557 
20558 #ifndef WITHOUT_SHELL
20559 
20568 static void
20569 setargv(int *argcp, char ***argvp, char *cmdline, char *argv0)
20570 {
20571     char *p, *arg, *argspace, **argv;
20572     int argc, size, inquote, copy, slashes;
20573 
20574     size = 2 + (argv0 ? 1 : 0);
20575     for (p = cmdline; *p != '\0'; p++) {
20576         if (ISSPACE(*p)) {
20577             size++;
20578             while (ISSPACE(*p)) {
20579                 p++;
20580             }
20581             if (*p == '\0') {
20582                 break;
20583             }
20584         }
20585     }
20586     argspace = malloc(size * sizeof (char *) + strlen(cmdline) + 1);
20587     argv = (char **) argspace;
20588     argspace += size * sizeof (char *);
20589     size--;
20590     argc = 0;
20591     if (argv0) {
20592         argv[argc++] = argv0;
20593     }
20594     p = cmdline;
20595     for (; argc < size; argc++) {
20596         argv[argc] = arg = argspace;
20597         while (ISSPACE(*p)) {
20598             p++;
20599         }
20600         if (*p == '\0') {
20601             break;
20602         }
20603         inquote = 0;
20604         slashes = 0;
20605         while (1) {
20606             copy = 1;
20607             while (*p == '\\') {
20608                 slashes++;
20609                 p++;
20610             }
20611             if (*p == '"') {
20612                 if ((slashes & 1) == 0) {
20613                     copy = 0;
20614                     if (inquote && p[1] == '"') {
20615                         p++;
20616                         copy = 1;
20617                     } else {
20618                         inquote = !inquote;
20619                     }
20620                 }
20621                 slashes >>= 1;
20622             }
20623             while (slashes) {
20624                 *arg = '\\';
20625                 arg++;
20626                 slashes--;
20627             }
20628             if (*p == '\0' || (!inquote && ISSPACE(*p))) {
20629                 break;
20630             }
20631             if (copy != 0) {
20632                 *arg = *p;
20633                 arg++;
20634             }
20635             p++;
20636         }
20637         *arg = '\0';
20638         argspace = arg + 1;
20639     }
20640     argv[argc] = 0;
20641     *argcp = argc;
20642     *argvp = argv;
20643 }
20644 
20653 void CALLBACK
20654 shell(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20655 {
20656     int argc, needcon = 0;
20657     char **argv;
20658     extern int sqlite3_main(int, char **);
20659     static const char *name = "SQLite3 Shell";
20660     DWORD ftype0, ftype1, ftype2;
20661 
20662     ftype0 = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
20663     ftype1 = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
20664     ftype2 = GetFileType(GetStdHandle(STD_ERROR_HANDLE));
20665     if (ftype0 != FILE_TYPE_DISK && ftype0 != FILE_TYPE_CHAR &&
20666         ftype0 != FILE_TYPE_PIPE) {
20667         fclose(stdin);
20668         ++needcon;
20669         ftype0 = FILE_TYPE_UNKNOWN;
20670     }
20671     if (ftype1 != FILE_TYPE_DISK && ftype1 != FILE_TYPE_CHAR &&
20672         ftype1 != FILE_TYPE_PIPE) {
20673         fclose(stdout);
20674         ++needcon;
20675         ftype1 = FILE_TYPE_UNKNOWN;
20676     }
20677     if (ftype2 != FILE_TYPE_DISK && ftype2 != FILE_TYPE_CHAR &&
20678         ftype2 != FILE_TYPE_PIPE) {
20679         fclose(stderr);
20680         ++needcon;
20681         ftype2 = FILE_TYPE_UNKNOWN;
20682     }
20683     if (needcon > 0) {
20684         AllocConsole();
20685         SetConsoleTitle(name);
20686     }
20687     if (ftype0 == FILE_TYPE_UNKNOWN) {
20688         freopen("CONIN$", "r", stdin);
20689     }
20690     if (ftype1 == FILE_TYPE_UNKNOWN) {
20691         freopen("CONOUT$", "w", stdout);
20692     }
20693     if (ftype2 == FILE_TYPE_UNKNOWN) {
20694         freopen("CONOUT$", "w", stderr);
20695     }
20696     setargv(&argc, &argv, lpszCmdLine, (char *) name);
20697 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
20698     nvfs_init();
20699 #endif
20700     sqlite3_main(argc, argv);
20701 }
20702 
20703 #endif /* WITHOUT_SHELL */
20704 
20705 #endif /* _WIN32 || _WIN64 */
20706 
20707 #if defined(HAVE_ODBCINSTEXT_H) && (HAVE_ODBCINSTEXT_H)
20708 
20709 /*
20710  * unixODBC property page for this driver,
20711  * may or may not work depending on unixODBC version.
20712  */
20713 
20714 #include <odbcinstext.h>
20715 
20716 int
20717 ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
20718 {
20719     static const char *instYN[] = { "No", "Yes", NULL };
20720     static const char *syncPragma[] = { "NORMAL", "OFF", "FULL", NULL };
20721     static const char *jmPragma[] = {
20722         "DELETE", "PERSIST", "OFF", "TRUNCATE", "MEMORY", "WAL", NULL
20723     };
20724 
20725     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20726     prop = prop->pNext;
20727     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20728     prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
20729     strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
20730     strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
20731     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20732     prop = prop->pNext;
20733     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20734     prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
20735     strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
20736     strncpy(prop->szValue, "100000", INI_MAX_PROPERTY_VALUE);
20737     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20738     prop = prop->pNext;
20739     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20740     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20741     prop->aPromptData = malloc(sizeof (instYN));
20742     memcpy(prop->aPromptData, instYN, sizeof (instYN));
20743     strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
20744     strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20745     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20746     prop = prop->pNext;
20747     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20748     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20749     prop->aPromptData = malloc(sizeof (instYN));
20750     memcpy(prop->aPromptData, instYN, sizeof (instYN));
20751     strncpy(prop->szName, "ShortNames", INI_MAX_PROPERTY_NAME);
20752     strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20753     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20754     prop = prop->pNext;
20755     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20756     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20757     prop->aPromptData = malloc(sizeof (instYN));
20758     memcpy(prop->aPromptData, instYN, sizeof (instYN));
20759     strncpy(prop->szName, "LongNames", INI_MAX_PROPERTY_NAME);
20760     strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20761     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20762     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20763     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20764     prop->aPromptData = malloc(sizeof (instYN));
20765     memcpy(prop->aPromptData, instYN, sizeof (instYN));
20766     strncpy(prop->szName, "NoCreat", INI_MAX_PROPERTY_NAME);
20767     strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20768 #ifdef WINTERFACE
20769     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20770     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20771     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20772     prop->aPromptData = malloc(sizeof (instYN));
20773     memcpy(prop->aPromptData, instYN, sizeof (instYN));
20774     strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME);
20775     strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20776 #endif
20777     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20778     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20779     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20780     prop->aPromptData = malloc(sizeof (instYN));
20781     memcpy(prop->aPromptData, instYN, sizeof (instYN));
20782     strncpy(prop->szName, "FKSupport", INI_MAX_PROPERTY_NAME);
20783     strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20784     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20785     prop = prop->pNext;
20786     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20787     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20788     prop->aPromptData = malloc(sizeof (syncPragma));
20789     memcpy(prop->aPromptData, syncPragma, sizeof (syncPragma));
20790     strncpy(prop->szName, "SyncPragma", INI_MAX_PROPERTY_NAME);
20791     strncpy(prop->szValue, "NORMAL", INI_MAX_PROPERTY_VALUE);
20792     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20793     prop = prop->pNext;
20794     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20795     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20796     prop->aPromptData = malloc(sizeof (jmPragma));
20797     memcpy(prop->aPromptData, jmPragma, sizeof (jmPragma));
20798     strncpy(prop->szName, "JournalMode", INI_MAX_PROPERTY_NAME);
20799     strncpy(prop->szValue, "DELETE", INI_MAX_PROPERTY_VALUE);
20800     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20801     prop = prop->pNext;
20802     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20803     prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
20804     strncpy(prop->szName, "LoadExt", INI_MAX_PROPERTY_NAME);
20805     strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
20806     prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20807     memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20808     prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20809     prop->aPromptData = malloc(sizeof (instYN));
20810     memcpy(prop->aPromptData, instYN, sizeof (instYN));
20811     strncpy(prop->szName, "BigInt", INI_MAX_PROPERTY_NAME);
20812     strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20813     return 1;
20814 }
20815 
20816 #endif /* HAVE_ODBCINSTEXT_H */
20817 
20818 #ifdef SQLITE_DYNLOAD
20819 
20820 /*
20821  * SQLite3 shared library/DLL stubs.
20822  */
20823 
20824 static void
20825 dls_void(void)
20826 {
20827 }
20828 
20829 static int
20830 dls_error(void)
20831 {
20832     return SQLITE_ERROR;
20833 }
20834 
20835 static int
20836 dls_0(void)
20837 {
20838     return 0;
20839 }
20840 
20841 static sqlite_int64
20842 dls_0LL(void)
20843 {
20844     return 0;
20845 }
20846 
20847 static double
20848 dls_00(void)
20849 {
20850     return 0;
20851 }
20852 
20853 static void *
20854 dls_null(void)
20855 {
20856     return NULL;
20857 }
20858 
20859 static const char *
20860 dls_empty(void)
20861 {
20862     return "";
20863 }
20864 
20865 static int
20866 dls_snull(void)
20867 {
20868     return SQLITE_NULL;
20869 }
20870 
20871 #define DLS_ENT(name, func)                                             \
20872     { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, name),        \
20873       (void *) func }
20874 
20875 #define DLS_ENT3(name, off, func)                                       \
20876     { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, off),         \
20877       (void *) func }
20878 
20879 #define DLS_END { NULL, 0, NULL }
20880 
20881 static struct {
20882     const char *name;
20883     int offset;
20884     void *func;
20885 } dls_nametab[] = {
20886     DLS_ENT(activate_see, dls_void),
20887     DLS_ENT(bind_blob, dls_error),
20888     DLS_ENT(bind_double, dls_error),
20889     DLS_ENT(bind_int, dls_error),
20890     DLS_ENT(bind_int64, dls_error),
20891     DLS_ENT(bind_null, dls_error),
20892     DLS_ENT(bind_parameter_count, dls_0),
20893     DLS_ENT(bind_text, dls_error),
20894     DLS_ENT(busy_handler, dls_error),
20895     DLS_ENT(changes, dls_0),
20896     DLS_ENT(close, dls_error),
20897     DLS_ENT(column_blob, dls_null),
20898     DLS_ENT(column_bytes, dls_0),
20899     DLS_ENT(column_count, dls_0),
20900     DLS_ENT(column_database_name, dls_empty),
20901     DLS_ENT(column_decltype, dls_empty),
20902     DLS_ENT(column_double, dls_00),
20903     DLS_ENT(column_name, dls_empty),
20904     DLS_ENT(column_origin_name, dls_null),
20905     DLS_ENT(column_table_name, dls_null),
20906     DLS_ENT(column_text, dls_null),
20907     DLS_ENT(column_type, dls_snull),
20908     DLS_ENT(create_function, dls_error),
20909     DLS_ENT(enable_load_extension, dls_error),
20910     DLS_ENT(errcode, dls_error),
20911     DLS_ENT(errmsg, dls_empty),
20912     DLS_ENT(exec, dls_error),
20913     DLS_ENT(finalize, dls_error),
20914     DLS_ENT(free, free),
20915     DLS_ENT(free_table, dls_void),
20916     DLS_ENT(get_table, dls_error),
20917     DLS_ENT(interrupt, dls_void),
20918     DLS_ENT(key, dls_error),
20919     DLS_ENT(last_insert_rowid, dls_0LL),
20920     DLS_ENT(libversion, dls_empty),
20921     DLS_ENT(load_extension, dls_error),
20922     DLS_ENT(malloc, malloc),
20923     DLS_ENT(mprintf, dls_null),
20924     DLS_ENT(open, dls_error),
20925     DLS_ENT(open16, dls_error),
20926     DLS_ENT(open_v2, dls_error),
20927     DLS_ENT(prepare, dls_error),
20928     DLS_ENT(prepare_v2, dls_error),
20929     DLS_ENT(profile, dls_null),
20930     DLS_ENT(realloc, realloc),
20931     DLS_ENT(rekey, dls_error),
20932     DLS_ENT(reset, dls_error),
20933     DLS_ENT(result_blob, dls_void),
20934     DLS_ENT(result_error, dls_void),
20935     DLS_ENT(result_int, dls_void),
20936     DLS_ENT(result_null, dls_void),
20937     DLS_ENT(step, dls_error),
20938 #if defined(_WIN32) || defined(_WIN64)
20939     DLS_ENT3(strnicmp, xstrnicmp, _strnicmp),
20940 #else
20941     DLS_ENT3(strnicmp, xstrnicmp, strncasecmp),
20942 #endif
20943     DLS_ENT(table_column_metadata, dls_error),
20944     DLS_ENT(trace, dls_null),
20945     DLS_ENT(user_data, dls_null),
20946     DLS_ENT(value_blob, dls_null),
20947     DLS_ENT(value_bytes, dls_0),
20948     DLS_ENT(value_text, dls_empty),
20949     DLS_ENT(value_type, dls_snull),
20950     DLS_END
20951 };
20952 
20953 #if defined(_WIN32) || defined(_WIN64)
20954 
20955 static HMODULE sqlite3_dll = 0;
20956 
20957 static void
20958 dls_init(void)
20959 {
20960     int i;
20961     static const char *dll_names[] = {
20962         "System.Data.SQLite.dll",
20963         "sqlite3.dll",
20964         NULL,
20965     };
20966 
20967     i = 0;
20968     while (dll_names[i]) {
20969         sqlite3_dll = LoadLibrary(dll_names[i]);
20970         if (sqlite3_dll) {
20971             break;
20972         }
20973         ++i;
20974     }
20975     i = 0;
20976     while (dls_nametab[i].name) {
20977         void *func = 0, **loc;
20978 
20979         if (sqlite3_dll) {
20980             func = (void *) GetProcAddress(sqlite3_dll, dls_nametab[i].name);
20981         }
20982         if (!func) {
20983             func = dls_nametab[i].func;
20984         }
20985         loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
20986         *loc = func;
20987         ++i;
20988     }
20989     if (!sqlite3_dll) {
20990         char buf[MAXPATHLEN], msg[MAXPATHLEN];
20991 
20992         LoadString(hModule, IDS_DRVTITLE, buf, sizeof (buf));
20993         LoadString(hModule, IDS_DLLERR, msg, sizeof (msg));
20994         MessageBox(NULL, msg, buf,
20995                    MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
20996                    MB_SETFOREGROUND);
20997     }
20998 }
20999 
21000 static void
21001 dls_fini(void)
21002 {
21003     if (sqlite3_dll) {
21004         FreeLibrary(sqlite3_dll);
21005         sqlite3_dll = 0;
21006     }
21007 }
21008 
21009 #else
21010 
21011 #include <dlfcn.h>
21012 
21013 static void *libsqlite3_so = 0;
21014 
21015 void
21016 dls_init(void)
21017 {
21018     int i;
21019 
21020     libsqlite3_so = dlopen("libsqlite3.so.0", RTLD_NOW | RTLD_GLOBAL);
21021     i = 0;
21022     while (dls_nametab[i].name) {
21023         void *func = 0, **loc;
21024 
21025         if (libsqlite3_so) {
21026             func = dlsym(libsqlite3_so, dls_nametab[i].name);
21027         }
21028         if (!func) {
21029             func = dls_nametab[i].func;
21030         }
21031         loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
21032         *loc = func;
21033         ++i;
21034     }
21035     if (!libsqlite3_so) {
21036         const char errmsg[] = "SQLite3 shared library not found.\n";
21037 
21038         write(2, errmsg, sizeof (errmsg) - 1);
21039     }
21040 }
21041 
21042 void
21043 dls_fini(void)
21044 {
21045     if (libsqlite3_so) {
21046         dlclose(libsqlite3_so);
21047         libsqlite3_so = 0;
21048     }
21049 }
21050 
21051 #endif
21052 
21053 #endif
21054 
21055 /*
21056  * Local Variables:
21057  * mode: c
21058  * c-basic-offset: 4
21059  * fill-column: 78
21060  * tab-width: 8
21061  * End:
21062  */

Generated on 23 Oct 2023 by doxygen.
Contact: chw@ch-werner.de