Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

sqlite3odbc.c

Go to the documentation of this file.
00001 
00014 #if defined(SQLITE_HAS_CODEC) && defined(SQLITE_API)
00015 #undef WITH_SQLITE_DLLS
00016 #undef SQLITE_DYNLOAD
00017 #include "sqlite3.c"
00018 #endif
00019 
00020 #if defined(WITH_SQLITE_DLLS) && (WITH_SQLITE_DLLS > 1)
00021 #define SQLITE_DYNLOAD 1
00022 #undef  HAVE_SQLITE3CLOSEV2
00023 #endif
00024 
00025 #include "sqlite3odbc.h"
00026 
00027 #ifdef SQLITE_DYNLOAD
00028 
00029 #undef MEMORY_DEBUG
00030 
00031 #if defined(_WIN32) || defined(_WIN64)
00032 static void dls_init(void);
00033 static void dls_fini(void);
00034 #else
00035 void dls_init(void);
00036 void dls_fini(void);
00037 #endif
00038 
00039 static struct dl_sqlite3_funcs {
00040     void (*activate_see)(const char *p0);
00041     int (*bind_blob)(sqlite3_stmt *p0, int p1, const void *p2, int p3,
00042                      void (*p4)(void *));
00043     int (*bind_double)(sqlite3_stmt *p0, int p1, double p2);
00044     int (*bind_int)(sqlite3_stmt *p0, int p1, int p2);
00045     int (*bind_int64)(sqlite3_stmt *p0, int p1, sqlite_int64 p2);
00046     int (*bind_null)(sqlite3_stmt *p0, int p1);
00047     int (*bind_parameter_count)(sqlite3_stmt *p0);
00048     int (*bind_text)(sqlite3_stmt *p0, int p1, const char *p2, int p3,
00049                      void (*p4)(void *));
00050     int (*busy_handler)(sqlite3 *p0, int (*p2)(void *, int), void *p3);
00051     int (*changes)(sqlite3 *p0);
00052     int (*close)(sqlite3 *p0);
00053     const void * (*column_blob)(sqlite3_stmt *p0, int p1);
00054     int (*column_bytes)(sqlite3_stmt *p0, int p1);
00055     int (*column_count)(sqlite3_stmt *p0);
00056     const char * (*column_database_name)(sqlite3_stmt *p0, int p1);
00057     const char * (*column_decltype)(sqlite3_stmt *p0, int p1);
00058     double (*column_double)(sqlite3_stmt *p0, int p1);
00059     const char * (*column_name)(sqlite3_stmt *p0, int p1);
00060     const char * (*column_origin_name)(sqlite3_stmt *p0, int p1);
00061     const char * (*column_table_name)(sqlite3_stmt *p0, int p1);
00062     const unsigned char * (*column_text)(sqlite3_stmt *p0, int p1);
00063     int (*column_type)(sqlite3_stmt *p0, int p1);
00064     int (*create_function)(sqlite3 *p0, const char *p1, int p2, int p3,
00065                            void *p4,
00066                            void (*p5)(sqlite3_context *, int, sqlite3_value **),
00067                            void (*p6)(sqlite3_context *, int, sqlite3_value **),
00068                            void (*p7)(sqlite3_context *));
00069     int (*enable_load_extension)(sqlite3 *p0, int p1);
00070     int (*errcode)(sqlite3 *p0);
00071     const char * (*errmsg)(sqlite3 *p0);
00072     int (*exec)(sqlite3 *p0, const char *p1,
00073                 int (*p2)(void *, int, char **, char **),
00074                 void *p3, char **p4);
00075     int (*finalize)(sqlite3_stmt *p0);
00076     void (*free)(void *p0);
00077     void (*free_table)(char **p0);
00078     int (*get_table)(sqlite3 *p0, const char *p1, char ***p2,
00079                      int *p3, int *p4, char **p5);
00080     void (*interrupt)(sqlite3 *p0);
00081     int (*key)(sqlite3 *p0, const void *p1, int p2);
00082     sqlite_int64 (*last_insert_rowid)(sqlite3 *p0);
00083     const char * (*libversion)(void);
00084     int (*load_extension)(sqlite3 *p0, const char *p1, const char *p2,
00085                           char **p3);
00086     void * (*malloc)(int p0);
00087     char * (*mprintf)(const char *p0, ...);
00088     int (*open)(const char *p0, sqlite3 **p1);
00089     int (*open16)(const void *p0, sqlite3 **p1);
00090     int (*open_v2)(const char *p0, sqlite3 **p1, int p2, const char *p3);
00091     int (*prepare)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
00092                    const char **p4);
00093     int (*prepare_v2)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
00094                       const char **p4);
00095     void * (*profile)(sqlite3 *p0,
00096                       void (*p1)(void *, const char *, sqlite3_uint64),
00097                       void *p2);
00098     void * (*realloc)(void *p0, int p1);
00099     int (*rekey)(sqlite3 *p0, const void *p1, int p2);
00100     int (*reset)(sqlite3_stmt *p0);
00101     void (*result_blob)(sqlite3_context *p0, const void *p1,
00102                         int p2, void (*p3)(void *));
00103     void (*result_error)(sqlite3_context *p0, const char *p1, int p2);
00104     void (*result_int)(sqlite3_context *p0, int p1);
00105     void (*result_null)(sqlite3_context *p0);
00106     int (*step)(sqlite3_stmt *p0);
00107     int (*xstrnicmp)(const char *p0, const char *p1, int p2);
00108     int (*table_column_metadata)(sqlite3 *p0, const char *p1,
00109                                  const char *p2, const char *p3,
00110                                  char const **p4, char const **p5,
00111                                  int *p6, int *p7, int *p8);
00112     void * (*trace)(sqlite3 *p0, void (*p1)(void *, const char *), void *p2);
00113     void * (*user_data)(sqlite3_context *p0);
00114     const void * (*value_blob)(sqlite3_value *p0);
00115     int (*value_bytes)(sqlite3_value *p0);
00116     const unsigned char * (*value_text)(sqlite3_value *p0);
00117     int (*value_type)(sqlite3_value *p0);
00118 } dls_funcs;
00119 
00120 #define sqlite3_activate_see          dls_funcs.activate_see
00121 #define sqlite3_bind_blob             dls_funcs.bind_blob
00122 #define sqlite3_bind_double           dls_funcs.bind_double
00123 #define sqlite3_bind_int              dls_funcs.bind_int
00124 #define sqlite3_bind_int64            dls_funcs.bind_int64
00125 #define sqlite3_bind_null             dls_funcs.bind_null
00126 #define sqlite3_bind_parameter_count  dls_funcs.bind_parameter_count
00127 #define sqlite3_bind_text             dls_funcs.bind_text
00128 #define sqlite3_busy_handler          dls_funcs.busy_handler
00129 #define sqlite3_changes               dls_funcs.changes
00130 #define sqlite3_close                 dls_funcs.close
00131 #define sqlite3_column_blob           dls_funcs.column_blob
00132 #define sqlite3_column_bytes          dls_funcs.column_bytes
00133 #define sqlite3_column_count          dls_funcs.column_count
00134 #define sqlite3_column_database_name  dls_funcs.column_database_name
00135 #define sqlite3_column_decltype       dls_funcs.column_decltype
00136 #define sqlite3_column_double         dls_funcs.column_double
00137 #define sqlite3_column_name           dls_funcs.column_name
00138 #define sqlite3_column_origin_name    dls_funcs.column_origin_name
00139 #define sqlite3_column_table_name     dls_funcs.column_table_name
00140 #define sqlite3_column_text           dls_funcs.column_text
00141 #define sqlite3_column_type           dls_funcs.column_type
00142 #define sqlite3_create_function       dls_funcs.create_function
00143 #define sqlite3_enable_load_extension dls_funcs.enable_load_extension
00144 #define sqlite3_errcode               dls_funcs.errcode
00145 #define sqlite3_errmsg                dls_funcs.errmsg
00146 #define sqlite3_exec                  dls_funcs.exec
00147 #define sqlite3_finalize              dls_funcs.finalize
00148 #define sqlite3_free                  dls_funcs.free
00149 #define sqlite3_free_table            dls_funcs.free_table
00150 #define sqlite3_get_table             dls_funcs.get_table
00151 #define sqlite3_interrupt             dls_funcs.interrupt
00152 #define sqlite3_key                   dls_funcs.key
00153 #define sqlite3_last_insert_rowid     dls_funcs.last_insert_rowid
00154 #define sqlite3_libversion            dls_funcs.libversion
00155 #define sqlite3_load_extension        dls_funcs.load_extension
00156 #define sqlite3_malloc                dls_funcs.malloc
00157 #define sqlite3_mprintf               dls_funcs.mprintf
00158 #define sqlite3_open                  dls_funcs.open
00159 #define sqlite3_open16                dls_funcs.open16
00160 #define sqlite3_open_v2               dls_funcs.open_v2
00161 #define sqlite3_prepare               dls_funcs.prepare
00162 #define sqlite3_prepare_v2            dls_funcs.prepare_v2
00163 #define sqlite3_profile               dls_funcs.profile
00164 #define sqlite3_realloc               dls_funcs.realloc
00165 #define sqlite3_rekey                 dls_funcs.rekey
00166 #define sqlite3_reset                 dls_funcs.reset
00167 #define sqlite3_result_blob           dls_funcs.result_blob
00168 #define sqlite3_result_error          dls_funcs.result_error
00169 #define sqlite3_result_int            dls_funcs.result_int
00170 #define sqlite3_result_null           dls_funcs.result_null
00171 #define sqlite3_step                  dls_funcs.step
00172 #define sqlite3_strnicmp              dls_funcs.xstrnicmp
00173 #define sqlite3_table_column_metadata dls_funcs.table_column_metadata
00174 #define sqlite3_trace                 dls_funcs.trace
00175 #define sqlite3_user_data             dls_funcs.user_data
00176 #define sqlite3_value_blob            dls_funcs.value_blob
00177 #define sqlite3_value_bytes           dls_funcs.value_bytes
00178 #define sqlite3_value_text            dls_funcs.value_text
00179 #define sqlite3_value_type            dls_funcs.value_type
00180 
00181 #endif
00182 
00183 #ifndef WITHOUT_WINTERFACE
00184 #define WINTERFACE
00185 #define WCHARSUPPORT
00186 #endif
00187 
00188 #if !defined(_WIN32) && !defined(_WIN64)
00189 #if !defined(WCHARSUPPORT) && defined(HAVE_SQLWCHAR) && (HAVE_SQLWCHAR)
00190 #define WCHARSUPPORT
00191 #endif
00192 #endif
00193 
00194 #if defined(WINTERFACE)
00195 #include <sqlucode.h>
00196 #endif
00197 
00198 #if defined(_WIN32) || defined(_WIN64)
00199 #include "resource3.h"
00200 #define ODBC_INI "ODBC.INI"
00201 #ifndef DRIVER_VER_INFO
00202 #define DRIVER_VER_INFO VERSION
00203 #endif
00204 #else
00205 #define ODBC_INI ".odbc.ini"
00206 #endif
00207 
00208 #ifndef DRIVER_VER_INFO
00209 #define DRIVER_VER_INFO "0.0"
00210 #endif
00211 
00212 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
00213 #ifdef _WIN64
00214 #define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
00215 #else
00216 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
00217 #endif
00218 #endif
00219 
00220 #ifndef SETSTMTOPTION_LAST_ARG_TYPE
00221 #define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
00222 #endif
00223 
00224 #undef min
00225 #define min(a, b) ((a) < (b) ? (a) : (b))
00226 #undef max
00227 #define max(a, b) ((a) < (b) ? (b) : (a))
00228 
00229 #ifndef PTRDIFF_T
00230 #define PTRDIFF_T int
00231 #endif
00232 
00233 #define array_size(x) (sizeof (x) / sizeof (x[0]))
00234 
00235 #define stringify1(s) #s
00236 #define stringify(s) stringify1(s)
00237 
00238 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
00239 
00240 /* Column meta data from SQLite support */
00241 #undef FULL_METADATA
00242 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
00243 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
00244 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
00245 #if defined(HAVE_SQLITE3COLUMNORIGINNAME) && (HAVE_SQLITE3COLUMNORIGINNAME)
00246 #define FULL_METADATA 1
00247 #endif
00248 #endif
00249 #endif
00250 #endif
00251 
00252 /* Column types for static string column descriptions (SQLTables etc.) */
00253 
00254 #if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
00255 #define SCOL_VARCHAR SQL_WVARCHAR
00256 #define SCOL_CHAR SQL_WCHAR
00257 #else
00258 #define SCOL_VARCHAR SQL_VARCHAR
00259 #define SCOL_CHAR SQL_CHAR
00260 #endif
00261 
00262 #define ENV_MAGIC  0x53544145
00263 #define DBC_MAGIC  0x53544144
00264 #define DEAD_MAGIC 0xdeadbeef
00265 
00272 typedef struct dstr {
00273     int len;            
00274     int max;            
00275     int oom;            
00276     char buffer[1];     
00277 } dstr;
00278 
00279 static const char *xdigits = "0123456789ABCDEFabcdef";
00280 
00281 #ifdef MEMORY_DEBUG
00282 
00283 static void *
00284 xmalloc_(int n, char *file, int line)
00285 {
00286     int nn = n + 4 * sizeof (long);
00287     long *p;
00288 
00289     p = malloc(nn);
00290     if (!p) {
00291 #if (MEMORY_DEBUG > 1)
00292         fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
00293 #endif
00294         return NULL;
00295     }
00296     p[0] = 0xdead1234;
00297     nn = nn / sizeof (long) - 1;
00298     p[1] = n;
00299     p[nn] = 0xdead5678;
00300 #if (MEMORY_DEBUG > 1)
00301     fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
00302 #endif
00303     return (void *) &p[2];
00304 }
00305 
00306 static void *
00307 xrealloc_(void *old, int n, char *file, int line)
00308 {
00309     int nn = n + 4 * sizeof (long), nnn;
00310     long *p, *pp;
00311 
00312     if (n == 0 || !old) {
00313         return xmalloc_(n, file, line);
00314     }
00315     p = &((long *) old)[-2];
00316     if (p[0] != 0xdead1234) {
00317         fprintf(stderr, "*** low end corruption @ %p\n", old);
00318         abort();
00319     }
00320     nnn = p[1] + 4 * sizeof (long);
00321     nnn = nnn / sizeof (long) - 1;
00322     if (p[nnn] != 0xdead5678) {
00323         fprintf(stderr, "*** high end corruption @ %p\n", old);
00324         abort();
00325     }
00326     pp = realloc(p, nn);
00327     if (!pp) {
00328 #if (MEMORY_DEBUG > 1)
00329         fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
00330 #endif
00331         return NULL;
00332     }
00333 #if (MEMORY_DEBUG > 1)
00334     fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
00335 #endif
00336     p = pp;
00337     p[1] = n;
00338     nn = nn / sizeof (long) - 1;
00339     p[nn] = 0xdead5678;
00340     return (void *) &p[2];
00341 }
00342 
00343 static void
00344 xfree_(void *x, char *file, int line)
00345 {
00346     long *p;
00347     int n;
00348 
00349     if (!x) {
00350         return;
00351     }
00352     p = &((long *) x)[-2];
00353     if (p[0] != 0xdead1234) {
00354         fprintf(stderr, "*** low end corruption @ %p\n", x);
00355         abort();
00356     }
00357     n = p[1] + 4 * sizeof (long);
00358     n = n / sizeof (long) - 1;
00359     if (p[n] != 0xdead5678) {
00360         fprintf(stderr, "*** high end corruption @ %p\n", x);
00361         abort();
00362     }
00363 #if (MEMORY_DEBUG > 1)
00364     fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
00365 #endif
00366     free(p);
00367 }
00368 
00369 static void
00370 xfree__(void *x)
00371 {
00372     xfree_(x, "unknown location", 0);
00373 }
00374 
00375 static char *
00376 xstrdup_(const char *str, char *file, int line)
00377 {
00378     char *p;
00379 
00380     if (!str) {
00381 #if (MEMORY_DEBUG > 1)
00382         fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
00383 #endif
00384         return NULL;
00385     }
00386     p = xmalloc_(strlen(str) + 1, file, line);
00387     if (p) {
00388         strcpy(p, str);
00389     }
00390 #if (MEMORY_DEBUG > 1)
00391     fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
00392 #endif
00393     return p;
00394 }
00395 
00396 #define xmalloc(x)    xmalloc_(x, __FILE__, __LINE__)
00397 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
00398 #define xfree(x)      xfree_(x, __FILE__, __LINE__)
00399 #define xstrdup(x)    xstrdup_(x, __FILE__, __LINE__)
00400 
00401 #else
00402 
00403 #define xmalloc(x)    sqlite3_malloc(x)
00404 #define xrealloc(x,y) sqlite3_realloc(x, y)
00405 #define xfree(x)      sqlite3_free(x)
00406 #define xstrdup(x)    strdup_(x)
00407 
00408 #endif
00409 
00410 #if defined(_WIN32) || defined(_WIN64)
00411 
00412 #define vsnprintf   _vsnprintf
00413 #define snprintf    _snprintf
00414 #define strcasecmp  _stricmp
00415 #define strncasecmp _strnicmp
00416 
00417 #ifdef _MSC_VER
00418 #define strtoll     _strtoi64
00419 #define strtoull    _strtoui64
00420 #endif
00421 
00422 static HINSTANCE NEAR hModule;  /* Saved module handle for resources */
00423 
00424 #endif
00425 
00426 #ifdef HAVE_SQLITE3STRNICMP
00427 #undef  strncasecmp
00428 #define strncasecmp(A,B,C) sqlite3_strnicmp(A,B,C)
00429 #undef  strcasecmp
00430 #define strcasecmp(A,B) strcasecmp_(A,B)
00431 
00432 #if defined(__GNUC__) && (__GNUC__ >= 2)
00433 static int strcasecmp_(const char *a, const char *b)
00434     __attribute__((__unused__));
00435 #endif
00436 
00437 static int strcasecmp_(const char *a, const char *b)
00438 {
00439     int c = strlen(a), d = strlen(b);
00440 
00441     if (c > d) {
00442         return strncasecmp(a, b, c);
00443     }
00444     return strncasecmp(a, b, d);
00445 }
00446 #endif
00447 
00448 #if defined(_WIN32) || defined(_WIN64)
00449 
00450 /*
00451  * SQLHENV, SQLHDBC, and SQLHSTMT synchronization
00452  * is done using a critical section in ENV and DBC
00453  * structures.
00454  */
00455 
00456 #define HDBC_LOCK(hdbc)                         \
00457 {                                               \
00458     DBC *d;                                     \
00459                                                 \
00460     if ((hdbc) == SQL_NULL_HDBC) {              \
00461         return SQL_INVALID_HANDLE;              \
00462     }                                           \
00463     d = (DBC *) (hdbc);                         \
00464     if (d->magic != DBC_MAGIC) {                \
00465         return SQL_INVALID_HANDLE;              \
00466     }                                           \
00467     EnterCriticalSection(&d->cs);               \
00468     d->owner = GetCurrentThreadId();            \
00469 }
00470 
00471 #define HDBC_UNLOCK(hdbc)                       \
00472     if ((hdbc) != SQL_NULL_HDBC) {              \
00473         DBC *d;                                 \
00474                                                 \
00475         d = (DBC *) (hdbc);                     \
00476         if (d->magic == DBC_MAGIC) {            \
00477             d->owner = 0;                       \
00478             LeaveCriticalSection(&d->cs);       \
00479         }                                       \
00480     }
00481 
00482 #define HSTMT_LOCK(hstmt)                       \
00483 {                                               \
00484     DBC *d;                                     \
00485                                                 \
00486     if ((hstmt) == SQL_NULL_HSTMT) {            \
00487         return SQL_INVALID_HANDLE;              \
00488     }                                           \
00489     d = (DBC *) ((STMT *) (hstmt))->dbc;        \
00490     if (d->magic != DBC_MAGIC) {                \
00491         return SQL_INVALID_HANDLE;              \
00492     }                                           \
00493     EnterCriticalSection(&d->cs);               \
00494     d->owner = GetCurrentThreadId();            \
00495 }
00496 
00497 #define HSTMT_UNLOCK(hstmt)                     \
00498     if ((hstmt) != SQL_NULL_HSTMT) {            \
00499         DBC *d;                                 \
00500                                                 \
00501         d = (DBC *) ((STMT *) (hstmt))->dbc;    \
00502         if (d->magic == DBC_MAGIC) {            \
00503             d->owner = 0;                       \
00504             LeaveCriticalSection(&d->cs);       \
00505         }                                       \
00506     }
00507 
00508 #else
00509 
00510 /*
00511  * On UN*X assume that we are single-threaded or
00512  * the driver manager provides serialization for us.
00513  *
00514  * In iODBC (3.52.x) serialization can be turned
00515  * on using the DSN property "ThreadManager=yes".
00516  *
00517  * In unixODBC that property is named
00518  * "Threading=0-3" and takes one of these values:
00519  *
00520  *   0 - no protection
00521  *   1 - statement level protection
00522  *   2 - connection level protection
00523  *   3 - environment level protection
00524  *
00525  * unixODBC 2.2.11 uses environment level protection
00526  * by default when it has been built with pthread
00527  * support.
00528  */
00529 
00530 #define HDBC_LOCK(hdbc)
00531 #define HDBC_UNLOCK(hdbc)
00532 #define HSTMT_LOCK(hdbc)
00533 #define HSTMT_UNLOCK(hdbc)
00534 
00535 #endif
00536 
00537 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
00538 extern void nvfs_init(void);
00539 extern const char *nvfs_makevfs(const char *);
00540 #endif
00541 
00542 /*
00543  * tolower() replacement w/o locale
00544  */
00545 
00546 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00547 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
00548 
00549 static int
00550 TOLOWER(int c)
00551 {
00552     if (c) {
00553         char *p = strchr(upper_chars, c);
00554 
00555         if (p) {
00556             c = lower_chars[p - upper_chars];
00557         }
00558     }
00559     return c;
00560 }
00561 
00562 /*
00563  * isdigit() replacement w/o ctype.h
00564  */
00565 
00566 static const char digit_chars[] = "0123456789";
00567 
00568 #define ISDIGIT(c) \
00569     ((c) && strchr(digit_chars, (c)) != NULL)
00570 
00571 /*
00572  * isspace() replacement w/o ctype.h
00573  */
00574 
00575 static const char space_chars[] = " \f\n\r\t\v";
00576 
00577 #define ISSPACE(c) \
00578     ((c) && strchr(space_chars, (c)) != NULL)
00579 
00580 
00581 /*
00582  * Forward declarations of static functions.
00583  */
00584 
00585 static void dbtraceapi(DBC *d, char *fn, const char *sql);
00586 static void freedyncols(STMT *s);
00587 static void freeresult(STMT *s, int clrcols);
00588 static void freerows(char **rowp);
00589 static void unbindcols(STMT *s);
00590 static void s3stmt_drop(STMT *s);
00591 
00592 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
00593 static SQLRETURN freestmt(HSTMT stmt);
00594 static SQLRETURN mkbindcols(STMT *s, int ncols);
00595 static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp);
00596 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
00597 static SQLRETURN starttran(STMT *s);
00598 static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
00599 static SQLRETURN getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
00600                             SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp,
00601                             int partial);
00602 
00603 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
00604 /* MS Access hack part 1 (reserved error -7748) */
00605 static COL *statSpec2P, *statSpec3P;
00606 #endif
00607 
00608 #if (MEMORY_DEBUG < 1)
00609 
00615 static char *
00616 strdup_(const char *str)
00617 {
00618     char *p = NULL;
00619 
00620     if (str) {
00621         p = xmalloc(strlen(str) + 1);
00622         if (p) {
00623             strcpy(p, str);
00624         }
00625     }
00626     return p;
00627 }
00628 #endif
00629 
00637 static dstr *
00638 dsappend(dstr *dsp, const char *str)
00639 {
00640     int len;
00641 
00642     if (!str) {
00643         return dsp;
00644     }
00645     len = strlen(str);
00646     if (!dsp) {
00647         int max = 256;
00648 
00649         if (max < len) {
00650             max += len;
00651         }
00652         dsp = xmalloc(max);
00653         if (dsp) {
00654             dsp->max = max;
00655             dsp->len = dsp->oom = 0;
00656             goto copy;
00657         }
00658         return dsp;
00659     }
00660     if (dsp->oom) {
00661         return dsp;
00662     }
00663     if (dsp->len + len > dsp->max) {
00664         int max = dsp->max + len + 256;
00665         dstr *ndsp = xrealloc(dsp, max);
00666 
00667         if (!ndsp) {
00668             strcpy(dsp->buffer, "OUT OF MEMORY");
00669             dsp->max = dsp->len = 13;
00670             dsp->oom = 1;
00671             return dsp;
00672         }
00673         dsp = ndsp;
00674         dsp->max = max;
00675     }
00676 copy:
00677     strcpy(dsp->buffer + dsp->len, str);
00678     dsp->len += len;
00679     return dsp;
00680 }
00681 
00689 static dstr *
00690 dsappendq(dstr *dsp, const char *str)
00691 {
00692     int len;
00693     const char *p;
00694     char *q;
00695 
00696     if (!str) {
00697         return dsp;
00698     }
00699     len = strlen(str);
00700     for (p = str; *p; ++p) {
00701         if (p[0] == '"') {
00702             ++len;
00703         }
00704     }
00705     len += 2;
00706     if (!dsp) {
00707         int max = 256;
00708 
00709         if (max < len) {
00710             max += len;
00711         }
00712         dsp = xmalloc(max);
00713         if (dsp) {
00714             dsp->max = max;
00715             dsp->len = dsp->oom = 0;
00716             goto copy;
00717         }
00718         return dsp;
00719     }
00720     if (dsp->oom) {
00721         return dsp;
00722     }
00723     if (dsp->len + len > dsp->max) {
00724         int max = dsp->max + len + 256;
00725         dstr *ndsp = xrealloc(dsp, max);
00726 
00727         if (!ndsp) {
00728             strcpy(dsp->buffer, "OUT OF MEMORY");
00729             dsp->max = dsp->len = 13;
00730             dsp->oom = 1;
00731             return dsp;
00732         }
00733         dsp = ndsp;
00734         dsp->max = max;
00735     }
00736 copy:
00737     q = dsp->buffer + dsp->len;
00738     *q++ = '"';
00739     for (p = str; *p; ++p) {
00740         *q++ = *p;
00741         if (p[0] == '"') {
00742             *q++ = '"';
00743         }
00744     }
00745     *q++ = '"';
00746     *q = '\0';
00747     dsp->len += len;
00748     return dsp;
00749 }
00750 
00757 static const char *
00758 dsval(dstr *dsp)
00759 {
00760     if (dsp) {
00761         return (const char *) dsp->buffer;
00762     }
00763     return "ERROR";
00764 }
00765 
00772 static int
00773 dserr(dstr *dsp)
00774 {
00775     return !dsp || dsp->oom;
00776 }
00777 
00783 static void
00784 dsfree(dstr *dsp)
00785 {
00786     if (dsp) {
00787         xfree(dsp);
00788     }
00789 }
00790 
00791 #ifdef WCHARSUPPORT
00792 
00799 static int
00800 uc_strlen(SQLWCHAR *str)
00801 {
00802     int len = 0;
00803 
00804     if (str) {
00805         while (*str) {
00806             ++len;
00807             ++str;
00808         }
00809     }
00810     return len;
00811 }
00812 
00821 static SQLWCHAR *
00822 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
00823 {
00824     int i = 0;
00825 
00826     while (i < len) {
00827         if (!src[i]) {
00828             break;
00829         }
00830         dest[i] = src[i];
00831         ++i;
00832     }
00833     if (i < len) {
00834         dest[i] = 0;
00835     }
00836     return dest;
00837 }
00838 
00847 static void
00848 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
00849 {
00850     ucLen = ucLen / sizeof (SQLWCHAR);
00851     if (!uc || ucLen < 0) {
00852         return;
00853     }
00854     if (len < 0) {
00855         len = ucLen * 5;
00856     }
00857     uc[0] = 0;
00858     if (str) {
00859         int i = 0;
00860 
00861         while (i < len && *str && i < ucLen) {
00862             unsigned char c = str[0];
00863 
00864             if (c < 0x80) {
00865                 uc[i++] = c;
00866                 ++str;
00867             } else if (c <= 0xc1 || c >= 0xf5) {
00868                 /* illegal, ignored */
00869                 ++str;
00870             } else if (c < 0xe0) {
00871                 if ((str[1] & 0xc0) == 0x80) {
00872                     unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
00873 
00874                     uc[i++] = t;
00875                     str += 2;
00876                 } else {
00877                     uc[i++] = c;
00878                     ++str;
00879                 }
00880             } else if (c < 0xf0) {
00881                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
00882                     unsigned long t = ((c & 0x0f) << 12) |
00883                         ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
00884 
00885                     uc[i++] = t;
00886                     str += 3;
00887                 } else {
00888                     uc[i++] = c;
00889                     ++str;
00890                 }
00891             } else if (c < 0xf8) {
00892                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00893                     (str[3] & 0xc0) == 0x80) {
00894                     unsigned long t = ((c & 0x03) << 18) |
00895                         ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
00896                         (str[3] & 0x3f);
00897 
00898                     if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00899                         t >= 0x10000) {
00900                         t -= 0x10000;
00901                         uc[i++] = 0xd800 | ((t >> 10) & 0x3ff);
00902                         if (i >= ucLen) {
00903                             break;
00904                         }
00905                         t = 0xdc00 | (t & 0x3ff);
00906                     }
00907                     uc[i++] = t;
00908                     str += 4;
00909                 } else {
00910                     uc[i++] = c;
00911                     ++str;
00912                 }
00913             } else {
00914                 /* ignore */
00915                 ++str;
00916             }
00917         }
00918         if (i < ucLen) {
00919             uc[i] = 0;
00920         }
00921     }
00922 }
00923 
00931 static SQLWCHAR *
00932 uc_from_utf(unsigned char *str, int len)
00933 {
00934     SQLWCHAR *uc = NULL;
00935     int ucLen;
00936 
00937     if (str) {
00938         if (len == SQL_NTS) {
00939             len = strlen((char *) str);
00940         }
00941         ucLen = sizeof (SQLWCHAR) * (len + 1);
00942         uc = xmalloc(ucLen);
00943         if (uc) {
00944             uc_from_utf_buf(str, len, uc, ucLen);
00945         }
00946     }
00947     return uc;
00948 }
00949 
00957 static char *
00958 uc_to_utf(SQLWCHAR *str, int len)
00959 {
00960     int i;
00961     char *cp, *ret = NULL;
00962 
00963     if (!str) {
00964         return ret;
00965     }
00966     if (len == SQL_NTS) {
00967         len = uc_strlen(str);
00968     } else {
00969         len = len / sizeof (SQLWCHAR);
00970     }
00971     cp = xmalloc(len * 6 + 1);
00972     if (!cp) {
00973         return ret;
00974     }
00975     ret = cp;
00976     for (i = 0; i < len; i++) {
00977         unsigned long c = str[i];
00978 
00979         if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
00980             c &= 0xffff;
00981         }
00982         if (c < 0x80) {
00983             *cp++ = c;
00984         } else if (c < 0x800) {
00985             *cp++ = 0xc0 | ((c >> 6) & 0x1f);
00986             *cp++ = 0x80 | (c & 0x3f);
00987         } else if (c < 0x10000) {
00988             if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00989                 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
00990                 unsigned long c2 = str[i + 1] & 0xffff;
00991 
00992                 if (c2 >= 0xdc00 && c2 <= 0xdfff) {
00993                     c = (((c & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
00994                     *cp++ = 0xf0 | ((c >> 18) & 0x07);
00995                     *cp++ = 0x80 | ((c >> 12) & 0x3f);
00996                     *cp++ = 0x80 | ((c >> 6) & 0x3f);
00997                     *cp++ = 0x80 | (c & 0x3f);
00998                     ++i;
00999                     continue;
01000                 }
01001             }
01002             *cp++ = 0xe0 | ((c >> 12) & 0x0f);
01003             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01004             *cp++ = 0x80 | (c & 0x3f);
01005         } else if (c <= 0x10ffff) {
01006             *cp++ = 0xf0 | ((c >> 18) & 0x07);
01007             *cp++ = 0x80 | ((c >> 12) & 0x3f);
01008             *cp++ = 0x80 | ((c >> 6) & 0x3f);
01009             *cp++ = 0x80 | (c & 0x3f);
01010         }
01011     }
01012     *cp = '\0';
01013     return ret;
01014 }
01015 
01016 #endif
01017 
01018 #ifdef WINTERFACE
01019 
01027 static char *
01028 uc_to_utf_c(SQLWCHAR *str, int len)
01029 {
01030     if (len != SQL_NTS) {
01031         len = len * sizeof (SQLWCHAR);
01032     }
01033     return uc_to_utf(str, len);
01034 }
01035 
01036 #endif
01037 
01038 #if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
01039 
01045 static void
01046 uc_free(void *str)
01047 {
01048     if (str) {
01049         xfree(str);
01050     }
01051 }
01052 
01053 #endif
01054 
01055 #if defined(_WIN32) || defined(_WIN64)
01056 
01064 static char *
01065 wmb_to_utf(char *str, int len)
01066 {
01067     WCHAR *wstr;
01068     OSVERSIONINFO ovi;
01069     int nchar, is2k, cp = CP_OEMCP;
01070 
01071     ovi.dwOSVersionInfoSize = sizeof (ovi);
01072     GetVersionEx(&ovi);
01073     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01074     if (AreFileApisANSI()) {
01075         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01076     }
01077     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01078     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01079     if (!wstr) {
01080         return NULL;
01081     }
01082     wstr[0] = 0;
01083     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01084     wstr[nchar] = 0;
01085     str = xmalloc((nchar + 1) * 7);
01086     if (!str) {
01087         xfree(wstr);
01088         return NULL;
01089     }
01090     str[0] = '\0';
01091     nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
01092     str[nchar] = '\0';
01093     xfree(wstr);
01094     return str;
01095 }
01096 
01097 #ifndef WINTERFACE
01098 
01106 static char *
01107 wmb_to_utf_c(char *str, int len)
01108 {
01109     if (len == SQL_NTS) {
01110         len = strlen(str);
01111     }
01112     return wmb_to_utf(str, len);
01113 }
01114 
01115 #endif
01116 
01124 static char *
01125 utf_to_wmb(char *str, int len)
01126 {
01127     WCHAR *wstr;
01128     OSVERSIONINFO ovi;
01129     int nchar, is2k, cp = CP_OEMCP;
01130 
01131     ovi.dwOSVersionInfoSize = sizeof (ovi);
01132     GetVersionEx(&ovi);
01133     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01134     if (AreFileApisANSI()) {
01135         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01136     }
01137     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
01138     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01139     if (!wstr) {
01140         return NULL;
01141     }
01142     wstr[0] = 0;
01143     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
01144     wstr[nchar] = 0;
01145     str = xmalloc((nchar + 1) * 7);
01146     if (!str) {
01147         xfree(wstr);
01148         return NULL;
01149     }
01150     str[0] = '\0';
01151     nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
01152     str[nchar] = '\0';
01153     xfree(wstr);
01154     return str;
01155 }
01156 
01157 #ifdef WINTERFACE
01158 
01166 static WCHAR *
01167 wmb_to_uc(char *str, int len)
01168 {
01169     WCHAR *wstr;
01170     OSVERSIONINFO ovi;
01171     int nchar, is2k, cp = CP_OEMCP;
01172 
01173     ovi.dwOSVersionInfoSize = sizeof (ovi);
01174     GetVersionEx(&ovi);
01175     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01176     if (AreFileApisANSI()) {
01177         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01178     }
01179     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01180     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01181     if (!wstr) {
01182         return NULL;
01183     }
01184     wstr[0] = 0;
01185     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01186     wstr[nchar] = 0;
01187     return wstr;
01188 }
01189 
01197 static char *
01198 uc_to_wmb(WCHAR *wstr, int len)
01199 {
01200     char *str;
01201     OSVERSIONINFO ovi;
01202     int nchar, is2k, cp = CP_OEMCP;
01203 
01204     ovi.dwOSVersionInfoSize = sizeof (ovi);
01205     GetVersionEx(&ovi);
01206     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01207     if (AreFileApisANSI()) {
01208         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01209     }
01210     nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
01211     str = xmalloc((nchar + 1) * 2);
01212     if (!str) {
01213         return NULL;
01214     }
01215     str[0] = '\0';
01216     nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
01217     str[nchar] = '\0';
01218     return str;
01219 }
01220 
01221 #endif /* WINTERFACE */
01222 
01223 #endif /* _WIN32 || _WIN64 */
01224 
01225 
01226 #ifdef USE_DLOPEN_FOR_GPPS
01227 
01228 #include <dlfcn.h>
01229 
01230 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
01231 
01232 /*
01233  * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
01234  * dlopen(), in theory this makes the driver independent from the
01235  * driver manager, i.e. the same driver binary can run with iODBC
01236  * and unixODBC.
01237  */
01238 
01239 static void
01240 drvgetgpps(DBC *d)
01241 {
01242     void *lib;
01243     int (*gpps)();
01244 
01245     lib = dlopen("libodbcinst.so.2", RTLD_LAZY);
01246     if (!lib) {
01247         lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
01248     }
01249     if (!lib) {
01250         lib = dlopen("libodbcinst.so", RTLD_LAZY);
01251     }
01252     if (!lib) {
01253         lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
01254     }
01255     if (!lib) {
01256         lib = dlopen("libiodbcinst.so", RTLD_LAZY);
01257     }
01258     if (lib) {
01259         gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
01260         if (!gpps) {
01261             dlclose(lib);
01262             return;
01263         }
01264         d->instlib = lib;
01265         d->gpps = gpps;
01266     }
01267 }
01268 
01269 static void
01270 drvrelgpps(DBC *d)
01271 {
01272     if (d->instlib) {
01273         dlclose(d->instlib);
01274         d->instlib = 0;
01275     }
01276 }
01277 
01278 static int
01279 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
01280         int bufsiz, char *fname)
01281 {
01282     if (d->gpps) {
01283         return d->gpps(sect, ent, def, buf, bufsiz, fname);
01284     }
01285     strncpy(buf, def, bufsiz);
01286     buf[bufsiz - 1] = '\0';
01287     return 1;
01288 }
01289 #else
01290 #include <odbcinst.h>
01291 #define drvgetgpps(d)
01292 #define drvrelgpps(d)
01293 #endif
01294 
01295 /*
01296  * Internal function to bind SQLite3 parameters.
01297  */
01298 
01299 static void
01300 s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
01301 {
01302     int i;
01303 
01304     if (stmt && p && nparams > 0) {
01305         for (i = 0; i < nparams; i++, p++) {
01306             switch (p->s3type) {
01307             default:
01308             case SQLITE_NULL:
01309                 sqlite3_bind_null(stmt, i + 1);
01310                 if (d->trace) {
01311                     fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
01312                     fflush(d->trace);
01313                 }
01314                 break;
01315             case SQLITE_TEXT:
01316                 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
01317                                   SQLITE_STATIC);
01318                 if (d->trace) {
01319                     fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
01320                             p->s3size, (char *) p->s3val);
01321                     fflush(d->trace);
01322                 }
01323                 break;
01324             case SQLITE_BLOB:
01325                 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
01326                                   SQLITE_STATIC);
01327                 if (d->trace) {
01328                     fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
01329                     fflush(d->trace);
01330                 }
01331                 break;
01332             case SQLITE_FLOAT:
01333                 sqlite3_bind_double(stmt, i + 1, p->s3dval);
01334                 if (d->trace) {
01335                     fprintf(d->trace, "-- parameter %d: %g\n",
01336                             i + 1, p->s3dval);
01337                     fflush(d->trace);
01338                 }
01339                 break;
01340             case SQLITE_INTEGER:
01341                 if (p->s3size > sizeof (int)) {
01342                     sqlite3_bind_int64(stmt, i + 1, p->s3lival);
01343                     if (d->trace) {
01344                         fprintf(d->trace,
01345 #ifdef _WIN32
01346                                 "-- parameter %d: %I64d\n",
01347 #else
01348                                 "-- parameter %d: %lld\n",
01349 #endif
01350                                 i + 1, p->s3lival);
01351                         fflush(d->trace);
01352                     }
01353                 } else {
01354                     sqlite3_bind_int(stmt, i + 1, p->s3ival);
01355                     if (d->trace) {
01356                         fprintf(d->trace, "-- parameter %d: %d\n",
01357                                 i + 1, p->s3ival);
01358                         fflush(d->trace);
01359                     }
01360                 }
01361                 break;
01362             }
01363         }
01364     }
01365 }
01366 
01374 typedef struct tblres {
01375     char **resarr;      
01376     char *errmsg;       
01377     sqlite3_stmt *stmt; 
01378     STMT *s;            
01379     int nalloc;         
01380     int nrow;           
01381     int ncol;           
01382     PTRDIFF_T ndata;    
01383     int rc;             
01384 } TBLRES;
01385 
01386 /*
01387  * Driver's version of sqlite3_get_table() and friends which are
01388  * capable of dealing with blobs.
01389  */
01390 
01391 static int
01392 drvgettable_row(TBLRES *t, int ncol, int rc)
01393 {
01394     int need;
01395     int i;
01396     char *p;
01397 
01398     if (t->nrow == 0 && rc == SQLITE_ROW) {
01399         need = ncol * 2;
01400     } else {
01401         need = ncol;
01402     }
01403     if (t->ndata + need >= t->nalloc) {
01404         char **resnew;
01405         int nalloc = t->nalloc * 2 + need + 1;
01406 
01407         resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
01408         if (!resnew) {
01409 nomem:
01410             t->rc = SQLITE_NOMEM;
01411             return 1;
01412         }
01413         t->nalloc = nalloc;
01414         t->resarr = resnew;
01415     }
01416     /* column names when first row */
01417     if (t->nrow == 0) {
01418         t->ncol = ncol;
01419         for (i = 0; i < ncol; i++) {
01420             p = (char *) sqlite3_column_name(t->stmt, i);
01421             if (p) {
01422                 char *q = xmalloc(strlen(p) + 1);
01423 
01424                 if (!q) {
01425                     goto nomem;
01426                 }
01427                 strcpy(q, p);
01428                 p = q;
01429             }
01430             t->resarr[t->ndata++] = p;
01431         }
01432         if (t->s && t->s->guessed_types) {
01433             int ncol2 = ncol;
01434 
01435             setupdyncols(t->s, t->stmt, &ncol2);
01436             t->s->guessed_types = 0;
01437             t->s->ncols = ncol;
01438         }
01439     } else if (t->ncol != ncol) {
01440         t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
01441                                     " more incompatible queries");
01442         t->rc = SQLITE_ERROR;
01443         return 1;
01444     }
01445     /* copy row data */
01446     if (rc == SQLITE_ROW) {
01447         for (i = 0; i < ncol; i++) {
01448             int coltype = sqlite3_column_type(t->stmt, i);
01449 
01450             p = NULL;
01451             if (coltype == SQLITE_BLOB) {
01452                 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
01453                 char *qp;
01454                 unsigned const char *bp;
01455 
01456                 bp = sqlite3_column_blob(t->stmt, i);
01457                 qp = xmalloc(nbytes * 2 + 4);
01458                 if (!qp) {
01459                     goto nomem;
01460                 }
01461                 p = qp;
01462                 *qp++ = 'X';
01463                 *qp++ = '\'';
01464                 for (k = 0; k < nbytes; k++) {
01465                     *qp++ = xdigits[(bp[k] >> 4)];
01466                     *qp++ = xdigits[(bp[k] & 0xF)];
01467                 }
01468                 *qp++ = '\'';
01469                 *qp = '\0';
01470 #ifdef _MSC_VER
01471             } else if (coltype == SQLITE_FLOAT) {
01472                 struct lconv *lc = 0;
01473                 double val = sqlite3_column_double(t->stmt, i);
01474                 char buffer[128];
01475 
01476                 /*
01477                  * This avoids floating point rounding
01478                  * and formatting problems of some SQLite
01479                  * versions in conjunction with MSVC 2010.
01480                  */
01481                 snprintf(buffer, sizeof (buffer), "%.15g", val);
01482                 lc = localeconv();
01483                 if (lc && lc->decimal_point && lc->decimal_point[0] &&
01484                     lc->decimal_point[0] != '.') {
01485                     p = strchr(buffer, lc->decimal_point[0]);
01486                     if (p) {
01487                         *p = '.';
01488                     }
01489                 }
01490                 p = xstrdup(buffer);
01491                 if (!p) {
01492                     goto nomem;
01493                 }
01494 #endif
01495             } else if (coltype != SQLITE_NULL) {
01496                 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
01497                 if (!p) {
01498                     goto nomem;
01499                 }
01500             }
01501             t->resarr[t->ndata++] = p;
01502         }
01503         t->nrow++;
01504     }
01505     return 0;
01506 }
01507 
01508 static int
01509 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
01510             int *ncolp, char **errp, int nparam, BINDPARM *p)
01511 {
01512     DBC *d = (DBC *) s->dbc;
01513     int rc = SQLITE_OK, keep = sql == NULL;
01514     TBLRES tres;
01515     const char *sqlleft = 0;
01516     int nretry = 0, haveerr = 0;
01517 
01518     if (!resp) {
01519         return SQLITE_ERROR;
01520     }
01521     *resp = NULL;
01522     if (nrowp) {
01523         *nrowp = 0;
01524     }
01525     if (ncolp) {
01526         *ncolp = 0;
01527     }
01528     tres.errmsg = NULL;
01529     tres.nrow = 0;
01530     tres.ncol = 0;
01531     tres.ndata = 1;
01532     tres.nalloc = 20;
01533     tres.rc = SQLITE_OK;
01534     tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
01535     tres.stmt = NULL;
01536     tres.s = s;
01537     if (!tres.resarr) {
01538         return SQLITE_NOMEM;
01539     }
01540     tres.resarr[0] = 0;
01541     if (sql == NULL) {
01542         tres.stmt = s->s3stmt;
01543         if (tres.stmt == NULL) {
01544             return SQLITE_NOMEM;
01545         }
01546         goto retrieve;
01547     }
01548     while (sql && *sql && (rc == SQLITE_OK ||
01549                            (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
01550         int ncol;
01551 
01552         tres.stmt = NULL;
01553 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
01554         dbtraceapi(d, "sqlite3_prepare_v2", sql);
01555         rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01556 #else
01557         dbtraceapi(d, "sqlite3_prepare", sql);
01558         rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01559 #endif
01560         if (rc != SQLITE_OK) {
01561             if (tres.stmt) {
01562                 dbtraceapi(d, "sqlite3_finalize", 0);
01563                 sqlite3_finalize(tres.stmt);
01564                 tres.stmt = NULL;
01565             }
01566             continue;
01567         }
01568         if (!tres.stmt) {
01569             /* this happens for a comment or white-space */
01570             sql = sqlleft;
01571             continue;
01572         }
01573 retrieve:
01574         if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
01575             if (errp) {
01576                 *errp =
01577                     sqlite3_mprintf("%s", "parameter marker count incorrect");
01578             }
01579             haveerr = 1;
01580             rc = SQLITE_ERROR;
01581             goto tbldone;
01582         }
01583         s3bind(d, tres.stmt, nparam, p);
01584         ncol = sqlite3_column_count(tres.stmt);
01585         while (1) {
01586             if (s->max_rows && tres.nrow >= s->max_rows) {
01587                 rc = SQLITE_OK;
01588                 break;
01589             }
01590             rc = sqlite3_step(tres.stmt);
01591             if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
01592                 if (drvgettable_row(&tres, ncol, rc)) {
01593                     rc = SQLITE_ABORT;
01594                     goto tbldone;
01595                 }
01596             }
01597             if (rc != SQLITE_ROW) {
01598                 if (keep) {
01599                     dbtraceapi(d, "sqlite3_reset", 0);
01600                     rc = sqlite3_reset(tres.stmt);
01601                     s->s3stmt_noreset = 1;
01602                 } else {
01603                     dbtraceapi(d, "sqlite3_finalize", 0);
01604                     rc = sqlite3_finalize(tres.stmt);
01605                 }
01606                 tres.stmt = 0;
01607                 if (rc != SQLITE_SCHEMA) {
01608                     nretry = 0;
01609                     sql = sqlleft;
01610                     while (sql && ISSPACE(*sql)) {
01611                         sql++;
01612                     }
01613                 }
01614                 if (rc == SQLITE_DONE) {
01615                     rc = SQLITE_OK;
01616                 }
01617                 break;
01618             }
01619         }
01620     }
01621 tbldone:
01622     if (tres.stmt) {
01623         if (keep) {
01624             if (!s->s3stmt_noreset) {
01625                 dbtraceapi(d, "sqlite3_reset", 0);
01626                 sqlite3_reset(tres.stmt);
01627                 s->s3stmt_noreset = 1;
01628             }
01629         } else {
01630             dbtraceapi(d, "sqlite3_finalize", 0);
01631             sqlite3_finalize(tres.stmt);
01632         }
01633     }
01634     if (haveerr) {
01635         /* message already in *errp if any */
01636     } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
01637         *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
01638     } else if (errp) {
01639         *errp = NULL;
01640     }
01641     if (tres.resarr) {
01642         tres.resarr[0] = (char *) (tres.ndata - 1);
01643     }
01644     if (rc == SQLITE_ABORT) {
01645         freerows(&tres.resarr[1]);
01646         if (tres.errmsg) {
01647             if (errp) {
01648                 if (*errp) {
01649                     sqlite3_free(*errp);
01650                 }
01651                 *errp = tres.errmsg;
01652             } else {
01653                 sqlite3_free(tres.errmsg);
01654             }
01655         }
01656         return tres.rc;
01657     }
01658     sqlite3_free(tres.errmsg);
01659     if (rc != SQLITE_OK) {
01660         freerows(&tres.resarr[1]);
01661         return rc;
01662     }
01663     *resp = &tres.resarr[1];
01664     if (ncolp) {
01665         *ncolp = tres.ncol;
01666     }
01667     if (nrowp) {
01668         *nrowp = tres.nrow;
01669     }
01670     return rc;
01671 }
01672 
01681 #if defined(__GNUC__) && (__GNUC__ >= 2)
01682 static void setstatd(DBC *, int, char *, char *, ...)
01683     __attribute__((format (printf, 3, 5)));
01684 #endif
01685 
01686 static void
01687 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
01688 {
01689     va_list ap;
01690 
01691     if (!d) {
01692         return;
01693     }
01694     d->naterr = naterr;
01695     d->logmsg[0] = '\0';
01696     if (msg) {
01697         int count;
01698 
01699         va_start(ap, st);
01700         count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
01701         va_end(ap);
01702         if (count < 0) {
01703             d->logmsg[sizeof (d->logmsg) - 1] = '\0';
01704         }
01705     }
01706     if (!st) {
01707         st = "?????";
01708     }
01709     strncpy(d->sqlstate, st, 5);
01710     d->sqlstate[5] = '\0';
01711 }
01712 
01721 #if defined(__GNUC__) && (__GNUC__ >= 2)
01722 static void setstat(STMT *, int, char *, char *, ...)
01723     __attribute__((format (printf, 3, 5)));
01724 #endif
01725 
01726 static void
01727 setstat(STMT *s, int naterr, char *msg, char *st, ...)
01728 {
01729     va_list ap;
01730 
01731     if (!s) {
01732         return;
01733     }
01734     s->naterr = naterr;
01735     s->logmsg[0] = '\0';
01736     if (msg) {
01737         int count;
01738 
01739         va_start(ap, st);
01740         count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
01741         va_end(ap);
01742         if (count < 0) {
01743             s->logmsg[sizeof (s->logmsg) - 1] = '\0';
01744         }
01745     }
01746     if (!st) {
01747         st = "?????";
01748     }
01749     strncpy(s->sqlstate, st, 5);
01750     s->sqlstate[5] = '\0';
01751 }
01752 
01759 static SQLRETURN
01760 drvunimpldbc(HDBC dbc)
01761 {
01762     DBC *d;
01763 
01764     if (dbc == SQL_NULL_HDBC) {
01765         return SQL_INVALID_HANDLE;
01766     }
01767     d = (DBC *) dbc;
01768     setstatd(d, -1, "not supported", "IM001");
01769     return SQL_ERROR;
01770 }
01771 
01778 static SQLRETURN
01779 drvunimplstmt(HSTMT stmt)
01780 {
01781     STMT *s;
01782 
01783     if (stmt == SQL_NULL_HSTMT) {
01784         return SQL_INVALID_HANDLE;
01785     }
01786     s = (STMT *) stmt;
01787     setstat(s, -1, "not supported", "IM001");
01788     return SQL_ERROR;
01789 }
01790 
01796 static void
01797 freep(void *x)
01798 {
01799     if (x && ((char **) x)[0]) {
01800         xfree(((char **) x)[0]);
01801         ((char **) x)[0] = NULL;
01802     }
01803 }
01804 
01811 static SQLRETURN
01812 nomem(STMT *s)
01813 {
01814     setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
01815     return SQL_ERROR;
01816 }
01817 
01824 static SQLRETURN
01825 noconn(STMT *s)
01826 {
01827     setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
01828     return SQL_ERROR;
01829 }
01830 
01838 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
01839 
01840 static double
01841 ln_strtod(const char *data, char **endp)
01842 {
01843     struct lconv *lc = 0;
01844     char buf[128], *p, *end;
01845     double value;
01846 
01847     lc = localeconv();
01848     if (lc && lc->decimal_point && lc->decimal_point[0] &&
01849         lc->decimal_point[0] != '.') {
01850         strncpy(buf, data, sizeof (buf) - 1);
01851         buf[sizeof (buf) - 1] = '\0';
01852         p = strchr(buf, '.');
01853         if (p) {
01854             *p = lc->decimal_point[0];
01855         }
01856         p = buf;
01857     } else {
01858         p = (char *) data;
01859     }
01860     value = strtod(p, &end);
01861     end = (char *) data + (end - p);
01862     if (endp) {
01863         *endp = end;
01864     }
01865     return value;
01866 }
01867 
01868 #else
01869 
01870 #define ln_strtod(A,B) strtod(A,B)
01871 
01872 #endif
01873 
01879 static char *
01880 unquote(char *str)
01881 {
01882     if (str) {
01883         int len = strlen(str);
01884 
01885         if (len > 1) {
01886             int end = len - 1;
01887 
01888             if ((str[0] == '\'' && str[end] == '\'') ||
01889                 (str[0] == '"' && str[end] == '"') ||
01890                 (str[0] == '[' && str[end] == ']')) {
01891                 memmove(str, str + 1, end - 1);
01892                 str[end - 1] = '\0';
01893             }
01894         }
01895     }
01896     return str;
01897 }
01898 
01906 static int
01907 unescpat(char *str)
01908 {
01909     char *p, *q;
01910     int count = 0;
01911 
01912     p = str;
01913     while ((q = strchr(p, '_')) != NULL) {
01914         if (q == str || q[-1] != '\\') {
01915             count++;
01916         }
01917         p = q + 1;
01918     }
01919     p = str;
01920     while ((q = strchr(p, '%')) != NULL) {
01921         if (q == str || q[-1] != '\\') {
01922             count++;
01923         }
01924         p = q + 1;
01925     }
01926     p = str;
01927     while ((q = strchr(p, '\\')) != NULL) {
01928         if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
01929             memmove(q, q + 1, strlen(q));
01930         }
01931         p = q + 1;
01932     }
01933     return count;
01934 }
01935 
01944 static int
01945 namematch(char *str, char *pat, int esc)
01946 {
01947     int cp, ch;
01948 
01949     while (1) {
01950         cp = TOLOWER(*pat);
01951         if (cp == '\0') {
01952             if (*str != '\0') {
01953                 goto nomatch;
01954             }
01955             break;
01956         }
01957         if (*str == '\0' && cp != '%') {
01958             goto nomatch;
01959         }
01960         if (cp == '%') {
01961             while (*pat == '%') {
01962                 ++pat;
01963             }
01964             cp = TOLOWER(*pat);
01965             if (cp == '\0') {
01966                 break;
01967             }
01968             while (1) {
01969                 if (cp != '_' && cp != '\\') {
01970                     while (*str) {
01971                         ch = TOLOWER(*str);
01972                         if (ch == cp) {
01973                             break;
01974                         }
01975                         ++str;
01976                     }
01977                 }
01978                 if (namematch(str, pat, esc)) {
01979                     goto match;
01980                 }
01981                 if (*str == '\0') {
01982                     goto nomatch;
01983                 }
01984                 ch = TOLOWER(*str);
01985                 ++str;
01986             }
01987         }
01988         if (cp == '_') {
01989             pat++;
01990             str++;
01991             continue;
01992         }
01993         if (esc && cp == '\\' &&
01994             (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
01995             ++pat;
01996             cp = TOLOWER(*pat);
01997         }
01998         ch = TOLOWER(*str++);
01999         ++pat;
02000         if (ch != cp) {
02001             goto nomatch;
02002         }
02003     }
02004 match:
02005     return 1;
02006 nomatch:
02007     return 0;
02008 }
02009 
02017 static int
02018 busy_handler(void *udata, int count)
02019 {
02020     DBC *d = (DBC *) udata;
02021     long t1;
02022     int ret = 0;
02023 #if !defined(_WIN32) && !defined(_WIN64)
02024     struct timeval tv;
02025 #ifdef HAVE_NANOSLEEP
02026     struct timespec ts;
02027 #endif
02028 #endif
02029 
02030     if (d->busyint) {
02031         d->busyint = 0;
02032         return ret;
02033     }
02034     if (d->timeout <= 0) {
02035         return ret;
02036     }
02037     if (count <= 1) {
02038 #if defined(_WIN32) || defined(_WIN64)
02039         d->t0 = GetTickCount();
02040 #else
02041         gettimeofday(&tv, NULL);
02042         d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02043 #endif
02044     }
02045 #if defined(_WIN32) || defined(_WIN64)
02046     t1 = GetTickCount();
02047 #else
02048     gettimeofday(&tv, NULL);
02049     t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
02050 #endif
02051     if (t1 - d->t0 > d->timeout) {
02052         goto done;
02053     }
02054 #if defined(_WIN32) || defined(_WIN64)
02055     Sleep(10);
02056 #else
02057 #ifdef HAVE_NANOSLEEP
02058     ts.tv_sec = 0;
02059     ts.tv_nsec = 10000000;
02060     do {
02061         ret = nanosleep(&ts, &ts);
02062         if (ret < 0 && errno != EINTR) {
02063             ret = 0;
02064         }
02065     } while (ret);
02066 #else
02067 #ifdef HAVE_USLEEP
02068     usleep(10000);
02069 #else
02070     tv.tv_sec = 0;
02071     tv.tv_usec = 10000;
02072     select(0, NULL, NULL, NULL, &tv);
02073 #endif
02074 #endif
02075 #endif
02076     ret = 1;
02077 done:
02078     return ret;
02079 }
02080 
02092 static int
02093 setsqliteopts(sqlite3 *x, DBC *d)
02094 {
02095     int count = 0, step = 0, max, rc = SQLITE_ERROR;
02096 
02097 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
02098     max = d->longnames ? 3 : 1;
02099 #else
02100     max = 3;
02101 #endif
02102     if (d->shortnames) {
02103         max = 3;
02104     }
02105     while (step < max) {
02106         if (step < 1) {
02107             rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
02108                               NULL, NULL, NULL);
02109             if (rc == SQLITE_OK) {
02110                 rc = sqlite3_exec(x, d->fksupport ?
02111                                   "PRAGMA foreign_keys = on;" :
02112                                   "PRAGMA foreign_keys = off;",
02113                                   NULL, NULL, NULL);
02114             }
02115         } else if (step < 2) {
02116             rc = sqlite3_exec(x, d->shortnames ?
02117                               "PRAGMA full_column_names = off;" :
02118                               "PRAGMA full_column_names = on;",
02119                               NULL, NULL, NULL);
02120         } else if (step < 3) {
02121             rc = sqlite3_exec(x, d->shortnames ?
02122                               "PRAGMA short_column_names = on;" :
02123                               "PRAGMA short_column_names = off;",
02124                               NULL, NULL, NULL);
02125         }
02126         if (rc != SQLITE_OK) {
02127             if (rc != SQLITE_BUSY ||
02128                 !busy_handler((void *) d, ++count)) {
02129                 return rc;
02130             }
02131             continue;
02132         }
02133         count = 0;
02134         ++step;
02135     }
02136     sqlite3_busy_handler(x, busy_handler, (void *) d);
02137     return SQLITE_OK;
02138 }
02139 
02149 static void
02150 freerows(char **rowp)
02151 {
02152     PTRDIFF_T size, i;
02153 
02154     if (!rowp) {
02155         return;
02156     }
02157     --rowp;
02158     size = (PTRDIFF_T) rowp[0];
02159     for (i = 1; i <= size; i++) {
02160         freep(&rowp[i]);
02161     }
02162     freep(&rowp);
02163 }
02164 
02175 static int
02176 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
02177            int dobigint)
02178 {
02179     char *p, *q;
02180     int testsign = 0, result;
02181 
02182 #ifdef WINTERFACE
02183     result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
02184 #else
02185     result = SQL_VARCHAR;
02186 #endif
02187     if (!typename) {
02188         return result;
02189     }
02190     q = p = xmalloc(strlen(typename) + 1);
02191     if (!p) {
02192         return result;
02193     }
02194     strcpy(p, typename);
02195     while (*q) {
02196         *q = TOLOWER(*q);
02197         ++q;
02198     }
02199     if (strncmp(p, "inter", 5) == 0) {
02200     } else if (strncmp(p, "int", 3) == 0 ||
02201         strncmp(p, "mediumint", 9) == 0) {
02202         testsign = 1;
02203         result = SQL_INTEGER;
02204     } else if (strncmp(p, "numeric", 7) == 0) {
02205         result = SQL_DOUBLE;
02206     } else if (strncmp(p, "tinyint", 7) == 0) {
02207         testsign = 1;
02208         result = SQL_TINYINT;
02209     } else if (strncmp(p, "smallint", 8) == 0) {
02210         testsign = 1;
02211         result = SQL_SMALLINT;
02212     } else if (strncmp(p, "float", 5) == 0) {
02213         result = SQL_DOUBLE;
02214     } else if (strncmp(p, "double", 6) == 0 ||
02215         strncmp(p, "real", 4) == 0) {
02216         result = SQL_DOUBLE;
02217     } else if (strncmp(p, "timestamp", 9) == 0) {
02218 #ifdef SQL_TYPE_TIMESTAMP
02219         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02220 #else
02221         result = SQL_TIMESTAMP;
02222 #endif
02223     } else if (strncmp(p, "datetime", 8) == 0) {
02224 #ifdef SQL_TYPE_TIMESTAMP
02225         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02226 #else
02227         result = SQL_TIMESTAMP;
02228 #endif
02229     } else if (strncmp(p, "time", 4) == 0) {
02230 #ifdef SQL_TYPE_TIME
02231         result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
02232 #else
02233         result = SQL_TIME;
02234 #endif
02235     } else if (strncmp(p, "date", 4) == 0) {
02236 #ifdef SQL_TYPE_DATE
02237         result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
02238 #else
02239         result = SQL_DATE;
02240 #endif
02241 #ifdef SQL_LONGVARCHAR
02242     } else if (strncmp(p, "text", 4) == 0 ||
02243                strncmp(p, "memo", 4) == 0 ||
02244                strncmp(p, "longvarchar", 11) == 0) {
02245 #ifdef WINTERFACE
02246         result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
02247 #else
02248         result = SQL_LONGVARCHAR;
02249 #endif
02250 #ifdef WINTERFACE
02251     } else if (strncmp(p, "wtext", 5) == 0 ||
02252                strncmp(p, "wvarchar", 8) == 0 ||
02253                strncmp(p, "longwvarchar", 12) == 0) {
02254         result = SQL_WLONGVARCHAR;
02255 #endif
02256 #endif
02257 #ifdef SQL_BIT
02258     } else if (strncmp(p, "bool", 4) == 0 ||
02259                strncmp(p, "bit", 3) == 0) {
02260         result = SQL_BIT;
02261 #endif
02262 #ifdef SQL_BIGINT
02263     } else if (strncmp(p, "bigint", 6) == 0) {
02264         testsign = 1;
02265         result = SQL_BIGINT;
02266 #endif
02267     } else if (strncmp(p, "blob", 4) == 0) {
02268         result = SQL_BINARY;
02269     } else if (strncmp(p, "varbinary", 9) == 0) {
02270         result = SQL_VARBINARY;
02271     } else if (strncmp(p, "longvarbinary", 13) == 0) {
02272         result = SQL_LONGVARBINARY;
02273     }
02274     if (nosign) {
02275         if (testsign) {
02276             *nosign = strstr(p, "unsigned") != NULL;
02277         } else {
02278             *nosign = 1;
02279         }
02280     }
02281 #ifdef SQL_BIGINT
02282     if (dobigint && result == SQL_INTEGER) {
02283         result = SQL_BIGINT;
02284     }
02285 #endif
02286     xfree(p);
02287     return result;
02288 }
02289 
02299 static void
02300 getmd(const char *typename, int sqltype, int *mp, int *dp)
02301 {
02302     int m = 0, d = 0;
02303 
02304     switch (sqltype) {
02305     case SQL_INTEGER:       m = 10; d = 9; break;
02306     case SQL_TINYINT:       m = 4; d = 3; break;
02307     case SQL_SMALLINT:      m = 6; d = 5; break;
02308     case SQL_FLOAT:         m = 25; d = 24; break;
02309     case SQL_DOUBLE:        m = 54; d = 53; break;
02310     case SQL_VARCHAR:       m = 255; d = 0; break;
02311 #ifdef WINTERFACE
02312 #ifdef SQL_WVARCHAR
02313     case SQL_WVARCHAR:      m = 255; d = 0; break;
02314 #endif
02315 #endif
02316 #ifdef SQL_TYPE_DATE
02317     case SQL_TYPE_DATE:
02318 #endif
02319     case SQL_DATE:          m = 10; d = 0; break;
02320 #ifdef SQL_TYPE_TIME
02321     case SQL_TYPE_TIME:
02322 #endif
02323     case SQL_TIME:          m = 8; d = 0; break;
02324 #ifdef SQL_TYPE_TIMESTAMP
02325     case SQL_TYPE_TIMESTAMP:
02326 #endif
02327     case SQL_TIMESTAMP:     m = 32; d = 3; break;
02328 #ifdef SQL_LONGVARCHAR
02329     case SQL_LONGVARCHAR :  m = 65536; d = 0; break;
02330 #endif
02331 #ifdef WINTERFACE
02332 #ifdef SQL_WLONGVARCHAR
02333     case SQL_WLONGVARCHAR:  m = 65536; d = 0; break;
02334 #endif
02335 #endif
02336     case SQL_BINARY:
02337     case SQL_VARBINARY:     m = 255; d = 0; break;
02338     case SQL_LONGVARBINARY: m = 65536; d = 0; break;
02339 #ifdef SQL_BIGINT
02340     case SQL_BIGINT:        m = 20; d = 19; break;
02341 #endif
02342 #ifdef SQL_BIT
02343     case SQL_BIT:           m = 1; d = 1; break;
02344 #endif
02345     }
02346     if (m && typename) {
02347         int mm, dd;
02348         char clbr[4];
02349 
02350         if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
02351             m = mm;
02352             d = dd;
02353         } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
02354             if (sqltype == SQL_TIMESTAMP) {
02355                 d = mm;
02356             }
02357 #ifdef SQL_TYPE_TIMESTAMP
02358             else if (sqltype == SQL_TYPE_TIMESTAMP) {
02359                 d = mm;
02360             }
02361 #endif
02362             else {
02363                 m = d = mm;
02364             }
02365         }
02366     }
02367     if (mp) {
02368         *mp = m;
02369     }
02370     if (dp) {
02371         *dp = d;
02372     }
02373 }
02374 
02384 static int
02385 mapdeftype(int type, int stype, int nosign, int nowchar)
02386 {
02387     if (type == SQL_C_DEFAULT) {
02388         switch (stype) {
02389         case SQL_INTEGER:
02390             type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
02391             break;
02392         case SQL_TINYINT:
02393             type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
02394             break;
02395         case SQL_SMALLINT:
02396             type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
02397             break;
02398         case SQL_FLOAT:
02399             type = SQL_C_FLOAT;
02400             break;
02401         case SQL_DOUBLE:
02402             type = SQL_C_DOUBLE;
02403             break;
02404         case SQL_TIMESTAMP:
02405             type = SQL_C_TIMESTAMP;
02406             break;
02407         case SQL_TIME:
02408             type = SQL_C_TIME;
02409             break;
02410         case SQL_DATE:
02411             type = SQL_C_DATE;
02412             break;
02413 #ifdef SQL_C_TYPE_TIMESTAMP
02414         case SQL_TYPE_TIMESTAMP:
02415             type = SQL_C_TYPE_TIMESTAMP;
02416             break;
02417 #endif
02418 #ifdef SQL_C_TYPE_TIME
02419         case SQL_TYPE_TIME:
02420             type = SQL_C_TYPE_TIME;
02421             break;
02422 #endif
02423 #ifdef SQL_C_TYPE_DATE
02424         case SQL_TYPE_DATE:
02425             type = SQL_C_TYPE_DATE;
02426             break;
02427 #endif
02428 #ifdef WINTERFACE
02429         case SQL_WVARCHAR:
02430         case SQL_WCHAR:
02431 #ifdef SQL_WLONGVARCHAR
02432         case SQL_WLONGVARCHAR:
02433 #endif
02434             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02435             break;
02436 #endif
02437         case SQL_BINARY:
02438         case SQL_VARBINARY:
02439         case SQL_LONGVARBINARY:
02440             type = SQL_C_BINARY;
02441             break;
02442 #ifdef SQL_BIT
02443         case SQL_BIT:
02444             type = SQL_C_BIT;
02445             break;
02446 #endif
02447 #ifdef SQL_BIGINT
02448         case SQL_BIGINT:
02449             type = SQL_C_CHAR;
02450             break;
02451 #endif
02452         default:
02453 #ifdef WINTERFACE
02454             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02455 #else
02456             type = SQL_C_CHAR;
02457 #endif
02458             break;
02459         }
02460     }
02461     return type;
02462 }
02463 
02470 static int
02471 checkddl(char *sql)
02472 {
02473     int isddl = 0;
02474 
02475     while (*sql && ISSPACE(*sql)) {
02476         ++sql;
02477     }
02478     if (*sql && *sql != ';') {
02479         int i, size;
02480         static const struct {
02481             int len;
02482             const char *str;
02483         } ddlstr[] = {
02484             { 5, "alter" },
02485             { 7, "analyze" },
02486             { 6, "attach" },
02487             { 5, "begin" },
02488             { 6, "commit" },
02489             { 6, "create" },
02490             { 6, "detach" },
02491             { 4, "drop" },
02492             { 3, "end" },
02493             { 7, "reindex" },
02494             { 7, "release" },
02495             { 8, "rollback" },
02496             { 9, "savepoint" },
02497             { 6, "vacuum" }
02498         };
02499 
02500         size = strlen(sql);
02501         for (i = 0; i < array_size(ddlstr); i++) {
02502             if (size >= ddlstr[i].len &&
02503                 strncasecmp(sql, ddlstr[i].str, ddlstr[i].len) == 0) {
02504                 isddl = 1;
02505                 break;
02506             }
02507         }
02508     }
02509     return isddl;
02510 }
02511 
02523 static char *
02524 fixupsql(char *sql, int sqlLen, int cte, int *nparam, int *isselect,
02525          char **errmsg)
02526 {
02527     char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
02528     int np = 0, isddl = -1, size;
02529 
02530     if (errmsg) {
02531         *errmsg = NULL;
02532     }
02533     if (sqlLen != SQL_NTS) {
02534         qz = q = xmalloc(sqlLen + 1);
02535         if (!qz) {
02536             return NULL;
02537         }
02538         memcpy(q, sql, sqlLen);
02539         q[sqlLen] = '\0';
02540         size = sqlLen * 4;
02541     } else {
02542         size = strlen(sql) * 4;
02543     }
02544     size += sizeof (char *) - 1;
02545     size &= ~(sizeof (char *) - 1);
02546     p = xmalloc(size);
02547     if (!p) {
02548 errout:
02549         freep(&qz);
02550         return NULL;
02551     }
02552     memset(p, 0, size);
02553     out = p;
02554     while (*q) {
02555         switch (*q) {
02556         case '\'':
02557         case '\"':
02558             if (q == inq) {
02559                 inq = NULL;
02560             } else if (!inq) {
02561                 inq = q + 1;
02562 
02563                 while (*inq) {
02564                     if (*inq == *q) {
02565                         if (inq[1] == *q) {
02566                             inq++;
02567                         } else {
02568                             break;
02569                         }
02570                     }
02571                     inq++;
02572                 }
02573             }
02574             *p++ = *q;
02575             break;
02576         case '?':
02577             *p++ = *q;
02578             if (!inq) {
02579                 np++;
02580             }
02581             break;
02582         case ';':
02583             if (!inq) {
02584                 if (isddl < 0) {
02585                     isddl = checkddl(out);
02586                 }
02587                 if (isddl == 0) {
02588                     char *qq = q;
02589 
02590                     do {
02591                         ++qq;
02592                     } while (*qq && ISSPACE(*qq));
02593                     if (*qq && *qq != ';') {
02594                         freep(&out);
02595                         if (errmsg) {
02596                             *errmsg = "only one SQL statement allowed";
02597                         }
02598                         goto errout;
02599                     }
02600                 }
02601             }
02602             *p++ = *q;
02603             break;
02604         case '{':
02605             /*
02606              * Deal with escape sequences:
02607              * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
02608              * {oj ...}, {fn ...} etc.
02609              */
02610             if (!inq) {
02611                 int ojfn = 0, brc = 0;
02612                 char *inq2 = NULL, *end = q + 1, *start;
02613 
02614                 while (*end && ISSPACE(*end)) {
02615                     ++end;
02616                 }
02617                 if (*end != 'd' && *end != 'D' &&
02618                     *end != 't' && *end != 'T') {
02619                     ojfn = 1;
02620                 }
02621                 start = end;
02622                 while (*end) {
02623                     if (inq2 && *end == *inq2) {
02624                         inq2 = NULL;
02625                     } else if (inq2 == NULL && *end == '{') {
02626                         char *nerr = 0, *nsql;
02627 
02628                         nsql = fixupsql(end, SQL_NTS, cte, 0, 0, &nerr);
02629                         if (nsql && !nerr) {
02630                             strcpy(end, nsql);
02631                         } else {
02632                             brc++;
02633                         }
02634                         freep(&nsql);
02635                     } else if (inq2 == NULL && *end == '}') {
02636                         if (brc-- <= 0) {
02637                             break;
02638                         }
02639                     } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
02640                         inq2 = end;
02641                     } else if (inq2 == NULL && *end == '?') {
02642                         np++;
02643                     }
02644                     ++end;
02645                 }
02646                 if (*end == '}') {
02647                     char *end2 = end - 1;
02648 
02649                     if (ojfn) {
02650                         while (start < end) {
02651                             if (ISSPACE(*start)) {
02652                                 break;
02653                             }
02654                             ++start;
02655                         }
02656                         while (start < end) {
02657                             *p++ = *start;
02658                             ++start;
02659                         }
02660                         q = end;
02661                         break;
02662                     } else {
02663                         while (start < end2 && *start != '\'') {
02664                             ++start;
02665                         }
02666                         while (end2 > start && *end2 != '\'') {
02667                             --end2;
02668                         }
02669                         if (*start == '\'' && *end2 == '\'') {
02670                             while (start <= end2) {
02671                                 *p++ = *start;
02672                                 ++start;
02673                             }
02674                             q = end;
02675                             break;
02676                         }
02677                     }
02678                 }
02679             }
02680             /* FALL THROUGH */
02681         default:
02682             *p++ = *q;
02683         }
02684         ++q;
02685     }
02686     freep(&qz);
02687     *p = '\0';
02688     if (nparam) {
02689         *nparam = np;
02690     }
02691     if (isselect) {
02692         if (isddl < 0) {
02693             isddl = checkddl(out);
02694         }
02695         if (isddl > 0) {
02696             *isselect = 2;
02697         } else {
02698             int incom = 0;
02699 
02700             p = out;
02701             while (*p) {
02702                 switch (*p) {
02703                 case '-':
02704                     if (!incom && p[1] == '-') {
02705                         incom = -1;
02706                     }
02707                     break;
02708                 case '\n':
02709                     if (incom < 0) {
02710                         incom = 0;
02711                     }
02712                     break;
02713                 case '/':
02714                     if (incom > 0 && p[-1] == '*') {
02715                         incom = 0;
02716                         p++;
02717                         continue;
02718                     } else if (!incom && p[1] == '*') {
02719                         incom = 1;
02720                     }
02721                     break;
02722                 }
02723                 if (!incom && !ISSPACE(*p)) {
02724                     break;
02725                 }
02726                 p++;
02727             }
02728             size = strlen(p);
02729             if (size >= 6 &&
02730                 (strncasecmp(p, "select", 6) == 0 ||
02731                  strncasecmp(p, "pragma", 6) == 0)) {
02732                 *isselect = 1;
02733             } else if (cte && size >= 4 && strncasecmp(p, "with", 4) == 0) {
02734                 *isselect = 1;
02735             } else if (size >= 7 && strncasecmp(p, "explain", 7) == 0) {
02736                 *isselect = 1;
02737             } else {
02738                 *isselect = 0;
02739             }
02740         }
02741     }
02742     return out;
02743 }
02744 
02753 static int
02754 findcol(char **cols, int ncols, char *name)
02755 {
02756     int i;
02757 
02758     if (cols) {
02759         for (i = 0; i < ncols; i++) {
02760             if (strcmp(cols[i], name) == 0) {
02761                 return i;
02762             }
02763         }
02764     }
02765     return -1;
02766 }
02767 
02784 static void
02785 fixupdyncols(STMT *s, DBC *d)
02786 {
02787     int i, k;
02788 #ifndef FULL_METADATA
02789     int pk, nn, t, r, nrows, ncols;
02790     char **rowp, *flagp, flags[128];
02791 #endif
02792 
02793     if (!s->dyncols) {
02794         return;
02795     }
02796     /* fixup labels */
02797     if (!s->longnames) {
02798         if (s->dcols > 1) {
02799             char *table = s->dyncols[0].table;
02800 
02801             for (i = 1; table[0] && i < s->dcols; i++) {
02802                 if (strcmp(s->dyncols[i].table, table)) {
02803                     break;
02804                 }
02805             }
02806             if (i >= s->dcols) {
02807                 for (i = 0; i < s->dcols; i++) {
02808                     s->dyncols[i].label = s->dyncols[i].column;
02809                 }
02810             }
02811         } else if (s->dcols == 1) {
02812             s->dyncols[0].label = s->dyncols[0].column;
02813         }
02814     }
02815     for (i = 0; i < s->dcols; i++) {
02816         s->dyncols[i].type =
02817             mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
02818                        s->nowchar[0] || s->nowchar[1], s->dobigint);
02819         getmd(s->dyncols[i].typename, s->dyncols[i].type,
02820               &s->dyncols[i].size, &s->dyncols[i].prec);
02821 #ifdef SQL_LONGVARCHAR
02822         if (s->dyncols[i].type == SQL_VARCHAR &&
02823             s->dyncols[i].size > 255) {
02824             s->dyncols[i].type = SQL_LONGVARCHAR;
02825         }
02826 #endif
02827 #ifdef WINTERFACE
02828 #ifdef SQL_WLONGVARCHAR
02829         if (s->dyncols[i].type == SQL_WVARCHAR &&
02830             s->dyncols[i].size > 255) {
02831             s->dyncols[i].type = SQL_WLONGVARCHAR;
02832         }
02833 #endif
02834 #endif
02835         if (s->dyncols[i].type == SQL_VARBINARY &&
02836             s->dyncols[i].size > 255) {
02837             s->dyncols[i].type = SQL_LONGVARBINARY;
02838         }
02839     }
02840 #ifndef FULL_METADATA
02841     if (s->dcols > array_size(flags)) {
02842         flagp = xmalloc(sizeof (flags[0]) * s->dcols);
02843         if (flagp == NULL) {
02844             return;
02845         }
02846     } else {
02847         flagp = flags;
02848     }
02849     memset(flagp, 0, sizeof (flags[0]) * s->dcols);
02850     for (i = 0; i < s->dcols; i++) {
02851         s->dyncols[i].autoinc = SQL_FALSE;
02852         s->dyncols[i].notnull = SQL_NULLABLE;
02853     }
02854     for (i = 0; i < s->dcols; i++) {
02855         int ret, lastpk = -1, autoinccount = 0;
02856         char *sql;
02857 
02858         if (!s->dyncols[i].table[0]) {
02859             continue;
02860         }
02861         if (flagp[i]) {
02862             continue;
02863         }
02864         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
02865         if (!sql) {
02866             continue;
02867         }
02868         dbtraceapi(d, "sqlite3_get_table", sql);
02869         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
02870         sqlite3_free(sql);
02871         if (ret != SQLITE_OK) {
02872             continue;
02873         }
02874         k = findcol(rowp, ncols, "name");
02875         t = findcol(rowp, ncols, "type");
02876         pk = findcol(rowp, ncols, "pk");
02877         nn = findcol(rowp, ncols, "notnull");
02878         if (k < 0 || t < 0) {
02879             goto freet;
02880         }
02881         for (r = 1; r <= nrows; r++) {
02882             int m;
02883 
02884             for (m = i; m < s->dcols; m++) {
02885                 char *colname = s->dyncols[m].column;
02886 
02887                 if (s->longnames) {
02888                     char *dotp = strchr(colname, '.');
02889 
02890                     if (dotp) {
02891                         colname = dotp + 1;
02892                     }
02893                 }
02894                 if (!flagp[m] &&
02895                     strcmp(colname, rowp[r * ncols + k]) == 0 &&
02896                     strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
02897                     char *typename = rowp[r * ncols + t];
02898 
02899                     flagp[m] = i + 1;
02900                     freep(&s->dyncols[m].typename);
02901                     s->dyncols[m].typename = xstrdup(typename);
02902                     s->dyncols[m].type =
02903                         mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
02904                                    s->nowchar[0] || s->nowchar[1],
02905                                    s->dobigint);
02906                     getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
02907                           &s->dyncols[m].prec);
02908 #ifdef SQL_LONGVARCHAR
02909                     if (s->dyncols[m].type == SQL_VARCHAR &&
02910                         s->dyncols[m].size > 255) {
02911                         s->dyncols[m].type = SQL_LONGVARCHAR;
02912                     }
02913 #endif
02914 #ifdef WINTERFACE
02915 #ifdef SQL_WLONGVARCHAR
02916                     if (s->dyncols[i].type == SQL_WVARCHAR &&
02917                         s->dyncols[i].size > 255) {
02918                         s->dyncols[i].type = SQL_WLONGVARCHAR;
02919                     }
02920 #endif
02921 #endif
02922                     if (s->dyncols[i].type == SQL_VARBINARY &&
02923                         s->dyncols[i].size > 255) {
02924                         s->dyncols[i].type = SQL_LONGVARBINARY;
02925                     }
02926                     if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
02927                         s->dyncols[m].ispk = 1;
02928                         if (++autoinccount > 1) {
02929                             if (lastpk >= 0) {
02930                                 s->dyncols[lastpk].autoinc = SQL_FALSE;
02931                                 lastpk = -1;
02932                             }
02933                         } else {
02934                             lastpk = m;
02935                             if (strlen(typename) == 7 &&
02936                                 strncasecmp(typename, "integer", 7) == 0) {
02937                                 s->dyncols[m].autoinc = SQL_TRUE;
02938                             }
02939                         }
02940                     } else {
02941                         s->dyncols[m].ispk = 0;
02942                     }
02943                     if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
02944                         s->dyncols[m].notnull = SQL_NO_NULLS;
02945                     }
02946                 }
02947             }
02948         }
02949 freet:
02950         sqlite3_free_table(rowp);
02951     }
02952     for (i = k = 0; i < s->dcols; i++) {
02953         if (flagp[i] == 0) {
02954             break;
02955         }
02956         if (k == 0) {
02957             k = flagp[i];
02958         } else if (flagp[i] != k) {
02959             k = 0;
02960             break;
02961         }
02962     }
02963     s->one_tbl = k ? 1 : 0;
02964     k = 0;
02965     if (s->one_tbl) {
02966         for (i = 0; i < s->dcols; i++) {
02967             if (s->dyncols[i].ispk > 0) {
02968                 ++k;
02969             }
02970         }
02971     }
02972     s->has_pk = k;
02973     if (flagp != flags) {
02974         freep(&flagp);
02975     }
02976 #else
02977     for (i = 1, k = 0; i < s->dcols; i++) {
02978         if (strcmp(s->dyncols[i].table, s->dyncols[0].table) == 0) {
02979             k++;
02980         }
02981     }
02982     s->one_tbl = (k && k + 1 == s->dcols) ? 1 : 0;
02983     k = 0;
02984     if (s->one_tbl) {
02985         for (i = 0; i < s->dcols; i++) {
02986             if (s->dyncols[i].ispk > 0) {
02987                 ++k;
02988                 if (s->has_rowid < 0 && s->dyncols[i].isrowid > 0) {
02989                     s->has_rowid = i;
02990                 }
02991             }
02992         }
02993     }
02994     s->has_pk = k;
02995 #endif
02996 }
02997 
03004 static void
03005 convJD2YMD(double jd, DATE_STRUCT *ds)
03006 {
03007     int z, a, b, c, d, e, x1;
03008     sqlite_int64 ijd;
03009 
03010     ijd = jd * 86400000.0 + 0.5;
03011     z = (int) ((ijd + 43200000) / 86400000);
03012     a = (int) ((z - 1867216.25) / 36524.25);
03013     a = z + 1 + a - (a / 4);
03014     b = a + 1524;
03015     c = (int) ((b - 122.1) / 365.25);
03016     d = (36525 * c) / 100;
03017     e = (int) ((b - d) / 30.6001);
03018     x1 = (int) (30.6001 * e);
03019     ds->day = b - d - x1;
03020     ds->month = (e < 14) ? (e - 1) : (e - 13);
03021     ds->year = (ds->month > 2) ? (c - 4716) : (c - 4715);
03022 }
03023 
03024 
03032 static void
03033 convJD2HMS(double jd, TIME_STRUCT *ts, int *fp)
03034 {
03035     int s;
03036     double ds;
03037     sqlite_int64 ijd;
03038 
03039     ijd = jd * 86400000.0 + 0.5;
03040     s = (int)((ijd + 43200000) % 86400000);
03041     ds = s / 1000.0;
03042     if (fp) {
03043         *fp = (s % 1000) * 1000000;
03044     }
03045     s = (int) ds;
03046     ds -= s;
03047     ts->hour = s / 3600;
03048     s -= ts->hour * 3600;
03049     ts->minute = s / 60;
03050     ds += s - ts->minute *60;
03051     ts->second = (int) ds;
03052 }
03053 
03061 static int
03062 getmdays(int year, int month)
03063 {
03064     static const int mdays[] = {
03065         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
03066     };
03067     int mday;
03068 
03069     if (month < 1) {
03070         return 0;
03071     }
03072     mday = mdays[(month - 1) % 12];
03073     if (mday == 28 && year % 4 == 0 &&
03074         (!(year % 100 == 0) || year % 400 == 0)) {
03075         mday++;
03076     }
03077     return mday;
03078 }
03079 
03095 static int
03096 str2date(int jdconv, char *str, DATE_STRUCT *ds)
03097 {
03098     int i, err = 0;
03099     double jd;
03100     char *p, *q, sepc = '\0';
03101 
03102     ds->year = ds->month = ds->day = 0;
03103     if (jdconv) {
03104         p = strchr(str, '.');
03105         if (p) {
03106             /* julian day format */
03107             p = 0;
03108             jd = ln_strtod(str, &p);
03109             if (p && p > str) {
03110                 convJD2YMD(jd, ds);
03111                 return 0;
03112             }
03113         }
03114     }
03115     p = str;
03116     while (*p && !ISDIGIT(*p)) {
03117         ++p;
03118     }
03119     q = p;
03120     i = 0;
03121     while (*q && !ISDIGIT(*q)) {
03122         ++i;
03123         ++q;
03124     }
03125     if (i >= 8) {
03126         char buf[8];
03127 
03128         strncpy(buf, p + 0, 4); buf[4] = '\0';
03129         ds->year = strtol(buf, NULL, 10);
03130         strncpy(buf, p + 4, 2); buf[2] = '\0';
03131         ds->month = strtol(buf, NULL, 10);
03132         strncpy(buf, p + 6, 2); buf[2] = '\0';
03133         ds->day = strtol(buf, NULL, 10);
03134         goto done;
03135     }
03136     i = 0;
03137     while (i < 3) {
03138         int n;
03139 
03140         q = NULL;
03141         n = strtol(p, &q, 10);
03142         if (!q || q == p) {
03143             if (*q == '\0') {
03144                 if (i == 0) {
03145                     err = 1;
03146                 }
03147                 goto done;
03148             }
03149         }
03150         if (!sepc) {
03151             sepc = *q;
03152         }
03153         if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
03154             switch (i) {
03155             case 0: ds->year = n; break;
03156             case 1: ds->month = n; break;
03157             case 2: ds->day = n; break;
03158             }
03159             ++i;
03160             if (*q) {
03161                 ++q;
03162             }
03163         } else {
03164             i = 0;
03165             while (*q && !ISDIGIT(*q)) {
03166                 ++q;
03167             }
03168         }
03169         p = q;
03170     }
03171 done:
03172     /* final check for overflow */
03173     if (err ||
03174         ds->month < 1 || ds->month > 12 ||
03175         ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
03176         if (sepc == '/') {
03177             /* Try MM/DD/YYYY format */
03178             int t[3];
03179 
03180             t[0] = ds->year;
03181             t[1] = ds->month;
03182             t[2] = ds->day;
03183             ds->year = t[2];
03184             ds->day = t[1];
03185             ds->month = t[0];
03186             if (ds->month >= 1 && ds->month <= 12 &&
03187                 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
03188                 return 0;
03189             }
03190         }
03191         return -1;
03192     }
03193     return 0;
03194 }
03195 
03210 static int
03211 str2time(int jdconv, char *str, TIME_STRUCT *ts)
03212 {
03213     int i, err = 0, ampm = -1;
03214     double jd;
03215     char *p, *q;
03216 
03217     ts->hour = ts->minute = ts->second = 0;
03218     if (jdconv) {
03219         p = strchr(str, '.');
03220         if (p) {
03221             /* julian day format */
03222             p = 0;
03223             jd = ln_strtod(str, &p);
03224             if (p && p > str) {
03225                 convJD2HMS(jd, ts, 0);
03226                 return 0;
03227             }
03228         }
03229     }
03230     p = str;
03231     while (*p && !ISDIGIT(*p)) {
03232         ++p;
03233     }
03234     q = p;
03235     i = 0;
03236     while (*q && ISDIGIT(*q)) {
03237         ++i;
03238         ++q;
03239     }
03240     if (i >= 6) {
03241         char buf[4];
03242 
03243         strncpy(buf, p + 0, 2); buf[2] = '\0';
03244         ts->hour = strtol(buf, NULL, 10);
03245         strncpy(buf, p + 2, 2); buf[2] = '\0';
03246         ts->minute = strtol(buf, NULL, 10);
03247         strncpy(buf, p + 4, 2); buf[2] = '\0';
03248         ts->second = strtol(buf, NULL, 10);
03249         goto done;
03250     }
03251     i = 0;
03252     while (i < 3) {
03253         int n;
03254 
03255         q = NULL;
03256         n = strtol(p, &q, 10);
03257         if (!q || q == p) {
03258             if (*q == '\0') {
03259                 if (i == 0) {
03260                     err = 1;
03261                 }
03262                 goto done;
03263             }
03264         }
03265         if (*q == ':' || *q == '\0' || i == 2) {
03266             switch (i) {
03267             case 0: ts->hour = n; break;
03268             case 1: ts->minute = n; break;
03269             case 2: ts->second = n; break;
03270             }
03271             ++i;
03272             if (*q) {
03273                 ++q;
03274             }
03275         } else {
03276             i = 0;
03277             while (*q && !ISDIGIT(*q)) {
03278                 ++q;
03279             }
03280         }
03281         p = q;
03282     }
03283     if (!err) {
03284         while (*p) {
03285             if ((p[0] == 'p' || p[0] == 'P') &&
03286                 (p[1] == 'm' || p[1] == 'M')) {
03287                 ampm = 1;
03288             } else if ((p[0] == 'a' || p[0] == 'A') &&
03289                 (p[1] == 'm' || p[1] == 'M')) {
03290                 ampm = 0;
03291             }
03292             ++p;
03293         }
03294         if (ampm > 0) {
03295             if (ts->hour < 12) {
03296                 ts->hour += 12;
03297             }
03298         } else if (ampm == 0) {
03299             if (ts->hour == 12) {
03300                 ts->hour = 0;
03301             }
03302         }
03303     }
03304 done:
03305     /* final check for overflow */
03306     if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
03307         return -1;
03308     }
03309     return 0;
03310 }
03311 
03331 static int
03332 str2timestamp(int jdconv, char *str, TIMESTAMP_STRUCT *tss)
03333 {
03334     int i, m, n, err = 0, ampm = -1;
03335     double jd;
03336     char *p, *q, in = '\0', sepc = '\0';
03337 
03338     tss->year = tss->month = tss->day = 0;
03339     tss->hour = tss->minute = tss->second = 0;
03340     tss->fraction = 0;
03341     if (jdconv) {
03342         p = strchr(str, '.');
03343         if (p) {
03344             q = strchr(str, '-');
03345             if (q == str) {
03346                 q = 0;
03347             }
03348             if (!q) {
03349                 q = strchr(str, '/');
03350                 if (!q) {
03351                     q = strchr(str, ':');
03352                 }
03353             }
03354             if (!q || q > p) {
03355                 /* julian day format */
03356                 p = 0;
03357                 jd = ln_strtod(str, &p);
03358                 if (p && p > str) {
03359                     DATE_STRUCT ds;
03360                     TIME_STRUCT ts;
03361 
03362                     convJD2YMD(jd, &ds);
03363                     convJD2HMS(jd, &ts, &n);
03364                     tss->year = ds.year;
03365                     tss->month = ds.month;
03366                     tss->day = ds.day;
03367                     tss->hour = ts.hour;
03368                     tss->minute = ts.minute;
03369                     tss->second = ts.second;
03370                     tss->fraction = n;
03371                     return 0;
03372                 }
03373             }
03374         }
03375     }
03376     p = str;
03377     while (*p && !ISDIGIT(*p)) {
03378         ++p;
03379     }
03380     q = p;
03381     i = 0;
03382     while (*q && ISDIGIT(*q)) {
03383         ++i;
03384         ++q;
03385     }
03386     if (i >= 14) {
03387         char buf[16];
03388 
03389         strncpy(buf, p + 0, 4); buf[4] = '\0';
03390         tss->year = strtol(buf, NULL, 10);
03391         strncpy(buf, p + 4, 2); buf[2] = '\0';
03392         tss->month = strtol(buf, NULL, 10);
03393         strncpy(buf, p + 6, 2); buf[2] = '\0';
03394         tss->day = strtol(buf, NULL, 10);
03395         strncpy(buf, p + 8, 2); buf[2] = '\0';
03396         tss->hour = strtol(buf, NULL, 10);
03397         strncpy(buf, p + 10, 2); buf[2] = '\0';
03398         tss->minute = strtol(buf, NULL, 10);
03399         strncpy(buf, p + 12, 2); buf[2] = '\0';
03400         tss->second = strtol(buf, NULL, 10);
03401         if (i > 14) {
03402             m = i - 14;
03403             strncpy(buf, p + 14, m);
03404             while (m < 9) {
03405                 buf[m] = '0';
03406                 ++m;
03407             }
03408             buf[m] = '\0';
03409             tss->fraction = strtol(buf, NULL, 10);
03410         }
03411         m = 7;
03412         goto done;
03413     }
03414     m = i = 0;
03415     while ((m & 7) != 7) {
03416         q = NULL;
03417         n = strtol(p, &q, 10);
03418         if (!q || q == p) {
03419             if (*q == '\0') {
03420                 if (m < 1) {
03421                     err = 1;
03422                 }
03423                 goto done;
03424             }
03425         }
03426         if (in == '\0') {
03427             switch (*q) {
03428             case '-':
03429             case '/':
03430                 if ((m & 1) == 0) {
03431                     in = *q;
03432                     i = 0;
03433                 }
03434                 break;
03435             case ':':
03436                 if ((m & 2) == 0) {
03437                     in = *q;
03438                     i = 0;
03439                 }
03440                 break;
03441             case ' ':
03442             case '.':
03443                 break;
03444             default:
03445                 in = '\0';
03446                 i = 0;
03447                 break;
03448             }
03449         }
03450         switch (in) {
03451         case '-':
03452         case '/':
03453             if (!sepc) {
03454                 sepc = in;
03455             }
03456             switch (i) {
03457             case 0: tss->year = n; break;
03458             case 1: tss->month = n; break;
03459             case 2: tss->day = n; break;
03460             }
03461             if (++i >= 3) {
03462                 i = 0;
03463                 m |= 1;
03464                 if (!(m & 2)) {
03465                     m |= 8;
03466                 }
03467                 goto skip;
03468             } else {
03469                 ++q;
03470             }
03471             break;
03472         case ':':
03473             switch (i) {
03474             case 0: tss->hour = n; break;
03475             case 1: tss->minute = n; break;
03476             case 2: tss->second = n; break;
03477             }
03478             if (++i >= 3) {
03479                 i = 0;
03480                 m |= 2;
03481                 if (*q == '.') {
03482                     in = '.';
03483                     goto skip2;
03484                 }
03485                 if (*q == ' ') {
03486                     if ((m & 1) == 0) {
03487                         char *e = NULL;
03488 
03489                         (void) strtol(q + 1, &e, 10);
03490                         if (e && *e == '-') {
03491                             goto skip;
03492                         }
03493                     }
03494                     in = '.';
03495                     goto skip2;
03496                 }
03497                 goto skip;
03498             } else {
03499                 ++q;
03500             }
03501             break;
03502         case '.':
03503             if (++i >= 1) {
03504                 int ndig = q - p;
03505 
03506                 if (p[0] == '+' || p[0] == '-') {
03507                     ndig--;
03508                 }
03509                 while (ndig < 9) {
03510                     n = n * 10;
03511                     ++ndig;
03512                 }
03513                 tss->fraction = n;
03514                 m |= 4;
03515                 i = 0;
03516             }
03517         default:
03518         skip:
03519             in = '\0';
03520         skip2:
03521             while (*q && !ISDIGIT(*q)) {
03522                 if ((q[0] == 'a' || q[0] == 'A') &&
03523                     (q[1] == 'm' || q[1] == 'M')) {
03524                     ampm = 0;
03525                     ++q;
03526                 } else if ((q[0] == 'p' || q[0] == 'P') &&
03527                            (q[1] == 'm' || q[1] == 'M')) {
03528                     ampm = 1;
03529                     ++q;
03530                 }
03531                 ++q;
03532             }
03533         }
03534         p = q;
03535     }
03536     if ((m & 7) > 1 && (m & 8)) {
03537         /* ISO8601 timezone */
03538         if (p > str && ISDIGIT(*p)) {
03539             int nn, sign;
03540 
03541             q = p - 1;
03542             if (*q != '+' && *q != '-') {
03543                 goto done;
03544             }
03545             sign = (*q == '+') ? -1 : 1;
03546             q = NULL;
03547             n = strtol(p, &q, 10);
03548             if (!q || *q++ != ':' || !ISDIGIT(*q)) {
03549                 goto done;
03550             }
03551             p = q;
03552             q = NULL;
03553             nn = strtol(p, &q, 10);
03554             tss->minute += nn * sign;
03555             if ((SQLSMALLINT) tss->minute < 0) {
03556                 tss->hour -= 1;
03557                 tss->minute += 60;
03558             } else if (tss->minute >= 60) {
03559                 tss->hour += 1;
03560                 tss->minute -= 60;
03561             }
03562             tss->hour += n * sign;
03563             if ((SQLSMALLINT) tss->hour < 0) {
03564                 tss->day -= 1;
03565                 tss->hour += 24;
03566             } else if (tss->hour >= 24) {
03567                 tss->day += 1;
03568                 tss->hour -= 24;
03569             }
03570             if ((short) tss->day < 1 || tss->day >= 28) {
03571                 int mday, pday, pmon;
03572 
03573                 mday = getmdays(tss->year, tss->month);
03574                 pmon = tss->month - 1;
03575                 if (pmon < 1) {
03576                     pmon = 12;
03577                 }
03578                 pday = getmdays(tss->year, pmon);
03579                 if ((SQLSMALLINT) tss->day < 1) {
03580                     tss->month -= 1;
03581                     tss->day = pday;
03582                 } else if (tss->day > mday) {
03583                     tss->month += 1;
03584                     tss->day = 1;
03585                 }
03586                 if ((SQLSMALLINT) tss->month < 1) {
03587                     tss->year -= 1;
03588                     tss->month = 12;
03589                 } else if (tss->month > 12) {
03590                     tss->year += 1;
03591                     tss->month = 1;
03592                 }
03593             }
03594         }
03595     }
03596 done:
03597     if ((m & 1) &&
03598         (tss->month < 1 || tss->month > 12 ||
03599          tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
03600         if (sepc == '/') {
03601             /* Try MM/DD/YYYY format */
03602             int t[3];
03603 
03604             t[0] = tss->year;
03605             t[1] = tss->month;
03606             t[2] = tss->day;
03607             tss->year = t[2];
03608             tss->day = t[1];
03609             tss->month = t[0];
03610         }
03611     }
03612     /* Replace missing year/month/day with current date */
03613     if (!err && (m & 1) == 0) {
03614 #ifdef _WIN32
03615         SYSTEMTIME t;
03616 
03617         GetLocalTime(&t);
03618         tss->year = t.wYear;
03619         tss->month = t.wMonth;
03620         tss->day = t.wDay;
03621 #else
03622         struct timeval tv;
03623         struct tm tm;
03624 
03625         gettimeofday(&tv, NULL);
03626         tm = *localtime(&tv.tv_sec);
03627         tss->year = tm.tm_year + 1900;
03628         tss->month = tm.tm_mon + 1;
03629         tss->day = tm.tm_mday;
03630 #endif
03631     }
03632     /* Normalize fraction */
03633     if (tss->fraction < 0) {
03634         tss->fraction = 0;
03635     }
03636     /* Final check for overflow */
03637     if (err ||
03638         tss->month < 1 || tss->month > 12 ||
03639         tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
03640         tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
03641         return -1;
03642     }
03643     if ((m & 7) > 1) {
03644         if (ampm > 0) {
03645             if (tss->hour < 12) {
03646                 tss->hour += 12;
03647             }
03648         } else if (ampm == 0) {
03649             if (tss->hour == 12) {
03650                 tss->hour = 0;
03651             }
03652         }
03653     }
03654     return ((m & 7) < 1) ? -1 : 0;
03655 }
03656 
03663 static int
03664 getbool(char *string)
03665 {
03666     if (string) {
03667         return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
03668     }
03669     return 0;
03670 }
03671 
03679 static void
03680 blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03681 {
03682 #if 0
03683     DBC *d = (DBC *) sqlite3_user_data(ctx);
03684 #endif
03685     char *filename = 0;
03686 
03687     if (nargs > 0) {
03688         if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
03689             filename = (char *) sqlite3_value_text(args[0]);
03690         }
03691     }
03692     if (filename) {
03693 #ifdef _WIN32
03694         char *wname = utf_to_wmb(filename, -1);
03695         FILE *f;
03696 #else
03697         FILE *f = fopen(filename, "r");
03698 #endif
03699         char *p;
03700         long n, nn;
03701 
03702 #ifdef _WIN32
03703         if (wname) {
03704             f = fopen(wname, "rb");
03705         } else {
03706             sqlite3_result_error(ctx, "out of memory", -1);
03707             return;
03708         }
03709         uc_free(wname);
03710 #endif
03711         if (f) {
03712             if (fseek(f, 0, SEEK_END) == 0) {
03713                 n = ftell(f);
03714                 if (fseek(f, 0, SEEK_SET) == 0) {
03715                     p = sqlite3_malloc(n);
03716                     if (p) {
03717                         nn = fread(p, 1, n, f);
03718                         if (nn != n) {
03719                             sqlite3_result_error(ctx, "read error", -1);
03720                             sqlite3_free(p);
03721                         } else {
03722                             sqlite3_result_blob(ctx, p, n, sqlite3_free);
03723                         }
03724                     } else {
03725                         sqlite3_result_error(ctx, "out of memory", -1);
03726                     }
03727                 } else {
03728                     sqlite3_result_error(ctx, "seek error", -1);
03729                 }
03730             } else {
03731                 sqlite3_result_error(ctx, "seek error", -1);
03732             }
03733             fclose(f);
03734         } else {
03735             sqlite3_result_error(ctx, "cannot open file", -1);
03736         }
03737     } else {
03738         sqlite3_result_error(ctx, "no filename given", -1);
03739     }
03740 }
03741 
03749 static void
03750 blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03751 {
03752 #if 0
03753     DBC *d = (DBC *) sqlite3_user_data(ctx);
03754 #endif
03755     char *filename = 0;
03756     char *p = 0;
03757     int n = 0;
03758 
03759     if (nargs > 0) {
03760         p = (char *) sqlite3_value_blob(args[0]);
03761         n = sqlite3_value_bytes(args[0]);
03762     }
03763     if (nargs > 1) {
03764         if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
03765             filename = (char *) sqlite3_value_text(args[1]);
03766         }
03767     }
03768     if (p) {
03769         if (filename) {
03770 #ifdef _WIN32
03771             char *wname = utf_to_wmb(filename, -1);
03772             FILE *f;
03773 #else
03774             FILE *f = fopen(filename, "w");
03775 #endif
03776             int nn;
03777 
03778 #ifdef _WIN32
03779             if (wname) {
03780                 f = fopen(wname, "wb");
03781             } else {
03782                 sqlite3_result_error(ctx, "out of memory", -1);
03783                 return;
03784             }
03785             uc_free(wname);
03786 #endif
03787             if (f) {
03788                 nn = fwrite(p, 1, n, f);
03789                 fclose(f);
03790                 if (nn != n) {
03791                     sqlite3_result_error(ctx, "write error", -1);
03792                 } else {
03793                     sqlite3_result_int(ctx, nn);
03794                 }
03795             } else {
03796                 sqlite3_result_error(ctx, "cannot open file", -1);
03797             }
03798         } else {
03799             sqlite3_result_error(ctx, "no filename given", -1);
03800         }
03801     } else {
03802         sqlite3_result_null(ctx);
03803     }
03804 }
03805 
03813 static void
03814 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03815 dbtrace(void *arg, const char *msg, sqlite_uint64 et)
03816 #else
03817 dbtrace(void *arg, const char *msg)
03818 #endif
03819 {
03820     DBC *d = (DBC *) arg;
03821 
03822     if (msg && d->trace) {
03823         int len = strlen(msg);
03824 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03825         unsigned long s, f;
03826 #endif
03827 
03828         if (len > 0) {
03829             char *end = "\n";
03830 
03831             if (msg[len - 1] != ';') {
03832                 end = ";\n";
03833             }
03834             fprintf(d->trace, "%s%s", msg, end);
03835 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03836             s = et / 1000000000LL;
03837             f = et % 1000000000LL;
03838             fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
03839 #endif
03840             fflush(d->trace);
03841         }
03842     }
03843 }
03844 
03852 static void
03853 dbtraceapi(DBC *d, char *fn, const char *sql)
03854 {
03855     if (fn && d->trace) {
03856         if (sql) {
03857             fprintf(d->trace, "-- %s: %s\n", fn, sql);
03858         } else {
03859             fprintf(d->trace, "-- %s\n", fn);
03860         }
03861         fflush(d->trace);
03862     }
03863 }
03864 
03872 static void
03873 dbtracerc(DBC *d, int rc, char *err)
03874 {
03875     if (rc != SQLITE_OK && d->trace) {
03876         fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
03877         fprintf(d->trace, err ? ": %s\n" : "\n", err);
03878         fflush(d->trace);
03879     }
03880 }
03881 
03896 static SQLRETURN
03897 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
03898        char *spflag, char *ntflag, char *jmode, char *busy)
03899 {
03900     char *endp = NULL;
03901     int rc, tmp, busyto = 100000;
03902 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03903     int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
03904     char *uname = name;
03905     const char *vfs_name = NULL;
03906 #endif
03907 
03908     if (d->sqlite) {
03909         if (d->trace) {
03910             fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
03911                     d->dbname);
03912             fflush(d->trace);
03913         }
03914 #if defined(HAVE_SQLITE3CLOSEV2) && (HAVE_SQLITE3CLOSEV2)
03915         sqlite3_close_v2(d->sqlite);
03916 #else
03917         sqlite3_close(d->sqlite);
03918 #endif
03919         d->sqlite = NULL;
03920     }
03921 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03922     if (d->nocreat) {
03923         flags &= ~ SQLITE_OPEN_CREATE;
03924     }
03925 #if defined(_WIN32) || defined(_WIN64)
03926     if (!isu) {
03927         char expname[SQL_MAX_MESSAGE_LENGTH * 2];
03928 
03929         expname[0] = '\0';
03930         rc = ExpandEnvironmentStrings(name, expname, sizeof (expname));
03931         if (rc <= sizeof (expname)) {
03932             uname = wmb_to_utf(expname, rc - 1);
03933         } else {
03934             uname = wmb_to_utf(name, -1);
03935         }
03936         if (!uname) {
03937             rc = SQLITE_NOMEM;
03938             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
03939             return SQL_ERROR;
03940         }
03941     }
03942 #endif
03943 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
03944     vfs_name = nvfs_makevfs(uname);
03945 #endif
03946 #ifdef SQLITE_OPEN_URI
03947     flags |= SQLITE_OPEN_URI;
03948 #endif
03949     rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
03950 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
03951     if (uname != name) {
03952         uc_free(uname);
03953     }
03954 #endif
03955 #else
03956 #if defined(_WIN32) || defined(_WIN64)
03957     if (d->nocreat) {
03958         char *cname = NULL;
03959 
03960         if (isu) {
03961             cname = utf_to_wmb(name, -1);
03962         }
03963         if (GetFileAttributesA(cname ? cname : name) ==
03964             INVALID_FILE_ATTRIBUTES) {
03965             uc_free(cname);
03966             rc = SQLITE_CANTOPEN;
03967             setstatd(d, rc, "cannot open database",
03968                      (*d->ov3) ? "HY000" : "S1000");
03969             return SQL_ERROR;
03970         }
03971         uc_free(cname);
03972     }
03973 #else
03974     if (d->nocreat && access(name, 004) < 0) {
03975         rc = SQLITE_CANTOPEN;
03976         setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
03977         return SQL_ERROR;
03978     }
03979 #endif
03980 #if defined(_WIN32) || defined(_WIN64)
03981     if (!isu) {
03982         WCHAR *wname = wmb_to_uc(name, -1);
03983 
03984         if (!wname) {
03985             rc = SQLITE_NOMEM;
03986             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
03987             return SQL_ERROR;
03988         }
03989         rc = sqlite3_open16(wname, &d->sqlite);
03990         uc_free(wname);
03991     } else
03992 #endif
03993     rc = sqlite3_open(name, &d->sqlite);
03994 #endif /* !HAVE_SQLITE3VFS */
03995     if (rc != SQLITE_OK) {
03996 connfail:
03997         setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
03998         if (d->sqlite) {
03999             sqlite3_close(d->sqlite);
04000             d->sqlite = NULL;
04001         }
04002         return SQL_ERROR;
04003     }
04004 #if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
04005     if (d->pwd) {
04006         sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
04007     }
04008 #endif
04009     d->pwd = NULL;
04010     d->pwdLen = 0;
04011     if (d->trace) {
04012 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
04013         sqlite3_profile(d->sqlite, dbtrace, d);
04014 #else
04015         sqlite3_trace(d->sqlite, dbtrace, d);
04016 #endif
04017     }
04018     d->step_enable = getbool(sflag);
04019     d->trans_disable = getbool(ntflag);
04020     d->curtype = d->step_enable ?
04021         SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
04022     tmp = strtol(busy, &endp, 0);
04023     if (endp && *endp == '\0' && endp != busy) {
04024         busyto = tmp;
04025     }
04026     if (busyto < 1 || busyto > 1000000) {
04027         busyto = 1000000;
04028     }
04029     d->timeout = busyto;
04030     freep(&d->dbname);
04031     d->dbname = xstrdup(name);
04032     freep(&d->dsn);
04033     d->dsn = xstrdup(dsn);
04034     if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
04035         if (d->trace) {
04036             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
04037                     d->dbname);
04038             fflush(d->trace);
04039         }
04040         sqlite3_close(d->sqlite);
04041         d->sqlite = NULL;
04042         goto connfail;
04043     }
04044     if (!spflag || spflag[0] == '\0') {
04045         spflag = "NORMAL";
04046     }
04047     if (spflag[0] != '\0') {
04048         char syncp[128];
04049 
04050         sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
04051         sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
04052     }
04053     if (jmode[0] != '\0') {
04054         char jourp[128];
04055 
04056         sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
04057         sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
04058     }
04059     if (d->trace) {
04060         fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
04061         fflush(d->trace);
04062     }
04063 #if defined(_WIN32) || defined(_WIN64)
04064     {
04065         char pname[MAX_PATH];
04066         HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
04067                                FALSE, GetCurrentProcessId());
04068 
04069         pname[0] = '\0';
04070         if (h) {
04071             HMODULE m = NULL, l = LoadLibrary("psapi.dll");
04072             DWORD need;
04073             typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
04074             typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
04075             epmfunc epm;
04076             gmbfunc gmb;
04077 
04078             if (l) {
04079                 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
04080                 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
04081                 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
04082                     gmb(h, m, pname, sizeof (pname));
04083                 }
04084                 FreeLibrary(l);
04085             }
04086             CloseHandle(h);
04087         }
04088         d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
04089                      strncasecmp(pname, "MSQRY", 5) == 0;
04090         if (d->trace && d->xcelqrx) {
04091 
04092             fprintf(d->trace, "-- enabled EXCEL quirks\n");
04093             fflush(d->trace);
04094         }
04095     }
04096 #endif
04097     sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
04098                             d, blob_import, 0, 0);
04099     sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
04100                             d, blob_export, 0, 0);
04101     return SQL_SUCCESS;
04102 }
04103 
04110 static void
04111 dbloadext(DBC *d, char *exts)
04112 {
04113 #if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
04114     char *p;
04115     char path[SQL_MAX_MESSAGE_LENGTH];
04116     int plen = 0;
04117 
04118     if (!d->sqlite) {
04119         return;
04120     }
04121     sqlite3_enable_load_extension(d->sqlite, 1);
04122 #if defined(_WIN32) || defined(_WIN64)
04123     GetModuleFileName(hModule, path, sizeof (path));
04124     p = strrchr(path, '\\');
04125     plen = p ? ((p + 1) - path) : 0;
04126 #endif
04127     do {
04128         p = strchr(exts, ',');
04129         if (p) {
04130             strncpy(path + plen, exts, p - exts);
04131             path[plen + (p - exts)] = '\0';
04132         } else {
04133             strcpy(path + plen, exts);
04134         }
04135         if (exts[0]) {
04136             char *errmsg = NULL;
04137             int rc;
04138 #if defined(_WIN32) || defined(_WIN64)
04139             int i;
04140             char *q;
04141 
04142             q = path + plen;
04143             if (!(q[0] &&
04144                   ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
04145                    q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
04146                 q = path;
04147             }
04148             /* sqlite3_load_extension() dislikes backslashes */
04149             for (i = 0; q[i] != '\0'; i++) {
04150                 if (q[i] == '\\') {
04151                     q[i] = '/';
04152                 }
04153             }
04154             rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
04155 #else
04156             rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
04157 #endif
04158             if (rc != SQLITE_OK) {
04159 #if defined(_WIN32) || defined(_WIN64)
04160                 char buf[512], msg[512];
04161 
04162                 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
04163                 wsprintf(msg, buf, q, errmsg ?
04164                          errmsg : "no error info available");
04165                 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
04166                 MessageBox(NULL, msg, buf,
04167                            MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
04168                            MB_SETFOREGROUND);
04169 #else
04170                 fprintf(stderr, "extension '%s' did not load%s%s\n",
04171                         path, errmsg ? ": " : "", errmsg ? errmsg : "");
04172 #endif
04173             }
04174         }
04175         if (p) {
04176             exts = p + 1;
04177         }
04178     } while (p);
04179 #endif /* HAVE_SQLITE3LOADEXTENSION */
04180 }
04181 
04191 static char *
04192 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
04193 {
04194     char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
04195     char guess[64];
04196 
04197     guess[0] = '\0';
04198     if (!typename) {
04199         int coltype = sqlite3_column_type(s3stmt, col);
04200 
04201         if (guessed_types) {
04202             guessed_types[0]++;
04203         }
04204         if (d->trace) {
04205             sprintf(guess, " (guessed from %d)", coltype);
04206         }
04207         switch (coltype) {
04208         case SQLITE_INTEGER: typename = "integer"; break;
04209         case SQLITE_FLOAT:   typename = "double";  break;
04210         default:
04211         case SQLITE_TEXT:    typename = "varchar"; break;
04212         case SQLITE_BLOB:    typename = "blob";    break;
04213 #if 0
04214         case SQLITE_NULL:    typename = "null";    break;
04215 #endif
04216         }
04217     }
04218     if (d->trace) {
04219         fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
04220                 guess, typename);
04221         fflush(d->trace);
04222     }
04223     return typename;
04224 }
04225 
04226 #ifdef FULL_METADATA
04227 
04236 static void
04237 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
04238 {
04239     int nn = 0, pk = 0, ai = 0;
04240     const char *dn = NULL, *tn = NULL, *cn = NULL, *dummy[4];
04241 
04242     dn = sqlite3_column_database_name(s3stmt, col);
04243     tn = sqlite3_column_table_name(s3stmt, col);
04244     cn = sqlite3_column_origin_name(s3stmt, col);
04245     dummy[0] = dummy[1] = 0;
04246     if (tn && cn) {
04247         sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
04248                                       dummy, dummy + 1,
04249                                       &nn, &pk, &ai);
04250     }
04251     ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
04252     ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
04253     ci->ispk = pk ? 1 : 0;
04254     if (d->trace) {
04255         fprintf(d->trace, "-- column %d %s\n",
04256                 col + 1, nn ? "notnull" : "nullable");
04257         if (ai) {
04258             fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
04259         }
04260         fflush(d->trace);
04261     }
04262     ci->isrowid = 0;
04263     if (ci->ispk && tn) {
04264         nn = pk = ai = 0;
04265         dummy[2] = dummy[3] = 0;
04266 
04267         sqlite3_table_column_metadata(d->sqlite, dn, tn, "rowid",
04268                                       dummy + 2, dummy + 3,
04269                                       &nn, &pk, &ai);
04270         if (pk && dummy[0] && dummy[0] == dummy[2]) {
04271             ci->isrowid = 1;
04272         }
04273     }
04274 }
04275 
04276 #endif
04277 
04284 static int
04285 s3stmt_step(STMT *s)
04286 {
04287     DBC *d = (DBC *) s->dbc;
04288     char **rowd = NULL;
04289     const char *errp = NULL;
04290     int i, ncols, rc;
04291 
04292     if (s != d->cur_s3stmt || !s->s3stmt) {
04293         setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
04294         return SQL_ERROR;
04295     }
04296     rc = sqlite3_step(s->s3stmt);
04297     if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
04298         ++s->s3stmt_rownum;
04299         ncols = sqlite3_column_count(s->s3stmt);
04300         if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
04301             PTRDIFF_T size;
04302             char *p;
04303             COL *dyncols;
04304             const char *colname, *typename;
04305 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04306             char *tblname;
04307 #endif
04308 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04309             char *dbname;
04310 #endif
04311 
04312             for (i = size = 0; i < ncols; i++) {
04313                 colname = sqlite3_column_name(s->s3stmt, i);
04314                 size += 3 + 3 * strlen(colname);
04315             }
04316 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04317             tblname = (char *) size;
04318             for (i = 0; i < ncols; i++) {
04319                 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
04320                 size += 2 + (p ? strlen(p) : 0);
04321             }
04322 #endif
04323 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04324             dbname = (char *) size;
04325             for (i = 0; i < ncols; i++) {
04326                 p = (char *) sqlite3_column_database_name(s->s3stmt, i);
04327                 size += 2 + (p ? strlen(p) : 0);
04328             }
04329 #endif
04330             dyncols = xmalloc(ncols * sizeof (COL) + size);
04331             if (!dyncols) {
04332                 freedyncols(s);
04333                 s->ncols = 0;
04334                 dbtraceapi(d, "sqlite3_finalize", 0);
04335                 sqlite3_finalize(s->s3stmt);
04336                 s->s3stmt = NULL;
04337                 d->cur_s3stmt = NULL;
04338                 return nomem(s);
04339             }
04340             p = (char *) (dyncols + ncols);
04341 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04342             tblname = p + (PTRDIFF_T) tblname;
04343 #endif
04344 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04345             dbname = p + (PTRDIFF_T) dbname;
04346 #endif
04347             for (i = 0; i < ncols; i++) {
04348                 char *q;
04349 
04350                 colname = sqlite3_column_name(s->s3stmt, i);
04351                 if (d->trace) {
04352                     fprintf(d->trace, "-- column %d name: '%s'\n",
04353                             i + 1, colname);
04354                     fflush(d->trace);
04355                 }
04356 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
04357                 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
04358                 strcpy(tblname, q ? q : "");
04359                 if (d->trace) {
04360                     fprintf(d->trace, "-- table %d name: '%s'\n",
04361                             i + 1, tblname);
04362                     fflush(d->trace);
04363                 }
04364                 dyncols[i].table = tblname;
04365                 tblname += strlen(tblname) + 1;
04366 #endif
04367 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
04368                 q = (char *) sqlite3_column_database_name(s->s3stmt, i);
04369                 strcpy(dbname, q ? q : "");
04370                 if (d->trace) {
04371                     fprintf(d->trace, "-- database %d name: '%s'\n",
04372                             i + 1, dbname);
04373                     fflush(d->trace);
04374                 }
04375                 dyncols[i].db = dbname;
04376                 dbname += strlen(dbname) + 1;
04377 #else
04378                 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
04379 #endif
04380                 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
04381                 strcpy(p, colname);
04382                 dyncols[i].label = p;
04383                 p += strlen(p) + 1;
04384                 q = strchr(colname, '.');
04385                 if (q) {
04386                     char *q2 = strchr(q + 1, '.');
04387 
04388                     /* SQLite 3.3.4 produces view.table.column sometimes */
04389                     if (q2) {
04390                         q = q2;
04391                     }
04392                 }
04393                 if (q) {
04394 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04395                     dyncols[i].table = p;
04396 #endif
04397                     strncpy(p, colname, q - colname);
04398                     p[q - colname] = '\0';
04399                     p += strlen(p) + 1;
04400                     strcpy(p, q + 1);
04401                     dyncols[i].column = p;
04402                     p += strlen(p) + 1;
04403                 } else {
04404 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
04405                     dyncols[i].table = "";
04406 #endif
04407                     strcpy(p, colname);
04408                     dyncols[i].column = p;
04409                     p += strlen(p) + 1;
04410                 }
04411                 if (s->longnames) {
04412                     dyncols[i].column = dyncols[i].label;
04413                 }
04414 #ifdef SQL_LONGVARCHAR
04415                 dyncols[i].type = SQL_LONGVARCHAR;
04416                 dyncols[i].size = 65535;
04417 #else
04418                 dyncols[i].type = SQL_VARCHAR;
04419                 dyncols[i].size = 255;
04420 #endif
04421                 dyncols[i].index = i;
04422                 dyncols[i].scale = 0;
04423                 dyncols[i].prec = 0;
04424                 dyncols[i].nosign = 1;
04425                 dyncols[i].autoinc = SQL_FALSE;
04426                 dyncols[i].notnull = SQL_NULLABLE;
04427                 dyncols[i].ispk = -1;
04428                 dyncols[i].isrowid = -1;
04429 #ifdef FULL_METADATA
04430                 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
04431 #endif
04432                 dyncols[i].typename = xstrdup(typename);
04433             }
04434             freedyncols(s);
04435             s->ncols = s->dcols = ncols;
04436             s->dyncols = s->cols = dyncols;
04437             fixupdyncols(s, d);
04438             mkbindcols(s, s->ncols);
04439             d->s3stmt_needmeta = 0;
04440         }
04441         if (ncols <= 0) {
04442             goto killstmt;
04443         }
04444         if (rc == SQLITE_DONE) {
04445             freeresult(s, 0);
04446             s->nrows = 0;
04447             dbtraceapi(d, "sqlite3_finalize", 0);
04448             sqlite3_finalize(s->s3stmt);
04449             s->s3stmt = NULL;
04450             d->cur_s3stmt = NULL;
04451             return SQL_SUCCESS;
04452         }
04453         rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
04454         if (rowd) {
04455             const unsigned char *value;
04456 
04457             rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
04458             ++rowd;
04459             for (i = 0; i < ncols; i++) {
04460                 int coltype = sqlite3_column_type(s->s3stmt, i);
04461 
04462                 rowd[i] = rowd[i + ncols] = NULL;
04463                 if (coltype == SQLITE_BLOB) {
04464                     int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
04465                     char *qp;
04466                     unsigned const char *bp;
04467 
04468                     bp = sqlite3_column_blob(s->s3stmt, i);
04469                     qp = xmalloc(nbytes * 2 + 4);
04470                     if (qp) {
04471                         rowd[i + ncols] = qp;
04472                         *qp++ = 'X';
04473                         *qp++ = '\'';
04474                         for (k = 0; k < nbytes; k++) {
04475                             *qp++ = xdigits[(bp[k] >> 4)];
04476                             *qp++ = xdigits[(bp[k] & 0xF)];
04477                         }
04478                         *qp++ = '\'';
04479                         *qp = '\0';
04480                     }
04481 #ifdef _MSC_VER
04482                 } else if (coltype == SQLITE_FLOAT) {
04483                     struct lconv *lc = 0;
04484                     double d = sqlite3_column_double(s->s3stmt, i);
04485                     char *p, buffer[128];
04486 
04487                     /*
04488                      * This avoids floating point rounding
04489                      * and formatting problems of some SQLite
04490                      * versions in conjunction with MSVC 2010.
04491                      */
04492                     snprintf(buffer, sizeof (buffer), "%.15g", d);
04493                     lc = localeconv();
04494                     if (lc && lc->decimal_point && lc->decimal_point[0] &&
04495                         lc->decimal_point[0] != '.') {
04496                         p = strchr(buffer, lc->decimal_point[0]);
04497                         if (p) {
04498                             *p = '.';
04499                         }
04500                     }
04501                     rowd[i + ncols] = xstrdup(buffer);
04502 #endif
04503                 } else if (coltype != SQLITE_NULL) {
04504                     value = sqlite3_column_text(s->s3stmt, i);
04505                     rowd[i + ncols] = xstrdup((char *) value);
04506                 }
04507             }
04508             for (i = 0; i < ncols; i++) {
04509                 int coltype = sqlite3_column_type(s->s3stmt, i);
04510 
04511                 value = NULL;
04512                 if (coltype == SQLITE_BLOB) {
04513                     value = sqlite3_column_blob(s->s3stmt, i);
04514                 } else if (coltype != SQLITE_NULL) {
04515                     value = sqlite3_column_text(s->s3stmt, i);
04516                 }
04517                 if (value && !rowd[i + ncols]) {
04518                     freerows(rowd);
04519                     rowd = 0;
04520                     break;
04521                 }
04522             }
04523         }
04524         if (rowd) {
04525             freeresult(s, 0);
04526             s->nrows = 1;
04527             s->rows = rowd;
04528             s->rowfree = freerows;
04529             if (rc == SQLITE_DONE) {
04530                 dbtraceapi(d, "sqlite3_finalize", 0);
04531                 sqlite3_finalize(s->s3stmt);
04532                 s->s3stmt = NULL;
04533                 d->cur_s3stmt = NULL;
04534             }
04535             return SQL_SUCCESS;
04536         }
04537     }
04538 killstmt:
04539     dbtraceapi(d, "sqlite3_reset", 0);
04540     rc = sqlite3_reset(s->s3stmt);
04541     s->s3stmt_noreset = 1;
04542     errp = sqlite3_errmsg(d->sqlite);
04543     if (d->cur_s3stmt == s) {
04544         d->cur_s3stmt = NULL;
04545     }
04546     setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04547             errp ? errp : "unknown error", rc);
04548     return SQL_ERROR;
04549 }
04550 
04556 static void
04557 s3stmt_end(STMT *s)
04558 {
04559     DBC *d;
04560 
04561     if (!s || !s->s3stmt) {
04562         return;
04563     }
04564     d = (DBC *) s->dbc;
04565     if (d) {
04566         d->busyint = 0;
04567     }
04568     if (!s->s3stmt_noreset) {
04569         dbtraceapi(d, "sqlite3_reset", 0);
04570         sqlite3_reset(s->s3stmt);
04571         s->s3stmt_noreset = 1;
04572         s->s3stmt_rownum = -1;
04573     }
04574     if (d->cur_s3stmt == s) {
04575         d->cur_s3stmt = NULL;
04576     }
04577 }
04578 
04584 static void
04585 s3stmt_end_if(STMT *s)
04586 {
04587     DBC *d = (DBC *) s->dbc;
04588 
04589     if (d) {
04590         d->busyint = 0;
04591     }
04592     if (d && d->cur_s3stmt == s) {
04593         s3stmt_end(s);
04594     }
04595 }
04596 
04602 static void
04603 s3stmt_drop(STMT *s)
04604 {
04605     if (s->s3stmt) {
04606         DBC *d = (DBC *) s->dbc;
04607 
04608         if (d) {
04609             dbtraceapi(d, "sqlite3_finalize", 0);
04610         }
04611         sqlite3_finalize(s->s3stmt);
04612         s->s3stmt = NULL;
04613         s->s3stmt_rownum = 0;
04614     }
04615 }
04616 
04623 static SQLRETURN
04624 s3stmt_start(STMT *s)
04625 {
04626     DBC *d = (DBC *) s->dbc;
04627     const char *endp;
04628     sqlite3_stmt *s3stmt = NULL;
04629     int rc, nretry = 0;
04630 
04631     d->s3stmt_needmeta = 0;
04632     if (!s->s3stmt) {
04633 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04634         dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
04635 #else
04636         dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
04637 #endif
04638         do {
04639             s3stmt = NULL;
04640 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04641             rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
04642                                     &s3stmt, &endp);
04643 #else
04644             rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
04645                                  &s3stmt, &endp);
04646 #endif
04647             if (rc != SQLITE_OK) {
04648                 if (s3stmt) {
04649                     sqlite3_finalize(s3stmt);
04650                     s3stmt = NULL;
04651                 }
04652             }
04653         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
04654         dbtracerc(d, rc, NULL);
04655         if (rc != SQLITE_OK) {
04656             if (s3stmt) {
04657                 dbtraceapi(d, "sqlite3_finalize", NULL);
04658                 sqlite3_finalize(s3stmt);
04659             }
04660             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04661                     sqlite3_errmsg(d->sqlite), rc);
04662             return SQL_ERROR;
04663         }
04664         if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
04665             dbtraceapi(d, "sqlite3_finalize", 0);
04666             sqlite3_finalize(s3stmt);
04667             setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
04668                     (*s->ov3) ? "HY000" : "S1000");
04669             return SQL_ERROR;
04670         }
04671         s->s3stmt = s3stmt;
04672         s->s3stmt_noreset = 1;
04673         d->s3stmt_needmeta = 1;
04674     }
04675     d->cur_s3stmt = s;
04676     s->s3stmt_rownum = -1;
04677     s3bind(d, s->s3stmt, s->nparams, s->bindparms);
04678     return SQL_SUCCESS;
04679 }
04680 
04681 #ifndef WINTERFACE
04682 
04686 SQLRETURN SQL_API
04687 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
04688                SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04689                SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04690 {
04691     if (env == SQL_NULL_HENV) {
04692         return SQL_INVALID_HANDLE;
04693     }
04694     return SQL_ERROR;
04695 }
04696 #endif
04697 
04698 #ifdef WINTERFACE
04699 
04703 SQLRETURN SQL_API
04704 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
04705                 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04706                 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04707 {
04708     if (env == SQL_NULL_HENV) {
04709         return SQL_INVALID_HANDLE;
04710     }
04711     return SQL_ERROR;
04712 }
04713 #endif
04714 
04715 #ifndef WINTERFACE
04716 
04720 SQLRETURN SQL_API
04721 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
04722            SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04723            SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04724 {
04725     if (env == SQL_NULL_HENV) {
04726         return SQL_INVALID_HANDLE;
04727     }
04728     return SQL_ERROR;
04729 }
04730 #endif
04731 
04732 #ifdef WINTERFACE
04733 
04737 SQLRETURN SQL_API
04738 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
04739             SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04740             SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04741 {
04742     if (env == SQL_NULL_HENV) {
04743         return SQL_INVALID_HANDLE;
04744     }
04745     return SQL_ERROR;
04746 }
04747 #endif
04748 
04749 #ifndef WINTERFACE
04750 
04754 SQLRETURN SQL_API
04755 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
04756                  SQLCHAR *connout, SQLSMALLINT connoutMax,
04757                  SQLSMALLINT *connoutLen)
04758 {
04759     SQLRETURN ret;
04760 
04761     HDBC_LOCK(dbc);
04762     ret = drvunimpldbc(dbc);
04763     HDBC_UNLOCK(dbc);
04764     return ret;
04765 }
04766 #endif
04767 
04768 #ifdef WINTERFACE
04769 
04773 SQLRETURN SQL_API
04774 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
04775                   SQLWCHAR *connout, SQLSMALLINT connoutMax,
04776                   SQLSMALLINT *connoutLen)
04777 {
04778     SQLRETURN ret;
04779 
04780     HDBC_LOCK(dbc);
04781     ret = drvunimpldbc(dbc);
04782     HDBC_UNLOCK(dbc);
04783     return ret;
04784 }
04785 #endif
04786 
04795 static SQLRETURN
04796 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
04797 {
04798     STMT *s;
04799     int i, dlen, done = 0;
04800     BINDPARM *p;
04801 
04802     if (stmt == SQL_NULL_HSTMT) {
04803         return SQL_INVALID_HANDLE;
04804     }
04805     s = (STMT *) stmt;
04806     if (!s->query || s->nparams <= 0) {
04807 seqerr:
04808         setstat(s, -1, "sequence error", "HY010");
04809         return SQL_ERROR;
04810     }
04811     for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
04812         p = &s->bindparms[i];
04813         if (p->need > 0) {
04814             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
04815 
04816             if (len == SQL_NULL_DATA) {
04817                 freep(&p->parbuf);
04818                 p->param = NULL;
04819                 p->len = SQL_NULL_DATA;
04820                 p->need = -1;
04821             } else if (type != SQL_C_CHAR
04822 #ifdef WCHARSUPPORT
04823                        && type != SQL_C_WCHAR
04824 #endif
04825                        && type != SQL_C_BINARY) {
04826                 int size = 0;
04827 
04828                 switch (type) {
04829                 case SQL_C_TINYINT:
04830                 case SQL_C_UTINYINT:
04831                 case SQL_C_STINYINT:
04832 #ifdef SQL_BIT
04833                 case SQL_C_BIT:
04834 #endif
04835                     size = sizeof (SQLCHAR);
04836                     break;
04837                 case SQL_C_SHORT:
04838                 case SQL_C_USHORT:
04839                 case SQL_C_SSHORT:
04840                     size = sizeof (SQLSMALLINT);
04841                     break;
04842                 case SQL_C_LONG:
04843                 case SQL_C_ULONG:
04844                 case SQL_C_SLONG:
04845                     size = sizeof (SQLINTEGER);
04846                     break;
04847 #ifdef SQL_BIGINT
04848                 case SQL_C_UBIGINT:
04849                 case SQL_C_SBIGINT:
04850                     size = sizeof (SQLBIGINT);
04851                     break;
04852 #endif
04853                 case SQL_C_FLOAT:
04854                     size = sizeof (float);
04855                     break;
04856                 case SQL_C_DOUBLE:
04857                     size = sizeof (double);
04858                     break;
04859 #ifdef SQL_C_TYPE_DATE
04860                 case SQL_C_TYPE_DATE:
04861 #endif
04862                 case SQL_C_DATE:
04863                     size = sizeof (DATE_STRUCT);
04864                     break;
04865 #ifdef SQL_C_TYPE_DATE
04866                 case SQL_C_TYPE_TIME:
04867 #endif
04868                 case SQL_C_TIME:
04869                     size = sizeof (TIME_STRUCT);
04870                     break;
04871 #ifdef SQL_C_TYPE_DATE
04872                 case SQL_C_TYPE_TIMESTAMP:
04873 #endif
04874                 case SQL_C_TIMESTAMP:
04875                     size = sizeof (TIMESTAMP_STRUCT);
04876                     break;
04877                 }
04878                 freep(&p->parbuf);
04879                 p->parbuf = xmalloc(size);
04880                 if (!p->parbuf) {
04881                     return nomem(s);
04882                 }
04883                 p->param = p->parbuf;
04884                 memcpy(p->param, data, size);
04885                 p->len = size;
04886                 p->need = -1;
04887             } else if (len == SQL_NTS && (
04888                        type == SQL_C_CHAR
04889 #ifdef WCHARSUPPORT
04890                        || type == SQL_C_WCHAR
04891 #endif
04892                       )) {
04893                 char *dp = data;
04894 
04895 #ifdef WCHARSUPPORT
04896                 if (type == SQL_C_WCHAR) {
04897                     dp = uc_to_utf(data, len);
04898                     if (!dp) {
04899                         return nomem(s);
04900                     }
04901                 }
04902 #endif
04903 #if defined(_WIN32) || defined(_WIN64)
04904                 if (*s->oemcp) {
04905                     dp = wmb_to_utf(data, strlen (data));
04906                     if (!dp) {
04907                         return nomem(s);
04908                     }
04909                 }
04910 #endif
04911                 dlen = strlen(dp);
04912                 freep(&p->parbuf);
04913                 p->parbuf = xmalloc(dlen + 1);
04914                 if (!p->parbuf) {
04915                     if (dp != data) {
04916                         uc_free(dp);
04917                     }
04918                     return nomem(s);
04919                 }
04920                 p->param = p->parbuf;
04921                 strcpy(p->param, dp);
04922                 if (dp != data) {
04923                     uc_free(dp);
04924                 }
04925                 p->len = dlen;
04926                 p->need = -1;
04927             } else if (len < 0) {
04928                 setstat(s, -1, "invalid length", "HY090");
04929                 return SQL_ERROR;
04930             } else {
04931                 dlen = min(p->len - p->offs, len);
04932                 if (!p->param) {
04933                     setstat(s, -1, "no memory for parameter", "HY013");
04934                     return SQL_ERROR;
04935                 }
04936                 memcpy((char *) p->param + p->offs, data, dlen);
04937                 p->offs += dlen;
04938                 if (p->offs >= p->len) {
04939 #ifdef WCHARSUPPORT
04940                     if (type == SQL_C_WCHAR) {
04941                         char *dp = uc_to_utf(p->param, p->len);
04942                         char *np;
04943                         int nlen;
04944 
04945                         if (!dp) {
04946                             return nomem(s);
04947                         }
04948                         nlen = strlen(dp);
04949                         np = xmalloc(nlen + 1);
04950                         if (!np) {
04951                             uc_free(dp);
04952                             return nomem(s);
04953                         }
04954                         strcpy(np, dp);
04955                         uc_free(dp);
04956                         if (p->param == p->parbuf) {
04957                             freep(&p->parbuf);
04958                         }
04959                         p->parbuf = p->param = np;
04960                         p->len = nlen;
04961                     } else {
04962                         *((char *) p->param + p->len) = '\0';
04963                     }
04964                     p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
04965                             ? -1 : 0;
04966 #else
04967                     *((char *) p->param + p->len) = '\0';
04968                     p->need = (type == SQL_C_CHAR) ? -1 : 0;
04969 #endif
04970 #if defined(_WIN32) || defined(_WIN64)
04971                     if (type == SQL_C_CHAR && *s->oemcp &&
04972                         !(p->stype == SQL_BINARY ||
04973                           p->stype == SQL_VARBINARY ||
04974                           p->stype == SQL_LONGVARBINARY)) {
04975                         char *dp = wmb_to_utf(p->param, p->len);
04976 
04977                         if (!dp) {
04978                             return nomem(s);
04979                         }
04980                         if (p->param == p->parbuf) {
04981                             freep(&p->parbuf);
04982                         }
04983                         p->parbuf = p->param = dp;
04984                         p->len = strlen(dp);
04985                     }
04986                     if (p->type == SQL_C_WCHAR &&
04987                         (p->stype == SQL_VARCHAR ||
04988                          p->stype == SQL_LONGVARCHAR) &&
04989                          p->len == p->coldef * sizeof (SQLWCHAR)) {
04990                         /* fix for MS-Access */
04991                         p->len = p->coldef;
04992                     }
04993 #endif
04994                 }
04995             }
04996             done = 1;
04997             break;
04998         }
04999     }
05000     if (!done) {
05001         goto seqerr;
05002     }
05003     return SQL_SUCCESS;
05004 }
05005 
05014 SQLRETURN SQL_API
05015 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
05016 {
05017     SQLRETURN ret;
05018 
05019     HSTMT_LOCK(stmt);
05020     ret = drvputdata(stmt, data, len);
05021     HSTMT_UNLOCK(stmt);
05022     return ret;
05023 }
05024 
05030 static SQLRETURN
05031 freeparams(STMT *s)
05032 {
05033     if (s->bindparms) {
05034         int n;
05035 
05036         for (n = 0; n < s->nbindparms; n++) {
05037             freep(&s->bindparms[n].parbuf);
05038             memset(&s->bindparms[n], 0, sizeof (BINDPARM));
05039         }
05040     }
05041     return SQL_SUCCESS;
05042 }
05043 
05055 static SQLRETURN
05056 setupparam(STMT *s, char *sql, int pnum)
05057 {
05058     int type, len = 0, needalloc = 0;
05059     BINDPARM *p;
05060 
05061     if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
05062         goto error;
05063     }
05064     p = &s->bindparms[pnum];
05065     type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05066 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
05067     /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
05068     if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
05069         type = SQL_C_CHAR;
05070     }
05071 #endif
05072     if (p->need > 0) {
05073         return setupparbuf(s, p);
05074     }
05075     p->strbuf[0] = '\0';
05076     if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
05077         p->s3type = SQLITE_NULL;
05078         p->s3size = 0;
05079         return SQL_SUCCESS;
05080     }
05081     if (type == SQL_C_CHAR &&
05082         (p->stype == SQL_BINARY ||
05083          p->stype == SQL_VARBINARY ||
05084          p->stype == SQL_LONGVARBINARY)) {
05085         type = SQL_C_BINARY;
05086     }
05087     switch (type) {
05088     case SQL_C_BINARY:
05089         p->s3type = SQLITE_BLOB;
05090         p->s3size = p->len;
05091         p->s3val = p->param;
05092         if (p->need < 0) {
05093             break;
05094         }
05095         if (!p->lenp) {
05096             len = p->len;
05097         } else if (*p->lenp == SQL_DATA_AT_EXEC) {
05098             len = p->len;
05099         } else {
05100             len = *p->lenp;
05101             if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
05102                 len = SQL_LEN_DATA_AT_EXEC(len);
05103             }
05104         }
05105         if (len < 0) {
05106             setstat(s, -1, "invalid length", "HY009");
05107             return SQL_ERROR;
05108         }
05109         p->len = len;
05110         p->max = p->len;
05111         p->need = -1;
05112         p->s3size = len;
05113         break;
05114 #ifdef WCHARSUPPORT
05115     case SQL_C_WCHAR:
05116 #endif
05117     case SQL_C_CHAR:
05118         p->s3type = SQLITE_TEXT;
05119         p->s3size = -1;
05120         p->s3val = p->param;
05121         if (!p->parbuf) {
05122 #ifdef WCHARSUPPORT
05123             if (type == SQL_C_WCHAR) {
05124                 if (!p->lenp || *p->lenp == SQL_NTS) {
05125                     p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
05126                 } else if (*p->lenp >= 0) {
05127                     p->max = *p->lenp;
05128                 }
05129             } else
05130 #endif
05131             if (type == SQL_C_CHAR) {
05132                 if (!p->lenp || *p->lenp == SQL_NTS) {
05133                     p->len = p->max = strlen(p->param);
05134 #if defined(_WIN32) || defined(_WIN64)
05135                     needalloc = 1;
05136 #endif
05137                 } else if (*p->lenp >= 0) {
05138                     p->len = p->max = *p->lenp;
05139                     needalloc = 1;
05140                 }
05141             }
05142         }
05143         if (p->need < 0 && p->parbuf == p->param) {
05144             break;
05145         }
05146 #ifdef WCHARSUPPORT
05147         if (type == SQL_C_WCHAR) {
05148             char *dp = uc_to_utf(p->param, p->max);
05149 
05150             if (!dp) {
05151                 return nomem(s);
05152             }
05153             if (p->param == p->parbuf) {
05154                 freep(&p->parbuf);
05155             }
05156             p->parbuf = p->param = dp;
05157             p->need = -1;
05158             p->len = strlen(p->param);
05159             p->s3val = p->param;
05160             p->s3size = p->len;
05161         } else
05162 #endif
05163         if (type == SQL_C_CHAR) {
05164             p->s3val = p->param;
05165             if (needalloc) {
05166                 char *dp;
05167 
05168 #if defined(_WIN32) || defined(_WIN64)
05169                 if (*s->oemcp) {
05170                     dp = wmb_to_utf(p->param, p->len);
05171                 } else {
05172                     dp = xmalloc(p->len + 1);
05173                 }
05174 #else
05175                 dp = xmalloc(p->len + 1);
05176 #endif
05177                 if (!dp) {
05178                     return nomem(s);
05179                 }
05180 #if defined(_WIN32) || defined(_WIN64)
05181                 if (*s->oemcp) {
05182                     p->len = strlen(dp);
05183                 } else {
05184                     memcpy(dp, p->param, p->len);
05185                     dp[p->len] = '\0';
05186                 }
05187 #else
05188                 memcpy(dp, p->param, p->len);
05189                 dp[p->len] = '\0';
05190 #endif
05191                 if (p->param == p->parbuf) {
05192                     freep(&p->parbuf);
05193                 }
05194                 p->parbuf = p->param = dp;
05195                 p->need = -1;
05196                 p->s3val = p->param;
05197                 p->s3size = p->len;
05198             }
05199         }
05200         break;
05201     case SQL_C_UTINYINT:
05202     case SQL_C_TINYINT:
05203     case SQL_C_STINYINT:
05204         p->s3type = SQLITE_INTEGER;
05205         p->s3size = sizeof (int);
05206         p->s3ival = *((SQLCHAR *) p->param);
05207         break;
05208     case SQL_C_USHORT:
05209         p->s3type = SQLITE_INTEGER;
05210         p->s3size = sizeof (int);
05211         p->s3ival = *((SQLUSMALLINT *) p->param);
05212         break;
05213     case SQL_C_SHORT:
05214     case SQL_C_SSHORT:
05215         p->s3type = SQLITE_INTEGER;
05216         p->s3size = sizeof (int);
05217         p->s3ival = *((SQLSMALLINT *) p->param);
05218         break;
05219     case SQL_C_ULONG:
05220         p->s3type = SQLITE_INTEGER;
05221         p->s3size = sizeof (int);
05222         p->s3ival = *((SQLUINTEGER *) p->param);
05223         break;
05224     case SQL_C_LONG:
05225     case SQL_C_SLONG:
05226         p->s3type = SQLITE_INTEGER;
05227         p->s3size = sizeof (int);
05228         p->s3ival = *((SQLINTEGER *) p->param);
05229         break;
05230 #ifdef SQL_BIT
05231     case SQL_C_BIT:
05232         p->s3type = SQLITE_INTEGER;
05233         p->s3size = sizeof (int);
05234         p->s3ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
05235         break;
05236 #endif
05237 #ifdef SQL_BIGINT
05238     case SQL_C_SBIGINT:
05239         p->s3type = SQLITE_INTEGER;
05240         p->s3size = sizeof (sqlite_int64);
05241         p->s3lival = *((sqlite_int64 *) p->param);
05242         break;
05243     case SQL_C_UBIGINT:
05244         p->s3type = SQLITE_INTEGER;
05245         p->s3size = sizeof (sqlite_int64);
05246         p->s3lival = *((sqlite_uint64 *) p->param);
05247         break;
05248 #endif
05249     case SQL_C_FLOAT:
05250         p->s3type = SQLITE_FLOAT;
05251         p->s3size = sizeof (double);
05252         p->s3dval = *((float *) p->param);
05253         break;
05254     case SQL_C_DOUBLE:
05255         p->s3type = SQLITE_FLOAT;
05256         p->s3size = sizeof (double);
05257         p->s3dval = *((double *) p->param);
05258         break;
05259 #ifdef SQL_C_TYPE_DATE
05260     case SQL_C_TYPE_DATE:
05261 #endif
05262     case SQL_C_DATE:
05263         if (*s->jdconv) {
05264             int a, b, x1, x2, y, m, d;
05265 
05266             p->s3type = SQLITE_FLOAT;
05267             p->s3size = sizeof (double);
05268             y = ((DATE_STRUCT *) p->param)->year;
05269             m = ((DATE_STRUCT *) p->param)->month;
05270             d = ((DATE_STRUCT *) p->param)->day;
05271             if (m <= 2) {
05272                 y--;
05273                 m += 12;
05274             }
05275             a = y / 100;
05276             b = 2 - a + (a / 4);
05277             x1 = 36525 * (y + 4716) / 100;
05278             x2 = 306001 * (m + 1) / 10000;
05279             p->s3dval = x1 + x2 + d + b - 1524.5;
05280             break;
05281         }
05282         sprintf(p->strbuf, "%04d-%02d-%02d",
05283                 ((DATE_STRUCT *) p->param)->year,
05284                 ((DATE_STRUCT *) p->param)->month,
05285                 ((DATE_STRUCT *) p->param)->day);
05286         p->s3type = SQLITE_TEXT;
05287         p->s3size = -1;
05288         p->s3val = p->strbuf;
05289         break;
05290 #ifdef SQL_C_TYPE_TIME
05291     case SQL_C_TYPE_TIME:
05292 #endif
05293     case SQL_C_TIME:
05294         if (*s->jdconv) {
05295             p->s3type = SQLITE_FLOAT;
05296             p->s3size = sizeof (double);
05297             p->s3dval = 2451544.5 +
05298                (((TIME_STRUCT *) p->param)->hour * 3600000.0 +
05299                 ((TIME_STRUCT *) p->param)->minute * 60000.0 +
05300                 ((TIME_STRUCT *) p->param)->second * 1000.0) / 86400000.0;
05301             break;
05302         }
05303         sprintf(p->strbuf, "%02d:%02d:%02d",
05304                 ((TIME_STRUCT *) p->param)->hour,
05305                 ((TIME_STRUCT *) p->param)->minute,
05306                 ((TIME_STRUCT *) p->param)->second);
05307         p->s3type = SQLITE_TEXT;
05308         p->s3size = -1;
05309         p->s3val = p->strbuf;
05310         break;
05311 #ifdef SQL_C_TYPE_TIMESTAMP
05312     case SQL_C_TYPE_TIMESTAMP:
05313 #endif
05314     case SQL_C_TIMESTAMP:
05315         if (*s->jdconv) {
05316             int a, b, x1, x2, y, m, d;
05317 
05318             p->s3type = SQLITE_FLOAT;
05319             p->s3size = sizeof (double);
05320             y = ((TIMESTAMP_STRUCT *) p->param)->year;
05321             m = ((TIMESTAMP_STRUCT *) p->param)->month;
05322             d = ((TIMESTAMP_STRUCT *) p->param)->day;
05323             if (m <= 2) {
05324                 y--;
05325                 m += 12;
05326             }
05327             a = y / 100;
05328             b = 2 - a + (a / 4);
05329             x1 = 36525 * (y + 4716) / 100;
05330             x2 = 306001 * (m + 1) / 10000;
05331             p->s3dval = x1 + x2 + d + b - 1524.5 +
05332                (((TIMESTAMP_STRUCT *) p->param)->hour * 3600000.0 +
05333                 ((TIMESTAMP_STRUCT *) p->param)->minute * 60000.0 +
05334                 ((TIMESTAMP_STRUCT *) p->param)->second * 1000.0 +
05335                 ((TIMESTAMP_STRUCT *) p->param)->fraction / 1.0E6)
05336                / 86400000.0;
05337             break;
05338         }
05339         len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
05340         len /= 1000000;
05341         len = len % 1000;
05342         if (len < 0) {
05343             len = 0;
05344         }
05345         if (p->coldef && p->coldef <= 16) {
05346             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
05347                     ((TIMESTAMP_STRUCT *) p->param)->year,
05348                     ((TIMESTAMP_STRUCT *) p->param)->month,
05349                     ((TIMESTAMP_STRUCT *) p->param)->day,
05350                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05351                     ((TIMESTAMP_STRUCT *) p->param)->minute);
05352         } else if (p->coldef && p->coldef <= 19) {
05353             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
05354                     ((TIMESTAMP_STRUCT *) p->param)->year,
05355                     ((TIMESTAMP_STRUCT *) p->param)->month,
05356                     ((TIMESTAMP_STRUCT *) p->param)->day,
05357                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05358                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05359                     ((TIMESTAMP_STRUCT *) p->param)->second);
05360         } else {
05361             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
05362                     ((TIMESTAMP_STRUCT *) p->param)->year,
05363                     ((TIMESTAMP_STRUCT *) p->param)->month,
05364                     ((TIMESTAMP_STRUCT *) p->param)->day,
05365                     ((TIMESTAMP_STRUCT *) p->param)->hour,
05366                     ((TIMESTAMP_STRUCT *) p->param)->minute,
05367                     ((TIMESTAMP_STRUCT *) p->param)->second,
05368                     len);
05369         }
05370         p->s3type = SQLITE_TEXT;
05371         p->s3size = -1;
05372         p->s3val = p->strbuf;
05373         break;
05374     default:
05375     error:
05376         setstat(s, -1, "unsupported parameter type",
05377                 (*s->ov3) ? "07009" : "S1093");
05378         return SQL_ERROR;
05379     }
05380     return SQL_SUCCESS;
05381 }
05382 
05398 static SQLRETURN
05399 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05400              SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
05401              SQLSMALLINT scale,
05402              SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
05403 {
05404     STMT *s;
05405     BINDPARM *p;
05406 
05407     if (stmt == SQL_NULL_HSTMT) {
05408         return SQL_INVALID_HANDLE;
05409     }
05410     s = (STMT *) stmt;
05411     if (pnum == 0) {
05412         setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
05413         return SQL_ERROR;
05414     }
05415     if (!data && !len) {
05416         setstat(s, -1, "invalid buffer", "HY003");
05417         return SQL_ERROR;
05418     }
05419     --pnum;
05420     if (s->bindparms) {
05421         if (pnum >= s->nbindparms) {
05422             BINDPARM *newparms;
05423 
05424             newparms = xrealloc(s->bindparms,
05425                                 (pnum + 1) * sizeof (BINDPARM));
05426             if (!newparms) {
05427 outofmem:
05428                 return nomem(s);
05429             }
05430             s->bindparms = newparms;
05431             memset(&s->bindparms[s->nbindparms], 0,
05432                    (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
05433             s->nbindparms = pnum + 1;
05434         }
05435     } else {
05436         int npar = max(10, pnum + 1);
05437 
05438         s->bindparms = xmalloc(npar * sizeof (BINDPARM));
05439         if (!s->bindparms) {
05440             goto outofmem;
05441         }
05442         memset(s->bindparms, 0, npar * sizeof (BINDPARM));
05443         s->nbindparms = npar;
05444     }
05445     switch (buftype) {
05446     case SQL_C_STINYINT:
05447     case SQL_C_UTINYINT:
05448     case SQL_C_TINYINT:
05449 #ifdef SQL_C_BIT
05450     case SQL_C_BIT:
05451 #endif
05452         buflen = sizeof (SQLCHAR);
05453         break;
05454     case SQL_C_SHORT:
05455     case SQL_C_USHORT:
05456     case SQL_C_SSHORT:
05457         buflen = sizeof (SQLSMALLINT);
05458         break;
05459     case SQL_C_SLONG:
05460     case SQL_C_ULONG:
05461     case SQL_C_LONG:
05462         buflen = sizeof (SQLINTEGER);
05463         break;
05464     case SQL_C_FLOAT:
05465         buflen = sizeof (float);
05466         break;
05467     case SQL_C_DOUBLE:
05468         buflen = sizeof (double);
05469         break;
05470     case SQL_C_TIMESTAMP:
05471 #ifdef SQL_C_TYPE_TIMESTAMP
05472     case SQL_C_TYPE_TIMESTAMP:
05473 #endif
05474         buflen = sizeof (TIMESTAMP_STRUCT);
05475         break;
05476     case SQL_C_TIME:
05477 #ifdef SQL_C_TYPE_TIME
05478     case SQL_C_TYPE_TIME:
05479 #endif
05480         buflen = sizeof (TIME_STRUCT);
05481         break;
05482     case SQL_C_DATE:
05483 #ifdef SQL_C_TYPE_DATE
05484     case SQL_C_TYPE_DATE:
05485 #endif
05486         buflen = sizeof (DATE_STRUCT);
05487         break;
05488 #ifdef SQL_C_UBIGINT
05489     case SQL_C_UBIGINT:
05490         buflen = sizeof (SQLBIGINT);
05491         break;
05492 #endif
05493 #ifdef SQL_C_SBIGINT
05494     case SQL_C_SBIGINT:
05495         buflen = sizeof (SQLBIGINT);
05496         break;
05497 #endif
05498 #ifdef SQL_C_BIGINT
05499     case SQL_C_BIGINT:
05500         buflen = sizeof (SQLBIGINT);
05501         break;
05502 #endif
05503     }
05504     p = &s->bindparms[pnum];
05505     p->type = buftype;
05506     p->stype = ptype;
05507     p->coldef = coldef;
05508     p->scale = scale;
05509     p->max = buflen;
05510     p->inc = buflen;
05511     p->lenp = p->lenp0 = len;
05512     p->offs = 0;
05513     p->len = 0;
05514     p->param0 = data;
05515     freep(&p->parbuf);
05516     p->param = p->param0;
05517     p->bound = 1;
05518     p->need = 0;
05519     return SQL_SUCCESS;
05520 }
05521 
05537 SQLRETURN SQL_API
05538 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
05539                  SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
05540                  SQLSMALLINT scale,
05541                  SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
05542 {
05543     SQLRETURN ret;
05544 
05545     HSTMT_LOCK(stmt);
05546     ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
05547                        scale, data, buflen, len);
05548     HSTMT_UNLOCK(stmt);
05549     return ret;
05550 }
05551 
05552 #ifndef HAVE_IODBC
05553 
05566 SQLRETURN SQL_API
05567 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
05568              SQLSMALLINT ptype, SQLULEN lenprec,
05569              SQLSMALLINT scale, SQLPOINTER val,
05570              SQLLEN *lenp)
05571 {
05572     SQLRETURN ret;
05573 
05574     HSTMT_LOCK(stmt);
05575     ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
05576                        lenprec, scale, val, 0, lenp);
05577     HSTMT_UNLOCK(stmt);
05578     return ret;
05579 }
05580 #endif
05581 
05589 SQLRETURN SQL_API
05590 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
05591 {
05592     STMT *s;
05593     SQLSMALLINT dummy;
05594 
05595     HSTMT_LOCK(stmt);
05596     if (stmt == SQL_NULL_HSTMT) {
05597         return SQL_INVALID_HANDLE;
05598     }
05599     s = (STMT *) stmt;
05600     if (!nparam) {
05601         nparam = &dummy;
05602     }
05603     *nparam = s->nparams;
05604     HSTMT_UNLOCK(stmt);
05605     return SQL_SUCCESS;
05606 }
05607 
05615 static SQLRETURN
05616 setupparbuf(STMT *s, BINDPARM *p)
05617 {
05618     if (!p->parbuf) {
05619         if (*p->lenp == SQL_DATA_AT_EXEC) {
05620             p->len = p->max;
05621         } else {
05622             p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
05623         }
05624         if (p->len < 0 && p->len != SQL_NTS &&
05625             p->len != SQL_NULL_DATA) {
05626             setstat(s, -1, "invalid length", "HY009");
05627             return SQL_ERROR;
05628         }
05629         if (p->len >= 0) {
05630             p->parbuf = xmalloc(p->len + 2);
05631             if (!p->parbuf) {
05632                 return nomem(s);
05633             }
05634             p->param = p->parbuf;
05635         } else {
05636             p->param = NULL;
05637         }
05638     }
05639     return SQL_NEED_DATA;
05640 }
05641 
05649 SQLRETURN SQL_API
05650 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
05651 {
05652     STMT *s;
05653     int i;
05654     SQLPOINTER dummy;
05655     SQLRETURN ret;
05656     BINDPARM *p;
05657 
05658     HSTMT_LOCK(stmt);
05659     if (stmt == SQL_NULL_HSTMT) {
05660         return SQL_INVALID_HANDLE;
05661     }
05662     s = (STMT *) stmt;
05663     if (!pind) {
05664         pind = &dummy;
05665     }
05666     if (s->pdcount < s->nparams) {
05667         s->pdcount++;
05668     }
05669     for (i = 0; i < s->pdcount; i++) {
05670         p = &s->bindparms[i];
05671         if (p->need > 0) {
05672             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
05673 
05674             p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? -1 : 0;
05675         }
05676     }
05677     for (; i < s->nparams; i++) {
05678         p = &s->bindparms[i];
05679         if (p->need > 0) {
05680             *pind = (SQLPOINTER) p->param0;
05681             ret = setupparbuf(s, p);
05682             s->pdcount = i;
05683             goto done;
05684         }
05685     }
05686     ret = drvexecute(stmt, 0);
05687 done:
05688     HSTMT_UNLOCK(stmt);
05689     return ret;
05690 }
05691 
05703 SQLRETURN SQL_API
05704 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
05705                  SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
05706 {
05707     STMT *s;
05708     SQLRETURN ret = SQL_ERROR;
05709 
05710     HSTMT_LOCK(stmt);
05711     if (stmt == SQL_NULL_HSTMT) {
05712         return SQL_INVALID_HANDLE;
05713     }
05714     s = (STMT *) stmt;
05715     --pnum;
05716     if (pnum >= s->nparams) {
05717         setstat(s, -1, "invalid parameter index",
05718                 (*s->ov3) ? "HY000" : "S1000");
05719         goto done;
05720     }
05721     if (dtype) {
05722 #ifdef SQL_LONGVARCHAR
05723 #ifdef WINTERFACE
05724         *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
05725 #else
05726         *dtype = SQL_LONGVARCHAR;
05727 #endif
05728 #else
05729 #ifdef WINTERFACE
05730         *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
05731 #else
05732         *dtype = SQL_VARCHAR;
05733 #endif
05734 #endif
05735     }
05736     if (size) {
05737 #ifdef SQL_LONGVARCHAR
05738         *size = 65536;
05739 #else
05740         *size = 255;
05741 #endif
05742     }
05743     if (decdigits) {
05744         *decdigits = 0;
05745     }
05746     if (nullable) {
05747         *nullable = SQL_NULLABLE;
05748     }
05749     ret = SQL_SUCCESS;
05750 done:
05751     HSTMT_UNLOCK(stmt);
05752     return ret;
05753 }
05754 
05768 SQLRETURN SQL_API
05769 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
05770             SQLSMALLINT sqltype, SQLULEN coldef,
05771             SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
05772 {
05773     SQLRETURN ret;
05774 
05775     HSTMT_LOCK(stmt);
05776     ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
05777                        type, sqltype, coldef, scale, val,
05778                        SQL_SETPARAM_VALUE_MAX, nval);
05779     HSTMT_UNLOCK(stmt);
05780     return ret;
05781 }
05782 
05787 SQLRETURN SQL_API
05788 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
05789 {
05790     SQLRETURN ret;
05791 
05792     HSTMT_LOCK(stmt);
05793     ret = drvunimplstmt(stmt);
05794     HSTMT_UNLOCK(stmt);
05795     return ret;
05796 }
05797 
05798 #ifndef WINTERFACE
05799 
05803 SQLRETURN SQL_API
05804 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
05805                 SQLSMALLINT fieldid, SQLPOINTER value,
05806                 SQLINTEGER buflen, SQLINTEGER *strlen)
05807 {
05808     return SQL_ERROR;
05809 }
05810 #endif
05811 
05812 #ifdef WINTERFACE
05813 
05817 SQLRETURN SQL_API
05818 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05819                  SQLSMALLINT fieldid, SQLPOINTER value,
05820                  SQLINTEGER buflen, SQLINTEGER *strlen)
05821 {
05822     return SQL_ERROR;
05823 }
05824 #endif
05825 
05826 #ifndef WINTERFACE
05827 
05831 SQLRETURN SQL_API
05832 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
05833                 SQLSMALLINT fieldid, SQLPOINTER value,
05834                 SQLINTEGER buflen)
05835 {
05836     return SQL_ERROR;
05837 }
05838 #endif
05839 
05840 #ifdef WINTERFACE
05841 
05845 SQLRETURN SQL_API
05846 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05847                  SQLSMALLINT fieldid, SQLPOINTER value,
05848                  SQLINTEGER buflen)
05849 {
05850     return SQL_ERROR;
05851 }
05852 #endif
05853 
05854 #ifndef WINTERFACE
05855 
05859 SQLRETURN SQL_API
05860 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05861               SQLCHAR *name, SQLSMALLINT buflen,
05862               SQLSMALLINT *strlen, SQLSMALLINT *type,
05863               SQLSMALLINT *subtype, SQLLEN *len,
05864               SQLSMALLINT *prec, SQLSMALLINT *scale,
05865               SQLSMALLINT *nullable)
05866 {
05867     return SQL_ERROR;
05868 }
05869 #endif
05870 
05871 #ifdef WINTERFACE
05872 
05876 SQLRETURN SQL_API
05877 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
05878                SQLWCHAR *name, SQLSMALLINT buflen,
05879                SQLSMALLINT *strlen, SQLSMALLINT *type,
05880                SQLSMALLINT *subtype, SQLLEN *len,
05881                SQLSMALLINT *prec, SQLSMALLINT *scale,
05882                SQLSMALLINT *nullable)
05883 {
05884     return SQL_ERROR;
05885 }
05886 #endif
05887 
05892 SQLRETURN SQL_API
05893 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05894               SQLSMALLINT type, SQLSMALLINT subtype,
05895               SQLLEN len, SQLSMALLINT prec,
05896               SQLSMALLINT scale, SQLPOINTER data,
05897               SQLLEN *strlen, SQLLEN *indicator)
05898 {
05899     return SQL_ERROR;
05900 }
05901 
05913 static SQLRETURN
05914 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
05915             int ncols3, int *nret)
05916 {
05917     STMT *s;
05918     DBC *d;
05919 
05920     if (stmt == SQL_NULL_HSTMT) {
05921         return SQL_INVALID_HANDLE;
05922     }
05923     s = (STMT *) stmt;
05924     if (s->dbc == SQL_NULL_HDBC) {
05925 noconn:
05926         return noconn(s);
05927     }
05928     d = (DBC *) s->dbc;
05929     if (!d->sqlite) {
05930         goto noconn;
05931     }
05932     s3stmt_end_if(s);
05933     freeresult(s, 0);
05934     if (colspec3 && *s->ov3) {
05935         s->ncols = ncols3;
05936         s->cols = colspec3;
05937     } else {
05938         s->ncols = ncols;
05939         s->cols = colspec;
05940     }
05941     mkbindcols(s, s->ncols);
05942     s->nowchar[1] = 1;
05943     s->nrows = 0;
05944     s->rowp = s->rowprs = -1;
05945     s->isselect = -1;
05946     if (nret) {
05947         *nret = s->ncols;
05948     }
05949     return SQL_SUCCESS;
05950 }
05951 
05956 static COL tablePrivSpec2[] = {
05957     { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05958     { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
05959     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05960     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05961     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05962     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05963     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05964 };
05965 
05966 static COL tablePrivSpec3[] = {
05967     { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
05968     { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
05969     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05970     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05971     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05972     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05973     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05974 };
05975 
05988 static SQLRETURN
05989 drvtableprivileges(SQLHSTMT stmt,
05990                    SQLCHAR *cat, SQLSMALLINT catLen,
05991                    SQLCHAR *schema, SQLSMALLINT schemaLen,
05992                    SQLCHAR *table, SQLSMALLINT tableLen)
05993 {
05994     SQLRETURN ret;
05995     STMT *s;
05996     DBC *d;
05997     int ncols, rc, size, npatt;
05998     char *errp = NULL, *sql, tname[512];
05999 
06000     ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
06001                       tablePrivSpec3, array_size(tablePrivSpec3), NULL);
06002     if (ret != SQL_SUCCESS) {
06003         return ret;
06004     }
06005     s = (STMT *) stmt;
06006     d = (DBC *) s->dbc;
06007     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
06008         table = NULL;
06009         goto doit;
06010     }
06011     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
06012         schema[0] == '%') {
06013         if ((!cat || catLen == 0 || !cat[0]) &&
06014             (!table || tableLen == 0 || !table[0])) {
06015             table = NULL;
06016             goto doit;
06017         }
06018     }
06019 doit:
06020     if (!table) {
06021         size = 1;
06022         tname[0] = '%';
06023     } else {
06024         if (tableLen == SQL_NTS) {
06025             size = sizeof (tname) - 1;
06026         } else {
06027             size = min(sizeof (tname) - 1, tableLen);
06028         }
06029         strncpy(tname, (char *) table, size);
06030     }
06031     tname[size] = '\0';
06032     npatt = unescpat(tname);
06033 #if defined(_WIN32) || defined(_WIN64)
06034     if (npatt) {
06035         sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
06036                               "%s as 'TABLE_OWNER', "
06037                               "tbl_name as 'TABLE_NAME', "
06038                               "'' as 'GRANTOR', "
06039                               "'' as 'GRANTEE', "
06040                               "'SELECT' AS 'PRIVILEGE', "
06041                               "NULL as 'IS_GRANTABLE' "
06042                               "from sqlite_master where "
06043                               "(type = 'table' or type = 'view') "
06044                               "and tbl_name like %Q "
06045                               "UNION "
06046                               "select %s as 'TABLE_QUALIFIER', "
06047                               "%s as 'TABLE_OWNER', "
06048                               "tbl_name as 'TABLE_NAME', "
06049                               "'' as 'GRANTOR', "
06050                               "'' as 'GRANTEE', "
06051                               "'UPDATE' AS 'PRIVILEGE', "
06052                               "NULL as 'IS_GRANTABLE' "
06053                               "from sqlite_master where "
06054                               "(type = 'table' or type = 'view') "
06055                               "and tbl_name like %Q "
06056                               "UNION "
06057                               "select %s as 'TABLE_QUALIFIER', "
06058                               "%s as 'TABLE_OWNER', "
06059                               "tbl_name as 'TABLE_NAME', "
06060                               "'' as 'GRANTOR', "
06061                               "'' as 'GRANTEE', "
06062                               "'DELETE' AS 'PRIVILEGE', "
06063                               "NULL as 'IS_GRANTABLE' "
06064                               "from sqlite_master where "
06065                               "(type = 'table' or type = 'view') "
06066                               "and tbl_name like %Q "
06067                               "UNION "
06068                               "select %s as 'TABLE_QUALIFIER', "
06069                               "%s as 'TABLE_OWNER', "
06070                               "tbl_name as 'TABLE_NAME', "
06071                               "'' as 'GRANTOR', "
06072                               "'' as 'GRANTEE', "
06073                               "'INSERT' AS 'PRIVILEGE', "
06074                               "NULL as 'IS_GRANTABLE' "
06075                               "from sqlite_master where "
06076                               "(type = 'table' or type = 'view') "
06077                               "and tbl_name like %Q "
06078                               "UNION "
06079                               "select %s as 'TABLE_QUALIFIER', "
06080                               "%s as 'TABLE_OWNER', "
06081                               "tbl_name as 'TABLE_NAME', "
06082                               "'' as 'GRANTOR', "
06083                               "'' as 'GRANTEE', "
06084                               "'REFERENCES' AS 'PRIVILEGE', "
06085                               "NULL as 'IS_GRANTABLE' "
06086                               "from sqlite_master where "
06087                               "(type = 'table' or type = 'view') "
06088                               "and tbl_name like %Q",
06089                               d->xcelqrx ? "'main'" : "NULL",
06090                               d->xcelqrx ? "''" : "NULL",
06091                               tname,
06092                               d->xcelqrx ? "'main'" : "NULL",
06093                               d->xcelqrx ? "''" : "NULL",
06094                               tname,
06095                               d->xcelqrx ? "'main'" : "NULL",
06096                               d->xcelqrx ? "''" : "NULL",
06097                               tname,
06098                               d->xcelqrx ? "'main'" : "NULL",
06099                               d->xcelqrx ? "''" : "NULL",
06100                               tname,
06101                               d->xcelqrx ? "'main'" : "NULL",
06102                               d->xcelqrx ? "''" : "NULL",
06103                               tname);
06104     } else {
06105         sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
06106                               "%s as 'TABLE_OWNER', "
06107                               "tbl_name as 'TABLE_NAME', "
06108                               "'' as 'GRANTOR', "
06109                               "'' as 'GRANTEE', "
06110                               "'SELECT' AS 'PRIVILEGE', "
06111                               "NULL as 'IS_GRANTABLE' "
06112                               "from sqlite_master where "
06113                               "(type = 'table' or type = 'view') "
06114                               "and lower(tbl_name) = lower(%Q) "
06115                               "UNION "
06116                               "select %s as 'TABLE_QUALIFIER', "
06117                               "%s as 'TABLE_OWNER', "
06118                               "tbl_name as 'TABLE_NAME', "
06119                               "'' as 'GRANTOR', "
06120                               "'' as 'GRANTEE', "
06121                               "'UPDATE' AS 'PRIVILEGE', "
06122                               "NULL as 'IS_GRANTABLE' "
06123                               "from sqlite_master where "
06124                               "(type = 'table' or type = 'view') "
06125                               "and lower(tbl_name) = lower(%Q) "
06126                               "UNION "
06127                               "select %s as 'TABLE_QUALIFIER', "
06128                               "%s as 'TABLE_OWNER', "
06129                               "tbl_name as 'TABLE_NAME', "
06130                               "'' as 'GRANTOR', "
06131                               "'' as 'GRANTEE', "
06132                               "'DELETE' AS 'PRIVILEGE', "
06133                               "NULL as 'IS_GRANTABLE' "
06134                               "from sqlite_master where "
06135                               "(type = 'table' or type = 'view') "
06136                               "and lower(tbl_name) = lower(%Q) "
06137                               "UNION "
06138                               "select %s as 'TABLE_QUALIFIER', "
06139                               "%s as 'TABLE_OWNER', "
06140                               "tbl_name as 'TABLE_NAME', "
06141                               "'' as 'GRANTOR', "
06142                               "'' as 'GRANTEE', "
06143                               "'INSERT' AS 'PRIVILEGE', "
06144                               "NULL as 'IS_GRANTABLE' "
06145                               "from sqlite_master where "
06146                               "(type = 'table' or type = 'view') "
06147                               "and lower(tbl_name) = lower(%Q) "
06148                               "UNION "
06149                               "select %s as 'TABLE_QUALIFIER', "
06150                               "%s as 'TABLE_OWNER', "
06151                               "tbl_name as 'TABLE_NAME', "
06152                               "'' as 'GRANTOR', "
06153                               "'' as 'GRANTEE', "
06154                               "'REFERENCES' AS 'PRIVILEGE', "
06155                               "NULL as 'IS_GRANTABLE' "
06156                               "from sqlite_master where "
06157                               "(type = 'table' or type = 'view') "
06158                               "and lower(tbl_name) = lower(%Q)",
06159                               d->xcelqrx ? "'main'" : "NULL",
06160                               d->xcelqrx ? "''" : "NULL",
06161                               tname,
06162                               d->xcelqrx ? "'main'" : "NULL",
06163                               d->xcelqrx ? "''" : "NULL",
06164                               tname,
06165                               d->xcelqrx ? "'main'" : "NULL",
06166                               d->xcelqrx ? "''" : "NULL",
06167                               tname,
06168                               d->xcelqrx ? "'main'" : "NULL",
06169                               d->xcelqrx ? "''" : "NULL",
06170                               tname,
06171                               d->xcelqrx ? "'main'" : "NULL",
06172                               d->xcelqrx ? "''" : "NULL",
06173                               tname);
06174     }
06175 #else
06176     if (npatt) {
06177         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
06178                               "NULL as 'TABLE_OWNER', "
06179                               "tbl_name as 'TABLE_NAME', "
06180                               "'' as 'GRANTOR', "
06181                               "'' as 'GRANTEE', "
06182                               "'SELECT' AS 'PRIVILEGE', "
06183                               "NULL as 'IS_GRANTABLE' "
06184                               "from sqlite_master where "
06185                               "(type = 'table' or type = 'view') "
06186                               "and tbl_name like %Q "
06187                               "UNION "
06188                               "select NULL as 'TABLE_QUALIFIER', "
06189                               "NULL as 'TABLE_OWNER', "
06190                               "tbl_name as 'TABLE_NAME', "
06191                               "'' as 'GRANTOR', "
06192                               "'' as 'GRANTEE', "
06193                               "'UPDATE' AS 'PRIVILEGE', "
06194                               "NULL as 'IS_GRANTABLE' "
06195                               "from sqlite_master where "
06196                               "(type = 'table' or type = 'view') "
06197                               "and tbl_name like %Q "
06198                               "UNION "
06199                               "select NULL as 'TABLE_QUALIFIER', "
06200                               "NULL as 'TABLE_OWNER', "
06201                               "tbl_name as 'TABLE_NAME', "
06202                               "'' as 'GRANTOR', "
06203                               "'' as 'GRANTEE', "
06204                               "'DELETE' AS 'PRIVILEGE', "
06205                               "NULL as 'IS_GRANTABLE' "
06206                               "from sqlite_master where "
06207                               "(type = 'table' or type = 'view') "
06208                               "and tbl_name like %Q "
06209                               "UNION "
06210                               "select NULL as 'TABLE_QUALIFIER', "
06211                               "NULL as 'TABLE_OWNER', "
06212                               "tbl_name as 'TABLE_NAME', "
06213                               "'' as 'GRANTOR', "
06214                               "'' as 'GRANTEE', "
06215                               "'INSERT' AS 'PRIVILEGE', "
06216                               "NULL as 'IS_GRANTABLE' "
06217                               "from sqlite_master where "
06218                               "(type = 'table' or type = 'view') "
06219                               "and tbl_name like %Q "
06220                               "UNION "
06221                               "select NULL as 'TABLE_QUALIFIER', "
06222                               "NULL as 'TABLE_OWNER', "
06223                               "tbl_name as 'TABLE_NAME', "
06224                               "'' as 'GRANTOR', "
06225                               "'' as 'GRANTEE', "
06226                               "'REFERENCES' AS 'PRIVILEGE', "
06227                               "NULL as 'IS_GRANTABLE' "
06228                               "from sqlite_master where "
06229                               "(type = 'table' or type = 'view') "
06230                               "and tbl_name like %Q",
06231                               tname, tname, tname, tname, tname);
06232     } else {
06233         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
06234                               "NULL as 'TABLE_OWNER', "
06235                               "tbl_name as 'TABLE_NAME', "
06236                               "'' as 'GRANTOR', "
06237                               "'' as 'GRANTEE', "
06238                               "'SELECT' AS 'PRIVILEGE', "
06239                               "NULL as 'IS_GRANTABLE' "
06240                               "from sqlite_master where "
06241                               "(type = 'table' or type = 'view') "
06242                               "and lower(tbl_name) = lower(%Q) "
06243                               "UNION "
06244                               "select NULL as 'TABLE_QUALIFIER', "
06245                               "NULL as 'TABLE_OWNER', "
06246                               "tbl_name as 'TABLE_NAME', "
06247                               "'' as 'GRANTOR', "
06248                               "'' as 'GRANTEE', "
06249                               "'UPDATE' AS 'PRIVILEGE', "
06250                               "NULL as 'IS_GRANTABLE' "
06251                               "from sqlite_master where "
06252                               "(type = 'table' or type = 'view') "
06253                               "and lower(tbl_name) = lower(%Q) "
06254                               "UNION "
06255                               "select NULL as 'TABLE_QUALIFIER', "
06256                               "NULL as 'TABLE_OWNER', "
06257                               "tbl_name as 'TABLE_NAME', "
06258                               "'' as 'GRANTOR', "
06259                               "'' as 'GRANTEE', "
06260                               "'DELETE' AS 'PRIVILEGE', "
06261                               "NULL as 'IS_GRANTABLE' "
06262                               "from sqlite_master where "
06263                               "(type = 'table' or type = 'view') "
06264                               "and lower(tbl_name) = lower(%Q) "
06265                               "UNION "
06266                               "select NULL as 'TABLE_QUALIFIER', "
06267                               "NULL as 'TABLE_OWNER', "
06268                               "tbl_name as 'TABLE_NAME', "
06269                               "'' as 'GRANTOR', "
06270                               "'' as 'GRANTEE', "
06271                               "'INSERT' AS 'PRIVILEGE', "
06272                               "NULL as 'IS_GRANTABLE' "
06273                               "from sqlite_master where "
06274                               "(type = 'table' or type = 'view') "
06275                               "and lower(tbl_name) = lower(%Q) "
06276                               "UNION "
06277                               "select NULL as 'TABLE_QUALIFIER', "
06278                               "NULL as 'TABLE_OWNER', "
06279                               "tbl_name as 'TABLE_NAME', "
06280                               "'' as 'GRANTOR', "
06281                               "'' as 'GRANTEE', "
06282                               "'REFERENCES' AS 'PRIVILEGE', "
06283                               "NULL as 'IS_GRANTABLE' "
06284                               "from sqlite_master where "
06285                               "(type = 'table' or type = 'view') "
06286                               "and lower(tbl_name) = lower(%Q)",
06287                               tname, tname, tname, tname, tname);
06288     }
06289 #endif
06290     if (!sql) {
06291         return nomem(s);
06292     }
06293     ret = starttran(s);
06294     if (ret != SQL_SUCCESS) {
06295         sqlite3_free(sql);
06296         return ret;
06297     }
06298     dbtraceapi(d, "sqlite3_get_table", sql);
06299     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
06300     sqlite3_free(sql);
06301     if (rc == SQLITE_OK) {
06302         if (ncols != s->ncols) {
06303             freeresult(s, 0);
06304             s->nrows = 0;
06305         } else {
06306             s->rowfree = sqlite3_free_table;
06307         }
06308     } else {
06309         s->nrows = 0;
06310         s->rows = NULL;
06311         s->rowfree = NULL;
06312     }
06313     if (errp) {
06314         sqlite3_free(errp);
06315         errp = NULL;
06316     }
06317     s->rowp = s->rowprs = -1;
06318     return SQL_SUCCESS;
06319 }
06320 
06321 
06322 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06323 
06335 SQLRETURN SQL_API
06336 SQLTablePrivileges(SQLHSTMT stmt,
06337                    SQLCHAR *catalog, SQLSMALLINT catalogLen,
06338                    SQLCHAR *schema, SQLSMALLINT schemaLen,
06339                    SQLCHAR *table, SQLSMALLINT tableLen)
06340 {
06341 #if defined(_WIN32) || defined(_WIN64)
06342     char *c = NULL, *s = NULL, *t = NULL;
06343 #endif
06344     SQLRETURN ret;
06345 
06346     HSTMT_LOCK(stmt);
06347 #if defined(_WIN32) || defined(_WIN64)
06348     if (!((STMT *) stmt)->oemcp[0]) {
06349         ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06350                                  table, tableLen);
06351         goto done2;
06352     }
06353     if (catalog) {
06354         c = wmb_to_utf_c((char *) catalog, catalogLen);
06355         if (!c) {
06356             ret = nomem((STMT *) stmt);
06357             goto done;
06358         }
06359     }
06360     if (schema) {
06361         s = wmb_to_utf_c((char *) schema, schemaLen);
06362         if (!s) {
06363             ret = nomem((STMT *) stmt);
06364             goto done;
06365         }
06366     }
06367     if (table) {
06368         t = wmb_to_utf_c((char *) table, tableLen);
06369         if (!t) {
06370             ret = nomem((STMT *) stmt);
06371             goto done;
06372         }
06373     }
06374     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06375                              (SQLCHAR *) s, SQL_NTS,
06376                              (SQLCHAR *) t, SQL_NTS);
06377 #else
06378     ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
06379                              table, tableLen);
06380 #endif
06381 #if defined(_WIN32) || defined(_WIN64)
06382 done:
06383     uc_free(t);
06384     uc_free(s);
06385     uc_free(c);
06386 done2:
06387     ;
06388 #endif
06389     HSTMT_UNLOCK(stmt);
06390     return ret;
06391 }
06392 #endif
06393 
06394 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06395 #ifdef WINTERFACE
06396 
06408 SQLRETURN SQL_API
06409 SQLTablePrivilegesW(SQLHSTMT stmt,
06410                     SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06411                     SQLWCHAR *schema, SQLSMALLINT schemaLen,
06412                     SQLWCHAR *table, SQLSMALLINT tableLen)
06413 {
06414     char *c = NULL, *s = NULL, *t = NULL;
06415     SQLRETURN ret;
06416 
06417     HSTMT_LOCK(stmt);
06418     if (catalog) {
06419         c = uc_to_utf_c(catalog, catalogLen);
06420         if (!c) {
06421             ret = nomem((STMT *) stmt);
06422             goto done;
06423         }
06424     }
06425     if (schema) {
06426         s = uc_to_utf_c(schema, schemaLen);
06427         if (!s) {
06428             ret = nomem((STMT *) stmt);
06429             goto done;
06430         }
06431     }
06432     if (table) {
06433         t = uc_to_utf_c(table, tableLen);
06434         if (!t) {
06435             ret = nomem((STMT *) stmt);
06436             goto done;
06437         }
06438     }
06439     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
06440                              (SQLCHAR *) s, SQL_NTS,
06441                              (SQLCHAR *) t, SQL_NTS);
06442 done:
06443     uc_free(t);
06444     uc_free(s);
06445     uc_free(c);
06446     HSTMT_UNLOCK(stmt);
06447     return ret;
06448 }
06449 #endif
06450 #endif
06451 
06456 static COL colPrivSpec2[] = {
06457     { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06458     { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06459     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06460     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06461     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06462     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06463     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06464 };
06465 
06466 static COL colPrivSpec3[] = {
06467     { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
06468     { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06469     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
06470     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06471     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
06472     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
06473     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
06474 };
06475 
06476 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
06477 
06491 SQLRETURN SQL_API
06492 SQLColumnPrivileges(SQLHSTMT stmt,
06493                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
06494                     SQLCHAR *schema, SQLSMALLINT schemaLen,
06495                     SQLCHAR *table, SQLSMALLINT tableLen,
06496                     SQLCHAR *column, SQLSMALLINT columnLen)
06497 {
06498     SQLRETURN ret;
06499 
06500     HSTMT_LOCK(stmt);
06501     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06502                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06503     HSTMT_UNLOCK(stmt);
06504     return ret;
06505 }
06506 #endif
06507 
06508 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
06509 #ifdef WINTERFACE
06510 
06524 SQLRETURN SQL_API
06525 SQLColumnPrivilegesW(SQLHSTMT stmt,
06526                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06527                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
06528                      SQLWCHAR *table, SQLSMALLINT tableLen,
06529                      SQLWCHAR *column, SQLSMALLINT columnLen)
06530 {
06531     SQLRETURN ret;
06532 
06533     HSTMT_LOCK(stmt);
06534     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
06535                       colPrivSpec3, array_size(colPrivSpec3), NULL);
06536     HSTMT_UNLOCK(stmt);
06537     return ret;
06538 }
06539 #endif
06540 #endif
06541 
06546 static COL pkeySpec2[] = {
06547     { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06548     { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
06549     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06550     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06551     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06552     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06553 };
06554 
06555 static COL pkeySpec3[] = {
06556     { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
06557     { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
06558     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
06559     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06560     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
06561     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
06562 };
06563 
06576 static SQLRETURN
06577 drvprimarykeys(SQLHSTMT stmt,
06578                SQLCHAR *cat, SQLSMALLINT catLen,
06579                SQLCHAR *schema, SQLSMALLINT schemaLen,
06580                SQLCHAR *table, SQLSMALLINT tableLen)
06581 {
06582     STMT *s;
06583     DBC *d;
06584     SQLRETURN sret;
06585     int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
06586     int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
06587     PTRDIFF_T size;
06588     char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
06589 
06590     sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
06591                        pkeySpec3, array_size(pkeySpec3), &asize);
06592     if (sret != SQL_SUCCESS) {
06593         return sret;
06594     }
06595     s = (STMT *) stmt;
06596     d = (DBC *) s->dbc;
06597     if (!table || table[0] == '\0' || table[0] == '%') {
06598         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06599         return SQL_ERROR;
06600     }
06601     if (tableLen == SQL_NTS) {
06602         size = sizeof (tname) - 1;
06603     } else {
06604         size = min(sizeof (tname) - 1, tableLen);
06605     }
06606     strncpy(tname, (char *) table, size);
06607     tname[size] = '\0';
06608     unescpat(tname);
06609     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
06610     if (!sql) {
06611         return nomem(s);
06612     }
06613     sret = starttran(s);
06614     if (sret != SQL_SUCCESS) {
06615         sqlite3_free(sql);
06616         return sret;
06617     }
06618     dbtraceapi(d, "sqlite3_get_table", sql);
06619     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06620     sqlite3_free(sql);
06621     if (ret != SQLITE_OK) {
06622         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06623                 errp ? errp : "unknown error", ret);
06624         if (errp) {
06625             sqlite3_free(errp);
06626             errp = NULL;
06627         }
06628         return SQL_ERROR;
06629     }
06630     if (errp) {
06631         sqlite3_free(errp);
06632         errp = NULL;
06633     }
06634     size = 0;
06635     if (ncols * nrows > 0) {
06636         int typec;
06637 
06638         namec = findcol(rowp, ncols, "name");
06639         uniquec = findcol(rowp, ncols, "pk");
06640         typec = findcol(rowp, ncols, "type");
06641         if (namec >= 0 && uniquec >= 0 && typec >= 0) {
06642             for (i = 1; i <= nrows; i++) {
06643                 if (*rowp[i * ncols + uniquec] != '0') {
06644                     size++;
06645                 }
06646             }
06647         }
06648     }
06649     if (size == 0) {
06650         sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
06651         if (!sql) {
06652             sqlite3_free_table(rowp);
06653             return nomem(s);
06654         }
06655         dbtraceapi(d, "sqlite3_get_table", sql);
06656         ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
06657                                 &errp);
06658         sqlite3_free(sql);
06659         if (ret != SQLITE_OK) {
06660             sqlite3_free_table(rowp);
06661             sqlite3_free_table(rowp2);
06662             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06663                     errp ? errp : "unknown error", ret);
06664             if (errp) {
06665                 sqlite3_free(errp);
06666                 errp = NULL;
06667             }
06668             return SQL_ERROR;
06669         }
06670         if (errp) {
06671             sqlite3_free(errp);
06672             errp = NULL;
06673         }
06674     }
06675     if (ncols2 * nrows2 > 0) {
06676         namec2 = findcol(rowp2, ncols2, "name");
06677         uniquec2 = findcol(rowp2, ncols2, "unique");
06678         if (namec2 >= 0 && uniquec2 >=  0) {
06679             for (i = 1; i <= nrows2; i++) {
06680                 int nnrows, nncols, nlen = 0;
06681                 char **rowpp;
06682 
06683                 if (rowp2[i * ncols2 + namec2]) {
06684                     nlen = strlen(rowp2[i * ncols2 + namec2]);
06685                 }
06686                 if (nlen < 17 ||
06687                     strncmp(rowp2[i * ncols2 + namec2],
06688                             "sqlite_autoindex_", 17)) {
06689                     continue;
06690                 }
06691                 if (*rowp2[i * ncols2 + uniquec2] != '0') {
06692                     ret = SQLITE_ERROR;
06693                     sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06694                                           rowp2[i * ncols2 + namec2]);
06695                     if (sql) {
06696                         dbtraceapi(d, "sqlite3_get_table", sql);
06697                         ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06698                                                 &nnrows, &nncols, NULL);
06699                         sqlite3_free(sql);
06700                     }
06701                     if (ret == SQLITE_OK) {
06702                         size += nnrows;
06703                         sqlite3_free_table(rowpp);
06704                     }
06705                 }
06706             }
06707         }
06708     }
06709     if (size == 0) {
06710         sqlite3_free_table(rowp);
06711         sqlite3_free_table(rowp2);
06712         return SQL_SUCCESS;
06713     }
06714     s->nrows = size;
06715     size = (size + 1) * asize;
06716     s->rows = xmalloc((size + 1) * sizeof (char *));
06717     if (!s->rows) {
06718         s->nrows = 0;
06719         sqlite3_free_table(rowp);
06720         sqlite3_free_table(rowp2);
06721         return nomem(s);
06722     }
06723     s->rows[0] = (char *) size;
06724     s->rows += 1;
06725     memset(s->rows, 0, sizeof (char *) * size);
06726     s->rowfree = freerows;
06727     offs = s->ncols;
06728     if (rowp) {
06729         for (i = 1; i <= nrows; i++) {
06730             if (*rowp[i * ncols + uniquec] != '0') {
06731                 char buf[32];
06732 
06733 #if defined(_WIN32) || defined(_WIN64)
06734                 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
06735                 s->rows[offs + 1] = xstrdup("");
06736 #else
06737                 s->rows[offs + 0] = xstrdup("");
06738                 s->rows[offs + 1] = xstrdup("");
06739 #endif
06740                 s->rows[offs + 2] = xstrdup(tname);
06741                 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
06742                 sprintf(buf, "%d", seq++);
06743                 s->rows[offs + 4] = xstrdup(buf);
06744                 offs += s->ncols;
06745             }
06746         }
06747     }
06748     if (rowp2) {
06749         for (i = 1; i <= nrows2; i++) {
06750             int nnrows, nncols, nlen = 0;
06751             char **rowpp;
06752 
06753             if (rowp2[i * ncols2 + namec2]) {
06754                 nlen = strlen(rowp2[i * ncols2 + namec2]);
06755             }
06756             if (nlen < 17 ||
06757                 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
06758                 continue;
06759             }
06760             if (*rowp2[i * ncols2 + uniquec2] != '0') {
06761                 int k;
06762 
06763                 ret = SQLITE_ERROR;
06764                 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06765                                       rowp2[i * ncols2 + namec2]);
06766                 if (sql) {
06767                     dbtraceapi(d, "sqlite3_get_table", sql);
06768                     ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06769                                             &nnrows, &nncols, NULL);
06770                     sqlite3_free(sql);
06771                 }
06772                 if (ret != SQLITE_OK) {
06773                     continue;
06774                 }
06775                 for (k = 0; nnrows && k < nncols; k++) {
06776                     if (strcmp(rowpp[k], "name") == 0) {
06777                         int m;
06778 
06779                         for (m = 1; m <= nnrows; m++) {
06780                             int roffs = offs + (m - 1) * s->ncols;
06781 
06782 #if defined(_WIN32) || defined(_WIN64)
06783                             s->rows[roffs + 0] =
06784                                 xstrdup(d->xcelqrx ? "main" : "");
06785                             s->rows[roffs + 1] = xstrdup("");
06786 #else
06787                             s->rows[roffs + 0] = xstrdup("");
06788                             s->rows[roffs + 1] = xstrdup("");
06789 #endif
06790                             s->rows[roffs + 2] = xstrdup(tname);
06791                             s->rows[roffs + 3] =
06792                                 xstrdup(rowpp[m * nncols + k]);
06793                             s->rows[roffs + 5] =
06794                                 xstrdup(rowp2[i * ncols2 + namec2]);
06795                         }
06796                     } else if (strcmp(rowpp[k], "seqno") == 0) {
06797                         int m;
06798 
06799                         for (m = 1; m <= nnrows; m++) {
06800                             int roffs = offs + (m - 1) * s->ncols;
06801                             int pos = m - 1;
06802                             char buf[32];
06803 
06804                             sscanf(rowpp[m * nncols + k], "%d", &pos);
06805                             sprintf(buf, "%d", pos + 1);
06806                             s->rows[roffs + 4] = xstrdup(buf);
06807                         }
06808                     }
06809                 }
06810                 offs += nnrows * s->ncols;
06811                 sqlite3_free_table(rowpp);
06812             }
06813         }
06814     }
06815     sqlite3_free_table(rowp);
06816     sqlite3_free_table(rowp2);
06817     return SQL_SUCCESS;
06818 }
06819 
06820 #ifndef WINTERFACE
06821 
06833 SQLRETURN SQL_API
06834 SQLPrimaryKeys(SQLHSTMT stmt,
06835                SQLCHAR *cat, SQLSMALLINT catLen,
06836                SQLCHAR *schema, SQLSMALLINT schemaLen,
06837                SQLCHAR *table, SQLSMALLINT tableLen)
06838 {
06839 #if defined(_WIN32) || defined(_WIN64)
06840     char *c = NULL, *s = NULL, *t = NULL;
06841 #endif
06842     SQLRETURN ret;
06843 
06844     HSTMT_LOCK(stmt);
06845 #if defined(_WIN32) || defined(_WIN64)
06846     if (!((STMT *) stmt)->oemcp[0]) {
06847         ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06848                              table, tableLen);
06849         goto done2;
06850     }
06851     if (cat) {
06852         c = wmb_to_utf_c((char *) cat, catLen);
06853         if (!c) {
06854             ret = nomem((STMT *) stmt);
06855             goto done;
06856         }
06857     }
06858     if (schema) {
06859         s = wmb_to_utf_c((char *) schema, schemaLen);
06860         if (!s) {
06861             ret = nomem((STMT *) stmt);
06862             goto done;
06863         }
06864     }
06865     if (table) {
06866         t = wmb_to_utf_c((char *) table, tableLen);
06867         if (!t) {
06868             ret = nomem((STMT *) stmt);
06869             goto done;
06870         }
06871     }
06872     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06873                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06874 #else
06875     ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06876                          table, tableLen);
06877 #endif
06878 #if defined(_WIN32) || defined(_WIN64)
06879 done:
06880     uc_free(t);
06881     uc_free(s);
06882     uc_free(c);
06883 done2:
06884     ;
06885 #endif
06886     HSTMT_UNLOCK(stmt);
06887     return ret;
06888 }
06889 #endif
06890 
06891 #ifdef WINTERFACE
06892 
06904 SQLRETURN SQL_API
06905 SQLPrimaryKeysW(SQLHSTMT stmt,
06906                 SQLWCHAR *cat, SQLSMALLINT catLen,
06907                 SQLWCHAR *schema, SQLSMALLINT schemaLen,
06908                 SQLWCHAR *table, SQLSMALLINT tableLen)
06909 {
06910     char *c = NULL, *s = NULL, *t = NULL;
06911     SQLRETURN ret;
06912 
06913     HSTMT_LOCK(stmt);
06914     if (cat) {
06915         c = uc_to_utf_c(cat, catLen);
06916         if (!c) {
06917             ret = nomem((STMT *) stmt);
06918             goto done;
06919         }
06920     }
06921     if (schema) {
06922         s = uc_to_utf_c(schema, schemaLen);
06923         if (!s) {
06924             ret = nomem((STMT *) stmt);
06925             goto done;
06926         }
06927     }
06928     if (table) {
06929         t = uc_to_utf_c(table, tableLen);
06930         if (!t) {
06931             ret = nomem((STMT *) stmt);
06932             goto done;
06933         }
06934     }
06935     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06936                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06937 done:
06938     uc_free(t);
06939     uc_free(s);
06940     uc_free(c);
06941     HSTMT_UNLOCK(stmt);
06942     return ret;
06943 }
06944 #endif
06945 
06950 static COL scolSpec2[] = {
06951     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06952     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06953     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06954     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06955     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
06956     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
06957     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06958     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06959     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06960 };
06961 
06962 static COL scolSpec3[] = {
06963     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06964     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06965     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06966     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06967     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
06968     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
06969     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06970     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06971     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06972 };
06973 
06989 static SQLRETURN
06990 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
06991                   SQLCHAR *cat, SQLSMALLINT catLen,
06992                   SQLCHAR *schema, SQLSMALLINT schemaLen,
06993                   SQLCHAR *table, SQLSMALLINT tableLen,
06994                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
06995 {
06996     STMT *s;
06997     DBC *d;
06998     SQLRETURN sret;
06999     int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
07000     PTRDIFF_T size;
07001     int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
07002     int notnullcc = -1, mkrowid = 0;
07003     char *errp = NULL, *sql, tname[512];
07004     char **rowp = NULL, **rowppp = NULL;
07005 
07006     sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
07007                        scolSpec3, array_size(scolSpec3), &asize);
07008     if (sret != SQL_SUCCESS) {
07009         return sret;
07010     }
07011     s = (STMT *) stmt;
07012     d = (DBC *) s->dbc;
07013     if (!table || table[0] == '\0' || table[0] == '%') {
07014         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
07015         return SQL_ERROR;
07016     }
07017     if (tableLen == SQL_NTS) {
07018         size = sizeof (tname) - 1;
07019     } else {
07020         size = min(sizeof (tname) - 1, tableLen);
07021     }
07022     strncpy(tname, (char *) table, size);
07023     tname[size] = '\0';
07024     unescpat(tname);
07025     if (id != SQL_BEST_ROWID) {
07026         return SQL_SUCCESS;
07027     }
07028     sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
07029     if (!sql) {
07030         return nomem(s);
07031     }
07032     sret = starttran(s);
07033     if (sret != SQL_SUCCESS) {
07034         sqlite3_free(sql);
07035         return sret;
07036     }
07037     dbtraceapi(d, "sqlite3_get_table", sql);
07038     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
07039     sqlite3_free(sql);
07040     if (ret != SQLITE_OK) {
07041 doerr:
07042         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07043                 errp ? errp : "unknown error", ret);
07044         if (errp) {
07045             sqlite3_free(errp);
07046             errp = NULL;
07047         }
07048         return SQL_ERROR;
07049     }
07050     if (errp) {
07051         sqlite3_free(errp);
07052         errp = NULL;
07053     }
07054     size = 0; /* number result rows */
07055     if (ncols * nrows <= 0) {
07056         goto nodata_but_rowid;
07057     }
07058     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
07059     if (!sql) {
07060         return nomem(s);
07061     }
07062     dbtraceapi(d, "sqlite3_get_table", sql);
07063     ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
07064                             &errp);
07065     sqlite3_free(sql);
07066     if (ret != SQLITE_OK) {
07067         sqlite3_free_table(rowp);
07068         goto doerr;
07069     }
07070     if (errp) {
07071         sqlite3_free(errp);
07072         errp = NULL;
07073     }
07074     namec = findcol(rowp, ncols, "name");
07075     uniquec = findcol(rowp, ncols, "unique");
07076     if (namec < 0 || uniquec < 0) {
07077         goto nodata_but_rowid;
07078     }
07079     namecc = findcol(rowppp, nnncols, "name");
07080     typecc = findcol(rowppp, nnncols, "type");
07081     notnullcc = findcol(rowppp, nnncols, "notnull");
07082     for (i = 1; i <= nrows; i++) {
07083         int nnrows, nncols;
07084         char **rowpp = NULL;
07085 
07086         if (*rowp[i * ncols + uniquec] != '0') {
07087             ret = SQLITE_ERROR;
07088             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
07089                                   rowp[i * ncols + namec]);
07090             if (sql) {
07091                 dbtraceapi(d, "sqlite3_get_table", sql);
07092                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07093                                         &nnrows, &nncols, NULL);
07094                 sqlite3_free(sql);
07095             }
07096             if (ret == SQLITE_OK) {
07097                 size += nnrows;
07098                 sqlite3_free_table(rowpp);
07099             }
07100         }
07101     }
07102 nodata_but_rowid:
07103     if (size == 0) {
07104         size = 1;
07105         mkrowid = 1;
07106     }
07107     s->nrows = size;
07108     size = (size + 1) * asize;
07109     s->rows = xmalloc((size + 1) * sizeof (char *));
07110     if (!s->rows) {
07111         s->nrows = 0;
07112         sqlite3_free_table(rowp);
07113         sqlite3_free_table(rowppp);
07114         return nomem(s);
07115     }
07116     s->rows[0] = (char *) size;
07117     s->rows += 1;
07118     memset(s->rows, 0, sizeof (char *) * size);
07119     s->rowfree = freerows;
07120     if (mkrowid) {
07121         s->nrows = 0;
07122         goto mkrowid;
07123     }
07124     offs = 0;
07125     for (i = 1; i <= nrows; i++) {
07126         int nnrows, nncols;
07127         char **rowpp = NULL;
07128 
07129         if (*rowp[i * ncols + uniquec] != '0') {
07130             int k;
07131 
07132             ret = SQLITE_ERROR;
07133             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
07134                                   rowp[i * ncols + namec]);
07135             if (sql) {
07136                 dbtraceapi(d, "sqlite3_get_table", sql);
07137                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07138                                         &nnrows, &nncols, NULL);
07139                 sqlite3_free(sql);
07140             }
07141             if (ret != SQLITE_OK) {
07142                 continue;
07143             }
07144             for (k = 0; nnrows && k < nncols; k++) {
07145                 if (strcmp(rowpp[k], "name") == 0) {
07146                     int m;
07147 
07148                     for (m = 1; m <= nnrows; m++) {
07149                         int roffs = (offs + m) * s->ncols;
07150 
07151                         s->rows[roffs + 0] =
07152                             xstrdup(stringify(SQL_SCOPE_SESSION));
07153                         s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
07154                         s->rows[roffs + 4] = xstrdup("0");
07155                         s->rows[roffs + 7] =
07156                             xstrdup(stringify(SQL_PC_NOT_PSEUDO));
07157                         if (namecc >= 0 && typecc >= 0) {
07158                             int ii;
07159 
07160                             for (ii = 1; ii <= nnnrows; ii++) {
07161                                 if (strcmp(rowppp[ii * nnncols + namecc],
07162                                            rowpp[m * nncols + k]) == 0) {
07163                                     char *typen = rowppp[ii * nnncols + typecc];
07164                                     int sqltype, mm, dd, isnullable = 0;
07165                                     char buf[32];
07166 
07167                                     s->rows[roffs + 3] = xstrdup(typen);
07168                                     sqltype = mapsqltype(typen, NULL, *s->ov3,
07169                                                          s->nowchar[0],
07170                                                          s->dobigint);
07171                                     getmd(typen, sqltype, &mm, &dd);
07172 #ifdef SQL_LONGVARCHAR
07173                                     if (sqltype == SQL_VARCHAR && mm > 255) {
07174                                         sqltype = SQL_LONGVARCHAR;
07175                                     }
07176 #endif
07177 #ifdef WINTERFACE
07178 #ifdef SQL_WLONGVARCHAR
07179                                     if (sqltype == SQL_WVARCHAR && mm > 255) {
07180                                         sqltype = SQL_WLONGVARCHAR;
07181                                     }
07182 #endif
07183 #endif
07184                                     if (sqltype == SQL_VARBINARY && mm > 255) {
07185                                         sqltype = SQL_LONGVARBINARY;
07186                                     }
07187                                     sprintf(buf, "%d", sqltype);
07188                                     s->rows[roffs + 2] = xstrdup(buf);
07189                                     sprintf(buf, "%d", mm);
07190                                     s->rows[roffs + 5] = xstrdup(buf);
07191                                     sprintf(buf, "%d", dd);
07192                                     s->rows[roffs + 6] = xstrdup(buf);
07193                                     if (notnullcc >= 0) {
07194                                         char *inp =
07195                                            rowppp[ii * nnncols + notnullcc];
07196 
07197                                         isnullable = inp[0] != '0';
07198                                     }
07199                                     sprintf(buf, "%d", isnullable);
07200                                     s->rows[roffs + 8] = xstrdup(buf);
07201                                 }
07202                             }
07203                         }
07204                     }
07205                 }
07206             }
07207             offs += nnrows;
07208             sqlite3_free_table(rowpp);
07209         }
07210     }
07211     if (nullable == SQL_NO_NULLS) {
07212         for (i = 1; i < s->nrows; i++) {
07213             if (s->rows[i * s->ncols + 8][0] == '0') {
07214                 int m, i1 = i + 1;
07215 
07216                 for (m = 0; m < s->ncols; m++) {
07217                     freep(&s->rows[i * s->ncols + m]);
07218                 }
07219                 size = s->ncols * sizeof (char *) * (s->nrows - i1);
07220                 if (size > 0) {
07221                     memmove(s->rows + i * s->ncols,
07222                             s->rows + i1 * s->ncols,
07223                             size);
07224                     memset(s->rows + s->nrows * s->ncols, 0,
07225                            s->ncols * sizeof (char *));
07226                 }
07227                 s->nrows--;
07228                 --i;
07229             }
07230         }
07231     }
07232 mkrowid:
07233     sqlite3_free_table(rowp);
07234     sqlite3_free_table(rowppp);
07235     if (s->nrows == 0) {
07236         s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
07237         s->rows[s->ncols + 1] = xstrdup("_ROWID_");
07238         s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
07239         s->rows[s->ncols + 3] = xstrdup("integer");
07240         s->rows[s->ncols + 4] = xstrdup("0");
07241         s->rows[s->ncols + 5] = xstrdup("10");
07242         s->rows[s->ncols + 6] = xstrdup("9");
07243         s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
07244         s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
07245         s->nrows = 1;
07246     }
07247     return SQL_SUCCESS;
07248 }
07249 
07250 #ifndef WINTERFACE
07251 
07266 SQLRETURN SQL_API
07267 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
07268                   SQLCHAR *cat, SQLSMALLINT catLen,
07269                   SQLCHAR *schema, SQLSMALLINT schemaLen,
07270                   SQLCHAR *table, SQLSMALLINT tableLen,
07271                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
07272 {
07273 #if defined(_WIN32) || defined(_WIN64)
07274     char *c = NULL, *s = NULL, *t = NULL;
07275 #endif
07276     SQLRETURN ret;
07277 
07278     HSTMT_LOCK(stmt);
07279 #if defined(_WIN32) || defined(_WIN64)
07280     if (!((STMT *) stmt)->oemcp[0]) {
07281         ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07282                                 table, tableLen, scope, nullable);
07283         goto done2;
07284     }
07285     if (cat) {
07286         c = wmb_to_utf_c((char *) cat, catLen);
07287         if (!c) {
07288             ret = nomem((STMT *) stmt);
07289             goto done;
07290         }
07291     }
07292     if (schema) {
07293         s = wmb_to_utf_c((char *) schema, schemaLen);
07294         if (!s) {
07295             ret = nomem((STMT *) stmt);
07296             goto done;
07297         }
07298     }
07299     if (table) {
07300         t = wmb_to_utf_c((char *) table, tableLen);
07301         if (!t) {
07302             ret = nomem((STMT *) stmt);
07303             goto done;
07304         }
07305     }
07306     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07307                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07308                             scope, nullable);
07309 #else
07310     ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
07311                             table, tableLen, scope, nullable);
07312 #endif
07313 #if defined(_WIN32) || defined(_WIN64)
07314 done:
07315     uc_free(t);
07316     uc_free(s);
07317     uc_free(c);
07318 done2:
07319     ;
07320 #endif
07321     HSTMT_UNLOCK(stmt);
07322     return ret;
07323 }
07324 #endif
07325 
07326 #ifdef WINTERFACE
07327 
07342 SQLRETURN SQL_API
07343 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
07344                    SQLWCHAR *cat, SQLSMALLINT catLen,
07345                    SQLWCHAR *schema, SQLSMALLINT schemaLen,
07346                    SQLWCHAR *table, SQLSMALLINT tableLen,
07347                    SQLUSMALLINT scope, SQLUSMALLINT nullable)
07348 {
07349     char *c = NULL, *s = NULL, *t = NULL;
07350     SQLRETURN ret;
07351 
07352     HSTMT_LOCK(stmt);
07353     if (cat) {
07354         c = uc_to_utf_c(cat, catLen);
07355         if (!c) {
07356             ret = nomem((STMT *) stmt);
07357             goto done;
07358         }
07359     }
07360     if (schema) {
07361         s = uc_to_utf_c(schema, schemaLen);
07362         if (!s) {
07363             ret = nomem((STMT *) stmt);
07364             goto done;
07365         }
07366     }
07367     if (table) {
07368         t = uc_to_utf_c(table, tableLen);
07369         if (!t) {
07370             ret = nomem((STMT *) stmt);
07371             goto done;
07372         }
07373     }
07374     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
07375                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
07376                             scope, nullable);
07377 done:
07378     uc_free(t);
07379     uc_free(s);
07380     uc_free(c);
07381     HSTMT_UNLOCK(stmt);
07382     return ret;
07383 }
07384 #endif
07385 
07390 static COL fkeySpec2[] = {
07391     { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07392     { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
07393     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07394     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07395     { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07396     { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
07397     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07398     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07399     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07400     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07401     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07402     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07403     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07404     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07405 };
07406 
07407 static COL fkeySpec3[] = {
07408     { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
07409     { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07410     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
07411     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07412     { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
07413     { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
07414     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
07415     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
07416     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
07417     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
07418     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
07419     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
07420     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
07421     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
07422 };
07423 
07442 static SQLRETURN SQL_API
07443 drvforeignkeys(SQLHSTMT stmt,
07444                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07445                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07446                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07447                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07448                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07449                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07450 {
07451     STMT *s;
07452     DBC *d;
07453     SQLRETURN sret;
07454     int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
07455     int onu, ond;
07456     PTRDIFF_T size;
07457     char **rowp, *errp = NULL, *sql, pname[512], fname[512];
07458 
07459     sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
07460                        fkeySpec3, array_size(fkeySpec3), &asize);
07461     if (sret != SQL_SUCCESS) {
07462         return sret;
07463     }
07464     s = (STMT *) stmt;
07465     sret = starttran(s);
07466     if (sret != SQL_SUCCESS) {
07467         return sret;
07468     }
07469     d = (DBC *) s->dbc;
07470     if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
07471         (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
07472         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
07473         return SQL_ERROR;
07474     }
07475     size = 0;
07476     if (PKtable) {
07477         if (PKtableLen == SQL_NTS) {
07478             size = sizeof (pname) - 1;
07479         } else {
07480             size = min(sizeof (pname) - 1, PKtableLen);
07481         }
07482         strncpy(pname, (char *) PKtable, size);
07483     }
07484     pname[size] = '\0';
07485     size = 0;
07486     if (FKtable) {
07487 
07488         if (FKtableLen == SQL_NTS) {
07489             size = sizeof (fname) - 1;
07490         } else {
07491             size = min(sizeof (fname) - 1, FKtableLen);
07492         }
07493         strncpy(fname, (char *) FKtable, size);
07494     }
07495     fname[size] = '\0';
07496     if (fname[0] != '\0') {
07497         int plen;
07498 
07499         ret = SQLITE_ERROR;
07500         sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
07501         if (sql) {
07502             dbtraceapi(d, "sqlite3_get_table", sql);
07503             ret = sqlite3_get_table(d->sqlite, sql, &rowp,
07504                                     &nrows, &ncols, &errp);
07505             sqlite3_free(sql);
07506         }
07507         if (ret != SQLITE_OK) {
07508             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07509                     errp ? errp : "unknown error", ret);
07510             if (errp) {
07511                 sqlite3_free(errp);
07512                 errp = NULL;
07513             }
07514             return SQL_ERROR;
07515         }
07516         if (errp) {
07517             sqlite3_free(errp);
07518             errp = NULL;
07519         }
07520         if (ncols * nrows <= 0) {
07521 nodata:
07522             sqlite3_free_table(rowp);
07523             return SQL_SUCCESS;
07524         }
07525         size = 0;
07526         namec = findcol(rowp, ncols, "table");
07527         seqc = findcol(rowp, ncols, "seq");
07528         fromc = findcol(rowp, ncols, "from");
07529         toc = findcol(rowp, ncols, "to");
07530         onu = findcol(rowp, ncols, "on_update");
07531         ond = findcol(rowp, ncols, "on_delete");
07532         if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07533             goto nodata;
07534         }
07535         plen = strlen(pname);
07536         for (i = 1; i <= nrows; i++) {
07537             char *ptab = unquote(rowp[i * ncols + namec]);
07538 
07539             if (plen && ptab) {
07540                 int len = strlen(ptab);
07541 
07542                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07543                     continue;
07544                 }
07545             }
07546             size++;
07547         }
07548         if (size == 0) {
07549             goto nodata;
07550         }
07551         s->nrows = size;
07552         size = (size + 1) * asize;
07553         s->rows = xmalloc((size + 1) * sizeof (char *));
07554         if (!s->rows) {
07555             s->nrows = 0;
07556             return nomem(s);
07557         }
07558         s->rows[0] = (char *) size;
07559         s->rows += 1;
07560         memset(s->rows, 0, sizeof (char *) * size);
07561         s->rowfree = freerows;
07562         offs = 0;
07563         for (i = 1; i <= nrows; i++) {
07564             int pos = 0, roffs = (offs + 1) * s->ncols;
07565             char *ptab = rowp[i * ncols + namec];
07566             char buf[32];
07567 
07568             if (plen && ptab) {
07569                 int len = strlen(ptab);
07570 
07571                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
07572                     continue;
07573                 }
07574             }
07575 #if defined(_WIN32) || defined(_WIN64)
07576             s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07577             s->rows[roffs + 1] = xstrdup("");
07578 #else
07579             s->rows[roffs + 0] = xstrdup("");
07580             s->rows[roffs + 1] = xstrdup("");
07581 #endif
07582             s->rows[roffs + 2] = xstrdup(ptab);
07583             s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
07584             s->rows[roffs + 4] = xstrdup("");
07585             s->rows[roffs + 5] = xstrdup("");
07586             s->rows[roffs + 6] = xstrdup(fname);
07587             s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
07588             sscanf(rowp[i * ncols + seqc], "%d", &pos);
07589             sprintf(buf, "%d", pos + 1);
07590             s->rows[roffs + 8] = xstrdup(buf);
07591             if (onu < 0) {
07592                 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07593             } else {
07594                 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
07595                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07596                 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
07597                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
07598                 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
07599                     s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07600                 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
07601                     s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07602                 } else {
07603                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07604                 }
07605             }
07606             if (ond < 0) {
07607                 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07608             } else {
07609                 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
07610                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07611                 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
07612                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
07613                 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
07614                     s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07615                 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
07616                     s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07617                 } else {
07618                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07619                 }
07620             }
07621             s->rows[roffs + 11] = NULL;
07622             s->rows[roffs + 12] = NULL;
07623             s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07624             offs++;
07625         }
07626         sqlite3_free_table(rowp);
07627     } else {
07628         int nnrows, nncols, plen = strlen(pname);
07629         char **rowpp;
07630 
07631         sql = "select name from sqlite_master where type='table'";
07632         dbtraceapi(d, "sqlite3_get_table", sql);
07633         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
07634         if (ret != SQLITE_OK) {
07635             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07636                     errp ? errp : "unknown error", ret);
07637             if (errp) {
07638                 sqlite3_free(errp);
07639                 errp = NULL;
07640             }
07641             return SQL_ERROR;
07642         }
07643         if (errp) {
07644             sqlite3_free(errp);
07645             errp = NULL;
07646         }
07647         if (ncols * nrows <= 0) {
07648             goto nodata;
07649         }
07650         size = 0;
07651         for (i = 1; i <= nrows; i++) {
07652             int k;
07653 
07654             if (!rowp[i]) {
07655                 continue;
07656             }
07657             rowpp = NULL;
07658             ret = SQLITE_ERROR;
07659             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07660             if (sql) {
07661                 dbtraceapi(d, "sqlite3_get_table", sql);
07662                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07663                                       &nnrows, &nncols, NULL);
07664                 sqlite3_free(sql);
07665             }
07666             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07667                 sqlite3_free_table(rowpp);
07668                 continue;
07669             }
07670             namec = findcol(rowpp, nncols, "table");
07671             seqc = findcol(rowpp, nncols, "seq");
07672             fromc = findcol(rowpp, nncols, "from");
07673             toc = findcol(rowpp, nncols, "to");
07674             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07675                 sqlite3_free_table(rowpp);
07676                 continue;
07677             }
07678             for (k = 1; k <= nnrows; k++) {
07679                 char *ptab = unquote(rowpp[k * nncols + namec]);
07680 
07681                 if (plen && ptab) {
07682                     int len = strlen(ptab);
07683 
07684                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07685                         continue;
07686                     }
07687                 }
07688                 size++;
07689             }
07690             sqlite3_free_table(rowpp);
07691         }
07692         if (size == 0) {
07693             goto nodata;
07694         }
07695         s->nrows = size;
07696         size = (size + 1) * asize;
07697         s->rows = xmalloc((size + 1) * sizeof (char *));
07698         if (!s->rows) {
07699             s->nrows = 0;
07700             return nomem(s);
07701         }
07702         s->rows[0] = (char *) size;
07703         s->rows += 1;
07704         memset(s->rows, 0, sizeof (char *) * size);
07705         s->rowfree = freerows;
07706         offs = 0;
07707         for (i = 1; i <= nrows; i++) {
07708             int k;
07709 
07710             if (!rowp[i]) {
07711                 continue;
07712             }
07713             rowpp = NULL;
07714             ret = SQLITE_ERROR;
07715             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07716             if (sql) {
07717                 dbtraceapi(d, "sqlite3_get_table", sql);
07718                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07719                                         &nnrows, &nncols, NULL);
07720                 sqlite3_free(sql);
07721             }
07722             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07723                 sqlite3_free_table(rowpp);
07724                 continue;
07725             }
07726             namec = findcol(rowpp, nncols, "table");
07727             seqc = findcol(rowpp, nncols, "seq");
07728             fromc = findcol(rowpp, nncols, "from");
07729             toc = findcol(rowpp, nncols, "to");
07730             onu = findcol(rowpp, nncols, "on_update");
07731             ond = findcol(rowpp, nncols, "on_delete");
07732             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07733                 sqlite3_free_table(rowpp);
07734                 continue;
07735             }
07736             for (k = 1; k <= nnrows; k++) {
07737                 int pos = 0, roffs = (offs + 1) * s->ncols;
07738                 char *ptab = unquote(rowpp[k * nncols + namec]);
07739                 char buf[32];
07740 
07741                 if (plen && ptab) {
07742                     int len = strlen(ptab);
07743 
07744                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07745                         continue;
07746                     }
07747                 }
07748 #if defined(_WIN32) || defined(_WIN64)
07749                 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
07750                 s->rows[roffs + 1] = xstrdup("");
07751 #else
07752                 s->rows[roffs + 0] = xstrdup("");
07753                 s->rows[roffs + 1] = xstrdup("");
07754 #endif
07755                 s->rows[roffs + 2] = xstrdup(ptab);
07756                 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
07757                 s->rows[roffs + 4] = xstrdup("");
07758                 s->rows[roffs + 5] = xstrdup("");
07759                 s->rows[roffs + 6] = xstrdup(rowp[i]);
07760                 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
07761                 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
07762                 sprintf(buf, "%d", pos + 1);
07763                 s->rows[roffs + 8] = xstrdup(buf);
07764                 if (onu < 0) {
07765                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07766                 } else {
07767                     if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
07768                         s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07769                     } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
07770                                == 0) {
07771                         s->rows[roffs + 9] =
07772                             xstrdup(stringify(SQL_SET_DEFAULT));
07773                     } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
07774                                == 0) {
07775                         s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07776                     } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
07777                                == 0) {
07778                         s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07779                     } else {
07780                         s->rows[roffs + 9] =
07781                             xstrdup(stringify(SQL_NO_ACTION));
07782                     }
07783                 }
07784                 if (ond < 0) {
07785                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07786                 } else {
07787                     if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
07788                         s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07789                     } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
07790                                == 0) {
07791                         s->rows[roffs + 10] =
07792                             xstrdup(stringify(SQL_SET_DEFAULT));
07793                     } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
07794                                == 0) {
07795                         s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07796                     } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
07797                                == 0) {
07798                         s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07799                     } else {
07800                         s->rows[roffs + 10] =
07801                             xstrdup(stringify(SQL_NO_ACTION));
07802                     }
07803                 }
07804                 s->rows[roffs + 11] = NULL;
07805                 s->rows[roffs + 12] = NULL;
07806                 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07807                 offs++;
07808             }
07809             sqlite3_free_table(rowpp);
07810         }
07811         sqlite3_free_table(rowp);
07812     }
07813     return SQL_SUCCESS;
07814 }
07815 
07816 #ifndef WINTERFACE
07817 
07835 SQLRETURN SQL_API
07836 SQLForeignKeys(SQLHSTMT stmt,
07837                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07838                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07839                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07840                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07841                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07842                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07843 {
07844 #if defined(_WIN32) || defined(_WIN64)
07845     char *pc = NULL, *ps = NULL, *pt = NULL;
07846     char *fc = NULL, *fs = NULL, *ft = NULL;
07847 #endif
07848     SQLRETURN ret;
07849 
07850     HSTMT_LOCK(stmt);
07851 #if defined(_WIN32) || defined(_WIN64)
07852     if (!((STMT *) stmt)->oemcp[0]) {
07853         ret = drvforeignkeys(stmt,
07854                              PKcatalog, PKcatalogLen,
07855                              PKschema, PKschemaLen, PKtable, PKtableLen,
07856                              FKcatalog, FKcatalogLen,
07857                              FKschema, FKschemaLen,
07858                              FKtable, FKtableLen);
07859         goto done2;
07860     }
07861     if (PKcatalog) {
07862         pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
07863         if (!pc) {
07864             ret = nomem((STMT *) stmt);
07865             goto done;
07866         }
07867     }
07868     if (PKschema) {
07869         ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
07870         if (!ps) {
07871             ret = nomem((STMT *) stmt);
07872             goto done;
07873         }
07874     }
07875     if (PKtable) {
07876         pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
07877         if (!pt) {
07878             ret = nomem((STMT *) stmt);
07879             goto done;
07880         }
07881     }
07882     if (FKcatalog) {
07883         fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
07884         if (!fc) {
07885             ret = nomem((STMT *) stmt);
07886             goto done;
07887         }
07888     }
07889     if (FKschema) {
07890         fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
07891         if (!fs) {
07892             ret = nomem((STMT *) stmt);
07893             goto done;
07894         }
07895     }
07896     if (FKtable) {
07897         ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
07898         if (!ft) {
07899             ret = nomem((STMT *) stmt);
07900             goto done;
07901         }
07902     }
07903     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
07904                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
07905                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
07906                          (SQLCHAR *) ft, SQL_NTS);
07907 #else
07908     ret = drvforeignkeys(stmt,
07909                          PKcatalog, PKcatalogLen,
07910                          PKschema, PKschemaLen, PKtable, PKtableLen,
07911                          FKcatalog, FKcatalogLen,
07912                          FKschema, FKschemaLen,
07913                          FKtable, FKtableLen);
07914 #endif
07915 #if defined(_WIN32) || defined(_WIN64)
07916 done:
07917     uc_free(ft);
07918     uc_free(fs);
07919     uc_free(fc);
07920     uc_free(pt);
07921     uc_free(ps);
07922     uc_free(pc);
07923 done2:
07924     ;
07925 #endif
07926     HSTMT_UNLOCK(stmt);
07927     return ret;
07928 }
07929 #endif
07930 
07931 #ifdef WINTERFACE
07932 
07950 SQLRETURN SQL_API
07951 SQLForeignKeysW(SQLHSTMT stmt,
07952                 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07953                 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
07954                 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
07955                 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07956                 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
07957                 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
07958 {
07959     char *pc = NULL, *ps = NULL, *pt = NULL;
07960     char *fc = NULL, *fs = NULL, *ft = NULL;
07961     SQLRETURN ret;
07962 
07963     HSTMT_LOCK(stmt);
07964     if (PKcatalog) {
07965         pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
07966         if (!pc) {
07967             ret = nomem((STMT *) stmt);
07968             goto done;
07969         }
07970     }
07971     if (PKschema) {
07972         ps = uc_to_utf_c(PKschema, PKschemaLen);
07973         if (!ps) {
07974             ret = nomem((STMT *) stmt);
07975             goto done;
07976         }
07977     }
07978     if (PKtable) {
07979         pt = uc_to_utf_c(PKtable, PKtableLen);
07980         if (!pt) {
07981             ret = nomem((STMT *) stmt);
07982             goto done;
07983         }
07984     }
07985     if (FKcatalog) {
07986         fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
07987         if (!fc) {
07988             ret = nomem((STMT *) stmt);
07989             goto done;
07990         }
07991     }
07992     if (FKschema) {
07993         fs = uc_to_utf_c(FKschema, FKschemaLen);
07994         if (!fs) {
07995             ret = nomem((STMT *) stmt);
07996             goto done;
07997         }
07998     }
07999     if (FKtable) {
08000         ft = uc_to_utf_c(FKtable, FKtableLen);
08001         if (!ft) {
08002             ret = nomem((STMT *) stmt);
08003             goto done;
08004         }
08005     }
08006     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
08007                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
08008                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
08009                          (SQLCHAR *) ft, SQL_NTS);
08010 done:
08011     uc_free(ft);
08012     uc_free(fs);
08013     uc_free(fc);
08014     uc_free(pt);
08015     uc_free(ps);
08016     uc_free(pc);
08017     HSTMT_UNLOCK(stmt);
08018     return ret;
08019 }
08020 #endif
08021 
08028 static SQLRETURN
08029 starttran(STMT *s)
08030 {
08031     int ret = SQL_SUCCESS, rc, busy_count = 0;
08032     char *errp = NULL;
08033     DBC *d = (DBC *) s->dbc;
08034 
08035     if (!d->autocommit && !d->intrans && !d->trans_disable) {
08036 begin_again:
08037         rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
08038         if (rc == SQLITE_BUSY) {
08039             if (busy_handler((void *) d, ++busy_count)) {
08040                 if (errp) {
08041                     sqlite3_free(errp);
08042                     errp = NULL;
08043                 }
08044                 goto begin_again;
08045             }
08046         }
08047         dbtracerc(d, rc, errp);
08048         if (rc != SQLITE_OK) {
08049             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
08050                     errp ? errp : "unknown error", rc);
08051             ret = SQL_ERROR;
08052         } else {
08053             d->intrans = 1;
08054         }
08055         if (errp) {
08056             sqlite3_free(errp);
08057             errp = NULL;
08058         }
08059     }
08060     return ret;
08061 }
08062 
08071 static SQLRETURN
08072 endtran(DBC *d, SQLSMALLINT comptype, int force)
08073 {
08074     int ret, busy_count = 0;
08075     char *sql, *errp = NULL;
08076 
08077     if (!d->sqlite) {
08078         setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
08079         return SQL_ERROR;
08080     }
08081     if ((!force && d->autocommit) || !d->intrans) {
08082         return SQL_SUCCESS;
08083     }
08084     switch (comptype) {
08085     case SQL_COMMIT:
08086         sql = "COMMIT TRANSACTION";
08087         goto doit;
08088     case SQL_ROLLBACK:
08089         sql = "ROLLBACK TRANSACTION";
08090     doit:
08091         ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
08092         dbtracerc(d, ret, errp);
08093         if (ret == SQLITE_BUSY && busy_count < 10) {
08094             if (busy_handler((void *) d, ++busy_count)) {
08095                 if (errp) {
08096                     sqlite3_free(errp);
08097                     errp = NULL;
08098                 }
08099                 goto doit;
08100             }
08101         }
08102         if (ret != SQLITE_OK) {
08103             setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
08104                      errp ? errp : "transaction failed");
08105             if (errp) {
08106                 sqlite3_free(errp);
08107                 errp = NULL;
08108             }
08109             return SQL_ERROR;
08110         }
08111         if (errp) {
08112             sqlite3_free(errp);
08113             errp = NULL;
08114         }
08115         d->intrans = 0;
08116         return SQL_SUCCESS;
08117     }
08118     setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
08119     return SQL_ERROR;
08120 }
08121 
08130 static SQLRETURN
08131 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
08132 {
08133     DBC *dbc = NULL;
08134     int fail = 0;
08135     SQLRETURN ret;
08136 #if defined(_WIN32) || defined(_WIN64)
08137     ENV *env;
08138 #endif
08139 
08140     switch (type) {
08141     case SQL_HANDLE_DBC:
08142         HDBC_LOCK((SQLHDBC) handle);
08143         if (handle == SQL_NULL_HDBC) {
08144             return SQL_INVALID_HANDLE;
08145         }
08146         dbc = (DBC *) handle;
08147         ret = endtran(dbc, comptype, 0);
08148         HDBC_UNLOCK((SQLHDBC) handle);
08149         return ret;
08150     case SQL_HANDLE_ENV:
08151         if (handle == SQL_NULL_HENV) {
08152             return SQL_INVALID_HANDLE;
08153         }
08154 #if defined(_WIN32) || defined(_WIN64)
08155         env = (ENV *) handle;
08156         if (env->magic != ENV_MAGIC) {
08157             return SQL_INVALID_HANDLE;
08158         }
08159         EnterCriticalSection(&env->cs);
08160 #endif
08161         dbc = ((ENV *) handle)->dbcs;
08162         while (dbc) {
08163             HDBC_LOCK((SQLHDBC) dbc);
08164             ret = endtran(dbc, comptype, 0);
08165             HDBC_UNLOCK((SQLHDBC) dbc);
08166             if (ret != SQL_SUCCESS) {
08167                 fail++;
08168             }
08169             dbc = dbc->next;
08170         }
08171 #if defined(_WIN32) || defined(_WIN64)
08172         LeaveCriticalSection(&env->cs);
08173 #endif
08174         return fail ? SQL_ERROR : SQL_SUCCESS;
08175     }
08176     return SQL_INVALID_HANDLE;
08177 }
08178 
08187 SQLRETURN SQL_API
08188 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
08189 {
08190     return drvendtran(type, handle, comptype);
08191 }
08192 
08201 SQLRETURN SQL_API
08202 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
08203 {
08204     if (dbc != SQL_NULL_HDBC) {
08205         return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
08206     }
08207     return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
08208 }
08209 
08214 SQLRETURN SQL_API
08215 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
08216 {
08217     return SQL_ERROR;
08218 }
08219 
08220 #ifndef WINTERFACE
08221 
08232 SQLRETURN SQL_API
08233 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
08234              SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08235 {
08236     int outLen = 0;
08237     SQLRETURN ret = SQL_SUCCESS;
08238 
08239     HSTMT_LOCK(stmt);
08240     if (sqlinLen == SQL_NTS) {
08241         sqlinLen = strlen((char *) sqlin);
08242     }
08243     if (sql) {
08244         if (sqlMax > 0) {
08245             strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
08246             sqlin[sqlMax - 1] = '\0';
08247             outLen = min(sqlMax - 1, sqlinLen);
08248         }
08249     } else {
08250         outLen = sqlinLen;
08251     }
08252     if (sqlLen) {
08253         *sqlLen = outLen;
08254     }
08255     if (sql && outLen < sqlinLen) {
08256         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08257         ret = SQL_SUCCESS_WITH_INFO;
08258     }
08259     HSTMT_UNLOCK(stmt);
08260     return ret;
08261 }
08262 #endif
08263 
08264 #ifdef WINTERFACE
08265 
08276 SQLRETURN SQL_API
08277 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
08278               SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
08279 {
08280     int outLen = 0;
08281     SQLRETURN ret = SQL_SUCCESS;
08282 
08283     HSTMT_LOCK(stmt);
08284     if (sqlinLen == SQL_NTS) {
08285         sqlinLen = uc_strlen(sqlin);
08286     }
08287     if (sql) {
08288         if (sqlMax > 0) {
08289             uc_strncpy(sql, sqlin, sqlMax - 1);
08290             sqlin[sqlMax - 1] = 0;
08291             outLen = min(sqlMax  - 1, sqlinLen);
08292         }
08293     } else {
08294         outLen = sqlinLen;
08295     }
08296     if (sqlLen) {
08297         *sqlLen = outLen;
08298     }
08299     if (sql && outLen < sqlinLen) {
08300         setstat((STMT *) stmt, -1, "data right truncated", "01004");
08301         ret = SQL_SUCCESS_WITH_INFO;
08302     }
08303     HSTMT_UNLOCK(stmt);
08304     return ret;
08305 }
08306 #endif
08307 
08312 static COL procSpec2[] = {
08313     { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08314     { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08315     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08316     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08317     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08318     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08319     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08320     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08321 };
08322 
08323 static COL procSpec3[] = {
08324     { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08325     { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08326     { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08327     { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
08328     { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
08329     { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
08330     { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
08331     { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
08332 };
08333 
08334 #ifndef WINTERFACE
08335 
08347 SQLRETURN SQL_API
08348 SQLProcedures(SQLHSTMT stmt,
08349               SQLCHAR *catalog, SQLSMALLINT catalogLen,
08350               SQLCHAR *schema, SQLSMALLINT schemaLen,
08351               SQLCHAR *proc, SQLSMALLINT procLen)
08352 {
08353     SQLRETURN ret;
08354 
08355     HSTMT_LOCK(stmt);
08356     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08357                       procSpec3, array_size(procSpec3), NULL);
08358     HSTMT_UNLOCK(stmt);
08359     return ret;
08360 }
08361 #endif
08362 
08363 #ifdef WINTERFACE
08364 
08376 SQLRETURN SQL_API
08377 SQLProceduresW(SQLHSTMT stmt,
08378                SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08379                SQLWCHAR *schema, SQLSMALLINT schemaLen,
08380                SQLWCHAR *proc, SQLSMALLINT procLen)
08381 {
08382     SQLRETURN ret;
08383 
08384     HSTMT_LOCK(stmt);
08385     ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
08386                       procSpec3, array_size(procSpec3), NULL);
08387     HSTMT_UNLOCK(stmt);
08388     return ret;
08389 }
08390 #endif
08391 
08396 static COL procColSpec2[] = {
08397     { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
08398     { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
08399     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08400     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08401     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08402     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08403     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08404     { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
08405     { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
08406     { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
08407     { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
08408     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08409     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08410     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08411     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08412     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08413     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08414     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08415     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08416 };
08417 
08418 static COL procColSpec3[] = {
08419     { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
08420     { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
08421     { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
08422     { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08423     { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
08424     { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
08425     { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
08426     { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
08427     { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
08428     { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
08429     { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
08430     { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
08431     { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
08432     { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
08433     { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
08434     { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
08435     { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
08436     { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
08437     { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
08438 };
08439 
08440 #ifndef WINTERFACE
08441 
08455 SQLRETURN SQL_API
08456 SQLProcedureColumns(SQLHSTMT stmt,
08457                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
08458                     SQLCHAR *schema, SQLSMALLINT schemaLen,
08459                     SQLCHAR *proc, SQLSMALLINT procLen,
08460                     SQLCHAR *column, SQLSMALLINT columnLen)
08461 {
08462     SQLRETURN ret;
08463 
08464     HSTMT_LOCK(stmt);
08465     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08466                       procColSpec3, array_size(procColSpec3), NULL);
08467     HSTMT_UNLOCK(stmt);
08468     return ret;
08469 }
08470 #endif
08471 
08472 #ifdef WINTERFACE
08473 
08488 SQLRETURN SQL_API
08489 SQLProcedureColumnsW(SQLHSTMT stmt,
08490                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
08491                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
08492                      SQLWCHAR *proc, SQLSMALLINT procLen,
08493                      SQLWCHAR *column, SQLSMALLINT columnLen)
08494 {
08495     SQLRETURN ret;
08496 
08497     HSTMT_LOCK(stmt);
08498     ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
08499                       procColSpec3, array_size(procColSpec3), NULL);
08500     HSTMT_UNLOCK(stmt);
08501     return ret;
08502 }
08503 #endif
08504 
08515 SQLRETURN SQL_API
08516 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
08517               SQLINTEGER len, SQLINTEGER *lenp)
08518 {
08519     ENV *e;
08520     SQLRETURN ret = SQL_ERROR;
08521 
08522     if (env == SQL_NULL_HENV) {
08523         return SQL_INVALID_HANDLE;
08524     }
08525     e = (ENV *) env;
08526     if (!e || e->magic != ENV_MAGIC) {
08527         return SQL_INVALID_HANDLE;
08528     }
08529 #if defined(_WIN32) || defined(_WIN64)
08530     EnterCriticalSection(&e->cs);
08531 #endif
08532     switch (attr) {
08533     case SQL_ATTR_CONNECTION_POOLING:
08534         if (val) {
08535             *((SQLINTEGER *) val) = e->pool ?
08536                 SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
08537         }
08538         if (lenp) {
08539             *lenp = sizeof (SQLINTEGER);
08540         }
08541         ret = SQL_SUCCESS;
08542         break;
08543     case SQL_ATTR_CP_MATCH:
08544         *((SQLINTEGER *) val) = SQL_CP_RELAXED_MATCH;
08545         if (lenp) {
08546             *lenp = sizeof (SQLINTEGER);
08547         }
08548         ret = SQL_SUCCESS;
08549         break;
08550     case SQL_ATTR_OUTPUT_NTS:
08551         if (val) {
08552             *((SQLINTEGER *) val) = SQL_TRUE;
08553         }
08554         if (lenp) {
08555             *lenp = sizeof (SQLINTEGER);
08556         }
08557         ret = SQL_SUCCESS;
08558         break;
08559     case SQL_ATTR_ODBC_VERSION:
08560         if (val) {
08561             *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
08562         }
08563         if (lenp) {
08564             *lenp = sizeof (SQLINTEGER);
08565         }
08566         ret = SQL_SUCCESS;
08567         break;
08568     }
08569 #if defined(_WIN32) || defined(_WIN64)
08570     LeaveCriticalSection(&e->cs);
08571 #endif
08572     return ret;
08573 }
08574 
08584 SQLRETURN SQL_API
08585 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
08586 {
08587     ENV *e;
08588     SQLRETURN ret = SQL_ERROR;
08589 
08590     if (env == SQL_NULL_HENV) {
08591         return SQL_INVALID_HANDLE;
08592     }
08593     e = (ENV *) env;
08594     if (!e || e->magic != ENV_MAGIC) {
08595         return SQL_INVALID_HANDLE;
08596     }
08597 #if defined(_WIN32) || defined(_WIN64)
08598     EnterCriticalSection(&e->cs);
08599 #endif
08600     switch (attr) {
08601     case SQL_ATTR_CONNECTION_POOLING:
08602         if (val == (SQLPOINTER) SQL_CP_ONE_PER_DRIVER) {
08603             e->pool = 1;
08604             ret = SQL_SUCCESS;
08605         } else if (val == (SQLPOINTER) SQL_CP_OFF) {
08606             e->pool = 0;
08607             ret = SQL_SUCCESS;
08608         }
08609         break;
08610     case SQL_ATTR_CP_MATCH:
08611         ret = SQL_SUCCESS;
08612         break;
08613     case SQL_ATTR_OUTPUT_NTS:
08614         if (val == (SQLPOINTER) SQL_TRUE) {
08615             ret = SQL_SUCCESS;
08616         }
08617         break;
08618     case SQL_ATTR_ODBC_VERSION:
08619         if (!val) {
08620             break;
08621         }
08622         if (val == (SQLPOINTER) SQL_OV_ODBC2) {
08623             e->ov3 = 0;
08624             ret = SQL_SUCCESS;
08625         } else if (val == (SQLPOINTER) SQL_OV_ODBC3) {
08626             e->ov3 = 1;
08627             ret = SQL_SUCCESS;
08628         }
08629         break;
08630     }
08631 #if defined(_WIN32) || defined(_WIN64)
08632     LeaveCriticalSection(&e->cs);
08633 #endif
08634     return ret;
08635 }
08636 
08650 static SQLRETURN
08651 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08652               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08653               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08654 {
08655     DBC *d = NULL;
08656     STMT *s = NULL;
08657     int len, naterr;
08658     char *logmsg, *sqlst;
08659     SQLRETURN ret = SQL_ERROR;
08660 
08661     if (handle == SQL_NULL_HANDLE) {
08662         return SQL_INVALID_HANDLE;
08663     }
08664     if (sqlstate) {
08665         sqlstate[0] = '\0';
08666     }
08667     if (msg && buflen > 0) {
08668         msg[0] = '\0';
08669     }
08670     if (msglen) {
08671         *msglen = 0;
08672     }
08673     if (nativeerr) {
08674         *nativeerr = 0;
08675     }
08676     switch (htype) {
08677     case SQL_HANDLE_ENV:
08678     case SQL_HANDLE_DESC:
08679         return SQL_NO_DATA;
08680     case SQL_HANDLE_DBC:
08681         HDBC_LOCK((SQLHDBC) handle);
08682         d = (DBC *) handle;
08683         logmsg = (char *) d->logmsg;
08684         sqlst = d->sqlstate;
08685         naterr = d->naterr;
08686         break;
08687     case SQL_HANDLE_STMT:
08688         HSTMT_LOCK((SQLHSTMT) handle);
08689         s = (STMT *) handle;
08690         logmsg = (char *) s->logmsg;
08691         sqlst = s->sqlstate;
08692         naterr = s->naterr;
08693         break;
08694     default:
08695         return SQL_INVALID_HANDLE;
08696     }
08697     if (buflen < 0) {
08698         goto done;
08699     }
08700     if (recno > 1) {
08701         ret = SQL_NO_DATA;
08702         goto done;
08703     }
08704     len = strlen(logmsg);
08705     if (len == 0) {
08706         ret = SQL_NO_DATA;
08707         goto done;
08708     }
08709     if (nativeerr) {
08710         *nativeerr = naterr;
08711     }
08712     if (sqlstate) {
08713         strcpy((char *) sqlstate, sqlst);
08714     }
08715     if (msglen) {
08716         *msglen = len;
08717     }
08718     if (len >= buflen) {
08719         if (msg && buflen > 0) {
08720             strncpy((char *) msg, logmsg, buflen);
08721             msg[buflen - 1] = '\0';
08722             logmsg[0] = '\0';
08723         }
08724     } else if (msg) {
08725         strcpy((char *) msg, logmsg);
08726         logmsg[0] = '\0';
08727     }
08728     ret = SQL_SUCCESS;
08729 done:
08730     switch (htype) {
08731     case SQL_HANDLE_DBC:
08732         HDBC_UNLOCK((SQLHDBC) handle);
08733         break;
08734     case SQL_HANDLE_STMT:
08735         HSTMT_UNLOCK((SQLHSTMT) handle);
08736         break;
08737     }
08738     return ret;
08739 }
08740 
08741 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
08742 
08755 SQLRETURN SQL_API
08756 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08757               SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
08758               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08759 {
08760     return drvgetdiagrec(htype, handle, recno, sqlstate,
08761                          nativeerr, msg, buflen, msglen);
08762 }
08763 #endif
08764 
08765 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
08766 #ifdef WINTERFACE
08767 
08781 SQLRETURN SQL_API
08782 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08783               SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
08784               SQLSMALLINT buflen, SQLSMALLINT *msglen)
08785 {
08786     char state[16];
08787     SQLSMALLINT len;
08788     SQLRETURN ret;
08789 
08790     ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
08791                         nativeerr, (SQLCHAR *) msg, buflen, &len);
08792     if (ret == SQL_SUCCESS) {
08793         if (sqlstate) {
08794             uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
08795                             6 * sizeof (SQLWCHAR));
08796         }
08797         if (msg) {
08798             if (len > 0) {
08799                 SQLWCHAR *m = NULL;
08800 
08801                 m = uc_from_utf((unsigned char *) msg, len);
08802                 if (m) {
08803                     if (buflen) {
08804                         buflen /= sizeof (SQLWCHAR);
08805                         uc_strncpy(msg, m, buflen);
08806                         m[len] = 0;
08807                         len = min(buflen, uc_strlen(m));
08808                     } else {
08809                         len = uc_strlen(m);
08810                     }
08811                     uc_free(m);
08812                 } else {
08813                     len = 0;
08814                 }
08815             }
08816             if (len <= 0) {
08817                 len = 0;
08818                 if (buflen > 0) {
08819                     msg[0] = 0;
08820                 }
08821             }
08822         } else {
08823             /* estimated length !!! */
08824             len *= sizeof (SQLWCHAR);
08825         }
08826         if (msglen) {
08827             *msglen = len;
08828         }
08829     } else if (ret == SQL_NO_DATA) {
08830         if (sqlstate) {
08831             sqlstate[0] = 0;
08832         }
08833         if (msg) {
08834             if (buflen > 0) {
08835                 msg[0] = 0;
08836             }
08837         }
08838         if (msglen) {
08839             *msglen = 0;
08840         }
08841     }
08842     return ret;
08843 }
08844 #endif
08845 #endif
08846 
08859 static SQLRETURN
08860 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
08861                 SQLSMALLINT id, SQLPOINTER info,
08862                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
08863 {
08864     DBC *d = NULL;
08865     STMT *s = NULL;
08866     int len, naterr, strbuf = 1;
08867     char *logmsg, *sqlst, *clrmsg = NULL;
08868     SQLRETURN ret = SQL_ERROR;
08869 
08870     if (handle == SQL_NULL_HANDLE) {
08871         return SQL_INVALID_HANDLE;
08872     }
08873     if (stringlen) {
08874         *stringlen = 0;
08875     }
08876     switch (htype) {
08877     case SQL_HANDLE_ENV:
08878     case SQL_HANDLE_DESC:
08879         return SQL_NO_DATA;
08880     case SQL_HANDLE_DBC:
08881         HDBC_LOCK((SQLHDBC) handle);
08882         d = (DBC *) handle;
08883         logmsg = (char *) d->logmsg;
08884         sqlst = d->sqlstate;
08885         naterr = d->naterr;
08886         break;
08887     case SQL_HANDLE_STMT:
08888         HSTMT_LOCK((SQLHSTMT) handle);
08889         s = (STMT *) handle;
08890         d = (DBC *) s->dbc;
08891         logmsg = (char *) s->logmsg;
08892         sqlst = s->sqlstate;
08893         naterr = s->naterr;
08894         break;
08895     default:
08896         return SQL_INVALID_HANDLE;
08897     }
08898     if (buflen < 0) {
08899         switch (buflen) {
08900         case SQL_IS_POINTER:
08901         case SQL_IS_UINTEGER:
08902         case SQL_IS_INTEGER:
08903         case SQL_IS_USMALLINT:
08904         case SQL_IS_SMALLINT:
08905             strbuf = 0;
08906             break;
08907         default:
08908             ret = SQL_ERROR;
08909             goto done;
08910         }
08911     }
08912     if (recno > 1) {
08913         ret = SQL_NO_DATA;
08914         goto done;
08915     }
08916     switch (id) {
08917     case SQL_DIAG_CLASS_ORIGIN:
08918         logmsg = "ISO 9075";
08919         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
08920             logmsg = "ODBC 3.0";
08921         }
08922         break;
08923     case SQL_DIAG_SUBCLASS_ORIGIN:
08924         logmsg = "ISO 9075";
08925         if (sqlst[0] == 'I' && sqlst[1] == 'M') {
08926             logmsg = "ODBC 3.0";
08927         } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
08928             logmsg = "ODBC 3.0";
08929         } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
08930             logmsg = "ODBC 3.0";
08931         }
08932         break;
08933     case SQL_DIAG_CONNECTION_NAME:
08934     case SQL_DIAG_SERVER_NAME:
08935         logmsg = d->dsn ? d->dsn : "No DSN";
08936         break;
08937     case SQL_DIAG_SQLSTATE:
08938         logmsg = sqlst;
08939         break;
08940     case SQL_DIAG_MESSAGE_TEXT:
08941         if (info) {
08942             clrmsg = logmsg;
08943         }
08944         break;
08945     case SQL_DIAG_NUMBER:
08946         naterr = 1;
08947         /* fall through */
08948     case SQL_DIAG_NATIVE:
08949         len = strlen(logmsg);
08950         if (len == 0) {
08951             ret = SQL_NO_DATA;
08952             goto done;
08953         }
08954         if (info) {
08955             *((SQLINTEGER *) info) = naterr;
08956         }
08957         ret = SQL_SUCCESS;
08958         goto done;
08959     case SQL_DIAG_DYNAMIC_FUNCTION:
08960         logmsg = "";
08961         break;
08962     case SQL_DIAG_CURSOR_ROW_COUNT:
08963         if (htype == SQL_HANDLE_STMT) {
08964             SQLULEN count;
08965 
08966             count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
08967             *((SQLULEN *) info) = count;
08968             ret = SQL_SUCCESS;
08969         }
08970         goto done;
08971     case SQL_DIAG_ROW_COUNT:
08972         if (htype == SQL_HANDLE_STMT) {
08973             SQLULEN count;
08974 
08975             count = s->isselect ? 0 : s->nrows;
08976             *((SQLULEN *) info) = count;
08977             ret = SQL_SUCCESS;
08978         }
08979         goto done;
08980     default:
08981         goto done;
08982     }
08983     if (info && buflen > 0) {
08984         ((char *) info)[0] = '\0';
08985     }
08986     len = strlen(logmsg);
08987     if (len == 0) {
08988         ret = SQL_NO_DATA;
08989         goto done;
08990     }
08991     if (stringlen) {
08992         *stringlen = len;
08993     }
08994     if (strbuf) {
08995         if (len >= buflen) {
08996             if (info && buflen > 0) {
08997                 if (stringlen) {
08998                     *stringlen = buflen - 1;
08999                 }
09000                 strncpy((char *) info, logmsg, buflen);
09001                 ((char *) info)[buflen - 1] = '\0';
09002             }
09003         } else if (info) {
09004             strcpy((char *) info, logmsg);
09005         }
09006     }
09007     if (clrmsg) {
09008         *clrmsg = '\0';
09009     }
09010     ret = SQL_SUCCESS;
09011 done:
09012     switch (htype) {
09013     case SQL_HANDLE_DBC:
09014         HDBC_UNLOCK((SQLHDBC) handle);
09015         break;
09016     case SQL_HANDLE_STMT:
09017         HSTMT_UNLOCK((SQLHSTMT) handle);
09018         break;
09019     }
09020     return ret;
09021 }
09022 
09023 #ifndef WINTERFACE
09024 
09036 SQLRETURN SQL_API
09037 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
09038                 SQLSMALLINT id, SQLPOINTER info,
09039                 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
09040 {
09041     return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
09042 }
09043 #endif
09044 
09045 #ifdef WINTERFACE
09046 
09058 SQLRETURN SQL_API
09059 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
09060                  SQLSMALLINT id, SQLPOINTER info,
09061                  SQLSMALLINT buflen, SQLSMALLINT *stringlen)
09062 {
09063     SQLSMALLINT len;
09064     SQLRETURN ret;
09065 
09066     ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
09067     if (ret == SQL_SUCCESS) {
09068         if (info) {
09069             switch (id) {
09070             case SQL_DIAG_CLASS_ORIGIN:
09071             case SQL_DIAG_SUBCLASS_ORIGIN:
09072             case SQL_DIAG_CONNECTION_NAME:
09073             case SQL_DIAG_SERVER_NAME:
09074             case SQL_DIAG_SQLSTATE:
09075             case SQL_DIAG_MESSAGE_TEXT:
09076             case SQL_DIAG_DYNAMIC_FUNCTION:
09077                 if (len > 0) {
09078                     SQLWCHAR *m = NULL;
09079 
09080                     m = uc_from_utf((unsigned char *) info, len);
09081                     if (m) {
09082                         if (buflen) {
09083                             buflen /= sizeof (SQLWCHAR);
09084                             uc_strncpy(info, m, buflen);
09085                             m[len] = 0;
09086                             len = min(buflen, uc_strlen(m));
09087                         } else {
09088                             len = uc_strlen(m);
09089                         }
09090                         uc_free(m);
09091                         len *= sizeof (SQLWCHAR);
09092                     } else {
09093                         len = 0;
09094                     }
09095                 }
09096                 if (len <= 0) {
09097                     len = 0;
09098                     if (buflen > 0) {
09099                         ((SQLWCHAR *) info)[0] = 0;
09100                     }
09101                 }
09102             }
09103         } else {
09104             switch (id) {
09105             case SQL_DIAG_CLASS_ORIGIN:
09106             case SQL_DIAG_SUBCLASS_ORIGIN:
09107             case SQL_DIAG_CONNECTION_NAME:
09108             case SQL_DIAG_SERVER_NAME:
09109             case SQL_DIAG_SQLSTATE:
09110             case SQL_DIAG_MESSAGE_TEXT:
09111             case SQL_DIAG_DYNAMIC_FUNCTION:
09112                 len *= sizeof (SQLWCHAR);
09113                 break;
09114             }
09115         }
09116         if (stringlen) {
09117             *stringlen = len;
09118         }
09119     }
09120     return ret;
09121 }
09122 #endif
09123 
09134 static SQLRETURN
09135 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09136                SQLINTEGER bufmax, SQLINTEGER *buflen)
09137 {
09138     STMT *s = (STMT *) stmt;
09139     SQLULEN *uval = (SQLULEN *) val;
09140     SQLINTEGER dummy;
09141     char dummybuf[16];
09142 
09143     if (!buflen) {
09144         buflen = &dummy;
09145     }
09146     if (!uval) {
09147         uval = (SQLPOINTER) dummybuf;
09148     }
09149     switch (attr) {
09150     case SQL_QUERY_TIMEOUT:
09151         *uval = 0;
09152         *buflen = sizeof (SQLULEN);
09153         return SQL_SUCCESS;
09154     case SQL_ATTR_CURSOR_TYPE:
09155         *uval = s->curtype;
09156         *buflen = sizeof (SQLULEN);
09157         return SQL_SUCCESS;
09158     case SQL_ATTR_CURSOR_SCROLLABLE:
09159         *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
09160             SQL_SCROLLABLE : SQL_NONSCROLLABLE;
09161         *buflen = sizeof (SQLULEN);
09162         return SQL_SUCCESS;
09163 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09164     case SQL_ATTR_CURSOR_SENSITIVITY:
09165         *uval = SQL_UNSPECIFIED;
09166         *buflen = sizeof (SQLULEN);
09167         return SQL_SUCCESS;
09168 #endif
09169     case SQL_ATTR_ROW_NUMBER:
09170         if (s->s3stmt) {
09171             *uval = (s->s3stmt_rownum < 0) ?
09172                     SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09173         } else {
09174             *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09175         }
09176         *buflen = sizeof (SQLULEN);
09177         return SQL_SUCCESS;
09178     case SQL_ATTR_ASYNC_ENABLE:
09179         *uval = SQL_ASYNC_ENABLE_OFF;
09180         *buflen = sizeof (SQLULEN);
09181         return SQL_SUCCESS;
09182     case SQL_CONCURRENCY:
09183         *uval = SQL_CONCUR_LOCK;
09184         *buflen = sizeof (SQLULEN);
09185         return SQL_SUCCESS;
09186     case SQL_ATTR_RETRIEVE_DATA:
09187         *uval = s->retr_data;
09188         *buflen = sizeof (SQLULEN);
09189         return SQL_SUCCESS;
09190     case SQL_ROWSET_SIZE:
09191     case SQL_ATTR_ROW_ARRAY_SIZE:
09192         *uval = s->rowset_size;
09193         *buflen = sizeof (SQLULEN);
09194         return SQL_SUCCESS;
09195     /* Needed for some driver managers, but dummies for now */
09196     case SQL_ATTR_IMP_ROW_DESC:
09197     case SQL_ATTR_APP_ROW_DESC:
09198     case SQL_ATTR_IMP_PARAM_DESC:
09199     case SQL_ATTR_APP_PARAM_DESC:
09200         *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
09201         *buflen = sizeof (SQLHDESC);
09202         return SQL_SUCCESS;
09203     case SQL_ATTR_ROW_STATUS_PTR:
09204         *((SQLUSMALLINT **) uval) = s->row_status;
09205         *buflen = sizeof (SQLUSMALLINT *);
09206         return SQL_SUCCESS;
09207     case SQL_ATTR_ROWS_FETCHED_PTR:
09208         *((SQLULEN **) uval) = s->row_count;
09209         *buflen = sizeof (SQLULEN *);
09210         return SQL_SUCCESS;
09211     case SQL_ATTR_USE_BOOKMARKS: {
09212         STMT *s = (STMT *) stmt;
09213 
09214         *(SQLUINTEGER *) uval = s->bkmrk;
09215         *buflen = sizeof (SQLUINTEGER);
09216         return SQL_SUCCESS;
09217     }
09218     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09219         *(SQLPOINTER *) uval = s->bkmrkptr;
09220         *buflen = sizeof (SQLPOINTER);
09221         return SQL_SUCCESS;
09222     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09223         *((SQLULEN **) uval) = s->parm_bind_offs;
09224         *buflen = sizeof (SQLULEN *);
09225         return SQL_SUCCESS;
09226     case SQL_ATTR_PARAM_BIND_TYPE:
09227         *((SQLULEN *) uval) = s->parm_bind_type;
09228         *buflen = sizeof (SQLULEN);
09229         return SQL_SUCCESS;
09230     case SQL_ATTR_PARAM_OPERATION_PTR:
09231         *((SQLUSMALLINT **) uval) = s->parm_oper;
09232         *buflen = sizeof (SQLUSMALLINT *);
09233         return SQL_SUCCESS;
09234     case SQL_ATTR_PARAM_STATUS_PTR:
09235         *((SQLUSMALLINT **) uval) = s->parm_status;
09236         *buflen = sizeof (SQLUSMALLINT *);
09237         return SQL_SUCCESS;
09238     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09239         *((SQLULEN **) uval) = s->parm_proc;
09240         *buflen = sizeof (SQLULEN *);
09241         return SQL_SUCCESS;
09242     case SQL_ATTR_PARAMSET_SIZE:
09243         *((SQLULEN *) uval) = s->paramset_size;
09244         *buflen = sizeof (SQLULEN);
09245         return SQL_SUCCESS;
09246     case SQL_ATTR_ROW_BIND_TYPE:
09247         *(SQLULEN *) uval = s->bind_type;
09248         *buflen = sizeof (SQLULEN);
09249         return SQL_SUCCESS;
09250     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09251         *((SQLULEN **) uval) = s->bind_offs;
09252         *buflen = sizeof (SQLULEN *);
09253         return SQL_SUCCESS;
09254     case SQL_ATTR_MAX_ROWS:
09255         *((SQLULEN *) uval) = s->max_rows;
09256         *buflen = sizeof (SQLULEN);
09257         return SQL_SUCCESS;
09258     case SQL_ATTR_MAX_LENGTH:
09259         *((SQLULEN *) uval) = 1000000000;
09260         *buflen = sizeof (SQLULEN);
09261         return SQL_SUCCESS;
09262 #ifdef SQL_ATTR_METADATA_ID
09263     case SQL_ATTR_METADATA_ID:
09264         *((SQLULEN *) uval) = SQL_FALSE;
09265         *buflen = sizeof (SQLULEN);
09266         return SQL_SUCCESS;
09267 #endif
09268     }
09269     return drvunimplstmt(stmt);
09270 }
09271 
09272 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09273 
09283 SQLRETURN SQL_API
09284 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09285                SQLINTEGER bufmax, SQLINTEGER *buflen)
09286 {
09287     SQLRETURN ret;
09288 
09289     HSTMT_LOCK(stmt);
09290     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09291     HSTMT_UNLOCK(stmt);
09292     return ret;
09293 }
09294 #endif
09295 
09296 #ifdef WINTERFACE
09297 
09307 SQLRETURN SQL_API
09308 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09309                 SQLINTEGER bufmax, SQLINTEGER *buflen)
09310 {
09311     SQLRETURN ret;
09312 
09313     HSTMT_LOCK(stmt);
09314     ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
09315     HSTMT_UNLOCK(stmt);
09316     return ret;
09317 }
09318 #endif
09319 
09329 static SQLRETURN
09330 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09331                SQLINTEGER buflen)
09332 {
09333     STMT *s = (STMT *) stmt;
09334 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
09335     SQLBIGINT uval;
09336 
09337     uval = (SQLBIGINT) val;
09338 #else
09339     SQLULEN uval;
09340 
09341     uval = (SQLULEN) val;
09342 #endif
09343     switch (attr) {
09344     case SQL_ATTR_CURSOR_TYPE:
09345         if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
09346             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09347         } else {
09348             s->curtype = SQL_CURSOR_STATIC;
09349         }
09350         if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
09351             val != (SQLPOINTER) SQL_CURSOR_STATIC) {
09352             goto e01s02;
09353         }
09354         return SQL_SUCCESS;
09355     case SQL_ATTR_CURSOR_SCROLLABLE:
09356         if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
09357             s->curtype = SQL_CURSOR_FORWARD_ONLY;
09358         } else {
09359             s->curtype = SQL_CURSOR_STATIC;
09360         }
09361         return SQL_SUCCESS;
09362     case SQL_ATTR_ASYNC_ENABLE:
09363         if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
09364     e01s02:
09365             setstat(s, -1, "option value changed", "01S02");
09366             return SQL_SUCCESS_WITH_INFO;
09367         }
09368         return SQL_SUCCESS;
09369     case SQL_CONCURRENCY:
09370         if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
09371             goto e01s02;
09372         }
09373         return SQL_SUCCESS;
09374 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
09375     case SQL_ATTR_CURSOR_SENSITIVITY:
09376         if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
09377             goto e01s02;
09378         }
09379         return SQL_SUCCESS;
09380 #endif
09381     case SQL_ATTR_QUERY_TIMEOUT:
09382         return SQL_SUCCESS;
09383     case SQL_ATTR_RETRIEVE_DATA:
09384         if (val != (SQLPOINTER) SQL_RD_ON &&
09385             val != (SQLPOINTER) SQL_RD_OFF) {
09386             goto e01s02;
09387         }
09388         s->retr_data = uval;
09389         return SQL_SUCCESS;
09390     case SQL_ROWSET_SIZE:
09391     case SQL_ATTR_ROW_ARRAY_SIZE:
09392         if (uval < 1) {
09393             setstat(s, -1, "invalid rowset size", "HY000");
09394             return SQL_ERROR;
09395         } else {
09396             SQLUSMALLINT *rst = &s->row_status1;
09397 
09398             if (uval > 1) {
09399                 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
09400                 if (!rst) {
09401                     return nomem(s);
09402                 }
09403             }
09404             if (s->row_status0 != &s->row_status1) {
09405                 freep(&s->row_status0);
09406             }
09407             s->row_status0 = rst;
09408             s->rowset_size = uval;
09409         }
09410         return SQL_SUCCESS;
09411     case SQL_ATTR_ROW_STATUS_PTR:
09412         s->row_status = (SQLUSMALLINT *) val;
09413         return SQL_SUCCESS;
09414     case SQL_ATTR_ROWS_FETCHED_PTR:
09415         s->row_count = (SQLULEN *) val;
09416         return SQL_SUCCESS;
09417     case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
09418         s->parm_bind_offs = (SQLULEN *) val;
09419         return SQL_SUCCESS;
09420     case SQL_ATTR_PARAM_BIND_TYPE:
09421         s->parm_bind_type = uval;
09422         return SQL_SUCCESS;
09423     case SQL_ATTR_PARAM_OPERATION_PTR:
09424         s->parm_oper = (SQLUSMALLINT *) val;
09425         return SQL_SUCCESS;
09426     case SQL_ATTR_PARAM_STATUS_PTR:
09427         s->parm_status = (SQLUSMALLINT *) val;
09428         return SQL_SUCCESS;
09429     case SQL_ATTR_PARAMS_PROCESSED_PTR:
09430         s->parm_proc = (SQLULEN *) val;
09431         return SQL_SUCCESS;
09432     case SQL_ATTR_PARAMSET_SIZE:
09433         if (uval < 1) {
09434             goto e01s02;
09435         }
09436         s->paramset_size = uval;
09437         s->paramset_count = 0;
09438         return SQL_SUCCESS;
09439     case SQL_ATTR_ROW_BIND_TYPE:
09440         s->bind_type = uval;
09441         return SQL_SUCCESS;
09442     case SQL_ATTR_ROW_BIND_OFFSET_PTR:
09443         s->bind_offs = (SQLULEN *) val;
09444         return SQL_SUCCESS;
09445     case SQL_ATTR_USE_BOOKMARKS:
09446         if (val != (SQLPOINTER) SQL_UB_OFF &&
09447             val != (SQLPOINTER) SQL_UB_ON &&
09448             val != (SQLPOINTER) SQL_UB_VARIABLE) {
09449             goto e01s02;
09450         }
09451         if (*s->ov3 && val == (SQLPOINTER) SQL_UB_VARIABLE) {
09452             s->bkmrk = SQL_UB_VARIABLE;
09453             return SQL_SUCCESS;
09454         }
09455         if (val == (SQLPOINTER) SQL_UB_VARIABLE) {
09456             s->bkmrk = SQL_UB_ON;
09457             goto e01s02;
09458         }
09459         s->bkmrk = (val == (SQLPOINTER) SQL_UB_ON) ? SQL_UB_ON : SQL_UB_OFF;
09460         return SQL_SUCCESS;
09461     case SQL_ATTR_FETCH_BOOKMARK_PTR:
09462         s->bkmrkptr = (SQLINTEGER *) val;
09463         return SQL_SUCCESS;
09464     case SQL_ATTR_MAX_ROWS:
09465         s->max_rows = uval;
09466         return SQL_SUCCESS;
09467     case SQL_ATTR_MAX_LENGTH:
09468         if (val != (SQLPOINTER) 1000000000) {
09469             goto e01s02;
09470         }
09471         return SQL_SUCCESS;
09472 #ifdef SQL_ATTR_METADATA_ID
09473     case SQL_ATTR_METADATA_ID:
09474         if (val != (SQLPOINTER) SQL_FALSE) {
09475             goto e01s02;
09476         }
09477         return SQL_SUCCESS;
09478 #endif
09479     }
09480     return drvunimplstmt(stmt);
09481 }
09482 
09483 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
09484 
09493 SQLRETURN SQL_API
09494 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09495                SQLINTEGER buflen)
09496 {
09497     SQLRETURN ret;
09498 
09499     HSTMT_LOCK(stmt);
09500     ret = drvsetstmtattr(stmt, attr, val, buflen);
09501     HSTMT_UNLOCK(stmt);
09502     return ret;
09503 }
09504 #endif
09505 
09506 #ifdef WINTERFACE
09507 
09516 SQLRETURN SQL_API
09517 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
09518                 SQLINTEGER buflen)
09519 {
09520     SQLRETURN ret;
09521 
09522     HSTMT_LOCK(stmt);
09523     ret = drvsetstmtattr(stmt, attr, val, buflen);
09524     HSTMT_UNLOCK(stmt);
09525     return ret;
09526 }
09527 #endif
09528 
09537 static SQLRETURN
09538 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09539 {
09540     STMT *s = (STMT *) stmt;
09541     SQLUINTEGER *ret = (SQLUINTEGER *) param;
09542 
09543     switch (opt) {
09544     case SQL_QUERY_TIMEOUT:
09545         *ret = 0;
09546         return SQL_SUCCESS;
09547     case SQL_CURSOR_TYPE:
09548         *ret = s->curtype;
09549         return SQL_SUCCESS;
09550     case SQL_ROW_NUMBER:
09551         if (s->s3stmt) {
09552             *ret = (s->s3stmt_rownum < 0) ?
09553                    SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
09554         } else {
09555             *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
09556         }
09557         return SQL_SUCCESS;
09558     case SQL_ASYNC_ENABLE:
09559         *ret = SQL_ASYNC_ENABLE_OFF;
09560         return SQL_SUCCESS;
09561     case SQL_CONCURRENCY:
09562         *ret = SQL_CONCUR_LOCK;
09563         return SQL_SUCCESS;
09564     case SQL_ATTR_RETRIEVE_DATA:
09565         *ret = s->retr_data;
09566         return SQL_SUCCESS;
09567     case SQL_ROWSET_SIZE:
09568     case SQL_ATTR_ROW_ARRAY_SIZE:
09569         *ret = s->rowset_size;
09570         return SQL_SUCCESS;
09571     case SQL_ATTR_MAX_ROWS:
09572         *ret = s->max_rows;
09573         return SQL_SUCCESS;
09574     case SQL_ATTR_MAX_LENGTH:
09575         *ret = 1000000000;
09576         return SQL_SUCCESS;
09577     }
09578     return drvunimplstmt(stmt);
09579 }
09580 
09589 SQLRETURN SQL_API
09590 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09591 {
09592     SQLRETURN ret;
09593 
09594     HSTMT_LOCK(stmt);
09595     ret = drvgetstmtoption(stmt, opt, param);
09596     HSTMT_UNLOCK(stmt);
09597     return ret;
09598 }
09599 
09600 #ifdef WINTERFACE
09601 
09609 SQLRETURN SQL_API
09610 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
09611 {
09612     SQLRETURN ret;
09613 
09614     HSTMT_LOCK(stmt);
09615     ret = drvgetstmtoption(stmt, opt, param);
09616     HSTMT_UNLOCK(stmt);
09617     return ret;
09618 }
09619 #endif
09620 
09629 static SQLRETURN
09630 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
09631 {
09632     STMT *s = (STMT *) stmt;
09633 
09634     switch (opt) {
09635     case SQL_CURSOR_TYPE:
09636         if (param == SQL_CURSOR_FORWARD_ONLY) {
09637             s->curtype = param;
09638         } else {
09639             s->curtype = SQL_CURSOR_STATIC;
09640         }
09641         if (param != SQL_CURSOR_FORWARD_ONLY &&
09642             param != SQL_CURSOR_STATIC) {
09643             goto e01s02;
09644         }
09645         return SQL_SUCCESS;
09646     case SQL_ASYNC_ENABLE:
09647         if (param != SQL_ASYNC_ENABLE_OFF) {
09648             goto e01s02;
09649         }
09650         return SQL_SUCCESS;
09651     case SQL_CONCURRENCY:
09652         if (param != SQL_CONCUR_LOCK) {
09653             goto e01s02;
09654         }
09655         return SQL_SUCCESS;
09656     case SQL_QUERY_TIMEOUT:
09657         return SQL_SUCCESS;
09658     case SQL_RETRIEVE_DATA:
09659         if (param != SQL_RD_ON && param != SQL_RD_OFF) {
09660     e01s02:
09661             setstat(s, -1, "option value changed", "01S02");
09662             return SQL_SUCCESS_WITH_INFO;
09663         }
09664         s->retr_data = (int) param;
09665         return SQL_SUCCESS;
09666     case SQL_ROWSET_SIZE:
09667     case SQL_ATTR_ROW_ARRAY_SIZE:
09668         if (param < 1) {
09669             setstat(s, -1, "invalid rowset size", "HY000");
09670             return SQL_ERROR;
09671         } else {
09672             SQLUSMALLINT *rst = &s->row_status1;
09673 
09674             if (param > 1) {
09675                 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
09676                 if (!rst) {
09677                     return nomem(s);
09678                 }
09679             }
09680             if (s->row_status0 != &s->row_status1) {
09681                 freep(&s->row_status0);
09682             }
09683             s->row_status0 = rst;
09684             s->rowset_size = param;
09685         }
09686         return SQL_SUCCESS;
09687     case SQL_ATTR_MAX_ROWS:
09688         s->max_rows = param;
09689         return SQL_SUCCESS;
09690     case SQL_ATTR_MAX_LENGTH:
09691         if (param != 1000000000) {
09692             goto e01s02;
09693         }
09694         return SQL_SUCCESS;
09695     }
09696     return drvunimplstmt(stmt);
09697 }
09698 
09707 SQLRETURN SQL_API
09708 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
09709                  SETSTMTOPTION_LAST_ARG_TYPE param)
09710 {
09711     SQLRETURN ret;
09712 
09713     HSTMT_LOCK(stmt);
09714     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09715     HSTMT_UNLOCK(stmt);
09716     return ret;
09717 }
09718 
09719 #ifdef WINTERFACE
09720 
09728 SQLRETURN SQL_API
09729 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
09730                   SETSTMTOPTION_LAST_ARG_TYPE param)
09731 {
09732     SQLRETURN ret;
09733 
09734     HSTMT_LOCK(stmt);
09735     ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
09736     HSTMT_UNLOCK(stmt);
09737     return ret;
09738 }
09739 #endif
09740 
09747 static SQLRETURN
09748 chkunbound(STMT *s)
09749 {
09750     int i;
09751 
09752     if (!s->bindcols || s->nbindcols < s->ncols) {
09753 unbound:
09754         setstat(s, -1, "unbound columns", (*s->ov3) ? "HY000" : "S1000");
09755         return SQL_ERROR;
09756     }
09757     for (i = 0; i < s->ncols; i++) {
09758         BINDCOL *b = &s->bindcols[i];
09759 
09760         if (b->type == SQL_UNKNOWN_TYPE || !b->valp) {
09761             goto unbound;
09762         }
09763     }
09764     return SQL_SUCCESS;
09765 }
09766 
09778 static SQLRETURN
09779 setposbind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
09780 {
09781     DBC *d = (DBC *) s->dbc;
09782     SQLPOINTER dp = 0;
09783     SQLLEN *lp = 0;
09784     BINDCOL *b = &s->bindcols[i];
09785     COL *c = &s->cols[i];
09786     char strbuf[128], *cp;
09787 
09788     if (b->valp) {
09789         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09790             dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
09791         } else {
09792             dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
09793         }
09794         if (s->bind_offs) {
09795             dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
09796         }
09797     }
09798     if (b->lenp) {
09799         if (s->bind_type != SQL_BIND_BY_COLUMN) {
09800             lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
09801         } else {
09802             lp = b->lenp + rsi;
09803         }
09804         if (s->bind_offs) {
09805             lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
09806         }
09807     }
09808     if (!dp || !lp) {
09809         setstat(s, -1, "unbound column in positional update",
09810                 (*s->ov3) ? "HY000" : "S1000");
09811         return SQL_ERROR;
09812     }
09813     if (*lp == SQL_NULL_DATA) {
09814         sqlite3_bind_null(stmt, si);
09815         if (d->trace) {
09816             fprintf(d->trace, "-- parameter %d: NULL\n", si);
09817             fflush(d->trace);
09818         }
09819         return SQL_SUCCESS;
09820     }
09821     switch (b->type) {
09822     case SQL_C_UTINYINT:
09823     case SQL_C_TINYINT:
09824     case SQL_C_STINYINT:
09825         sqlite3_bind_int(stmt, si, *(SQLCHAR *) dp);
09826         if (d->trace) {
09827             fprintf(d->trace, "-- parameter %d: %d\n", si, *(SQLCHAR *) dp);
09828             fflush(d->trace);
09829         }
09830         break;
09831 #ifdef SQL_BIT
09832     case SQL_C_BIT:
09833         sqlite3_bind_int(stmt, si, (*(SQLCHAR *) dp) ? 1 : 0);
09834         if (d->trace) {
09835             fprintf(d->trace, "-- parameter %d: %d\n", si,
09836                     (*(SQLCHAR *) dp) ? 1 : 0);
09837             fflush(d->trace);
09838         }
09839         break;
09840 #endif
09841     case SQL_C_USHORT:
09842         sqlite3_bind_int(stmt, si, *(SQLUSMALLINT *) dp);
09843         if (d->trace) {
09844             fprintf(d->trace, "-- parameter %d: %d\n", si,
09845                     *(SQLUSMALLINT *) dp);
09846             fflush(d->trace);
09847         }
09848         break;
09849     case SQL_C_SHORT:
09850     case SQL_C_SSHORT:
09851         sqlite3_bind_int(stmt, si, *(SQLSMALLINT *) dp);
09852         if (d->trace) {
09853             fprintf(d->trace, "-- parameter %d: %d\n", si,
09854                     *(SQLSMALLINT *) dp);
09855             fflush(d->trace);
09856         }
09857         break;
09858     case SQL_C_ULONG:
09859         sqlite3_bind_int(stmt, si, *(SQLUINTEGER *) dp);
09860         if (d->trace) {
09861             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09862                     (long) *(SQLUINTEGER *) dp);
09863             fflush(d->trace);
09864         }
09865         break;
09866     case SQL_C_LONG:
09867     case SQL_C_SLONG:
09868         sqlite3_bind_int(stmt, si, *(SQLINTEGER *) dp);
09869         if (d->trace) {
09870             fprintf(d->trace, "-- parameter %d: %ld\n", si,
09871                     (long) *(SQLINTEGER *) dp);
09872             fflush(d->trace);
09873         }
09874         break;
09875 #ifdef SQL_BIGINT
09876     case SQL_C_UBIGINT:
09877     case SQL_C_SBIGINT:
09878         sqlite3_bind_int64(stmt, si, *(SQLBIGINT *) dp);
09879         if (d->trace) {
09880             fprintf(d->trace,
09881 #ifdef _WIN32
09882                     "-- parameter %d: %I64d\n",
09883 #else
09884                     "-- parameter %d: %lld\n",
09885 #endif
09886                     si, (sqlite_int64) *(SQLBIGINT *) dp);
09887             fflush(d->trace);
09888         }
09889         break;
09890 #endif
09891     case SQL_C_FLOAT:
09892         sqlite3_bind_double(stmt, si, *(float *) dp);
09893         if (d->trace) {
09894             fprintf(d->trace, "-- parameter %d: %g\n", si,
09895                     *(float *) dp);
09896             fflush(d->trace);
09897         }
09898         break;
09899     case SQL_C_DOUBLE:
09900         sqlite3_bind_double(stmt, si, *(double *) dp);
09901         if (d->trace) {
09902             fprintf(d->trace, "-- parameter %d: %g\n", si,
09903                     *(double *) dp);
09904             fflush(d->trace);
09905         }
09906         break;
09907     case SQL_C_BINARY:
09908         sqlite3_bind_blob(stmt, si, (char *) dp, *lp, SQLITE_STATIC);
09909         if (d->trace) {
09910             fprintf(d->trace, "-- parameter %d: [BLOB]\n", si);
09911             fflush(d->trace);
09912         }
09913         break;
09914 #ifdef WCHARSUPPORT
09915     case SQL_C_WCHAR:
09916         cp = uc_to_utf((SQLWCHAR *) dp, *lp);
09917         if (!cp) {
09918             return nomem(s);
09919         }
09920         sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
09921         if (d->trace) {
09922             fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
09923             fflush(d->trace);
09924         }
09925         uc_free(cp);
09926         break;
09927 #endif
09928     case SQL_C_CHAR:
09929 #if defined(_WIN32) || defined(_WIN64)
09930         if (*s->oemcp) {
09931             cp = wmb_to_utf((char *) dp, *lp);
09932             if (!cp) {
09933                 return nomem(s);
09934             }
09935             sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
09936             if (d->trace) {
09937                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
09938                 fflush(d->trace);
09939             }
09940             uc_free(cp);
09941         } else
09942 #endif
09943         {
09944             if (*lp == SQL_NTS) {
09945                 sqlite3_bind_text(stmt, si, (char *) dp, -1,
09946                                   SQLITE_STATIC);
09947                 if (d->trace) {
09948                     fprintf(d->trace, "-- parameter %d: '%s'\n", si,
09949                             (char *) dp);
09950                     fflush(d->trace);
09951                 }
09952             } else {
09953                 sqlite3_bind_text(stmt, si, (char *) dp, *lp,
09954                                   SQLITE_STATIC);
09955                 if (d->trace) {
09956                     fprintf(d->trace, "-- parameter %d: '%*s'\n", si,
09957                             (int) *lp, (char *) dp);
09958                     fflush(d->trace);
09959                 }
09960             }
09961         }
09962         break;
09963 #ifdef SQL_C_TYPE_DATE
09964     case SQL_C_TYPE_DATE:
09965 #endif
09966     case SQL_C_DATE:
09967         if (*s->jdconv) {
09968             int a, b, x1, x2, y, m, dd;
09969             double v;
09970 
09971             y = ((DATE_STRUCT *) dp)->year;
09972             m = ((DATE_STRUCT *) dp)->month;
09973             dd = ((DATE_STRUCT *) dp)->day;
09974             if (m <= 2) {
09975                 y--;
09976                 m += 12;
09977             }
09978             a = y / 100;
09979             b = 2 - a + (a / 4);
09980             x1 = 36525 * (y + 4716) / 100;
09981             x2 = 306001 * (m + 1) / 10000;
09982             v = x1 + x2 + dd + b - 1524.5;
09983             sqlite3_bind_double(stmt, si, v);
09984             if (d->trace) {
09985                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
09986                 fflush(d->trace);
09987             }
09988         } else {
09989             sprintf(strbuf, "%04d-%02d-%02d",
09990                     ((DATE_STRUCT *) dp)->year,
09991                     ((DATE_STRUCT *) dp)->month,
09992                     ((DATE_STRUCT *) dp)->day);
09993             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
09994             if (d->trace) {
09995                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
09996                 fflush(d->trace);
09997             }
09998         }
09999         break;
10000 #ifdef SQL_C_TYPE_TIME
10001     case SQL_C_TYPE_TIME:
10002 #endif
10003     case SQL_C_TIME:
10004         if (*s->jdconv) {
10005             double v;
10006 
10007             v = 2451544.5 +
10008                (((TIME_STRUCT *) dp)->hour * 3600000.0 +
10009                 ((TIME_STRUCT *) dp)->minute * 60000.0 +
10010                 ((TIME_STRUCT *) dp)->second * 1000.0) / 86400000.0;
10011             sqlite3_bind_double(stmt, si, v);
10012             if (d->trace) {
10013                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10014                 fflush(d->trace);
10015             }
10016         } else {
10017             sprintf(strbuf, "%02d:%02d:%02d",
10018                     ((TIME_STRUCT *) dp)->hour,
10019                     ((TIME_STRUCT *) dp)->minute,
10020                     ((TIME_STRUCT *) dp)->second);
10021             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10022             if (d->trace) {
10023                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10024                 fflush(d->trace);
10025             }
10026         }
10027         break;
10028 #ifdef SQL_C_TYPE_TIMESTAMP
10029     case SQL_C_TYPE_TIMESTAMP:
10030 #endif
10031     case SQL_C_TIMESTAMP:
10032         if (*s->jdconv) {
10033             int a, b, x1, x2, y, m, dd;
10034             double v;
10035 
10036             y = ((TIMESTAMP_STRUCT *) dp)->year;
10037             m = ((TIMESTAMP_STRUCT *) dp)->month;
10038             dd = ((TIMESTAMP_STRUCT *) dp)->day;
10039             if (m <= 2) {
10040                 y--;
10041                 m += 12;
10042             }
10043             a = y / 100;
10044             b = 2 - a + (a / 4);
10045             x1 = 36525 * (y + 4716) / 100;
10046             x2 = 306001 * (m + 1) / 10000;
10047             v = x1 + x2 + dd + b - 1524.5 +
10048                (((TIMESTAMP_STRUCT *) dp)->hour * 3600000.0 +
10049                 ((TIMESTAMP_STRUCT *) dp)->minute * 60000.0 +
10050                 ((TIMESTAMP_STRUCT *) dp)->second * 1000.0 +
10051                 ((TIMESTAMP_STRUCT *) dp)->fraction / 1.0E6)
10052                / 86400000.0;
10053             sqlite3_bind_double(stmt, si, v);
10054             if (d->trace) {
10055                 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10056                 fflush(d->trace);
10057             }
10058         } else {
10059             int frac;
10060 
10061             frac = (int) ((TIMESTAMP_STRUCT *) dp)->fraction;
10062             frac /= 1000000;
10063             frac = frac % 1000;
10064             if (frac < 0) {
10065                 frac = 0;
10066             }
10067             if (c->prec && c->prec <= 16) {
10068                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
10069                         ((TIMESTAMP_STRUCT *) dp)->year,
10070                         ((TIMESTAMP_STRUCT *) dp)->month,
10071                         ((TIMESTAMP_STRUCT *) dp)->day,
10072                         ((TIMESTAMP_STRUCT *) dp)->hour,
10073                         ((TIMESTAMP_STRUCT *) dp)->minute);
10074             } else if (c->prec && c->prec <= 19) {
10075                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
10076                         ((TIMESTAMP_STRUCT *) dp)->year,
10077                         ((TIMESTAMP_STRUCT *) dp)->month,
10078                         ((TIMESTAMP_STRUCT *) dp)->day,
10079                         ((TIMESTAMP_STRUCT *) dp)->hour,
10080                         ((TIMESTAMP_STRUCT *) dp)->minute,
10081                         ((TIMESTAMP_STRUCT *) dp)->second);
10082             } else {
10083                 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
10084                         ((TIMESTAMP_STRUCT *) dp)->year,
10085                         ((TIMESTAMP_STRUCT *) dp)->month,
10086                         ((TIMESTAMP_STRUCT *) dp)->day,
10087                         ((TIMESTAMP_STRUCT *) dp)->hour,
10088                         ((TIMESTAMP_STRUCT *) dp)->minute,
10089                         ((TIMESTAMP_STRUCT *) dp)->second,
10090                         frac);
10091             }
10092             sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10093             if (d->trace) {
10094                 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10095                 fflush(d->trace);
10096             }
10097         }
10098         break;
10099     default:
10100         setstat(s, -1, "unsupported column type in positional update",
10101                 (*s->ov3) ? "HY000" : "S1000");
10102         return SQL_ERROR;
10103     }
10104     return SQL_SUCCESS;
10105 }
10106 
10118 static SQLRETURN
10119 setposibind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
10120 {
10121     DBC *d = (DBC *) s->dbc;
10122     char **data;
10123     int pos;
10124 
10125     pos = s->rowprs;
10126     if (pos < 0) {
10127         setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10128         return SQL_ERROR;
10129     }
10130     pos += rsi;
10131     data = s->rows + s->ncols + (pos * s->ncols) + i;
10132     if (*data == NULL) {
10133         sqlite3_bind_null(stmt, si);
10134         if (d->trace) {
10135             fprintf(d->trace, "-- parameter %d: NULL\n", si);
10136             fflush(d->trace);
10137         }
10138     } else {
10139         sqlite3_bind_text(stmt, si, *data, -1, SQLITE_STATIC);
10140         if (d->trace) {
10141             fprintf(d->trace, "-- parameter %d: '%s'\n", si, *data);
10142             fflush(d->trace);
10143         }
10144     }
10145     return SQL_SUCCESS;
10146 }
10147 
10155 static SQLRETURN
10156 setposrefr(STMT *s, int rsi)
10157 {
10158     int i, withinfo = 0;
10159     SQLRETURN ret = SQL_SUCCESS;
10160 
10161     for (i = 0; s->bindcols && i < s->ncols; i++) {
10162         BINDCOL *b = &s->bindcols[i];
10163         SQLPOINTER dp = 0;
10164         SQLLEN *lp = 0;
10165 
10166         b->offs = 0;
10167         if (b->valp) {
10168             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10169                 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
10170             } else {
10171                 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
10172             }
10173             if (s->bind_offs) {
10174                 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
10175             }
10176         }
10177         if (b->lenp) {
10178             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10179                 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
10180             } else {
10181                 lp = b->lenp + rsi;
10182             }
10183             if (s->bind_offs) {
10184                 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
10185             }
10186         }
10187         if (dp || lp) {
10188             int rowp = s->rowp;
10189 
10190             s->rowp = s->rowprs + rsi;
10191             ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp,
10192                              b->max, lp, 0);
10193             s->rowp = rowp;
10194             if (!SQL_SUCCEEDED(ret)) {
10195                 s->row_status0[rsi] = SQL_ROW_ERROR;
10196                 break;
10197             }
10198             if (ret != SQL_SUCCESS) {
10199                 withinfo = 1;
10200 #ifdef SQL_ROW_SUCCESS_WITH_INFO
10201                 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
10202 #endif
10203             }
10204         }
10205     }
10206     if (SQL_SUCCEEDED(ret)) {
10207         ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10208     }
10209     return ret;
10210 }
10211 
10221 static SQLRETURN
10222 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10223 {
10224     STMT *s = (STMT *) stmt;
10225     DBC *d = (DBC *) s->dbc;
10226     int rowp, i, k, rc, nretry = 0;
10227     dstr *sql = 0;
10228     const char *endp;
10229     sqlite3_stmt *s3stmt = NULL;
10230     SQLRETURN ret;
10231 
10232     if (lock != SQL_LOCK_NO_CHANGE) {
10233         setstat(s, -1, "unsupported locking mode",
10234                 (*s->ov3) ? "HY000" : "S1000");
10235         return SQL_ERROR;
10236     }
10237     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10238         setstat(s, -1, "incompatible statement",
10239                 (*s->ov3) ? "HY000" : "S1000");
10240         return SQL_ERROR;
10241     }
10242     if (op == SQL_ADD) {
10243         if (s->one_tbl <= 0) {
10244             setstat(s, -1, "incompatible rowset",
10245                     (*s->ov3) ? "HY000" : "S1000");
10246             return SQL_ERROR;
10247         }
10248         if (row == 0 || row > s->rowset_size + 1) {
10249             goto rowoor;
10250         }
10251         ret = chkunbound(s);
10252         if (ret != SQL_SUCCESS) {
10253             return ret;
10254         }
10255         sql = dsappend(sql, "INSERT INTO ");
10256         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10257             sql = dsappendq(sql, s->dyncols[0].db);
10258             sql = dsappend(sql, ".");
10259         }
10260         sql = dsappendq(sql, s->dyncols[0].table);
10261         for (i = 0; i < s->ncols; i++) {
10262             sql = dsappend(sql, (i > 0) ? "," : "(");
10263             sql = dsappendq(sql, s->dyncols[i].column);
10264         }
10265         sql = dsappend(sql, ") VALUES ");
10266         for (i = 0; i < s->ncols; i++) {
10267             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10268         }
10269         sql = dsappend(sql, ")");
10270         if (dserr(sql)) {
10271             dsfree(sql);
10272             return nomem(s);
10273         }
10274 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10275         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10276 #else
10277         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10278 #endif
10279         do {
10280             s3stmt = NULL;
10281 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10282             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10283                                     &s3stmt, &endp);
10284 #else
10285             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10286                                  &s3stmt, &endp);
10287 #endif
10288             if (rc != SQLITE_OK) {
10289                 if (s3stmt) {
10290                     sqlite3_finalize(s3stmt);
10291                     s3stmt = NULL;
10292                 }
10293             }
10294         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10295         dbtracerc(d, rc, NULL);
10296         dsfree(sql);
10297         if (rc != SQLITE_OK) {
10298 istmterr:
10299             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10300                     sqlite3_errmsg(d->sqlite), rc);
10301             if (s3stmt) {
10302                 dbtraceapi(d, "sqlite3_finalize", NULL);
10303                 sqlite3_finalize(s3stmt);
10304             }
10305             return SQL_ERROR;
10306         }
10307         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10308             ret = setposbind(s, s3stmt, i, k, row - 1);
10309             if (ret != SQL_SUCCESS) {
10310                 dbtraceapi(d, "sqlite3_finalize", NULL);
10311                 sqlite3_finalize(s3stmt);
10312                 return ret;
10313             }
10314             k++;
10315         }
10316         rc = sqlite3_step(s3stmt);
10317         if (rc != SQLITE_DONE) {
10318             goto istmterr;
10319         }
10320         sqlite3_finalize(s3stmt);
10321         if (sqlite3_changes(d->sqlite) > 0 && row <= s->rowset_size) {
10322             if (s->row_status0) {
10323                 s->row_status0[row - 1] = SQL_ROW_ADDED;
10324             }
10325             if (s->row_status) {
10326                 s->row_status[row - 1] = SQL_ROW_ADDED;
10327             }
10328         }
10329         return SQL_SUCCESS;
10330     } else if (op == SQL_UPDATE || op == SQL_DELETE) {
10331         if (s->one_tbl <= 0 || s->has_pk <= 0) {
10332             setstat(s, -1, "incompatible rowset",
10333                     (*s->ov3) ? "HY000" : "S1000");
10334             return SQL_ERROR;
10335         }
10336         if (row == 0) {
10337             ret = SQL_SUCCESS;
10338             for (i = 1; i <= s->rowset_size; i++) {
10339                 ret = drvsetpos(stmt, i, op, lock);
10340                 if (!SQL_SUCCEEDED(ret)) {
10341                     break;
10342                 }
10343             }
10344             return ret;
10345         }
10346         if (row > s->rowset_size) {
10347             goto rowoor;
10348         }
10349     }
10350     if (op != SQL_POSITION && op != SQL_REFRESH &&
10351         op != SQL_DELETE && op != SQL_UPDATE) {
10352         return drvunimplstmt(stmt);
10353     }
10354     if (op == SQL_POSITION) {
10355         rowp = s->rowp + row - 1;
10356         if (!s->rows || row == 0 || rowp < -1 || rowp >= s->nrows) {
10357 rowoor:
10358             setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10359             return SQL_ERROR;
10360         }
10361         s->rowp = rowp;
10362     } else if (op == SQL_REFRESH) {
10363         if (row > s->rowset_size) {
10364             goto rowoor;
10365         }
10366         if (row == 0) {
10367             ret = SQL_SUCCESS;
10368             for (i = 0; i < s->rowset_size; i++) {
10369                 ret = setposrefr(s, i);
10370                 if (!SQL_SUCCEEDED(ret)) {
10371                     break;
10372                 }
10373             }
10374             return ret;
10375         }
10376         return setposrefr(s, row - 1);
10377     } else if (op == SQL_DELETE) {
10378         sql = dsappend(sql, "DELETE FROM ");
10379         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10380             sql = dsappendq(sql, s->dyncols[0].db);
10381             sql = dsappend(sql, ".");
10382         }
10383         sql = dsappendq(sql, s->dyncols[0].table);
10384         for (i = k = 0; i < s->ncols; i++) {
10385             if (s->dyncols[i].ispk <= 0) {
10386                 continue;
10387             }
10388             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10389             sql = dsappendq(sql, s->dyncols[i].column);
10390             sql = dsappend(sql, " = ?");
10391             k++;
10392         }
10393         if (dserr(sql)) {
10394             dsfree(sql);
10395             return nomem(s);
10396         }
10397 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10398         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10399 #else
10400         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10401 #endif
10402         do {
10403             s3stmt = NULL;
10404 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10405             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10406                                     &s3stmt, &endp);
10407 #else
10408             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10409                                  &s3stmt, &endp);
10410 #endif
10411             if (rc != SQLITE_OK) {
10412                 if (s3stmt) {
10413                     sqlite3_finalize(s3stmt);
10414                     s3stmt = NULL;
10415                 }
10416             }
10417         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10418         dbtracerc(d, rc, NULL);
10419         dsfree(sql);
10420         if (rc != SQLITE_OK) {
10421 dstmterr:
10422             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10423                     sqlite3_errmsg(d->sqlite), rc);
10424             if (s3stmt) {
10425                 dbtraceapi(d, "sqlite3_finalize", NULL);
10426                 sqlite3_finalize(s3stmt);
10427             }
10428             return SQL_ERROR;
10429         }
10430         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10431             if (s->dyncols[i].ispk <= 0) {
10432                 continue;
10433             }
10434             ret = setposibind(s, s3stmt, i, k, row - 1);
10435             if (ret != SQL_SUCCESS) {
10436                 dbtraceapi(d, "sqlite3_finalize", NULL);
10437                 sqlite3_finalize(s3stmt);
10438                 return ret;
10439             }
10440             k++;
10441         }
10442         rc = sqlite3_step(s3stmt);
10443         if (rc != SQLITE_DONE) {
10444             goto dstmterr;
10445         }
10446         sqlite3_finalize(s3stmt);
10447         if (sqlite3_changes(d->sqlite) > 0) {
10448             if (s->row_status0) {
10449                 s->row_status0[row - 1] = SQL_ROW_DELETED;
10450             }
10451             if (s->row_status) {
10452                 s->row_status[row - 1] = SQL_ROW_DELETED;
10453             }
10454         }
10455         return SQL_SUCCESS;
10456     } else if (op == SQL_UPDATE) {
10457         ret = chkunbound(s);
10458         if (ret != SQL_SUCCESS) {
10459             return ret;
10460         }
10461         sql = dsappend(sql, "UPDATE ");
10462         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10463             sql = dsappendq(sql, s->dyncols[0].db);
10464             sql = dsappend(sql, ".");
10465         }
10466         sql = dsappendq(sql, s->dyncols[0].table);
10467         for (i = 0; i < s->ncols; i++) {
10468             sql = dsappend(sql, (i > 0) ? ", " : " SET ");
10469             sql = dsappendq(sql, s->dyncols[i].column);
10470             sql = dsappend(sql, " = ?");
10471         }
10472         for (i = k = 0; i < s->ncols; i++) {
10473             if (s->dyncols[i].ispk <= 0) {
10474                 continue;
10475             }
10476             sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10477             sql = dsappendq(sql, s->dyncols[i].column);
10478             sql = dsappend(sql, " = ?");
10479             k++;
10480         }
10481         if (dserr(sql)) {
10482             dsfree(sql);
10483             return nomem(s);
10484         }
10485 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10486         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10487 #else
10488         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10489 #endif
10490         do {
10491             s3stmt = NULL;
10492 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10493             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10494                                     &s3stmt, &endp);
10495 #else
10496             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10497                                  &s3stmt, &endp);
10498 #endif
10499             if (rc != SQLITE_OK) {
10500                 if (s3stmt) {
10501                     sqlite3_finalize(s3stmt);
10502                     s3stmt = NULL;
10503                 }
10504             }
10505         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10506         dbtracerc(d, rc, NULL);
10507         dsfree(sql);
10508         if (rc != SQLITE_OK) {
10509 ustmterr:
10510             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10511                     sqlite3_errmsg(d->sqlite), rc);
10512             if (s3stmt) {
10513                 dbtraceapi(d, "sqlite3_finalize", NULL);
10514                 sqlite3_finalize(s3stmt);
10515             }
10516             return SQL_ERROR;
10517         }
10518         for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10519             ret = setposbind(s, s3stmt, i, k, row - 1);
10520             if (ret != SQL_SUCCESS) {
10521                 dbtraceapi(d, "sqlite3_finalize", NULL);
10522                 sqlite3_finalize(s3stmt);
10523                 return ret;
10524             }
10525             k++;
10526         }
10527         for (i = 0; s->bindcols && i < s->ncols; i++) {
10528             if (s->dyncols[i].ispk <= 0) {
10529                 continue;
10530             }
10531             ret = setposibind(s, s3stmt, i, k, row - 1);
10532             if (ret != SQL_SUCCESS) {
10533                 dbtraceapi(d, "sqlite3_finalize", NULL);
10534                 sqlite3_finalize(s3stmt);
10535                 return ret;
10536             }
10537             k++;
10538         }
10539         rc = sqlite3_step(s3stmt);
10540         if (rc != SQLITE_DONE) {
10541             goto ustmterr;
10542         }
10543         sqlite3_finalize(s3stmt);
10544         if (sqlite3_changes(d->sqlite) > 0) {
10545             if (s->row_status0) {
10546                 s->row_status0[row - 1] = SQL_ROW_UPDATED;
10547             }
10548             if (s->row_status) {
10549                 s->row_status[row - 1] = SQL_ROW_UPDATED;
10550             }
10551         }
10552         return SQL_SUCCESS;
10553     }
10554     return SQL_SUCCESS;
10555 }
10556 
10566 SQLRETURN SQL_API
10567 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10568 {
10569     SQLRETURN ret;
10570 
10571     HSTMT_LOCK(stmt);
10572     ret = drvsetpos(stmt, row, op, lock);
10573     HSTMT_UNLOCK(stmt);
10574     return ret;
10575 }
10576 
10584 static SQLRETURN
10585 drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
10586 {
10587     STMT *s = (STMT *) stmt;
10588     DBC *d = (DBC *) s->dbc;
10589     int row, i, k, rc, nretry = 0;
10590     dstr *sql = 0;
10591     const char *endp;
10592     sqlite3_stmt *s3stmt = NULL;
10593     SQLRETURN ret;
10594 
10595     if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10596         setstat(s, -1, "incompatible statement",
10597                 (*s->ov3) ? "HY000" : "S1000");
10598         return SQL_ERROR;
10599     }
10600     if (op == SQL_ADD) {
10601         if (s->one_tbl <= 0) {
10602             setstat(s, -1, "incompatible rowset",
10603                     (*s->ov3) ? "HY000" : "S1000");
10604             return SQL_ERROR;
10605         }
10606         ret = chkunbound(s);
10607         if (ret != SQL_SUCCESS) {
10608             return ret;
10609         }
10610         sql = dsappend(sql, "INSERT INTO ");
10611         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10612             sql = dsappendq(sql, s->dyncols[0].db);
10613             sql = dsappend(sql, ".");
10614         }
10615         sql = dsappendq(sql, s->dyncols[0].table);
10616         for (i = 0; i < s->ncols; i++) {
10617             sql = dsappend(sql, (i > 0) ? "," : "(");
10618             sql = dsappendq(sql, s->dyncols[i].column);
10619         }
10620         sql = dsappend(sql, ") VALUES ");
10621         for (i = 0; i < s->ncols; i++) {
10622             sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10623         }
10624         sql = dsappend(sql, ")");
10625         if (dserr(sql)) {
10626             dsfree(sql);
10627             return nomem(s);
10628         }
10629 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10630         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10631 #else
10632         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10633 #endif
10634         do {
10635             s3stmt = NULL;
10636 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10637             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10638                                     &s3stmt, &endp);
10639 #else
10640             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10641                                  &s3stmt, &endp);
10642 #endif
10643             if (rc != SQLITE_OK) {
10644                 if (s3stmt) {
10645                     sqlite3_finalize(s3stmt);
10646                     s3stmt = NULL;
10647                 }
10648             }
10649         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10650         dbtracerc(d, rc, NULL);
10651         dsfree(sql);
10652         if (rc != SQLITE_OK) {
10653             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10654                     sqlite3_errmsg(d->sqlite), rc);
10655             if (s3stmt) {
10656                 dbtraceapi(d, "sqlite3_finalize", NULL);
10657                 sqlite3_finalize(s3stmt);
10658             }
10659             return SQL_ERROR;
10660         }
10661         for (row = 0; row < s->rowset_size; row++) {
10662             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10663                 ret = setposbind(s, s3stmt, i, k, row);
10664                 if (ret != SQL_SUCCESS) {
10665 istmterr:
10666                     if (s->row_status0) {
10667                         s->row_status0[row] = SQL_ROW_ERROR;
10668                     }
10669                     if (s->row_status) {
10670                         s->row_status[row] = SQL_ROW_ERROR;
10671                     }
10672                     dbtraceapi(d, "sqlite3_finalize", NULL);
10673                     sqlite3_finalize(s3stmt);
10674                     return ret;
10675                 }
10676                 k++;
10677             }
10678             rc = sqlite3_step(s3stmt);
10679             if (rc != SQLITE_DONE) {
10680                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10681                         sqlite3_errmsg(d->sqlite), rc);
10682                 ret = SQL_ERROR;
10683                 goto istmterr;
10684             }
10685             if (sqlite3_changes(d->sqlite) > 0) {
10686                 if (s->row_status0) {
10687                     s->row_status0[row] = SQL_ROW_ADDED;
10688                 }
10689                 if (s->row_status) {
10690                     s->row_status[row] = SQL_ROW_ADDED;
10691                 }
10692             }
10693             if (s->bkmrk == SQL_UB_VARIABLE &&
10694                 s->bkmrkcol.type == SQL_C_VARBOOKMARK &&
10695                 s->bkmrkcol.valp) {
10696                 SQLPOINTER *val;
10697 
10698                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10699                     val = (SQLPOINTER)
10700                         ((char *) s->bkmrkcol.valp + s->bind_type * row);
10701                 } else {
10702                     val = (SQLPOINTER)
10703                         ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10704                 }
10705                 if (s->bind_offs) {
10706                     val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10707                 }
10708                 *(sqlite_int64 *) val = sqlite3_last_insert_rowid(d->sqlite);
10709                 if (s->bkmrkcol.lenp) {
10710                     SQLLEN *ival;
10711 
10712                     if (s->bind_type != SQL_BIND_BY_COLUMN) {
10713                         ival = (SQLLEN *)
10714                             ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10715                     } else {
10716                         ival = &s->bkmrkcol.lenp[row];
10717                     }
10718                     if (s->bind_offs) {
10719                         ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10720                     }
10721                     *ival = sizeof (sqlite_int64);
10722                 }
10723             }
10724             dbtraceapi(d, "sqlite3_reset", NULL);
10725             sqlite3_reset(s3stmt);
10726         }
10727         dbtraceapi(d, "sqlite3_finalize", NULL);
10728         sqlite3_finalize(s3stmt);
10729         return SQL_SUCCESS;
10730     } else if (op == SQL_DELETE_BY_BOOKMARK) {
10731         if (s->has_rowid < 0 ||
10732             s->bkmrk != SQL_UB_VARIABLE ||
10733             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10734             !s->bkmrkcol.valp) {
10735             setstat(s, -1, "incompatible rowset",
10736                     (*s->ov3) ? "HY000" : "S1000");
10737             return SQL_ERROR;
10738         }
10739         sql = dsappend(sql, "DELETE FROM ");
10740         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10741             sql = dsappendq(sql, s->dyncols[0].db);
10742             sql = dsappend(sql, ".");
10743         }
10744         sql = dsappendq(sql, s->dyncols[0].table);
10745         sql = dsappend(sql, " WHERE ");
10746         sql = dsappendq(sql, s->dyncols[0].column);
10747         sql = dsappend(sql, " = ?");
10748         if (dserr(sql)) {
10749             dsfree(sql);
10750             return nomem(s);
10751         }
10752 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10753         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10754 #else
10755         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10756 #endif
10757         do {
10758             s3stmt = NULL;
10759 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10760             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10761                                     &s3stmt, &endp);
10762 #else
10763             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10764                                  &s3stmt, &endp);
10765 #endif
10766             if (rc != SQLITE_OK) {
10767                 if (s3stmt) {
10768                     sqlite3_finalize(s3stmt);
10769                     s3stmt = NULL;
10770                 }
10771             }
10772         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10773         dbtracerc(d, rc, NULL);
10774         dsfree(sql);
10775         if (rc != SQLITE_OK) {
10776             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10777                     sqlite3_errmsg(d->sqlite), rc);
10778             if (s3stmt) {
10779                 dbtraceapi(d, "sqlite3_finalize", NULL);
10780                 sqlite3_finalize(s3stmt);
10781             }
10782             return SQL_ERROR;
10783         }
10784         for (row = 0; row < s->rowset_size; row++) {
10785             SQLPOINTER *val;
10786             sqlite_int64 rowid;
10787 
10788             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10789                 val = (SQLPOINTER)
10790                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
10791             } else {
10792                 val = (SQLPOINTER)
10793                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10794             }
10795             if (s->bind_offs) {
10796                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10797             }
10798             if (s->bkmrkcol.lenp) {
10799                 SQLLEN *ival;
10800 
10801                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10802                     ival = (SQLLEN *)
10803                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10804                 } else {
10805                     ival = &s->bkmrkcol.lenp[row];
10806                 }
10807                 if (s->bind_offs) {
10808                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10809                 }
10810                 if (*ival != sizeof (sqlite_int64)) {
10811                     continue;
10812                 }
10813             }
10814             rowid = *(sqlite_int64 *) val;
10815             sqlite3_bind_int64(s3stmt, 1, rowid);
10816             if (d->trace) {
10817                 fprintf(d->trace,
10818 #ifdef _WIN32
10819                         "-- parameter 1: %I64d\n",
10820 #else
10821                         "-- parameter 1: %lld\n",
10822 #endif
10823                         rowid);
10824                 fflush(d->trace);
10825             }
10826             rc = sqlite3_step(s3stmt);
10827             if (rc != SQLITE_DONE) {
10828                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10829                         sqlite3_errmsg(d->sqlite), rc);
10830                 if (s->row_status0) {
10831                     s->row_status0[row] = SQL_ROW_ERROR;
10832                 }
10833                 if (s->row_status) {
10834                     s->row_status[row] = SQL_ROW_ERROR;
10835                 }
10836                 dbtraceapi(d, "sqlite3_finalize", NULL);
10837                 sqlite3_finalize(s3stmt);
10838                 return SQL_ERROR;
10839             }
10840             if (sqlite3_changes(d->sqlite) > 0) {
10841                 if (s->row_status0) {
10842                     s->row_status0[row] = SQL_ROW_DELETED;
10843                 }
10844                 if (s->row_status) {
10845                     s->row_status[row] = SQL_ROW_DELETED;
10846                 }
10847             }
10848             dbtraceapi(d, "sqlite3_reset", NULL);
10849             sqlite3_reset(s3stmt);
10850         }
10851         dbtraceapi(d, "sqlite3_finalize", NULL);
10852         sqlite3_finalize(s3stmt);
10853         return SQL_SUCCESS;
10854     } else if (op == SQL_UPDATE_BY_BOOKMARK) {
10855         if (s->has_rowid < 0 ||
10856             s->bkmrk != SQL_UB_VARIABLE ||
10857             s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10858             !s->bkmrkcol.valp) {
10859             setstat(s, -1, "incompatible rowset",
10860                     (*s->ov3) ? "HY000" : "S1000");
10861             return SQL_ERROR;
10862         }
10863         ret = chkunbound(s);
10864         if (ret != SQL_SUCCESS) {
10865             return ret;
10866         }
10867         sql = dsappend(sql, "UPDATE ");
10868         if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10869             sql = dsappendq(sql, s->dyncols[0].db);
10870             sql = dsappend(sql, ".");
10871         }
10872         sql = dsappendq(sql, s->dyncols[0].table);
10873         for (i = 0, k = 0; i < s->ncols; i++) {
10874             sql = dsappend(sql, (k > 0) ? ", " : " SET ");
10875             sql = dsappendq(sql, s->dyncols[i].column);
10876             sql = dsappend(sql, " = ?");
10877             k++;
10878         }
10879         sql = dsappend(sql, " WHERE ");
10880         sql = dsappendq(sql, s->dyncols[s->has_rowid].column);
10881         sql = dsappend(sql, " = ?");
10882         if (dserr(sql)) {
10883             dsfree(sql);
10884             return nomem(s);
10885         }
10886 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10887         dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10888 #else
10889         dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10890 #endif
10891         do {
10892             s3stmt = NULL;
10893 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10894             rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10895                                     &s3stmt, &endp);
10896 #else
10897             rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10898                                  &s3stmt, &endp);
10899 #endif
10900             if (rc != SQLITE_OK) {
10901                 if (s3stmt) {
10902                     sqlite3_finalize(s3stmt);
10903                     s3stmt = NULL;
10904                 }
10905             }
10906         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10907         dbtracerc(d, rc, NULL);
10908         dsfree(sql);
10909         if (rc != SQLITE_OK) {
10910             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10911                     sqlite3_errmsg(d->sqlite), rc);
10912             if (s3stmt) {
10913                 dbtraceapi(d, "sqlite3_finalize", NULL);
10914                 sqlite3_finalize(s3stmt);
10915             }
10916             return SQL_ERROR;
10917         }
10918         for (row = 0; row < s->rowset_size; row++) {
10919             SQLPOINTER *val;
10920             sqlite_int64 rowid;
10921 
10922             if (s->bind_type != SQL_BIND_BY_COLUMN) {
10923                 val = (SQLPOINTER)
10924                     ((char *) s->bkmrkcol.valp + s->bind_type * row);
10925             } else {
10926                 val = (SQLPOINTER)
10927                     ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10928             }
10929             if (s->bind_offs) {
10930                 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10931             }
10932             if (s->bkmrkcol.lenp) {
10933                 SQLLEN *ival;
10934 
10935                 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10936                     ival = (SQLLEN *)
10937                         ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10938                 } else {
10939                     ival = &s->bkmrkcol.lenp[row];
10940                 }
10941                 if (s->bind_offs) {
10942                     ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10943                 }
10944                 if (*ival != sizeof (sqlite_int64)) {
10945                     continue;
10946                 }
10947             }
10948             for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10949                 ret = setposbind(s, s3stmt, i, k, row);
10950                 if (ret != SQL_SUCCESS) {
10951 ustmterr:
10952                     if (s->row_status0) {
10953                         s->row_status0[row] = SQL_ROW_ERROR;
10954                     }
10955                     if (s->row_status) {
10956                         s->row_status[row] = SQL_ROW_ERROR;
10957                     }
10958                     dbtraceapi(d, "sqlite3_finalize", NULL);
10959                     sqlite3_finalize(s3stmt);
10960                     return ret;
10961                 }
10962                 k++;
10963             }
10964             rowid = *(sqlite_int64 *) val;
10965             sqlite3_bind_int64(s3stmt, k, rowid);
10966             if (d->trace) {
10967                 fprintf(d->trace,
10968 #ifdef _WIN32
10969                         "-- parameter %d: %I64d\n",
10970 #else
10971                         "-- parameter %d: %lld\n",
10972 #endif
10973                         k, rowid);
10974                 fflush(d->trace);
10975             }
10976             rc = sqlite3_step(s3stmt);
10977             if (rc != SQLITE_DONE) {
10978                 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10979                         sqlite3_errmsg(d->sqlite), rc);
10980                 ret = SQL_ERROR;
10981                 goto ustmterr;
10982             }
10983             if (sqlite3_changes(d->sqlite) > 0) {
10984                 if (s->row_status0) {
10985                     s->row_status0[row] = SQL_ROW_UPDATED;
10986                 }
10987                 if (s->row_status) {
10988                     s->row_status[row] = SQL_ROW_UPDATED;
10989                 }
10990             }
10991             dbtraceapi(d, "sqlite3_reset", NULL);
10992             sqlite3_reset(s3stmt);
10993         }
10994         dbtraceapi(d, "sqlite3_finalize", NULL);
10995         sqlite3_finalize(s3stmt);
10996         return SQL_SUCCESS;
10997     }
10998     setstat(s, -1, "unsupported operation", (*s->ov3) ? "HY000" : "S1000");
10999     return SQL_ERROR;
11000 }
11001 
11009 SQLRETURN SQL_API
11010 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
11011 {
11012     SQLRETURN ret;
11013 
11014     HSTMT_LOCK(stmt);
11015     ret = drvbulkoperations(stmt, oper);
11016     HSTMT_UNLOCK(stmt);
11017     return ret;
11018 }
11019 
11020 
11025 SQLRETURN SQL_API
11026 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
11027                     SQLUSMALLINT rowset)
11028 {
11029     SQLRETURN ret;
11030 
11031     HSTMT_LOCK(stmt);
11032     ret = drvunimplstmt(stmt);
11033     HSTMT_UNLOCK(stmt);
11034     return ret;
11035 }
11036 
11037 #define strmak(dst, src, max, lenp) { \
11038     int len = strlen(src); \
11039     int cnt = min(len + 1, max); \
11040     strncpy(dst, src, cnt); \
11041     *lenp = (cnt > len) ? len : cnt; \
11042 }
11043 
11054 static SQLRETURN
11055 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11056            SQLSMALLINT *valLen)
11057 {
11058     DBC *d;
11059     char dummyc[301];
11060     SQLSMALLINT dummy;
11061 #if defined(_WIN32) || defined(_WIN64)
11062     char pathbuf[301], *drvname;
11063 #else
11064     static char drvname[] = "sqlite3odbc.so";
11065 #endif
11066 
11067     if (dbc == SQL_NULL_HDBC) {
11068         return SQL_INVALID_HANDLE;
11069     }
11070     d = (DBC *) dbc;
11071     if (valMax) {
11072         valMax--;
11073     }
11074     if (!valLen) {
11075         valLen = &dummy;
11076     }
11077     if (!val) {
11078         val = dummyc;
11079         valMax = sizeof (dummyc) - 1;
11080     }
11081     switch (type) {
11082     case SQL_MAX_USER_NAME_LEN:
11083         *((SQLSMALLINT *) val) = 16;
11084         *valLen = sizeof (SQLSMALLINT);
11085         break;
11086     case SQL_USER_NAME:
11087         strmak(val, "", valMax, valLen);
11088         break;
11089     case SQL_DRIVER_ODBC_VER:
11090 #if 0
11091         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11092 #else
11093         strmak(val, "03.00", valMax, valLen);
11094 #endif
11095         break;
11096     case SQL_ACTIVE_CONNECTIONS:
11097     case SQL_ACTIVE_STATEMENTS:
11098         *((SQLSMALLINT *) val) = 0;
11099         *valLen = sizeof (SQLSMALLINT);
11100         break;
11101 #ifdef SQL_ASYNC_MODE
11102     case SQL_ASYNC_MODE:
11103         *((SQLUINTEGER *) val) = SQL_AM_NONE;
11104         *valLen = sizeof (SQLUINTEGER);
11105         break;
11106 #endif
11107 #ifdef SQL_CREATE_TABLE
11108     case SQL_CREATE_TABLE:
11109         *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
11110                                  SQL_CT_COLUMN_DEFAULT |
11111                                  SQL_CT_COLUMN_CONSTRAINT |
11112                                  SQL_CT_CONSTRAINT_NON_DEFERRABLE;
11113         *valLen = sizeof (SQLUINTEGER);
11114         break;
11115 #endif
11116 #ifdef SQL_CREATE_VIEW
11117     case SQL_CREATE_VIEW:
11118         *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
11119         *valLen = sizeof (SQLUINTEGER);
11120         break;
11121 #endif
11122 #ifdef SQL_DDL_INDEX
11123     case SQL_DDL_INDEX:
11124         *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
11125         *valLen = sizeof (SQLUINTEGER);
11126         break;
11127 #endif
11128 #ifdef SQL_DROP_TABLE
11129     case SQL_DROP_TABLE:
11130         *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
11131         *valLen = sizeof (SQLUINTEGER);
11132         break;
11133 #endif
11134 #ifdef SQL_DROP_VIEW
11135     case SQL_DROP_VIEW:
11136         *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
11137         *valLen = sizeof (SQLUINTEGER);
11138         break;
11139 #endif
11140 #ifdef SQL_INDEX_KEYWORDS
11141     case SQL_INDEX_KEYWORDS:
11142         *((SQLUINTEGER *) val) = SQL_IK_ALL;
11143         *valLen = sizeof (SQLUINTEGER);
11144         break;
11145 #endif
11146     case SQL_DATA_SOURCE_NAME:
11147         strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
11148         break;
11149     case SQL_DRIVER_NAME:
11150 #if defined(_WIN32) || defined(_WIN64)
11151         GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
11152         drvname = strrchr(pathbuf, '\\');
11153         if (drvname == NULL) {
11154             drvname = strrchr(pathbuf, '/');
11155         }
11156         if (drvname == NULL) {
11157             drvname = pathbuf;
11158         } else {
11159             drvname++;
11160         }
11161 #endif
11162         strmak(val, drvname, valMax, valLen);
11163         break;
11164     case SQL_DRIVER_VER:
11165         strmak(val, DRIVER_VER_INFO, valMax, valLen);
11166         break;
11167     case SQL_FETCH_DIRECTION:
11168         *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
11169             SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
11170         *valLen = sizeof (SQLUINTEGER);
11171         break;
11172     case SQL_ODBC_VER:
11173         strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11174         break;
11175     case SQL_ODBC_SAG_CLI_CONFORMANCE:
11176         *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
11177         *valLen = sizeof (SQLSMALLINT);
11178         break;
11179     case SQL_STANDARD_CLI_CONFORMANCE:
11180         *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
11181         *valLen = sizeof (SQLUINTEGER);
11182         break;
11183     case SQL_SQL_CONFORMANCE:
11184         *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
11185         *valLen = sizeof (SQLUINTEGER);
11186         break;
11187     case SQL_SERVER_NAME:
11188     case SQL_DATABASE_NAME:
11189         strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
11190         break;
11191     case SQL_SEARCH_PATTERN_ESCAPE:
11192         strmak(val, "\\", valMax, valLen);
11193         break;
11194     case SQL_ODBC_SQL_CONFORMANCE:
11195         *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
11196         *valLen = sizeof (SQLSMALLINT);
11197         break;
11198     case SQL_ODBC_API_CONFORMANCE:
11199         *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
11200         *valLen = sizeof (SQLSMALLINT);
11201         break;
11202     case SQL_DBMS_NAME:
11203         strmak(val, "SQLite", valMax, valLen);
11204         break;
11205     case SQL_DBMS_VER:
11206         strmak(val, SQLITE_VERSION, valMax, valLen);
11207         break;
11208     case SQL_COLUMN_ALIAS:
11209     case SQL_NEED_LONG_DATA_LEN:
11210     case SQL_OUTER_JOINS:
11211         strmak(val, "Y", valMax, valLen);
11212         break;
11213     case SQL_ROW_UPDATES:
11214     case SQL_ACCESSIBLE_PROCEDURES:
11215     case SQL_PROCEDURES:
11216     case SQL_EXPRESSIONS_IN_ORDERBY:
11217     case SQL_ODBC_SQL_OPT_IEF:
11218     case SQL_LIKE_ESCAPE_CLAUSE:
11219     case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11220     case SQL_ACCESSIBLE_TABLES:
11221     case SQL_MULT_RESULT_SETS:
11222     case SQL_MULTIPLE_ACTIVE_TXN:
11223     case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11224         strmak(val, "N", valMax, valLen);
11225         break;
11226 #ifdef SQL_CATALOG_NAME
11227     case SQL_CATALOG_NAME:
11228 #if defined(_WIN32) || defined(_WIN64)
11229         strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
11230 #else
11231         strmak(val, "N", valMax, valLen);
11232 #endif
11233         break;
11234 #endif
11235     case SQL_DATA_SOURCE_READ_ONLY:
11236         strmak(val, "N", valMax, valLen);
11237         break;
11238 #ifdef SQL_OJ_CAPABILITIES
11239     case SQL_OJ_CAPABILITIES:
11240         *((SQLUINTEGER *) val) = SQL_OJ_LEFT;
11241         *valLen = sizeof (SQLUINTEGER);
11242         break;
11243 #endif
11244 #ifdef SQL_MAX_IDENTIFIER_LEN
11245     case SQL_MAX_IDENTIFIER_LEN:
11246         *((SQLUSMALLINT *) val) = 255;
11247         *valLen = sizeof (SQLUSMALLINT);
11248         break;
11249 #endif
11250     case SQL_CONCAT_NULL_BEHAVIOR:
11251         *((SQLSMALLINT *) val) = SQL_CB_NULL;
11252         *valLen = sizeof (SQLSMALLINT);
11253         break;
11254     case SQL_CURSOR_COMMIT_BEHAVIOR:
11255     case SQL_CURSOR_ROLLBACK_BEHAVIOR:
11256         *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
11257         *valLen = sizeof (SQLSMALLINT);
11258         break;
11259 #ifdef SQL_CURSOR_SENSITIVITY
11260     case SQL_CURSOR_SENSITIVITY:
11261         *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
11262         *valLen = sizeof (SQLUINTEGER);
11263         break;
11264 #endif
11265     case SQL_DEFAULT_TXN_ISOLATION:
11266         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11267         *valLen = sizeof (SQLUINTEGER);
11268         break;
11269 #ifdef SQL_DESCRIBE_PARAMETER
11270     case SQL_DESCRIBE_PARAMETER:
11271         strmak(val, "Y", valMax, valLen);
11272         break;
11273 #endif
11274     case SQL_TXN_ISOLATION_OPTION:
11275         *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11276         *valLen = sizeof (SQLUINTEGER);
11277         break;
11278     case SQL_IDENTIFIER_CASE:
11279         *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
11280         *valLen = sizeof (SQLSMALLINT);
11281         break;
11282     case SQL_IDENTIFIER_QUOTE_CHAR:
11283         strmak(val, "\"", valMax, valLen);
11284         break;
11285     case SQL_MAX_TABLE_NAME_LEN:
11286     case SQL_MAX_COLUMN_NAME_LEN:
11287         *((SQLSMALLINT *) val) = 255;
11288         *valLen = sizeof (SQLSMALLINT);
11289         break;
11290     case SQL_MAX_CURSOR_NAME_LEN:
11291         *((SQLSMALLINT *) val) = 255;
11292         *valLen = sizeof (SQLSMALLINT);
11293         break;
11294     case SQL_MAX_PROCEDURE_NAME_LEN:
11295         *((SQLSMALLINT *) val) = 0;
11296         break;
11297     case SQL_MAX_QUALIFIER_NAME_LEN:
11298     case SQL_MAX_OWNER_NAME_LEN:
11299         *((SQLSMALLINT *) val) = 255;
11300         break;
11301     case SQL_OWNER_TERM:
11302         strmak(val, "", valMax, valLen);
11303         break;
11304     case SQL_PROCEDURE_TERM:
11305         strmak(val, "PROCEDURE", valMax, valLen);
11306         break;
11307     case SQL_QUALIFIER_NAME_SEPARATOR:
11308         strmak(val, ".", valMax, valLen);
11309         break;
11310     case SQL_QUALIFIER_TERM:
11311 #if defined(_WIN32) || defined(_WIN64)
11312         strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
11313 #else
11314         strmak(val, "", valMax, valLen);
11315 #endif
11316         break;
11317     case SQL_QUALIFIER_USAGE:
11318 #if defined(_WIN32) || defined(_WIN64)
11319         *((SQLUINTEGER *) val) = d->xcelqrx ?
11320             (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
11321              SQL_CU_TABLE_DEFINITION) : 0;
11322 #else
11323         *((SQLUINTEGER *) val) = 0;
11324 #endif
11325         *valLen = sizeof (SQLUINTEGER);
11326         break;
11327     case SQL_SCROLL_CONCURRENCY:
11328         *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
11329         *valLen = sizeof (SQLUINTEGER);
11330         break;
11331     case SQL_SCROLL_OPTIONS:
11332         *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
11333         *valLen = sizeof (SQLUINTEGER);
11334         break;
11335     case SQL_TABLE_TERM:
11336         strmak(val, "TABLE", valMax, valLen);
11337         break;
11338     case SQL_TXN_CAPABLE:
11339         *((SQLSMALLINT *) val) = SQL_TC_ALL;
11340         *valLen = sizeof (SQLSMALLINT);
11341         break;
11342     case SQL_CONVERT_FUNCTIONS:
11343         *((SQLUINTEGER *) val) = 0;
11344         *valLen = sizeof (SQLUINTEGER);
11345        break;
11346     case SQL_SYSTEM_FUNCTIONS:
11347     case SQL_NUMERIC_FUNCTIONS:
11348     case SQL_STRING_FUNCTIONS:
11349     case SQL_TIMEDATE_FUNCTIONS:
11350         *((SQLUINTEGER *) val) = 0;
11351         *valLen = sizeof (SQLUINTEGER);
11352         break;
11353     case SQL_CONVERT_BIGINT:
11354     case SQL_CONVERT_BIT:
11355     case SQL_CONVERT_CHAR:
11356     case SQL_CONVERT_DATE:
11357     case SQL_CONVERT_DECIMAL:
11358     case SQL_CONVERT_DOUBLE:
11359     case SQL_CONVERT_FLOAT:
11360     case SQL_CONVERT_INTEGER:
11361     case SQL_CONVERT_LONGVARCHAR:
11362     case SQL_CONVERT_NUMERIC:
11363     case SQL_CONVERT_REAL:
11364     case SQL_CONVERT_SMALLINT:
11365     case SQL_CONVERT_TIME:
11366     case SQL_CONVERT_TIMESTAMP:
11367     case SQL_CONVERT_TINYINT:
11368     case SQL_CONVERT_VARCHAR:
11369         *((SQLUINTEGER *) val) =
11370             SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
11371             SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
11372             SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
11373             SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
11374             SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
11375         *valLen = sizeof (SQLUINTEGER);
11376         break;
11377     case SQL_CONVERT_BINARY:
11378     case SQL_CONVERT_VARBINARY:
11379     case SQL_CONVERT_LONGVARBINARY:
11380         *((SQLUINTEGER *) val) = 0;
11381         *valLen = sizeof (SQLUINTEGER);
11382         break;
11383     case SQL_POSITIONED_STATEMENTS:
11384         *((SQLUINTEGER *) val) = 0;
11385         *valLen = sizeof (SQLUINTEGER);
11386         break;
11387     case SQL_LOCK_TYPES:
11388         *((SQLUINTEGER *) val) = SQL_LCK_NO_CHANGE;
11389         *valLen = sizeof (SQLUINTEGER);
11390         break;
11391     case SQL_BOOKMARK_PERSISTENCE:
11392         *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
11393         *valLen = sizeof (SQLUINTEGER);
11394         break;
11395     case SQL_UNION:
11396         *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
11397         *valLen = sizeof (SQLUINTEGER);
11398         break;
11399     case SQL_OWNER_USAGE:
11400     case SQL_SUBQUERIES:
11401     case SQL_TIMEDATE_ADD_INTERVALS:
11402     case SQL_TIMEDATE_DIFF_INTERVALS:
11403         *((SQLUINTEGER *) val) = 0;
11404         *valLen = sizeof (SQLUINTEGER);
11405         break;
11406     case SQL_QUOTED_IDENTIFIER_CASE:
11407         *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
11408         *valLen = sizeof (SQLUSMALLINT);
11409         break;
11410     case SQL_POS_OPERATIONS:
11411         *((SQLUINTEGER *) val) = SQL_POS_POSITION | SQL_POS_UPDATE |
11412             SQL_POS_DELETE | SQL_POS_ADD | SQL_POS_REFRESH;
11413         *valLen = sizeof (SQLUINTEGER);
11414         break;
11415     case SQL_ALTER_TABLE:
11416         *((SQLUINTEGER *) val) = 0;
11417         *valLen = sizeof (SQLUINTEGER);
11418         break;
11419     case SQL_CORRELATION_NAME:
11420         *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
11421         *valLen = sizeof (SQLSMALLINT);
11422         break;
11423     case SQL_NON_NULLABLE_COLUMNS:
11424         *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
11425         *valLen = sizeof (SQLSMALLINT);
11426         break;
11427     case SQL_NULL_COLLATION:
11428         *((SQLSMALLINT *) val) = SQL_NC_START;
11429         *valLen = sizeof (SQLSMALLINT);
11430         break;
11431     case SQL_MAX_COLUMNS_IN_GROUP_BY:
11432     case SQL_MAX_COLUMNS_IN_ORDER_BY:
11433     case SQL_MAX_COLUMNS_IN_SELECT:
11434     case SQL_MAX_COLUMNS_IN_TABLE:
11435     case SQL_MAX_ROW_SIZE:
11436     case SQL_MAX_TABLES_IN_SELECT:
11437         *((SQLSMALLINT *) val) = 0;
11438         *valLen = sizeof (SQLSMALLINT);
11439         break;
11440     case SQL_MAX_BINARY_LITERAL_LEN:
11441     case SQL_MAX_CHAR_LITERAL_LEN:
11442         *((SQLUINTEGER *) val) = 0;
11443         *valLen = sizeof (SQLUINTEGER);
11444         break;
11445     case SQL_MAX_COLUMNS_IN_INDEX:
11446         *((SQLSMALLINT *) val) = 0;
11447         *valLen = sizeof (SQLSMALLINT);
11448         break;
11449     case SQL_MAX_INDEX_SIZE:
11450         *((SQLUINTEGER *) val) = 0;
11451         *valLen = sizeof (SQLUINTEGER);
11452         break;
11453 #ifdef SQL_MAX_IDENTIFIER_LENGTH
11454     case SQL_MAX_IDENTIFIER_LENGTH:
11455         *((SQLUINTEGER *) val) = 255;
11456         *valLen = sizeof (SQLUINTEGER);
11457         break;
11458 #endif
11459     case SQL_MAX_STATEMENT_LEN:
11460         *((SQLUINTEGER *) val) = 16384;
11461         *valLen = sizeof (SQLUINTEGER);
11462         break;
11463     case SQL_QUALIFIER_LOCATION:
11464         *((SQLSMALLINT *) val) = SQL_QL_START;
11465         *valLen = sizeof (SQLSMALLINT);
11466         break;
11467     case SQL_GETDATA_EXTENSIONS:
11468         *((SQLUINTEGER *) val) =
11469             SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
11470         *valLen = sizeof (SQLUINTEGER);
11471         break;
11472     case SQL_STATIC_SENSITIVITY:
11473         *((SQLUINTEGER *) val) = 0;
11474         *valLen = sizeof (SQLUINTEGER);
11475         break;
11476     case SQL_FILE_USAGE:
11477 #if defined(_WIN32) || defined(_WIN64)
11478         *((SQLSMALLINT *) val) =
11479             d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
11480 #else
11481         *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
11482 #endif
11483         *valLen = sizeof (SQLSMALLINT);
11484         break;
11485     case SQL_GROUP_BY:
11486         *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
11487         *valLen = sizeof (SQLSMALLINT);
11488         break;
11489     case SQL_KEYWORDS:
11490         strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
11491                "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
11492                valMax, valLen);
11493         break;
11494     case SQL_SPECIAL_CHARACTERS:
11495 #ifdef SQL_COLLATION_SEQ
11496     case SQL_COLLATION_SEQ:
11497 #endif
11498         strmak(val, "", valMax, valLen);
11499         break;
11500     case SQL_BATCH_SUPPORT:
11501     case SQL_BATCH_ROW_COUNT:
11502     case SQL_PARAM_ARRAY_ROW_COUNTS:
11503         *((SQLUINTEGER *) val) = 0;
11504         *valLen = sizeof (SQLUINTEGER);
11505         break;
11506     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
11507         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
11508         *valLen = sizeof (SQLUINTEGER);
11509         break;
11510     case SQL_STATIC_CURSOR_ATTRIBUTES1:
11511         *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
11512             SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_POS_POSITION |
11513             SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_REFRESH |
11514             SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_BULK_ADD |
11515             SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK;
11516         *valLen = sizeof (SQLUINTEGER);
11517         break;
11518     case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
11519     case SQL_STATIC_CURSOR_ATTRIBUTES2:
11520         *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
11521             SQL_CA2_LOCK_CONCURRENCY;
11522         *valLen = sizeof (SQLUINTEGER);
11523         break;
11524     case SQL_KEYSET_CURSOR_ATTRIBUTES1:
11525     case SQL_KEYSET_CURSOR_ATTRIBUTES2:
11526     case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
11527     case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
11528         *((SQLUINTEGER *) val) = 0;
11529         *valLen = sizeof (SQLUINTEGER);
11530         break;
11531     case SQL_ODBC_INTERFACE_CONFORMANCE:
11532         *((SQLUINTEGER *) val) = SQL_OIC_CORE;
11533         *valLen = sizeof (SQLUINTEGER);
11534         break;
11535     default:
11536         setstatd(d, -1, "unsupported info option %d",
11537                  (*d->ov3) ? "HYC00" : "S1C00", type);
11538         return SQL_ERROR;
11539     }
11540     return SQL_SUCCESS;
11541 }
11542 
11543 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
11544 
11554 SQLRETURN SQL_API
11555 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11556            SQLSMALLINT *valLen)
11557 {
11558     SQLRETURN ret;
11559 
11560     HDBC_LOCK(dbc);
11561     ret = drvgetinfo(dbc, type, val, valMax, valLen);
11562     HDBC_UNLOCK(dbc);
11563     return ret;
11564 }
11565 #endif
11566 
11567 #ifdef WINTERFACE
11568 
11578 SQLRETURN SQL_API
11579 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11580             SQLSMALLINT *valLen)
11581 {
11582     SQLRETURN ret;
11583     SQLSMALLINT len = 0;
11584 
11585     HDBC_LOCK(dbc);
11586     ret = drvgetinfo(dbc, type, val, valMax, &len);
11587     HDBC_UNLOCK(dbc);
11588     if (ret == SQL_SUCCESS) {
11589         SQLWCHAR *v = NULL;
11590 
11591         switch (type) {
11592         case SQL_USER_NAME:
11593         case SQL_DRIVER_ODBC_VER:
11594         case SQL_DATA_SOURCE_NAME:
11595         case SQL_DRIVER_NAME:
11596         case SQL_DRIVER_VER:
11597         case SQL_ODBC_VER:
11598         case SQL_SERVER_NAME:
11599         case SQL_DATABASE_NAME:
11600         case SQL_SEARCH_PATTERN_ESCAPE:
11601         case SQL_DBMS_NAME:
11602         case SQL_DBMS_VER:
11603         case SQL_NEED_LONG_DATA_LEN:
11604         case SQL_ROW_UPDATES:
11605         case SQL_ACCESSIBLE_PROCEDURES:
11606         case SQL_PROCEDURES:
11607         case SQL_EXPRESSIONS_IN_ORDERBY:
11608         case SQL_ODBC_SQL_OPT_IEF:
11609         case SQL_LIKE_ESCAPE_CLAUSE:
11610         case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11611         case SQL_OUTER_JOINS:
11612         case SQL_COLUMN_ALIAS:
11613         case SQL_ACCESSIBLE_TABLES:
11614         case SQL_MULT_RESULT_SETS:
11615         case SQL_MULTIPLE_ACTIVE_TXN:
11616         case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11617         case SQL_DATA_SOURCE_READ_ONLY:
11618 #ifdef SQL_DESCRIBE_PARAMETER
11619         case SQL_DESCRIBE_PARAMETER:
11620 #endif
11621         case SQL_IDENTIFIER_QUOTE_CHAR:
11622         case SQL_OWNER_TERM:
11623         case SQL_PROCEDURE_TERM:
11624         case SQL_QUALIFIER_NAME_SEPARATOR:
11625         case SQL_QUALIFIER_TERM:
11626         case SQL_TABLE_TERM:
11627         case SQL_KEYWORDS:
11628         case SQL_SPECIAL_CHARACTERS:
11629 #ifdef SQL_CATALOG_NAME
11630         case SQL_CATALOG_NAME:
11631 #endif
11632 #ifdef SQL_COLLATION_SEQ
11633         case SQL_COLLATION_SEQ:
11634 #endif
11635             if (val) {
11636                 if (len > 0) {
11637                     v = uc_from_utf((SQLCHAR *) val, len);
11638                     if (v) {
11639                         int vmax = valMax / sizeof (SQLWCHAR);
11640 
11641                         uc_strncpy(val, v, vmax);
11642                         if (len < vmax) {
11643                             len = min(vmax, uc_strlen(v));
11644                             v[len] = 0;
11645                         } else {
11646                             len = vmax;
11647                         }
11648                         uc_free(v);
11649                         len *= sizeof (SQLWCHAR);
11650                     } else {
11651                         len = 0;
11652                     }
11653                 }
11654                 if (len <= 0) {
11655                     len = 0;
11656                     if (valMax >= sizeof (SQLWCHAR)) {
11657                         *((SQLWCHAR *)val) = 0;
11658                     }
11659                 }
11660             } else {
11661                 len *= sizeof (SQLWCHAR);
11662             }
11663             break;
11664         }
11665         if (valLen) {
11666             *valLen = len;
11667         }
11668     }
11669     return ret;
11670 }
11671 #endif
11672 
11681 SQLRETURN SQL_API
11682 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
11683                 SQLUSMALLINT *flags)
11684 {
11685     int i;
11686     SQLUSMALLINT exists[100];
11687 
11688     if (dbc == SQL_NULL_HDBC) {
11689         return SQL_INVALID_HANDLE;
11690     }
11691     for (i = 0; i < array_size(exists); i++) {
11692         exists[i] = SQL_FALSE;
11693     }
11694     exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
11695     exists[SQL_API_SQLFETCH] = SQL_TRUE;
11696     exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
11697     exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
11698     exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
11699     exists[SQL_API_SQLFREEENV] = SQL_TRUE;
11700     exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
11701     exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
11702     exists[SQL_API_SQLCANCEL] = SQL_TRUE;
11703     exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
11704     exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
11705     exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
11706     exists[SQL_API_SQLCONNECT] = SQL_TRUE;
11707     exists[SQL_API_SQLPREPARE] = SQL_TRUE;
11708     exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
11709     exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
11710     exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
11711     exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
11712     exists[SQL_API_SQLERROR] = SQL_TRUE;
11713     exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
11714     exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
11715     exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
11716     exists[SQL_API_SQLBULKOPERATIONS] = SQL_TRUE;
11717     exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
11718     exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
11719     exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
11720     exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
11721     exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
11722     exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
11723     exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
11724     exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
11725     exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
11726     exists[SQL_API_SQLGETDATA] = SQL_TRUE;
11727     exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
11728     exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
11729     exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
11730     exists[SQL_API_SQLGETINFO] = SQL_TRUE;
11731     exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
11732     exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
11733     exists[SQL_API_SQLTABLES] = SQL_TRUE;
11734     exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
11735     exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
11736     exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
11737     exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
11738     exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
11739     exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
11740     exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
11741     exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
11742     exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
11743     exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
11744     exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
11745     exists[SQL_API_SQLSETPOS] = SQL_TRUE;
11746     exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
11747     exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
11748     exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
11749     exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
11750     exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
11751     if (func == SQL_API_ALL_FUNCTIONS) {
11752         memcpy(flags, exists, sizeof (exists));
11753     } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
11754         int i;
11755 #define SET_EXISTS(x) \
11756         flags[(x) >> 4] |= (1 << ((x) & 0xF))
11757 #define CLR_EXISTS(x) \
11758         flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
11759 
11760         memset(flags, 0,
11761                sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
11762         for (i = 0; i < array_size(exists); i++) {
11763             if (exists[i]) {
11764                 flags[i >> 4] |= (1 << (i & 0xF));
11765             }
11766         }
11767         SET_EXISTS(SQL_API_SQLALLOCHANDLE);
11768         SET_EXISTS(SQL_API_SQLFREEHANDLE);
11769         SET_EXISTS(SQL_API_SQLGETSTMTATTR);
11770         SET_EXISTS(SQL_API_SQLSETSTMTATTR);
11771         SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
11772         SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
11773         SET_EXISTS(SQL_API_SQLGETENVATTR);
11774         SET_EXISTS(SQL_API_SQLSETENVATTR);
11775         SET_EXISTS(SQL_API_SQLCLOSECURSOR);
11776         SET_EXISTS(SQL_API_SQLBINDPARAM);
11777 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11778         /*
11779          * Some unixODBC versions have problems with
11780          * SQLError() vs. SQLGetDiagRec() with loss
11781          * of error/warning messages.
11782          */
11783         SET_EXISTS(SQL_API_SQLGETDIAGREC);
11784 #endif
11785         SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
11786         SET_EXISTS(SQL_API_SQLFETCHSCROLL);
11787         SET_EXISTS(SQL_API_SQLENDTRAN);
11788     } else {
11789         if (func < array_size(exists)) {
11790             *flags = exists[func];
11791         } else {
11792             switch (func) {
11793             case SQL_API_SQLALLOCHANDLE:
11794             case SQL_API_SQLFREEHANDLE:
11795             case SQL_API_SQLGETSTMTATTR:
11796             case SQL_API_SQLSETSTMTATTR:
11797             case SQL_API_SQLGETCONNECTATTR:
11798             case SQL_API_SQLSETCONNECTATTR:
11799             case SQL_API_SQLGETENVATTR:
11800             case SQL_API_SQLSETENVATTR:
11801             case SQL_API_SQLCLOSECURSOR:
11802             case SQL_API_SQLBINDPARAM:
11803 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11804             /*
11805              * Some unixODBC versions have problems with
11806              * SQLError() vs. SQLGetDiagRec() with loss
11807              * of error/warning messages.
11808              */
11809             case SQL_API_SQLGETDIAGREC:
11810 #endif
11811             case SQL_API_SQLGETDIAGFIELD:
11812             case SQL_API_SQLFETCHSCROLL:
11813             case SQL_API_SQLENDTRAN:
11814                 *flags = SQL_TRUE;
11815                 break;
11816             default:
11817                 *flags = SQL_FALSE;
11818             }
11819         }
11820     }
11821     return SQL_SUCCESS;
11822 }
11823 
11830 static SQLRETURN
11831 drvallocenv(SQLHENV *env)
11832 {
11833     ENV *e;
11834 
11835     if (env == NULL) {
11836         return SQL_INVALID_HANDLE;
11837     }
11838     e = (ENV *) xmalloc(sizeof (ENV));
11839     if (e == NULL) {
11840         *env = SQL_NULL_HENV;
11841         return SQL_ERROR;
11842     }
11843     e->magic = ENV_MAGIC;
11844     e->ov3 = 0;
11845     e->pool = 0;
11846 #if defined(_WIN32) || defined(_WIN64)
11847     InitializeCriticalSection(&e->cs);
11848 #else
11849 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
11850     nvfs_init();
11851 #endif
11852 #endif
11853     e->dbcs = NULL;
11854     *env = (SQLHENV) e;
11855     return SQL_SUCCESS;
11856 }
11857 
11864 SQLRETURN SQL_API
11865 SQLAllocEnv(SQLHENV *env)
11866 {
11867     return drvallocenv(env);
11868 }
11869 
11876 static SQLRETURN
11877 drvfreeenv(SQLHENV env)
11878 {
11879     ENV *e;
11880 
11881     if (env == SQL_NULL_HENV) {
11882         return SQL_INVALID_HANDLE;
11883     }
11884     e = (ENV *) env;
11885     if (e->magic != ENV_MAGIC) {
11886         return SQL_SUCCESS;
11887     }
11888 #if defined(_WIN32) || defined(_WIN64)
11889     EnterCriticalSection(&e->cs);
11890 #endif
11891     if (e->dbcs) {
11892 #if defined(_WIN32) || defined(_WIN64)
11893         LeaveCriticalSection(&e->cs);
11894 #endif
11895         return SQL_ERROR;
11896     }
11897     e->magic = DEAD_MAGIC;
11898 #if defined(_WIN32) || defined(_WIN64)
11899     LeaveCriticalSection(&e->cs);
11900     DeleteCriticalSection(&e->cs);
11901 #endif
11902     xfree(e);
11903     return SQL_SUCCESS;
11904 }
11905 
11912 SQLRETURN SQL_API
11913 SQLFreeEnv(SQLHENV env)
11914 {
11915     return drvfreeenv(env);
11916 }
11917 
11925 static SQLRETURN
11926 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
11927 {
11928     DBC *d;
11929     ENV *e;
11930     const char *verstr;
11931     int maj = 0, min = 0, lev = 0;
11932 
11933     if (dbc == NULL) {
11934         return SQL_ERROR;
11935     }
11936     d = (DBC *) xmalloc(sizeof (DBC));
11937     if (d == NULL) {
11938         *dbc = SQL_NULL_HDBC;
11939         return SQL_ERROR;
11940     }
11941     memset(d, 0, sizeof (DBC));
11942     d->curtype = SQL_CURSOR_STATIC;
11943     d->ov3 = &d->ov3val;
11944     verstr = sqlite3_libversion();
11945     sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
11946     d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
11947     e = (ENV *) env;
11948 #if defined(_WIN32) || defined(_WIN64)
11949     if (e->magic == ENV_MAGIC) {
11950         EnterCriticalSection(&e->cs);
11951     }
11952 #endif
11953     if (e->magic == ENV_MAGIC) {
11954         DBC *n, *p;
11955 
11956         d->env = e;
11957         d->ov3 = &e->ov3;
11958         p = NULL;
11959         n = e->dbcs;
11960         while (n) {
11961             p = n;
11962             n = n->next;
11963         }
11964         if (p) {
11965             p->next = d;
11966         } else {
11967             e->dbcs = d;
11968         }
11969     }
11970 #if defined(_WIN32) || defined(_WIN64)
11971     InitializeCriticalSection(&d->cs);
11972     d->owner = 0;
11973     if (e->magic == ENV_MAGIC) {
11974         LeaveCriticalSection(&e->cs);
11975     }
11976     d->oemcp = 1;
11977 #endif
11978     d->autocommit = 1;
11979     d->magic = DBC_MAGIC;
11980     *dbc = (SQLHDBC) d;
11981     drvgetgpps(d);
11982     return SQL_SUCCESS;
11983 }
11984 
11992 SQLRETURN SQL_API
11993 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
11994 {
11995     return drvallocconnect(env, dbc);
11996 }
11997 
12004 static SQLRETURN
12005 drvfreeconnect(SQLHDBC dbc)
12006 {
12007     DBC *d;
12008     ENV *e;
12009     SQLRETURN ret = SQL_ERROR;
12010 
12011     if (dbc == SQL_NULL_HDBC) {
12012         return SQL_INVALID_HANDLE;
12013     }
12014     d = (DBC *) dbc;
12015     if (d->magic != DBC_MAGIC) {
12016         return SQL_INVALID_HANDLE;
12017     }
12018     e = d->env;
12019     if (e && e->magic == ENV_MAGIC) {
12020 #if defined(_WIN32) || defined(_WIN64)
12021         EnterCriticalSection(&e->cs);
12022 #endif
12023     } else {
12024         e = NULL;
12025     }
12026     HDBC_LOCK(dbc);
12027     if (d->sqlite) {
12028         setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
12029         HDBC_UNLOCK(dbc);
12030         goto done;
12031     }
12032     while (d->stmt) {
12033         freestmt((HSTMT) d->stmt);
12034     }
12035     if (e && e->magic == ENV_MAGIC) {
12036         DBC *n, *p;
12037 
12038         p = NULL;
12039         n = e->dbcs;
12040         while (n) {
12041             if (n == d) {
12042                 break;
12043             }
12044             p = n;
12045             n = n->next;
12046         }
12047         if (n) {
12048             if (p) {
12049                 p->next = d->next;
12050             } else {
12051                 e->dbcs = d->next;
12052             }
12053         }
12054     }
12055     drvrelgpps(d);
12056     d->magic = DEAD_MAGIC;
12057     if (d->trace) {
12058         fclose(d->trace);
12059     }
12060 #if defined(_WIN32) || defined(_WIN64)
12061     d->owner = 0;
12062     LeaveCriticalSection(&d->cs);
12063     DeleteCriticalSection(&d->cs);
12064 #endif
12065     xfree(d);
12066     ret = SQL_SUCCESS;
12067 done:
12068 #if defined(_WIN32) || defined(_WIN64)
12069     if (e) {
12070         LeaveCriticalSection(&e->cs);
12071     }
12072 #endif
12073     return ret;
12074 }
12075 
12082 SQLRETURN SQL_API
12083 SQLFreeConnect(SQLHDBC dbc)
12084 {
12085     return drvfreeconnect(dbc);
12086 }
12087 
12098 static SQLRETURN
12099 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12100                   SQLINTEGER bufmax, SQLINTEGER *buflen)
12101 {
12102     DBC *d;
12103     SQLINTEGER dummy;
12104 
12105     if (dbc == SQL_NULL_HDBC) {
12106         return SQL_INVALID_HANDLE;
12107     }
12108     d = (DBC *) dbc;
12109     if (!val) {
12110         val = (SQLPOINTER) &dummy;
12111     }
12112     if (!buflen) {
12113         buflen = &dummy;
12114     }
12115     switch (attr) {
12116     case SQL_ATTR_CONNECTION_DEAD:
12117         *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
12118         *buflen = sizeof (SQLINTEGER);
12119         break;
12120     case SQL_ATTR_ACCESS_MODE:
12121         *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
12122         *buflen = sizeof (SQLINTEGER);
12123         break;
12124     case SQL_ATTR_AUTOCOMMIT:
12125         *((SQLINTEGER *) val) =
12126             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12127         *buflen = sizeof (SQLINTEGER);
12128         break;
12129     case SQL_ATTR_LOGIN_TIMEOUT:
12130         *((SQLINTEGER *) val) = 100;
12131         *buflen = sizeof (SQLINTEGER);
12132         break;
12133     case SQL_ATTR_ODBC_CURSORS:
12134         *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
12135         *buflen = sizeof (SQLINTEGER);
12136         break;
12137     case SQL_ATTR_PACKET_SIZE:
12138         *((SQLINTEGER *) val) = 16384;
12139         *buflen = sizeof (SQLINTEGER);
12140         break;
12141     case SQL_ATTR_TXN_ISOLATION:
12142         *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
12143         *buflen = sizeof (SQLINTEGER);
12144         break;
12145     case SQL_ATTR_TRACEFILE:
12146     case SQL_ATTR_TRANSLATE_LIB:
12147         *((SQLCHAR *) val) = 0;
12148         *buflen = 0;
12149         break;
12150     case SQL_ATTR_CURRENT_CATALOG:
12151 #if defined(_WIN32) || defined(_WIN64)
12152         if (d->xcelqrx) {
12153             if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
12154                 strcpy((char *) val, "main");
12155                 *buflen = 4;
12156                 break;
12157             }
12158         }
12159 #endif
12160         *((SQLCHAR *) val) = 0;
12161         *buflen = 0;
12162         break;
12163     case SQL_ATTR_TRACE:
12164     case SQL_ATTR_QUIET_MODE:
12165     case SQL_ATTR_TRANSLATE_OPTION:
12166     case SQL_ATTR_KEYSET_SIZE:
12167     case SQL_ATTR_QUERY_TIMEOUT:
12168         *((SQLINTEGER *) val) = 0;
12169         *buflen = sizeof (SQLINTEGER);
12170         break;
12171     case SQL_ATTR_PARAM_BIND_TYPE:
12172         *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
12173         *buflen = sizeof (SQLUINTEGER);
12174         break;
12175     case SQL_ATTR_ROW_BIND_TYPE:
12176         *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
12177         *buflen = sizeof (SQLULEN);
12178         break;
12179     case SQL_ATTR_USE_BOOKMARKS:
12180         *((SQLINTEGER *) val) = SQL_UB_OFF;
12181         *buflen = sizeof (SQLINTEGER);
12182         break;
12183     case SQL_ATTR_ASYNC_ENABLE:
12184         *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
12185         *buflen = sizeof (SQLINTEGER);
12186         break;
12187     case SQL_ATTR_NOSCAN:
12188         *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
12189         *buflen = sizeof (SQLINTEGER);
12190         break;
12191     case SQL_ATTR_CONCURRENCY:
12192         *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
12193         *buflen = sizeof (SQLINTEGER);
12194         break;
12195 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
12196     case SQL_ATTR_CURSOR_SENSITIVITY:
12197         *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
12198         *buflen = sizeof (SQLINTEGER);
12199         break;
12200 #endif
12201     case SQL_ATTR_SIMULATE_CURSOR:
12202         *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
12203         *buflen = sizeof (SQLINTEGER);
12204         break;
12205     case SQL_ATTR_MAX_ROWS:
12206         *((SQLINTEGER *) val) = 0;
12207         *buflen = sizeof (SQLINTEGER);
12208     case SQL_ATTR_MAX_LENGTH:
12209         *((SQLINTEGER *) val) = 1000000000;
12210         *buflen = sizeof (SQLINTEGER);
12211         break;
12212     case SQL_ATTR_CURSOR_TYPE:
12213         *((SQLINTEGER *) val) = d->curtype;
12214         *buflen = sizeof (SQLINTEGER);
12215         break;
12216     case SQL_ATTR_RETRIEVE_DATA:
12217         *((SQLINTEGER *) val) = SQL_RD_ON;
12218         *buflen = sizeof (SQLINTEGER);
12219         break;
12220 #ifdef SQL_ATTR_METADATA_ID
12221     case SQL_ATTR_METADATA_ID:
12222         *((SQLULEN *) val) = SQL_FALSE;
12223         return SQL_SUCCESS;
12224 #endif
12225     default:
12226         *((SQLINTEGER *) val) = 0;
12227         *buflen = sizeof (SQLINTEGER);
12228         setstatd(d, -1, "unsupported connect attribute %d",
12229                  (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
12230         return SQL_ERROR;
12231     }
12232     return SQL_SUCCESS;
12233 }
12234 
12235 #ifndef WINTERFACE
12236 
12246 SQLRETURN SQL_API
12247 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12248                   SQLINTEGER bufmax, SQLINTEGER *buflen)
12249 {
12250     SQLRETURN ret;
12251 
12252     HDBC_LOCK(dbc);
12253     ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
12254     HDBC_UNLOCK(dbc);
12255     return ret;
12256 }
12257 #endif
12258 
12259 #ifdef WINTERFACE
12260 
12270 SQLRETURN SQL_API
12271 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12272                    SQLINTEGER bufmax, SQLINTEGER *buflen)
12273 {
12274     SQLRETURN ret;
12275     SQLINTEGER len = 0;
12276 
12277     HDBC_LOCK(dbc);
12278     ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
12279     if (ret == SQL_SUCCESS) {
12280         SQLWCHAR *v = NULL;
12281 
12282         switch (attr) {
12283         case SQL_ATTR_TRACEFILE:
12284         case SQL_ATTR_CURRENT_CATALOG:
12285         case SQL_ATTR_TRANSLATE_LIB:
12286             if (val) {
12287                 if (len > 0) {
12288                     v = uc_from_utf((SQLCHAR *) val, len);
12289                     if (v) {
12290                         int vmax = bufmax / sizeof (SQLWCHAR);
12291 
12292                         uc_strncpy(val, v, vmax);
12293                         if (len < vmax) {
12294                             len = min(vmax, uc_strlen(v));
12295                             v[len] = 0;
12296                         } else {
12297                             len = vmax;
12298                         }
12299                         uc_free(v);
12300                         len *= sizeof (SQLWCHAR);
12301                     } else {
12302                         len = 0;
12303                     }
12304                 }
12305                 if (len <= 0) {
12306                     len = 0;
12307                     if (bufmax >= sizeof (SQLWCHAR)) {
12308                         *((SQLWCHAR *)val) = 0;
12309                     }
12310                 }
12311             } else {
12312                 len *= sizeof (SQLWCHAR);
12313             }
12314             break;
12315         }
12316         if (buflen) {
12317             *buflen = len;
12318         }
12319     }
12320     HDBC_UNLOCK(dbc);
12321     return ret;
12322 }
12323 #endif
12324 
12334 static SQLRETURN
12335 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12336                   SQLINTEGER len)
12337 {
12338     DBC *d;
12339 
12340     if (dbc == SQL_NULL_HDBC) {
12341         return SQL_INVALID_HANDLE;
12342     }
12343     d = (DBC *) dbc;
12344     switch (attr) {
12345     case SQL_AUTOCOMMIT:
12346         d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
12347         if (d->autocommit && d->intrans) {
12348             return endtran(d, SQL_COMMIT, 1);
12349         } else if (!d->autocommit) {
12350             s3stmt_end(d->cur_s3stmt);
12351         }
12352         break;
12353         return SQL_SUCCESS;
12354 #ifdef SQL_ATTR_METADATA_ID
12355     case SQL_ATTR_METADATA_ID:
12356         if (val == (SQLPOINTER) SQL_FALSE) {
12357             break;
12358         }
12359         /* fall through */
12360 #endif
12361     default:
12362         setstatd(d, -1, "option value changed", "01S02");
12363         return SQL_SUCCESS_WITH_INFO;
12364     }
12365     return SQL_SUCCESS;
12366 }
12367 
12368 #ifndef WINTERFACE
12369 
12378 SQLRETURN SQL_API
12379 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12380                   SQLINTEGER len)
12381 {
12382     SQLRETURN ret;
12383 
12384     HDBC_LOCK(dbc);
12385     ret = drvsetconnectattr(dbc, attr, val, len);
12386     HDBC_UNLOCK(dbc);
12387     return ret;
12388 }
12389 #endif
12390 
12391 #ifdef WINTERFACE
12392 
12401 SQLRETURN SQL_API
12402 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12403                    SQLINTEGER len)
12404 {
12405     SQLRETURN ret;
12406 
12407     HDBC_LOCK(dbc);
12408     ret = drvsetconnectattr(dbc, attr, val, len);
12409     HDBC_UNLOCK(dbc);
12410     return ret;
12411 }
12412 #endif
12413 
12422 static SQLRETURN
12423 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12424 {
12425     DBC *d;
12426     SQLINTEGER dummy;
12427 
12428     if (dbc == SQL_NULL_HDBC) {
12429         return SQL_INVALID_HANDLE;
12430     }
12431     d = (DBC *) dbc;
12432     if (!param) {
12433         param = (SQLPOINTER) &dummy;
12434     }
12435     switch (opt) {
12436     case SQL_ACCESS_MODE:
12437         *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
12438         break;
12439     case SQL_AUTOCOMMIT:
12440         *((SQLINTEGER *) param) =
12441             d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12442         break;
12443     case SQL_LOGIN_TIMEOUT:
12444         *((SQLINTEGER *) param) = 100;
12445         break;
12446     case SQL_ODBC_CURSORS:
12447         *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
12448         break;
12449     case SQL_PACKET_SIZE:
12450         *((SQLINTEGER *) param) = 16384;
12451         break;
12452     case SQL_TXN_ISOLATION:
12453         *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
12454         break;
12455     case SQL_OPT_TRACE:
12456     case SQL_OPT_TRACEFILE:
12457     case SQL_QUIET_MODE:
12458     case SQL_TRANSLATE_DLL:
12459     case SQL_TRANSLATE_OPTION:
12460     case SQL_KEYSET_SIZE:
12461     case SQL_QUERY_TIMEOUT:
12462     case SQL_BIND_TYPE:
12463     case SQL_CURRENT_QUALIFIER:
12464         *((SQLINTEGER *) param) = 0;
12465         break;
12466     case SQL_USE_BOOKMARKS:
12467         *((SQLINTEGER *) param) = SQL_UB_OFF;
12468         break;
12469     case SQL_ASYNC_ENABLE:
12470         *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
12471         break;
12472     case SQL_NOSCAN:
12473         *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
12474         break;
12475     case SQL_CONCURRENCY:
12476         *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
12477         break;
12478     case SQL_SIMULATE_CURSOR:
12479         *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
12480         break;
12481     case SQL_MAX_ROWS:
12482         *((SQLINTEGER *) param) = 0;
12483         break;
12484     case SQL_ROWSET_SIZE:
12485     case SQL_MAX_LENGTH:
12486         *((SQLINTEGER *) param) = 1000000000;
12487         break;
12488     case SQL_CURSOR_TYPE:
12489         *((SQLINTEGER *) param) = d->curtype;
12490         break;
12491     case SQL_RETRIEVE_DATA:
12492         *((SQLINTEGER *) param) = SQL_RD_ON;
12493         break;
12494     default:
12495         *((SQLINTEGER *) param) = 0;
12496         setstatd(d, -1, "unsupported connect option %d",
12497                  (*d->ov3) ? "HYC00" : "S1C00", opt);
12498         return SQL_ERROR;
12499     }
12500     return SQL_SUCCESS;
12501 }
12502 
12503 #ifndef WINTERFACE
12504 
12512 SQLRETURN SQL_API
12513 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12514 {
12515     SQLRETURN ret;
12516 
12517     HDBC_LOCK(dbc);
12518     ret = drvgetconnectoption(dbc, opt, param);
12519     HDBC_UNLOCK(dbc);
12520     return ret;
12521 }
12522 #endif
12523 
12524 #ifdef WINTERFACE
12525 
12533 SQLRETURN SQL_API
12534 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12535 {
12536     SQLRETURN ret;
12537 
12538     HDBC_LOCK(dbc);
12539     ret = drvgetconnectoption(dbc, opt, param);
12540     if (SQL_SUCCEEDED(ret)) {
12541         switch (opt) {
12542         case SQL_OPT_TRACEFILE:
12543         case SQL_CURRENT_QUALIFIER:
12544         case SQL_TRANSLATE_DLL:
12545             if (param) {
12546                 *(SQLWCHAR *) param = 0;
12547             }
12548             break;
12549         }
12550     }
12551     HDBC_UNLOCK(dbc);
12552     return ret;
12553 }
12554 #endif
12555 
12564 static SQLRETURN
12565 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
12566 {
12567     DBC *d;
12568 
12569     if (dbc == SQL_NULL_HDBC) {
12570         return SQL_INVALID_HANDLE;
12571     }
12572     d = (DBC *) dbc;
12573     switch (opt) {
12574     case SQL_AUTOCOMMIT:
12575         d->autocommit = param == SQL_AUTOCOMMIT_ON;
12576         if (d->autocommit && d->intrans) {
12577             return endtran(d, SQL_COMMIT, 1);
12578         } else if (!d->autocommit) {
12579             s3stmt_end(d->cur_s3stmt);
12580         }
12581         break;
12582     default:
12583         setstatd(d, -1, "option value changed", "01S02");
12584         return SQL_SUCCESS_WITH_INFO;
12585     }
12586     return SQL_SUCCESS;
12587 }
12588 
12589 #ifndef WINTERFACE
12590 
12598 SQLRETURN SQL_API
12599 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12600 {
12601     SQLRETURN ret;
12602 
12603     HDBC_LOCK(dbc);
12604     ret = drvsetconnectoption(dbc, opt, param);
12605     HDBC_UNLOCK(dbc);
12606     return ret;
12607 }
12608 #endif
12609 
12610 #ifdef WINTERFACE
12611 
12619 SQLRETURN SQL_API
12620 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12621 {
12622     SQLRETURN ret;
12623 
12624     HDBC_LOCK(dbc);
12625     ret = drvsetconnectoption(dbc, opt, param);
12626     HDBC_UNLOCK(dbc);
12627     return ret;
12628 }
12629 #endif
12630 
12631 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12632 
12643 static int
12644 getdsnattr(char *dsn, char *attr, char *out, int outLen)
12645 {
12646     char *str = dsn, *start;
12647     int len = strlen(attr);
12648 
12649     while (*str) {
12650         while (*str && *str == ';') {
12651             ++str;
12652         }
12653         start = str;
12654         if ((str = strchr(str, '=')) == NULL) {
12655             return 0;
12656         }
12657         if (str - start == len && strncasecmp(start, attr, len) == 0) {
12658             start = ++str;
12659             while (*str && *str != ';') {
12660                 ++str;
12661             }
12662             len = min(outLen - 1, str - start);
12663             strncpy(out, start, len);
12664             out[len] = '\0';
12665             return 1;
12666         }
12667         while (*str && *str != ';') {
12668             ++str;
12669         }
12670     }
12671     return 0;
12672 }
12673 #endif
12674 
12686 static SQLRETURN
12687 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
12688            int pwdLen, int isu)
12689 {
12690     DBC *d;
12691     int len;
12692     SQLRETURN ret;
12693     char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12694     char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
12695     char loadext[SQL_MAX_MESSAGE_LENGTH];
12696     char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
12697     char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
12698     char jdflag[32];
12699 #if defined(_WIN32) || defined(_WIN64)
12700     char oemcp[32];
12701 #endif
12702 
12703     if (dbc == SQL_NULL_HDBC) {
12704         return SQL_INVALID_HANDLE;
12705     }
12706     d = (DBC *) dbc;
12707     if (d->magic != DBC_MAGIC) {
12708         return SQL_INVALID_HANDLE;
12709     }
12710     if (d->sqlite != NULL) {
12711         setstatd(d, -1, "connection already established", "08002");
12712         return SQL_ERROR;
12713     }
12714     buf[0] = '\0';
12715     if (dsnLen == SQL_NTS) {
12716         len = sizeof (buf) - 1;
12717     } else {
12718         len = min(sizeof (buf) - 1, dsnLen);
12719     }
12720     if (dsn != NULL) {
12721         strncpy(buf, (char *) dsn, len);
12722     }
12723     buf[len] = '\0';
12724     if (buf[0] == '\0') {
12725         setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
12726         return SQL_ERROR;
12727     }
12728 #if defined(_WIN32) || defined(_WIN64)
12729     /*
12730      * When DSN is in UTF it must be converted to ANSI
12731      * here for ANSI SQLGetPrivateProfileString()
12732      */
12733     if (isu) {
12734         char *cdsn = utf_to_wmb(buf, len);
12735 
12736         if (!cdsn) {
12737             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12738             return SQL_ERROR;
12739         }
12740         strcpy(buf, cdsn);
12741         uc_free(cdsn);
12742     }
12743 #endif
12744     busy[0] = '\0';
12745     dbname[0] = '\0';
12746 #ifdef WITHOUT_DRIVERMGR
12747     getdsnattr(buf, "database", dbname, sizeof (dbname));
12748     if (dbname[0] == '\0') {
12749         strncpy(dbname, buf, sizeof (dbname));
12750         dbname[sizeof (dbname) - 1] = '\0';
12751     }
12752     getdsnattr(buf, "timeout", busy, sizeof (busy));
12753     sflag[0] = '\0';
12754     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12755     spflag[0] = '\0';
12756     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12757     ntflag[0] = '\0';
12758     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12759     nwflag[0] = '\0';
12760     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12761     snflag[0] = '\0';
12762     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12763     lnflag[0] = '\0';
12764     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12765     ncflag[0] = '\0';
12766     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12767     fkflag[0] = '\0';
12768     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12769     loadext[0] = '\0';
12770     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12771     jmode[0] = '\0';
12772     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12773     jdflag[0] = '\0';
12774     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
12775 #if defined(_WIN32) || defined(_WIN64)
12776     oemcp[0] = '\0';
12777     getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
12778 #endif
12779     biflag[0] = '\0';
12780     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12781 #else
12782     SQLGetPrivateProfileString(buf, "timeout", "100000",
12783                                busy, sizeof (busy), ODBC_INI);
12784     SQLGetPrivateProfileString(buf, "database", "",
12785                                dbname, sizeof (dbname), ODBC_INI);
12786 #if defined(_WIN32) || defined(_WIN64)
12787     /* database name read from registry is not UTF8 !!! */
12788     isu = 0;
12789 #endif
12790     SQLGetPrivateProfileString(buf, "stepapi", "",
12791                                sflag, sizeof (sflag), ODBC_INI);
12792     SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
12793                                spflag, sizeof (spflag), ODBC_INI);
12794     SQLGetPrivateProfileString(buf, "notxn", "",
12795                                ntflag, sizeof (ntflag), ODBC_INI);
12796     SQLGetPrivateProfileString(buf, "nowchar", "",
12797                                nwflag, sizeof (nwflag), ODBC_INI);
12798     SQLGetPrivateProfileString(buf, "shortnames", "",
12799                                snflag, sizeof (snflag), ODBC_INI);
12800     SQLGetPrivateProfileString(buf, "longnames", "",
12801                                lnflag, sizeof (lnflag), ODBC_INI);
12802     SQLGetPrivateProfileString(buf, "nocreat", "",
12803                                ncflag, sizeof (ncflag), ODBC_INI);
12804     SQLGetPrivateProfileString(buf, "fksupport", "",
12805                                fkflag, sizeof (fkflag), ODBC_INI);
12806     SQLGetPrivateProfileString(buf, "loadext", "",
12807                                loadext, sizeof (loadext), ODBC_INI);
12808     SQLGetPrivateProfileString(buf, "journalmode", "",
12809                                jmode, sizeof (jmode), ODBC_INI);
12810     SQLGetPrivateProfileString(buf, "jdconv", "",
12811                                jdflag, sizeof (jdflag), ODBC_INI);
12812 #if defined(_WIN32) || defined(_WIN64)
12813     SQLGetPrivateProfileString(buf, "oemcp", "1",
12814                                oemcp, sizeof (oemcp), ODBC_INI);
12815 #endif
12816     SQLGetPrivateProfileString(buf, "bigint", "",
12817                                biflag, sizeof (biflag), ODBC_INI);
12818 #endif
12819     tracef[0] = '\0';
12820 #ifdef WITHOUT_DRIVERMGR
12821     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12822 #else
12823     SQLGetPrivateProfileString(buf, "tracefile", "",
12824                                tracef, sizeof (tracef), ODBC_INI);
12825 #endif
12826     if (tracef[0] != '\0') {
12827         d->trace = fopen(tracef, "a");
12828     }
12829     d->nowchar = getbool(nwflag);
12830     d->shortnames = getbool(snflag);
12831     d->longnames = getbool(lnflag);
12832     d->nocreat = getbool(ncflag);
12833     d->fksupport = getbool(fkflag);
12834     d->jdconv = getbool(jdflag);
12835 #if defined(_WIN32) || defined(_WIN64)
12836     d->oemcp = getbool(oemcp);
12837 #else
12838     d->oemcp = 0;
12839 #endif
12840     d->dobigint = getbool(biflag);
12841     d->pwd = pwd;
12842     d->pwdLen = 0;
12843     if (d->pwd) {
12844         d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
12845     }
12846     ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
12847                   jmode, busy);
12848     if (ret == SQL_SUCCESS) {
12849         dbloadext(d, loadext);
12850     }
12851     return ret;
12852 }
12853 
12854 #ifndef WINTERFACE
12855 
12867 SQLRETURN SQL_API
12868 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
12869            SQLCHAR *uid, SQLSMALLINT uidLen,
12870            SQLCHAR *pwd, SQLSMALLINT pwdLen)
12871 {
12872     SQLRETURN ret;
12873 
12874     HDBC_LOCK(dbc);
12875     ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
12876     HDBC_UNLOCK(dbc);
12877     return ret;
12878 }
12879 #endif
12880 
12881 #ifdef WINTERFACE
12882 
12894 SQLRETURN SQL_API
12895 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
12896             SQLWCHAR *uid, SQLSMALLINT uidLen,
12897             SQLWCHAR *pwd, SQLSMALLINT pwdLen)
12898 {
12899     char *dsna = NULL;
12900     char *pwda = NULL;
12901     SQLRETURN ret;
12902 
12903     HDBC_LOCK(dbc);
12904     if (dsn) {
12905         dsna = uc_to_utf_c(dsn, dsnLen);
12906         if (!dsna) {
12907             DBC *d = (DBC *) dbc;
12908 
12909             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12910             ret = SQL_ERROR;
12911             goto done;
12912         }
12913     }
12914     if (pwd) {
12915         pwda = uc_to_utf_c(pwd, pwdLen);
12916         if (!pwda) {
12917             DBC *d = (DBC *) dbc;
12918 
12919             setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12920             ret = SQL_ERROR;
12921             goto done;
12922         }
12923     }
12924     ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
12925 done:
12926     HDBC_UNLOCK(dbc);
12927     uc_free(dsna);
12928     uc_free(pwda);
12929     return ret;
12930 }
12931 #endif
12932 
12939 static SQLRETURN
12940 drvdisconnect(SQLHDBC dbc)
12941 {
12942     DBC *d;
12943     int rc;
12944 
12945     if (dbc == SQL_NULL_HDBC) {
12946         return SQL_INVALID_HANDLE;
12947     }
12948     d = (DBC *) dbc;
12949     if (d->magic != DBC_MAGIC) {
12950         return SQL_INVALID_HANDLE;
12951     }
12952     if (d->intrans) {
12953         setstatd(d, -1, "incomplete transaction", "25000");
12954         return SQL_ERROR;
12955     }
12956     if (d->cur_s3stmt) {
12957         s3stmt_end(d->cur_s3stmt);
12958     }
12959     if (d->sqlite) {
12960         if (d->trace) {
12961             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
12962                     d->dbname);
12963             fflush(d->trace);
12964         }
12965         rc = sqlite3_close(d->sqlite);
12966         if (rc == SQLITE_BUSY) {
12967             setstatd(d, -1, "unfinished statements", "25000");
12968             return SQL_ERROR;
12969         }
12970         d->sqlite = NULL;
12971     }
12972     freep(&d->dbname);
12973     freep(&d->dsn);
12974     return SQL_SUCCESS;
12975 }
12976 
12983 SQLRETURN SQL_API
12984 SQLDisconnect(SQLHDBC dbc)
12985 {
12986     SQLRETURN ret;
12987 
12988     HDBC_LOCK(dbc);
12989     ret = drvdisconnect(dbc);
12990     HDBC_UNLOCK(dbc);
12991     return ret;
12992 }
12993 
12994 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12995 
13009 static SQLRETURN
13010 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
13011                  SQLCHAR *connIn, SQLSMALLINT connInLen,
13012                  SQLCHAR *connOut, SQLSMALLINT connOutMax,
13013                  SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
13014 {
13015     DBC *d;
13016     int len;
13017     SQLRETURN ret;
13018     char buf[SQL_MAX_MESSAGE_LENGTH * 8], dbname[SQL_MAX_MESSAGE_LENGTH];
13019     char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
13020     char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
13021     char pwd[SQL_MAX_MESSAGE_LENGTH];
13022     char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
13023     char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
13024     char jdflag[32];
13025 
13026     if (dbc == SQL_NULL_HDBC) {
13027         return SQL_INVALID_HANDLE;
13028     }
13029     if (drvcompl != SQL_DRIVER_COMPLETE &&
13030         drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
13031         drvcompl != SQL_DRIVER_PROMPT &&
13032         drvcompl != SQL_DRIVER_NOPROMPT) {
13033         return SQL_NO_DATA;
13034     }
13035     d = (DBC *) dbc;
13036     if (d->sqlite) {
13037         setstatd(d, -1, "connection already established", "08002");
13038         return SQL_ERROR;
13039     }
13040     buf[0] = '\0';
13041     if (connInLen == SQL_NTS) {
13042         len = sizeof (buf) - 1;
13043     } else {
13044         len = min(connInLen, sizeof (buf) - 1);
13045     }
13046     if (connIn != NULL) {
13047         strncpy(buf, (char *) connIn, len);
13048     }
13049     buf[len] = '\0';
13050     if (!buf[0]) {
13051         setstatd(d, -1, "invalid connect attributes",
13052                  (*d->ov3) ? "HY090" : "S1090");
13053         return SQL_ERROR;
13054     }
13055     dsn[0] = '\0';
13056     getdsnattr(buf, "DSN", dsn, sizeof (dsn));
13057 
13058     /* special case: connIn is sole DSN value without keywords */
13059     if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
13060         strncpy(dsn, buf, sizeof (dsn) - 1);
13061         dsn[sizeof (dsn) - 1] = '\0';
13062     }
13063 
13064     busy[0] = '\0';
13065     getdsnattr(buf, "timeout", busy, sizeof (busy));
13066 #ifndef WITHOUT_DRIVERMGR
13067     if (dsn[0] && !busy[0]) {
13068         SQLGetPrivateProfileString(dsn, "timeout", "100000",
13069                                    busy, sizeof (busy), ODBC_INI);
13070     }
13071 #endif
13072     dbname[0] = '\0';
13073     getdsnattr(buf, "database", dbname, sizeof (dbname));
13074 #ifndef WITHOUT_DRIVERMGR
13075     if (dsn[0] && !dbname[0]) {
13076         SQLGetPrivateProfileString(dsn, "database", "",
13077                                    dbname, sizeof (dbname), ODBC_INI);
13078     }
13079 #endif
13080     sflag[0] = '\0';
13081     getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
13082 #ifndef WITHOUT_DRIVERMGR
13083     if (dsn[0] && !sflag[0]) {
13084         SQLGetPrivateProfileString(dsn, "stepapi", "",
13085                                    sflag, sizeof (sflag), ODBC_INI);
13086     }
13087 #endif
13088     spflag[0] = '\0';
13089     getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
13090 #ifndef WITHOUT_DRIVERMGR
13091     if (dsn[0] && !spflag[0]) {
13092         SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
13093                                    spflag, sizeof (spflag), ODBC_INI);
13094     }
13095 #endif
13096     ntflag[0] = '\0';
13097     getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
13098 #ifndef WITHOUT_DRIVERMGR
13099     if (dsn[0] && !ntflag[0]) {
13100         SQLGetPrivateProfileString(dsn, "notxn", "",
13101                                    ntflag, sizeof (ntflag), ODBC_INI);
13102     }
13103 #endif
13104     snflag[0] = '\0';
13105     getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
13106 #ifndef WITHOUT_DRIVERMGR
13107     if (dsn[0] && !snflag[0]) {
13108         SQLGetPrivateProfileString(dsn, "shortnames", "",
13109                                    snflag, sizeof (snflag), ODBC_INI);
13110     }
13111 #endif
13112     lnflag[0] = '\0';
13113     getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
13114 #ifndef WITHOUT_DRIVERMGR
13115     if (dsn[0] && !lnflag[0]) {
13116         SQLGetPrivateProfileString(dsn, "longnames", "",
13117                                    lnflag, sizeof (lnflag), ODBC_INI);
13118     }
13119 #endif
13120     ncflag[0] = '\0';
13121     getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
13122 #ifndef WITHOUT_DRIVERMGR
13123     if (dsn[0] && !ncflag[0]) {
13124         SQLGetPrivateProfileString(dsn, "nocreat", "",
13125                                    ncflag, sizeof (ncflag), ODBC_INI);
13126     }
13127 #endif
13128     nwflag[0] = '\0';
13129     getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
13130 #ifndef WITHOUT_DRIVERMGR
13131     if (dsn[0] && !nwflag[0]) {
13132         SQLGetPrivateProfileString(dsn, "nowchar", "",
13133                                    nwflag, sizeof (nwflag), ODBC_INI);
13134     }
13135 #endif
13136     fkflag[0] = '\0';
13137     getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
13138 #ifndef WITHOUT_DRIVERMGR
13139     if (dsn[0] && !fkflag[0]) {
13140         SQLGetPrivateProfileString(dsn, "fksupport", "",
13141                                    fkflag, sizeof (fkflag), ODBC_INI);
13142     }
13143 #endif
13144     loadext[0] = '\0';
13145     getdsnattr(buf, "loadext", loadext, sizeof (loadext));
13146 #ifndef WITHOUT_DRIVERMGR
13147     if (dsn[0] && !loadext[0]) {
13148         SQLGetPrivateProfileString(dsn, "loadext", "",
13149                                    loadext, sizeof (loadext), ODBC_INI);
13150     }
13151 #endif
13152     jmode[0] = '\0';
13153     getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
13154 #ifndef WITHOUT_DRIVERMGR
13155     if (dsn[0] && !jmode[0]) {
13156         SQLGetPrivateProfileString(dsn, "journalmode", "",
13157                                    jmode, sizeof (jmode), ODBC_INI);
13158     }
13159 #endif
13160     biflag[0] = '\0';
13161     getdsnattr(buf, "bigint", biflag, sizeof (biflag));
13162 #ifndef WITHOUT_DRIVERMGR
13163     if (dsn[0] && !biflag[0]) {
13164         SQLGetPrivateProfileString(dsn, "bigint", "",
13165                                    biflag, sizeof (biflag), ODBC_INI);
13166     }
13167 #endif
13168     jdflag[0] = '\0';
13169     getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
13170 #ifndef WITHOUT_DRIVERMGR
13171     if (dsn[0] && !jdflag[0]) {
13172         SQLGetPrivateProfileString(dsn, "jdconv", "",
13173                                    jdflag, sizeof (jdflag), ODBC_INI);
13174     }
13175 #endif
13176     pwd[0] = '\0';
13177     getdsnattr(buf, "pwd", pwd, sizeof (pwd));
13178 #ifndef WITHOUT_DRIVERMGR
13179     if (dsn[0] && !pwd[0]) {
13180         SQLGetPrivateProfileString(dsn, "pwd", "",
13181                                    pwd, sizeof (pwd), ODBC_INI);
13182     }
13183 #endif
13184 
13185     if (!dbname[0] && !dsn[0]) {
13186         strcpy(dsn, "SQLite");
13187         strncpy(dbname, buf, sizeof (dbname));
13188         dbname[sizeof (dbname) - 1] = '\0';
13189     }
13190     tracef[0] = '\0';
13191     getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
13192 #ifndef WITHOUT_DRIVERMGR
13193     if (dsn[0] && !tracef[0]) {
13194         SQLGetPrivateProfileString(dsn, "tracefile", "",
13195                                    tracef, sizeof (tracef), ODBC_INI);
13196     }
13197 #endif
13198     if (connOut || connOutLen) {
13199         int count;
13200 
13201         buf[0] = '\0';
13202         count = snprintf(buf, sizeof (buf),
13203                          "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
13204                          "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
13205                          "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
13206                          "JournalMode=%s;LoadExt=%s;BigInt=%s;JDConv=%s;"
13207                          "PWD=%s",
13208                          dsn, dbname, sflag, busy, spflag, ntflag,
13209                          snflag, lnflag, ncflag, nwflag, fkflag, tracef,
13210                          jmode, loadext, biflag, jdflag, pwd);
13211         if (count < 0) {
13212             buf[sizeof (buf) - 1] = '\0';
13213         }
13214         len = min(connOutMax - 1, strlen(buf));
13215         if (connOut) {
13216             strncpy((char *) connOut, buf, len);
13217             connOut[len] = '\0';
13218         }
13219         if (connOutLen) {
13220             *connOutLen = len;
13221         }
13222     }
13223     if (tracef[0] != '\0') {
13224         d->trace = fopen(tracef, "a");
13225     }
13226     d->shortnames = getbool(snflag);
13227     d->longnames = getbool(lnflag);
13228     d->nocreat = getbool(ncflag);
13229     d->nowchar = getbool(nwflag);
13230     d->fksupport = getbool(fkflag);
13231     d->dobigint = getbool(biflag);
13232     d->jdconv = getbool(jdflag);
13233     d->oemcp = 0;
13234     d->pwdLen = strlen(pwd);
13235     d->pwd = (d->pwdLen > 0) ? pwd : NULL;
13236     ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
13237     memset(pwd, 0, sizeof (pwd));
13238     if (ret == SQL_SUCCESS) {
13239         dbloadext(d, loadext);
13240     }
13241     return ret;
13242 }
13243 #endif
13244 
13251 static SQLRETURN
13252 freestmt(SQLHSTMT stmt)
13253 {
13254     STMT *s;
13255     DBC *d;
13256 
13257     if (stmt == SQL_NULL_HSTMT) {
13258         return SQL_INVALID_HANDLE;
13259     }
13260     s = (STMT *) stmt;
13261     s3stmt_drop(s);
13262     freeresult(s, 1);
13263     freep(&s->query);
13264     d = (DBC *) s->dbc;
13265     if (d && d->magic == DBC_MAGIC) {
13266         STMT *p, *n;
13267 
13268         p = NULL;
13269         n = d->stmt;
13270         while (n) {
13271             if (n == s) {
13272                 break;
13273             }
13274             p = n;
13275             n = n->next;
13276         }
13277         if (n) {
13278             if (p) {
13279                 p->next = s->next;
13280             } else {
13281                 d->stmt = s->next;
13282             }
13283         }
13284     }
13285     freeparams(s);
13286     freep(&s->bindparms);
13287     if (s->row_status0 != &s->row_status1) {
13288         freep(&s->row_status0);
13289         s->rowset_size = 1;
13290         s->row_status0 = &s->row_status1;
13291     }
13292     xfree(s);
13293     return SQL_SUCCESS;
13294 }
13295 
13303 static SQLRETURN
13304 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
13305 {
13306     DBC *d;
13307     STMT *s, *sl, *pl;
13308 
13309     if (dbc == SQL_NULL_HDBC) {
13310         return SQL_INVALID_HANDLE;
13311     }
13312     d = (DBC *) dbc;
13313     if (d->magic != DBC_MAGIC || stmt == NULL) {
13314         return SQL_INVALID_HANDLE;
13315     }
13316     s = (STMT *) xmalloc(sizeof (STMT));
13317     if (s == NULL) {
13318         *stmt = SQL_NULL_HSTMT;
13319         return SQL_ERROR;
13320     }
13321     *stmt = (SQLHSTMT) s;
13322     memset(s, 0, sizeof (STMT));
13323     s->dbc = dbc;
13324     s->ov3 = d->ov3;
13325     s->bkmrk = SQL_UB_OFF;
13326     s->bkmrkptr = 0;
13327     s->oemcp = &d->oemcp;
13328     s->jdconv = &d->jdconv;
13329     s->nowchar[0] = d->nowchar;
13330     s->nowchar[1] = 0;
13331     s->dobigint = d->dobigint;
13332     s->curtype = d->curtype;
13333     s->row_status0 = &s->row_status1;
13334     s->rowset_size = 1;
13335     s->longnames = d->longnames;
13336     s->retr_data = SQL_RD_ON;
13337     s->max_rows = 0;
13338     s->bind_type = SQL_BIND_BY_COLUMN;
13339     s->bind_offs = NULL;
13340     s->paramset_size = 1;
13341     s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
13342     s->one_tbl = -1;
13343     s->has_pk = -1;
13344     s->has_rowid = -1;
13345 #ifdef _WIN64
13346     sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
13347 #else
13348     sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
13349 #endif
13350     sl = d->stmt;
13351     pl = NULL;
13352     while (sl) {
13353         pl = sl;
13354         sl = sl->next;
13355     }
13356     if (pl) {
13357         pl->next = s;
13358     } else {
13359         d->stmt = s;
13360     }
13361     return SQL_SUCCESS;
13362 }
13363 
13371 SQLRETURN SQL_API
13372 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
13373 {
13374     SQLRETURN ret;
13375 
13376     HDBC_LOCK(dbc);
13377     ret = drvallocstmt(dbc, stmt);
13378     HDBC_UNLOCK(dbc);
13379     return ret;
13380 }
13381 
13389 static SQLRETURN
13390 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13391 {
13392     STMT *s;
13393     SQLRETURN ret = SQL_SUCCESS;
13394     SQLHDBC dbc;
13395 
13396     if (stmt == SQL_NULL_HSTMT) {
13397         return SQL_INVALID_HANDLE;
13398     }
13399     HSTMT_LOCK(stmt);
13400     s = (STMT *) stmt;
13401     dbc = s->dbc;
13402     switch (opt) {
13403     case SQL_RESET_PARAMS:
13404         freeparams(s);
13405         break;
13406     case SQL_UNBIND:
13407         unbindcols(s);
13408         break;
13409     case SQL_CLOSE:
13410         s3stmt_end_if(s);
13411         freeresult(s, 0);
13412         break;
13413     case SQL_DROP:
13414         s3stmt_end_if(s);
13415         ret = freestmt(stmt);
13416         break;
13417     default:
13418         setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
13419         ret = SQL_ERROR;
13420         break;
13421     }
13422     HDBC_UNLOCK(dbc);
13423     return ret;
13424 }
13425 
13433 SQLRETURN SQL_API
13434 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13435 {
13436     return drvfreestmt(stmt, opt);
13437 }
13438 
13445 SQLRETURN SQL_API
13446 SQLCancel(SQLHSTMT stmt)
13447 {
13448     if (stmt != SQL_NULL_HSTMT) {
13449         DBC *d = (DBC *) ((STMT *) stmt)->dbc;
13450 #if defined(_WIN32) || defined(_WIN64)
13451         /* interrupt when other thread owns critical section */
13452         if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
13453             d->owner != 0) {
13454             d->busyint = 1;
13455             sqlite3_interrupt(d->sqlite);
13456             return SQL_SUCCESS;
13457         }
13458 #else
13459         if (d->magic == DBC_MAGIC) {
13460             d->busyint = 1;
13461             sqlite3_interrupt(d->sqlite);
13462         }
13463 #endif
13464     }
13465     return drvfreestmt(stmt, SQL_CLOSE);
13466 }
13467 
13477 static SQLRETURN
13478 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13479                  SQLSMALLINT *lenp)
13480 {
13481     STMT *s;
13482 
13483     if (stmt == SQL_NULL_HSTMT) {
13484         return SQL_INVALID_HANDLE;
13485     }
13486     s = (STMT *) stmt;
13487     if (lenp && !cursor) {
13488         *lenp = strlen((char *) s->cursorname);
13489         return SQL_SUCCESS;
13490     }
13491     if (cursor) {
13492         if (buflen > 0) {
13493             strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
13494             cursor[buflen - 1] = '\0';
13495         }
13496         if (lenp) {
13497             *lenp = min(strlen((char *) s->cursorname), buflen - 1);
13498         }
13499     }
13500     return SQL_SUCCESS;
13501 }
13502 
13503 #ifndef WINTERFACE
13504 
13513 SQLRETURN SQL_API
13514 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13515                  SQLSMALLINT *lenp)
13516 {
13517     SQLRETURN ret;
13518 #if defined(_WIN32) || defined(_WIN64)
13519     SQLSMALLINT len = 0;
13520 #endif
13521 
13522     HSTMT_LOCK(stmt);
13523 #if defined(_WIN32) || defined(_WIN64)
13524     if (!((STMT *) stmt)->oemcp[0]) {
13525         ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13526         goto done;
13527     }
13528     ret = drvgetcursorname(stmt, cursor, buflen, &len);
13529     if (ret == SQL_SUCCESS) {
13530         char *c = NULL;
13531 
13532         if (cursor) {
13533             c = utf_to_wmb((char *) cursor, len);
13534             if (!c) {
13535                 ret = nomem((STMT *) stmt);
13536                 goto done;
13537             }
13538             c[len] = 0;
13539             len = strlen(c);
13540             if (buflen > 0) {
13541                 strncpy((char *) cursor, c, buflen - 1);
13542                 cursor[buflen - 1] = 0;
13543             }
13544             uc_free(c);
13545         }
13546         if (lenp) {
13547             *lenp = min(len, buflen - 1);
13548         }
13549     }
13550 done:
13551     ;
13552 #else
13553     ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13554 #endif
13555     HSTMT_UNLOCK(stmt);
13556     return ret;
13557 }
13558 #endif
13559 
13560 #ifdef WINTERFACE
13561 
13570 SQLRETURN SQL_API
13571 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
13572                   SQLSMALLINT *lenp)
13573 {
13574     SQLRETURN ret;
13575     SQLSMALLINT len = 0;
13576 
13577     HSTMT_LOCK(stmt);
13578     ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
13579     if (ret == SQL_SUCCESS) {
13580         SQLWCHAR *c = NULL;
13581 
13582         if (cursor) {
13583             c = uc_from_utf((SQLCHAR *) cursor, len);
13584             if (!c) {
13585                 ret = nomem((STMT *) stmt);
13586                 goto done;
13587             }
13588             c[len] = 0;
13589             len = uc_strlen(c);
13590             if (buflen > 0) {
13591                 uc_strncpy(cursor, c, buflen - 1);
13592                 cursor[buflen - 1] = 0;
13593             }
13594             uc_free(c);
13595         }
13596         if (lenp) {
13597             *lenp = min(len, buflen - 1);
13598         }
13599     }
13600 done:
13601     HSTMT_UNLOCK(stmt);
13602     return ret;
13603 }
13604 #endif
13605 
13614 static SQLRETURN
13615 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13616 {
13617     STMT *s;
13618 
13619     if (stmt == SQL_NULL_HSTMT) {
13620         return SQL_INVALID_HANDLE;
13621     }
13622     s = (STMT *) stmt;
13623     if (!cursor ||
13624         !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
13625           (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
13626         setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
13627         return SQL_ERROR;
13628     }
13629     if (len == SQL_NTS) {
13630         len = sizeof (s->cursorname) - 1;
13631     } else {
13632         len = min(sizeof (s->cursorname) - 1, len);
13633     }
13634     strncpy((char *) s->cursorname, (char *) cursor, len);
13635     s->cursorname[len] = '\0';
13636     return SQL_SUCCESS;
13637 }
13638 
13639 #ifndef WINTERFACE
13640 
13648 SQLRETURN SQL_API
13649 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13650 {
13651 #if defined(_WIN32) || defined(_WIN64)
13652     char *c = NULL;
13653 #endif
13654     SQLRETURN ret;
13655 
13656     HSTMT_LOCK(stmt);
13657 #if defined(_WIN32) || defined(_WIN64)
13658     if (!((STMT *) stmt)->oemcp[0]) {
13659         ret = drvsetcursorname(stmt, cursor, len);
13660         goto done2;
13661     }
13662     if (cursor) {
13663         c = wmb_to_utf_c((char *) cursor, len);
13664         if (!c) {
13665             ret = nomem((STMT *) stmt);
13666             goto done;
13667         }
13668     }
13669     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13670 #else
13671     ret = drvsetcursorname(stmt, cursor, len);
13672 #endif
13673 #if defined(_WIN32) || defined(_WIN64)
13674 done:
13675     uc_free(c);
13676 done2:
13677     ;
13678 #endif
13679     HSTMT_UNLOCK(stmt);
13680     return ret;
13681 }
13682 #endif
13683 
13684 #ifdef WINTERFACE
13685 
13693 SQLRETURN SQL_API
13694 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
13695 {
13696     char *c = NULL;
13697     SQLRETURN ret;
13698 
13699     HSTMT_LOCK(stmt);
13700     if (cursor) {
13701         c = uc_to_utf_c(cursor, len);
13702         if (!c) {
13703             ret = nomem((STMT *) stmt);
13704             goto done;
13705         }
13706     }
13707     ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13708 done:
13709     uc_free(c);
13710     HSTMT_UNLOCK(stmt);
13711     return ret;
13712 }
13713 #endif
13714 
13721 SQLRETURN SQL_API
13722 SQLCloseCursor(SQLHSTMT stmt)
13723 {
13724     return drvfreestmt(stmt, SQL_CLOSE);
13725 }
13726 
13735 SQLRETURN SQL_API
13736 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
13737 {
13738     SQLRETURN ret;
13739 
13740     switch (type) {
13741     case SQL_HANDLE_ENV:
13742         ret = drvallocenv((SQLHENV *) output);
13743         if (ret == SQL_SUCCESS) {
13744             ENV *e = (ENV *) *output;
13745 
13746             if (e && e->magic == ENV_MAGIC) {
13747                 e->ov3 = 1;
13748             }
13749         }
13750         return ret;
13751     case SQL_HANDLE_DBC:
13752         return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
13753     case SQL_HANDLE_STMT:
13754         HDBC_LOCK((SQLHDBC) input);
13755         ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
13756         HDBC_UNLOCK((SQLHDBC) input);
13757         return ret;
13758     }
13759     return SQL_ERROR;
13760 }
13761 
13769 SQLRETURN SQL_API
13770 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
13771 {
13772     switch (type) {
13773     case SQL_HANDLE_ENV:
13774         return drvfreeenv((SQLHENV) h);
13775     case SQL_HANDLE_DBC:
13776         return drvfreeconnect((SQLHDBC) h);
13777     case SQL_HANDLE_STMT:
13778         return drvfreestmt((SQLHSTMT) h, SQL_DROP);
13779     }
13780     return SQL_ERROR;
13781 }
13782 
13788 static void
13789 freedyncols(STMT *s)
13790 {
13791     if (s->dyncols) {
13792         int i;
13793 
13794         for (i = 0; i < s->dcols; i++) {
13795             freep(&s->dyncols[i].typename);
13796         }
13797         if (s->cols == s->dyncols) {
13798             s->cols = NULL;
13799             s->ncols = 0;
13800         }
13801         freep(&s->dyncols);
13802     }
13803     s->dcols = 0;
13804 }
13805 
13817 static void
13818 freeresult(STMT *s, int clrcols)
13819 {
13820     freep(&s->bincache);
13821     s->bincell = NULL;
13822     s->binlen = 0;
13823     if (s->rows) {
13824         if (s->rowfree) {
13825             s->rowfree(s->rows);
13826             s->rowfree = NULL;
13827         }
13828         s->rows = NULL;
13829     }
13830     s->nrows = -1;
13831     if (clrcols > 0) {
13832         freep(&s->bindcols);
13833         s->nbindcols = 0;
13834     }
13835     if (clrcols) {
13836         freedyncols(s);
13837         s->cols = NULL;
13838         s->ncols = 0;
13839         s->nowchar[1] = 0;
13840         s->one_tbl = -1;
13841         s->has_pk = -1;
13842         s->has_rowid = -1;
13843     }
13844 }
13845 
13851 static void
13852 unbindcols(STMT *s)
13853 {
13854     int i;
13855 
13856     for (i = 0; s->bindcols && i < s->nbindcols; i++) {
13857         s->bindcols[i].type = SQL_UNKNOWN_TYPE;
13858         s->bindcols[i].max = 0;
13859         s->bindcols[i].lenp = NULL;
13860         s->bindcols[i].valp = NULL;
13861         s->bindcols[i].index = i;
13862         s->bindcols[i].offs = 0;
13863     }
13864 }
13865 
13873 static SQLRETURN
13874 mkbindcols(STMT *s, int ncols)
13875 {
13876     if (s->bindcols) {
13877         if (s->nbindcols < ncols) {
13878             int i;
13879             BINDCOL *bindcols =
13880                 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
13881 
13882             if (!bindcols) {
13883                 return nomem(s);
13884             }
13885             for (i = s->nbindcols; i < ncols; i++) {
13886                 bindcols[i].type = SQL_UNKNOWN_TYPE;
13887                 bindcols[i].max = 0;
13888                 bindcols[i].lenp = NULL;
13889                 bindcols[i].valp = NULL;
13890                 bindcols[i].index = i;
13891                 bindcols[i].offs = 0;
13892             }
13893             s->bindcols = bindcols;
13894             s->nbindcols = ncols;
13895         }
13896     } else if (ncols > 0) {
13897         s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
13898         if (!s->bindcols) {
13899             return nomem(s);
13900         }
13901         s->nbindcols = ncols;
13902         unbindcols(s);
13903     }
13904     return SQL_SUCCESS;
13905 }
13906 
13920 static SQLRETURN
13921 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
13922            SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
13923 {
13924     char **data, valdummy[16];
13925     SQLLEN dummy;
13926     SQLINTEGER *ilenp = NULL;
13927     int valnull = 0;
13928     int type = otype;
13929     SQLRETURN sret = SQL_NO_DATA;
13930 
13931     if (!lenp) {
13932         lenp = &dummy;
13933     }
13934     /* workaround for JDK 1.7.0 on x86_64 */
13935     if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
13936         ilenp = (SQLINTEGER *) lenp;
13937         lenp = &dummy;
13938     }
13939     if (col >= s->ncols) {
13940         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13941         return SQL_ERROR;
13942     }
13943     if (s->retr_data != SQL_RD_ON) {
13944         return SQL_SUCCESS;
13945     }
13946     if (!s->rows) {
13947         *lenp = SQL_NULL_DATA;
13948         goto done;
13949     }
13950     if (s->rowp < 0 || s->rowp >= s->nrows) {
13951         *lenp = SQL_NULL_DATA;
13952         goto done;
13953     }
13954     type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
13955                       s->nowchar[0]);
13956 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
13957     /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
13958     if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
13959         type = SQL_C_CHAR;
13960     }
13961 #endif
13962     data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
13963     if (!val) {
13964         valnull = 1;
13965         val = (SQLPOINTER) valdummy;
13966     }
13967     if (*data == NULL) {
13968         *lenp = SQL_NULL_DATA;
13969         switch (type) {
13970         case SQL_C_UTINYINT:
13971         case SQL_C_TINYINT:
13972         case SQL_C_STINYINT:
13973 #ifdef SQL_BIT
13974         case SQL_C_BIT:
13975 #endif
13976             *((SQLCHAR *) val) = 0;
13977             break;
13978         case SQL_C_USHORT:
13979         case SQL_C_SHORT:
13980         case SQL_C_SSHORT:
13981             *((SQLSMALLINT *) val) = 0;
13982             break;
13983         case SQL_C_ULONG:
13984         case SQL_C_LONG:
13985         case SQL_C_SLONG:
13986             *((SQLINTEGER *) val) = 0;
13987             break;
13988 #ifdef SQL_BIGINT
13989         case SQL_C_SBIGINT:
13990         case SQL_C_UBIGINT:
13991             *((SQLBIGINT *) val) = 0;
13992             break;
13993 #endif
13994         case SQL_C_FLOAT:
13995             *((float *) val) = 0;
13996             break;
13997         case SQL_C_DOUBLE:
13998             *((double *) val) = 0;
13999             break;
14000         case SQL_C_BINARY:
14001         case SQL_C_CHAR:
14002             if (len > 0) {
14003                 *((SQLCHAR *) val) = '\0';
14004             }
14005             break;
14006 #ifdef WCHARSUPPORT
14007         case SQL_C_WCHAR:
14008             if (len > 0) {
14009                 *((SQLWCHAR *) val) = '\0';
14010             }
14011             break;
14012 #endif
14013 #ifdef SQL_C_TYPE_DATE
14014         case SQL_C_TYPE_DATE:
14015 #endif
14016         case SQL_C_DATE:
14017             memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
14018             break;
14019 #ifdef SQL_C_TYPE_TIME
14020         case SQL_C_TYPE_TIME:
14021 #endif
14022         case SQL_C_TIME:
14023             memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
14024             break;
14025 #ifdef SQL_C_TYPE_TIMESTAMP
14026         case SQL_C_TYPE_TIMESTAMP:
14027 #endif
14028         case SQL_C_TIMESTAMP:
14029             memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
14030             break;
14031         default:
14032             return SQL_ERROR;
14033         }
14034     } else {
14035         char *endp = NULL;
14036 #if defined(_WIN32) || defined(_WIN64)
14037 #ifdef SQL_BIGINT
14038         char endc;
14039 #endif
14040 #endif
14041 
14042         switch (type) {
14043         case SQL_C_UTINYINT:
14044         case SQL_C_TINYINT:
14045         case SQL_C_STINYINT:
14046             *((SQLCHAR *) val) = strtol(*data, &endp, 0);
14047             if (endp && endp == *data) {
14048                 *lenp = SQL_NULL_DATA;
14049             } else {
14050                 *lenp = sizeof (SQLCHAR);
14051             }
14052             break;
14053 #ifdef SQL_BIT
14054         case SQL_C_BIT:
14055             *((SQLCHAR *) val) = getbool(*data);
14056             *lenp = sizeof (SQLCHAR);
14057             break;
14058 #endif
14059         case SQL_C_USHORT:
14060         case SQL_C_SHORT:
14061         case SQL_C_SSHORT:
14062             *((SQLSMALLINT *) val) = strtol(*data, &endp, 0);
14063             if (endp && endp == *data) {
14064                 *lenp = SQL_NULL_DATA;
14065             } else {
14066                 *lenp = sizeof (SQLSMALLINT);
14067             }
14068             break;
14069         case SQL_C_ULONG:
14070         case SQL_C_LONG:
14071         case SQL_C_SLONG:
14072             *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
14073             if (endp && endp == *data) {
14074                 *lenp = SQL_NULL_DATA;
14075             } else {
14076                 *lenp = sizeof (SQLINTEGER);
14077             }
14078             break;
14079 #ifdef SQL_BIGINT
14080         case SQL_C_UBIGINT:
14081 #if defined(_WIN32) || defined(_WIN64)
14082             if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
14083                 *lenp = SQL_NULL_DATA;
14084             } else {
14085                 *lenp = sizeof (SQLUBIGINT);
14086             }
14087 #else
14088 #ifdef __osf__
14089             *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
14090 #else
14091             *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
14092 #endif
14093             if (endp && endp == *data) {
14094                 *lenp = SQL_NULL_DATA;
14095             } else {
14096                 *lenp = sizeof (SQLUBIGINT);
14097             }
14098 #endif
14099             break;
14100         case SQL_C_SBIGINT:
14101 #if defined(_WIN32) || defined(_WIN64)
14102             if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
14103                 *lenp = SQL_NULL_DATA;
14104             } else {
14105                 *lenp = sizeof (SQLBIGINT);
14106             }
14107 #else
14108 #ifdef __osf__
14109             *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
14110 #else
14111             *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
14112 #endif
14113             if (endp && endp == *data) {
14114                 *lenp = SQL_NULL_DATA;
14115             } else {
14116                 *lenp = sizeof (SQLBIGINT);
14117             }
14118 #endif
14119             break;
14120 #endif
14121         case SQL_C_FLOAT:
14122             *((float *) val) = ln_strtod(*data, &endp);
14123             if (endp && endp == *data) {
14124                 *lenp = SQL_NULL_DATA;
14125             } else {
14126                 *lenp = sizeof (float);
14127             }
14128             break;
14129         case SQL_C_DOUBLE:
14130             *((double *) val) = ln_strtod(*data, &endp);
14131             if (endp && endp == *data) {
14132                 *lenp = SQL_NULL_DATA;
14133             } else {
14134                 *lenp = sizeof (double);
14135             }
14136             break;
14137         case SQL_C_BINARY: {
14138             int dlen, offs = 0;
14139             char *bin;
14140 
14141             if (valnull) {
14142                 freep(&s->bincache);
14143                 s->binlen = 0;
14144                 goto doCHAR;
14145             }
14146             if (*data == s->bincell) {
14147                 if (s->bincache) {
14148                     bin = s->bincache;
14149                     dlen = s->binlen;
14150                 } else {
14151                     goto doCHAR;
14152                 }
14153             } else {
14154                 char *dp;
14155                 int i;
14156 
14157                 freep(&s->bincache);
14158                 dp = *data;
14159                 dlen = strlen(dp);
14160                 s->bincell = dp;
14161                 s->binlen = 0;
14162                 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
14163                     dp[dlen - 1] != '\'') {
14164                     goto doCHAR;
14165                 }
14166                 dlen -= 2;
14167                 dp += 2;
14168                 dlen = dlen / 2;
14169                 s->bincache = bin = xmalloc(dlen + 1);
14170                 if (!bin) {
14171                     return nomem(s);
14172                 }
14173                 s->binlen = dlen;
14174                 memset(bin, 0, dlen);
14175                 bin[dlen] = '\0';       /* terminator, just in case */
14176                 for (i = 0; i < dlen; i++) {
14177                     char *x;
14178                     int v;
14179 
14180                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14181                         goto converr;
14182                     }
14183                     v = x - xdigits;
14184                     bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
14185                     ++dp;
14186                     if (!*dp || !(x = strchr(xdigits, *dp))) {
14187 converr:
14188                         freep(&s->bincache);
14189                         s->binlen = 0;
14190                         setstat(s, -1, "conversion error",
14191                                 (*s->ov3) ? "HY000" : "S1000");
14192                         return SQL_ERROR;
14193                     }
14194                     v = x - xdigits;
14195                     bin[i] |= (v >= 16) ? (v - 6) : v;
14196                     ++dp;
14197                 }
14198                 bin = s->bincache;
14199             }
14200             if (partial && len && s->bindcols) {
14201                 if (s->bindcols[col].offs >= dlen) {
14202                     *lenp = 0;
14203                     if (!dlen && s->bindcols[col].offs == dlen) {
14204                         s->bindcols[col].offs = 1;
14205                         sret = SQL_SUCCESS;
14206                         goto done;
14207                     }
14208                     s->bindcols[col].offs = 0;
14209                     sret = SQL_NO_DATA;
14210                     goto done;
14211                 }
14212                 offs = s->bindcols[col].offs;
14213                 dlen -= offs;
14214             }
14215             if (val && len) {
14216                 memcpy(val, bin + offs, min(len, dlen));
14217             }
14218             if (len < 1) {
14219                 *lenp = dlen;
14220             } else {
14221                 *lenp = min(len, dlen);
14222                 if (*lenp == len && *lenp != dlen) {
14223                     *lenp = SQL_NO_TOTAL;
14224                 }
14225             }
14226             if (partial && len && s->bindcols) {
14227                 if (*lenp == SQL_NO_TOTAL) {
14228                     *lenp = dlen;
14229                     s->bindcols[col].offs += len;
14230                     setstat(s, -1, "data right truncated", "01004");
14231                     if (s->bindcols[col].lenp) {
14232                         *s->bindcols[col].lenp = dlen;
14233                     }
14234                     sret = SQL_SUCCESS_WITH_INFO;
14235                     goto done;
14236                 }
14237                 s->bindcols[col].offs += *lenp;
14238             }
14239             if (*lenp == SQL_NO_TOTAL) {
14240                 *lenp = dlen;
14241                 setstat(s, -1, "data right truncated", "01004");
14242                 sret = SQL_SUCCESS_WITH_INFO;
14243                 goto done;
14244             }
14245             break;
14246         }
14247         doCHAR:
14248 #ifdef WCHARSUPPORT
14249         case SQL_C_WCHAR:
14250 #endif
14251         case SQL_C_CHAR: {
14252             int doz, zlen = len - 1;
14253             int dlen = strlen(*data);
14254             int offs = 0;
14255 #ifdef WCHARSUPPORT
14256             SQLWCHAR *ucdata = NULL;
14257             SQLCHAR *cdata = (SQLCHAR *) *data;
14258 #endif
14259 
14260 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14261             /* MS Access hack part 2 (reserved error -7748) */
14262             if (!valnull &&
14263                 (s->cols == statSpec2P || s->cols == statSpec3P) &&
14264                 type == SQL_C_WCHAR) {
14265                 if (len > 0 && len <= sizeof (SQLWCHAR)) {
14266                     ((char *) val)[0] = data[0][0];
14267                     memset((char *) val + 1, 0, len - 1);
14268                     *lenp = 1;
14269                     sret = SQL_SUCCESS;
14270                     goto done;
14271                 }
14272             }
14273 #endif
14274 
14275 #ifdef WCHARSUPPORT
14276             switch (type) {
14277             case SQL_C_CHAR:
14278                 doz = 1;
14279                 break;
14280             case SQL_C_WCHAR:
14281                 doz = sizeof (SQLWCHAR);
14282                 break;
14283             default:
14284                 doz = 0;
14285                 break;
14286             }
14287             if (type == SQL_C_WCHAR) {
14288                 ucdata = uc_from_utf(cdata, dlen);
14289                 if (!ucdata) {
14290                     return nomem(s);
14291                 }
14292                 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
14293             }
14294 #if defined(_WIN32) || defined(_WIN64)
14295             else if (*s->oemcp && type == SQL_C_CHAR) {
14296                 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
14297                 if (!ucdata) {
14298                     return nomem(s);
14299                 }
14300                 cdata = (SQLCHAR *) ucdata;
14301                 dlen = strlen((char *) cdata);
14302             }
14303 #endif
14304 #else
14305             doz = (type == SQL_C_CHAR) ? 1 : 0;
14306 #endif
14307             if (partial && len && s->bindcols) {
14308                 if (s->bindcols[col].offs >= dlen) {
14309 #ifdef WCHARSUPPORT
14310                     uc_free(ucdata);
14311 #endif
14312                     *lenp = 0;
14313                     if (doz && val) {
14314 #ifdef WCHARSUPPORT
14315                         if (type == SQL_C_WCHAR) {
14316                             ((SQLWCHAR *) val)[0] = 0;
14317                         } else {
14318                             ((char *) val)[0] = '\0';
14319                         }
14320 #else
14321                         ((char *) val)[0] = '\0';
14322 #endif
14323                     }
14324                     if (!dlen && s->bindcols[col].offs == dlen) {
14325                         s->bindcols[col].offs = 1;
14326                         sret = SQL_SUCCESS;
14327                         goto done;
14328                     }
14329                     s->bindcols[col].offs = 0;
14330                     sret = SQL_NO_DATA;
14331                     goto done;
14332                 }
14333                 offs = s->bindcols[col].offs;
14334                 dlen -= offs;
14335             }
14336             if (val && !valnull && len) {
14337 #ifdef WCHARSUPPORT
14338                 if (type == SQL_C_WCHAR) {
14339                     uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
14340                                (len - doz) / sizeof (SQLWCHAR));
14341                 } else {
14342                     strncpy(val, (char *) cdata + offs, len - doz);
14343                 }
14344 #else
14345                 strncpy(val, *data + offs, len - doz);
14346 #endif
14347             }
14348             if (valnull || len < 1) {
14349                 *lenp = dlen;
14350             } else {
14351                 *lenp = min(len - doz, dlen);
14352                 if (*lenp == len - doz && *lenp != dlen) {
14353                     *lenp = SQL_NO_TOTAL;
14354                 } else if (*lenp < zlen) {
14355                     zlen = *lenp;
14356                 }
14357             }
14358             if (len && !valnull && doz) {
14359 #ifdef WCHARSUPPORT
14360                 if (type == SQL_C_WCHAR) {
14361                     ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
14362                 } else {
14363                     ((char *) val)[zlen] = '\0';
14364                 }
14365 #else
14366                 ((char *) val)[zlen] = '\0';
14367 #endif
14368             }
14369 #ifdef WCHARSUPPORT
14370             uc_free(ucdata);
14371 #endif
14372             if (partial && len && s->bindcols) {
14373                 if (*lenp == SQL_NO_TOTAL) {
14374                     *lenp = dlen;
14375                     s->bindcols[col].offs += len - doz;
14376                     setstat(s, -1, "data right truncated", "01004");
14377                     if (s->bindcols[col].lenp) {
14378                         *s->bindcols[col].lenp = dlen;
14379                     }
14380                     sret = SQL_SUCCESS_WITH_INFO;
14381                     goto done;
14382                 }
14383                 s->bindcols[col].offs += *lenp;
14384             }
14385             if (*lenp == SQL_NO_TOTAL) {
14386                 *lenp = dlen;
14387                 setstat(s, -1, "data right truncated", "01004");
14388                 sret = SQL_SUCCESS_WITH_INFO;
14389                 goto done;
14390             }
14391             break;
14392         }
14393 #ifdef SQL_C_TYPE_DATE
14394         case SQL_C_TYPE_DATE:
14395 #endif
14396         case SQL_C_DATE:
14397             if (str2date(*s->jdconv, *data, (DATE_STRUCT *) val) < 0) {
14398                 *lenp = SQL_NULL_DATA;
14399             } else {
14400                 *lenp = sizeof (DATE_STRUCT);
14401             }
14402             break;
14403 #ifdef SQL_C_TYPE_TIME
14404         case SQL_C_TYPE_TIME:
14405 #endif
14406         case SQL_C_TIME:
14407             if (str2time(*s->jdconv, *data, (TIME_STRUCT *) val) < 0) {
14408                 *lenp = SQL_NULL_DATA;
14409             } else {
14410                 *lenp = sizeof (TIME_STRUCT);
14411             }
14412             break;
14413 #ifdef SQL_C_TYPE_TIMESTAMP
14414         case SQL_C_TYPE_TIMESTAMP:
14415 #endif
14416         case SQL_C_TIMESTAMP:
14417             if (str2timestamp(*s->jdconv, *data,
14418                               (TIMESTAMP_STRUCT *) val) < 0) {
14419                 *lenp = SQL_NULL_DATA;
14420             } else {
14421                 *lenp = sizeof (TIMESTAMP_STRUCT);
14422             }
14423             switch (s->cols[col].prec) {
14424             case 0:
14425                 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
14426                 break;
14427             case 1:
14428                 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
14429                 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
14430                 break;
14431             case 2:
14432                 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
14433                 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
14434                 break;
14435             }
14436             break;
14437         default:
14438             return SQL_ERROR;
14439         }
14440     }
14441     sret = SQL_SUCCESS;
14442 done:
14443     if (ilenp) {
14444         *ilenp = *lenp;
14445     }
14446     return sret;
14447 }
14448 
14460 static SQLRETURN
14461 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14462            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14463 {
14464     STMT *s;
14465     int sz = 0;
14466 
14467     if (stmt == SQL_NULL_HSTMT) {
14468         return SQL_INVALID_HANDLE;
14469     }
14470     s = (STMT *) stmt;
14471     if (col < 1) {
14472         if (col == 0 && s->bkmrk == SQL_UB_ON &&
14473             type == SQL_C_BOOKMARK) {
14474             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14475             s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
14476             s->bkmrkcol.lenp = val ? lenp : 0;
14477             s->bkmrkcol.valp = val;
14478             s->bkmrkcol.offs = 0;
14479             if (val && lenp) {
14480                 *lenp = 0;
14481             }
14482             return SQL_SUCCESS;
14483         } else if (col == 0 && s->bkmrk == SQL_UB_VARIABLE &&
14484                    type == SQL_C_VARBOOKMARK &&
14485                    max >= sizeof (sqlite_int64)) {
14486             s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14487             s->bkmrkcol.max = val ? max : 0;
14488             s->bkmrkcol.lenp = val ? lenp : 0;
14489             s->bkmrkcol.valp = val;
14490             s->bkmrkcol.offs = 0;
14491             if (val && lenp) {
14492                 *lenp = 0;
14493             }
14494             return SQL_SUCCESS;
14495         }
14496         setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14497         return SQL_ERROR;
14498     }
14499     if (mkbindcols(s, col) != SQL_SUCCESS) {
14500         return SQL_ERROR;
14501     }
14502     --col;
14503     if (type == SQL_C_DEFAULT) {
14504         type = mapdeftype(type, s->cols[col].type, 0,
14505                           s->nowchar[0] || s->nowchar[1]);
14506     }
14507     switch (type) {
14508     case SQL_C_LONG:
14509     case SQL_C_ULONG:
14510     case SQL_C_SLONG:
14511         sz = sizeof (SQLINTEGER);
14512         break;
14513     case SQL_C_TINYINT:
14514     case SQL_C_UTINYINT:
14515     case SQL_C_STINYINT:
14516         sz = sizeof (SQLCHAR);
14517         break;
14518     case SQL_C_SHORT:
14519     case SQL_C_USHORT:
14520     case SQL_C_SSHORT:
14521         sz = sizeof (SQLSMALLINT);
14522         break;
14523     case SQL_C_FLOAT:
14524         sz = sizeof (SQLFLOAT);
14525         break;
14526     case SQL_C_DOUBLE:
14527         sz = sizeof (SQLDOUBLE);
14528         break;
14529     case SQL_C_TIMESTAMP:
14530         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14531         break;
14532     case SQL_C_TIME:
14533         sz = sizeof (SQL_TIME_STRUCT);
14534         break;
14535     case SQL_C_DATE:
14536         sz = sizeof (SQL_DATE_STRUCT);
14537         break;
14538     case SQL_C_CHAR:
14539         break;
14540 #ifdef WCHARSUPPORT
14541     case SQL_C_WCHAR:
14542         break;
14543 #endif
14544 #ifdef SQL_C_TYPE_DATE
14545     case SQL_C_TYPE_DATE:
14546         sz = sizeof (SQL_DATE_STRUCT);
14547         break;
14548 #endif
14549 #ifdef SQL_C_TYPE_TIME
14550     case SQL_C_TYPE_TIME:
14551         sz = sizeof (SQL_TIME_STRUCT);
14552         break;
14553 #endif
14554 #ifdef SQL_C_TYPE_TIMESTAMP
14555     case SQL_C_TYPE_TIMESTAMP:
14556         sz = sizeof (SQL_TIMESTAMP_STRUCT);
14557         break;
14558 #endif
14559 #ifdef SQL_BIT
14560     case SQL_C_BIT:
14561         sz = sizeof (SQLCHAR);
14562         break;
14563 #endif
14564     case SQL_C_BINARY:
14565         break;
14566 #ifdef SQL_BIGINT
14567     case SQL_C_SBIGINT:
14568     case SQL_C_UBIGINT:
14569         sz = sizeof (SQLBIGINT);
14570         break;
14571 #endif
14572     default:
14573         if (val == NULL) {
14574             /* fall through, unbinding column */
14575             break;
14576         }
14577         setstat(s, -1, "invalid type %d", "HY003", type);
14578         return SQL_ERROR;
14579     }
14580     if (val == NULL) {
14581         /* unbind column */
14582         s->bindcols[col].type = SQL_UNKNOWN_TYPE;
14583         s->bindcols[col].max = 0;
14584         s->bindcols[col].lenp = NULL;
14585         s->bindcols[col].valp = NULL;
14586         s->bindcols[col].offs = 0;
14587     } else {
14588         if (sz == 0 && max < 0) {
14589             setstat(s, -1, "invalid length", "HY090");
14590             return SQL_ERROR;
14591         }
14592         s->bindcols[col].type = type;
14593         s->bindcols[col].max = (sz == 0) ? max : sz;
14594         s->bindcols[col].lenp = lenp;
14595         s->bindcols[col].valp = val;
14596         s->bindcols[col].offs = 0;
14597         if (lenp) {
14598             *lenp = 0;
14599         }
14600     }
14601     return SQL_SUCCESS;
14602 }
14603 
14615 SQLRETURN SQL_API
14616 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14617            SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14618 {
14619     SQLRETURN ret;
14620 
14621     HSTMT_LOCK(stmt);
14622     ret = drvbindcol(stmt, col, type, val, max, lenp);
14623     HSTMT_UNLOCK(stmt);
14624     return ret;
14625 }
14626 
14631 static COL tableSpec2[] = {
14632     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14633     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14634     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14635     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14636     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14637 };
14638 
14639 static COL tableSpec3[] = {
14640     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14641     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14642     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14643     { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14644     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14645 };
14646 
14661 static SQLRETURN
14662 drvtables(SQLHSTMT stmt,
14663           SQLCHAR *cat, SQLSMALLINT catLen,
14664           SQLCHAR *schema, SQLSMALLINT schemaLen,
14665           SQLCHAR *table, SQLSMALLINT tableLen,
14666           SQLCHAR *type, SQLSMALLINT typeLen)
14667 {
14668     SQLRETURN ret;
14669     STMT *s;
14670     DBC *d;
14671     int ncols, asize, rc, size, npatt;
14672     char *errp = NULL, *sql, tname[512];
14673     char *where = "(type = 'table' or type = 'view')";
14674 
14675     ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
14676                       tableSpec3, array_size(tableSpec3), &asize);
14677     if (ret != SQL_SUCCESS) {
14678         return ret;
14679     }
14680     s = (STMT *) stmt;
14681     d = (DBC *) s->dbc;
14682     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
14683         int size = 3 * asize;
14684 
14685         s->rows = xmalloc(size * sizeof (char *));
14686         if (!s->rows) {
14687             s->nrows = 0;
14688             return nomem(s);
14689         }
14690         memset(s->rows, 0, sizeof (char *) * size);
14691         s->ncols = asize;
14692         s->rows[s->ncols + 0] = "";
14693         s->rows[s->ncols + 1] = "";
14694         s->rows[s->ncols + 2] = "";
14695         s->rows[s->ncols + 3] = "TABLE";
14696         s->rows[s->ncols + 5] = "";
14697         s->rows[s->ncols + 6] = "";
14698         s->rows[s->ncols + 7] = "";
14699         s->rows[s->ncols + 8] = "VIEW";
14700 #ifdef MEMORY_DEBUG
14701         s->rowfree = xfree__;
14702 #else
14703         s->rowfree = sqlite3_free;
14704 #endif
14705         s->nrows = 2;
14706         s->rowp = s->rowprs = -1;
14707         return SQL_SUCCESS;
14708     }
14709     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
14710         table = NULL;
14711         goto doit;
14712     }
14713     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
14714         schema[0] == '%') {
14715         if ((!cat || catLen == 0 || !cat[0]) &&
14716             (!table || tableLen == 0 || !table[0])) {
14717             table = NULL;
14718             goto doit;
14719         }
14720     }
14721     if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
14722         char tmp[256], *t;
14723         int with_view = 0, with_table = 0;
14724 
14725         if (typeLen == SQL_NTS) {
14726             strncpy(tmp, (char *) type, sizeof (tmp));
14727             tmp[sizeof (tmp) - 1] = '\0';
14728         } else {
14729             int len = min(sizeof (tmp) - 1, typeLen);
14730 
14731             strncpy(tmp, (char *) type, len);
14732             tmp[len] = '\0';
14733         }
14734         t = tmp;
14735         while (*t) {
14736             *t = TOLOWER(*t);
14737             t++;
14738         }
14739         t = tmp;
14740         unescpat(t);
14741         while (t) {
14742             if (t[0] == '\'') {
14743                 ++t;
14744             }
14745             if (strncmp(t, "table", 5) == 0) {
14746                 with_table++;
14747             } else if (strncmp(t, "view", 4) == 0) {
14748                 with_view++;
14749             }
14750             t = strchr(t, ',');
14751             if (t) {
14752                 ++t;
14753             }
14754         }
14755         if (with_view && with_table) {
14756             /* where is already preset */
14757         } else if (with_view && !with_table) {
14758             where = "type = 'view'";
14759         } else if (!with_view && with_table) {
14760             where = "type = 'table'";
14761         } else {
14762             return SQL_SUCCESS;
14763         }
14764     }
14765 doit:
14766     if (!table) {
14767         size = 1;
14768         tname[0] = '%';
14769     } else {
14770         if (tableLen == SQL_NTS) {
14771             size = sizeof (tname) - 1;
14772         } else {
14773             size = min(sizeof (tname) - 1, tableLen);
14774         }
14775         strncpy(tname, (char *) table, size);
14776     }
14777     tname[size] = '\0';
14778     npatt = unescpat(tname);
14779 #if defined(_WIN32) || defined(_WIN64)
14780     if (npatt) {
14781         sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14782                               "%s as 'TABLE_SCHEM', "
14783                               "tbl_name as 'TABLE_NAME', "
14784                               "upper(type) as 'TABLE_TYPE', "
14785                               "NULL as 'REMARKS' "
14786                               "from sqlite_master where %s "
14787                               "and tbl_name like %Q",
14788                               d->xcelqrx ? "'main'" : "NULL",
14789                               d->xcelqrx ? "''" : "NULL",
14790                               where, tname);
14791     } else {
14792         sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14793                               "%s as 'TABLE_SCHEM', "
14794                               "tbl_name as 'TABLE_NAME', "
14795                               "upper(type) as 'TABLE_TYPE', "
14796                               "NULL as 'REMARKS' "
14797                               "from sqlite_master where %s "
14798                               "and lower(tbl_name) = lower(%Q)",
14799                               d->xcelqrx ? "'main'" : "NULL",
14800                               d->xcelqrx ? "''" : "NULL",
14801                               where, tname);
14802     }
14803 #else
14804     if (npatt) {
14805         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14806                               "NULL as 'TABLE_OWNER', "
14807                               "tbl_name as 'TABLE_NAME', "
14808                               "upper(type) as 'TABLE_TYPE', "
14809                               "NULL as 'REMARKS' "
14810                               "from sqlite_master where %s "
14811                               "and tbl_name like %Q",
14812                               where, tname);
14813     } else {
14814         sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14815                               "NULL as 'TABLE_OWNER', "
14816                               "tbl_name as 'TABLE_NAME', "
14817                               "upper(type) as 'TABLE_TYPE', "
14818                               "NULL as 'REMARKS' "
14819                               "from sqlite_master where %s "
14820                               "and lower(tbl_name) = lower(%Q)",
14821                               where, tname);
14822     }
14823 #endif
14824     if (!sql) {
14825         return nomem(s);
14826     }
14827     ret = starttran(s);
14828     if (ret != SQL_SUCCESS) {
14829         sqlite3_free(sql);
14830         return ret;
14831     }
14832     dbtraceapi(d, "sqlite3_get_table", sql);
14833     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
14834     sqlite3_free(sql);
14835     if (rc == SQLITE_OK) {
14836         if (ncols != s->ncols) {
14837             freeresult(s, 0);
14838             s->nrows = 0;
14839         } else {
14840             s->rowfree = sqlite3_free_table;
14841         }
14842     } else {
14843         s->nrows = 0;
14844         s->rows = NULL;
14845         s->rowfree = NULL;
14846     }
14847     if (errp) {
14848         sqlite3_free(errp);
14849         errp = NULL;
14850     }
14851     s->rowp = s->rowprs = -1;
14852     return SQL_SUCCESS;
14853 }
14854 
14855 #ifndef WINTERFACE
14856 
14870 SQLRETURN SQL_API
14871 SQLTables(SQLHSTMT stmt,
14872           SQLCHAR *cat, SQLSMALLINT catLen,
14873           SQLCHAR *schema, SQLSMALLINT schemaLen,
14874           SQLCHAR *table, SQLSMALLINT tableLen,
14875           SQLCHAR *type, SQLSMALLINT typeLen)
14876 {
14877 #if defined(_WIN32) || defined(_WIN64)
14878     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14879 #endif
14880     SQLRETURN ret;
14881 
14882     HSTMT_LOCK(stmt);
14883 #if defined(_WIN32) || defined(_WIN64)
14884     if (!((STMT *) stmt)->oemcp[0]) {
14885         ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14886                         table, tableLen, type, typeLen);
14887         goto done2;
14888     }
14889     if (cat) {
14890         c = wmb_to_utf_c((char *) cat, catLen);
14891         if (!c) {
14892             ret = nomem((STMT *) stmt);
14893             goto done;
14894         }
14895     }
14896     if (schema) {
14897         s = wmb_to_utf_c((char *) schema, schemaLen);
14898         if (!s) {
14899             ret = nomem((STMT *) stmt);
14900             goto done;
14901         }
14902     }
14903     if (table) {
14904         t = wmb_to_utf_c((char *) table, tableLen);
14905         if (!t) {
14906             ret = nomem((STMT *) stmt);
14907             goto done;
14908         }
14909     }
14910     if (type) {
14911         y = wmb_to_utf_c((char *) type, typeLen);
14912         if (!y) {
14913             ret = nomem((STMT *) stmt);
14914             goto done;
14915         }
14916     }
14917     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14918                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14919 #else
14920     ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14921                     table, tableLen, type, typeLen);
14922 #endif
14923 #if defined(_WIN32) || defined(_WIN64)
14924 done:
14925     uc_free(y);
14926     uc_free(t);
14927     uc_free(s);
14928     uc_free(c);
14929 done2:
14930     ;
14931 #endif
14932     HSTMT_UNLOCK(stmt);
14933     return ret;
14934 }
14935 #endif
14936 
14937 #ifdef WINTERFACE
14938 
14952 SQLRETURN SQL_API
14953 SQLTablesW(SQLHSTMT stmt,
14954            SQLWCHAR *cat, SQLSMALLINT catLen,
14955            SQLWCHAR *schema, SQLSMALLINT schemaLen,
14956            SQLWCHAR *table, SQLSMALLINT tableLen,
14957            SQLWCHAR *type, SQLSMALLINT typeLen)
14958 {
14959     char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14960     SQLRETURN ret;
14961 
14962     HSTMT_LOCK(stmt);
14963     if (cat) {
14964         c = uc_to_utf_c(cat, catLen);
14965         if (!c) {
14966             ret = nomem((STMT *) stmt);
14967             goto done;
14968         }
14969     }
14970     if (schema) {
14971         s = uc_to_utf_c(schema, schemaLen);
14972         if (!s) {
14973             ret = nomem((STMT *) stmt);
14974             goto done;
14975         }
14976     }
14977     if (table) {
14978         t = uc_to_utf_c(table, tableLen);
14979         if (!t) {
14980             ret = nomem((STMT *) stmt);
14981             goto done;
14982         }
14983     }
14984     if (type) {
14985         y = uc_to_utf_c(type, typeLen);
14986         if (!y) {
14987             ret = nomem((STMT *) stmt);
14988             goto done;
14989         }
14990     }
14991     ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14992                     (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14993 done:
14994     uc_free(y);
14995     uc_free(t);
14996     uc_free(s);
14997     uc_free(c);
14998     HSTMT_UNLOCK(stmt);
14999     return ret;
15000 }
15001 #endif
15002 
15007 static COL colSpec2[] = {
15008     { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
15009     { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
15010     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15011     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15012     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15013     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15014     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
15015     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
15016     { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
15017     { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
15018     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15019     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15020     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15021     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15022     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15023     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15024     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15025     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15026 };
15027 
15028 static COL colSpec3[] = {
15029     { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
15030     { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
15031     { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15032     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15033     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15034     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15035     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
15036     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
15037     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
15038     { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
15039     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15040     { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15041     { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15042     { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15043     { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15044     { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15045     { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15046     { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15047 };
15048 
15063 static SQLRETURN
15064 drvcolumns(SQLHSTMT stmt,
15065            SQLCHAR *cat, SQLSMALLINT catLen,
15066            SQLCHAR *schema, SQLSMALLINT schemaLen,
15067            SQLCHAR *table, SQLSMALLINT tableLen,
15068            SQLCHAR *col, SQLSMALLINT colLen)
15069 {
15070     SQLRETURN sret;
15071     STMT *s;
15072     DBC *d;
15073     int ret, nrows, ncols, asize, i, k, roffs, namec;
15074     int tnrows, tncols, npatt;
15075     PTRDIFF_T size;
15076     char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
15077 
15078     sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
15079                        colSpec3, array_size(colSpec3), &asize);
15080     if (sret != SQL_SUCCESS) {
15081         return sret;
15082     }
15083     s = (STMT *) stmt;
15084     d = (DBC *) s->dbc;
15085     if (!table) {
15086         size = 1;
15087         tname[0] = '%';
15088     } else {
15089         if (tableLen == SQL_NTS) {
15090             size = sizeof (tname) - 1;
15091         } else {
15092             size = min(sizeof (tname) - 1, tableLen);
15093         }
15094         strncpy(tname, (char *) table, size);
15095     }
15096     tname[size] = '\0';
15097     npatt = unescpat(tname);
15098     size = 0;
15099     if (col) {
15100         if (colLen == SQL_NTS) {
15101             size = sizeof (cname) - 1;
15102         } else {
15103             size = min(sizeof (cname) - 1, colLen);
15104         }
15105         strncpy(cname, (char *) col, size);
15106     }
15107     cname[size] = '\0';
15108     if (!strcmp(cname, "%")) {
15109         cname[0] = '\0';
15110     }
15111     if (npatt) {
15112         sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15113                               "(type = 'table' or type = 'view') "
15114                               "and tbl_name like %Q", tname);
15115     } else {
15116         sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15117                               "(type = 'table' or type = 'view') "
15118                               "and lower(tbl_name) = lower(%Q)", tname);
15119     }
15120     if (!sql) {
15121         return nomem(s);
15122     }
15123     sret = starttran(s);
15124     if (sret != SQL_SUCCESS) {
15125         sqlite3_free(sql);
15126         return sret;
15127     }
15128     dbtraceapi(d, "sqlite3_get_table", sql);
15129     ret = sqlite3_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
15130     sqlite3_free(sql);
15131     if (ret != SQLITE_OK) {
15132         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15133                 errp ? errp : "unknown error", ret);
15134         if (errp) {
15135             sqlite3_free(errp);
15136             errp = NULL;
15137         }
15138         return SQL_ERROR;
15139     }
15140     if (errp) {
15141         sqlite3_free(errp);
15142         errp = NULL;
15143     }
15144     /* pass 1: compute number of rows of result set */
15145     if (tncols * tnrows <= 0) {
15146         sqlite3_free_table(trows);
15147         return SQL_SUCCESS;
15148     }
15149     size = 0;
15150     for (i = 1; i <= tnrows; i++) {
15151         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15152         if (!sql) {
15153             sqlite3_free_table(trows);
15154             return nomem(s);
15155         }
15156         dbtraceapi(d, "sqlite3_get_table", sql);
15157         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15158         sqlite3_free(sql);
15159         if (ret != SQLITE_OK) {
15160             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15161                     errp ? errp : "unknown error", ret);
15162             if (errp) {
15163                 sqlite3_free(errp);
15164                 errp = NULL;
15165             }
15166             sqlite3_free_table(trows);
15167             return SQL_ERROR;
15168         }
15169         if (errp) {
15170             sqlite3_free(errp);
15171             errp = NULL;
15172         }
15173         if (ncols * nrows > 0) {
15174             namec = -1;
15175             for (k = 0; k < ncols; k++) {
15176                 if (strcmp(rowp[k], "name") == 0) {
15177                     namec = k;
15178                     break;
15179                 }
15180             }
15181             if (cname[0]) {
15182                 if (namec >= 0) {
15183                     for (k = 1; k <= nrows; k++) {
15184                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15185                             size++;
15186                         }
15187                     }
15188                 }
15189             } else {
15190                 size += nrows;
15191             }
15192         }
15193         sqlite3_free_table(rowp);
15194     }
15195     /* pass 2: fill result set */
15196     if (size <= 0) {
15197         sqlite3_free_table(trows);
15198         return SQL_SUCCESS;
15199     }
15200     s->nrows = size;
15201     size = (size + 1) * asize;
15202     s->rows = xmalloc((size + 1) * sizeof (char *));
15203     if (!s->rows) {
15204         s->nrows = 0;
15205         sqlite3_free_table(trows);
15206         return nomem(s);
15207     }
15208     s->rows[0] = (char *) size;
15209     s->rows += 1;
15210     memset(s->rows, 0, sizeof (char *) * size);
15211     s->rowfree = freerows;
15212     roffs = 1;
15213     for (i = 1; i <= tnrows; i++) {
15214         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15215         if (!sql) {
15216             sqlite3_free_table(trows);
15217             return nomem(s);
15218         }
15219         dbtraceapi(d, "sqlite3_get_table", sql);
15220         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15221         sqlite3_free(sql);
15222         if (ret != SQLITE_OK) {
15223             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15224                     errp ? errp : "unknown error", ret);
15225             if (errp) {
15226                 sqlite3_free(errp);
15227                 errp = NULL;
15228             }
15229             sqlite3_free_table(trows);
15230             return SQL_ERROR;
15231         }
15232         if (errp) {
15233             sqlite3_free(errp);
15234             errp = NULL;
15235         }
15236         if (ncols * nrows > 0) {
15237             int m, mr, nr = nrows;
15238 
15239             namec = -1;
15240             for (k = 0; k < ncols; k++) {
15241                 if (strcmp(rowp[k], "name") == 0) {
15242                     namec = k;
15243                     break;
15244                 }
15245             }
15246             if (cname[0]) {
15247                 nr = 0;
15248                 if (namec >= 0) {
15249                     for (k = 1; k <= nrows; k++) {
15250                         if (namematch(rowp[k * ncols + namec], cname, 1)) {
15251                             nr++;
15252                         }
15253                     }
15254                 }
15255             }
15256