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 #endif
00023 
00024 #include "sqlite3odbc.h"
00025 
00026 #ifdef SQLITE_DYNLOAD
00027 
00028 #undef MEMORY_DEBUG
00029 
00030 #if defined(_WIN32) || defined(_WIN64)
00031 static void dls_init(void);
00032 static void dls_fini(void);
00033 #else
00034 void dls_init(void);
00035 void dls_fini(void);
00036 #endif
00037 
00038 static struct dl_sqlite3_funcs {
00039     void (*activate_see)(const char *p0);
00040     int (*bind_blob)(sqlite3_stmt *p0, int p1, const void *p2, int p3,
00041                      void (*p4)(void *));
00042     int (*bind_double)(sqlite3_stmt *p0, int p1, double p2);
00043     int (*bind_int)(sqlite3_stmt *p0, int p1, int p2);
00044     int (*bind_int64)(sqlite3_stmt *p0, int p1, sqlite3_int64 p2);
00045     int (*bind_null)(sqlite3_stmt *p0, int p1);
00046     int (*bind_parameter_count)(sqlite3_stmt *p0);
00047     int (*bind_text)(sqlite3_stmt *p0, int p1, const char *p2, int p3,
00048                      void (*p4)(void *));
00049     int (*busy_handler)(sqlite3 *p0, int (*p2)(void *, int), void *p3);
00050     int (*changes)(sqlite3 *p0);
00051     int (*close)(sqlite3 *p0);
00052     const void * (*column_blob)(sqlite3_stmt *p0, int p1);
00053     int (*column_bytes)(sqlite3_stmt *p0, int p1);
00054     int (*column_count)(sqlite3_stmt *p0);
00055     const char * (*column_database_name)(sqlite3_stmt *p0, int p1);
00056     const char * (*column_decltype)(sqlite3_stmt *p0, int p1);
00057     const char * (*column_name)(sqlite3_stmt *p0, int p1);
00058     const char * (*column_origin_name)(sqlite3_stmt *p0, int p1);
00059     const char * (*column_table_name)(sqlite3_stmt *p0, int p1);
00060     const unsigned char * (*column_text)(sqlite3_stmt *p0, int p1);
00061     int (*column_type)(sqlite3_stmt *p0, int p1);
00062     int (*create_function)(sqlite3 *p0, const char *p1, int p2, int p3,
00063                            void *p4,
00064                            void (*p5)(sqlite3_context *, int, sqlite3_value **),
00065                            void (*p6)(sqlite3_context *, int, sqlite3_value **),
00066                            void (*p7)(sqlite3_context *));
00067     int (*enable_load_extension)(sqlite3 *p0, int p1);
00068     int (*errcode)(sqlite3 *p0);
00069     const char * (*errmsg)(sqlite3 *p0);
00070     int (*exec)(sqlite3 *p0, const char *p1,
00071                 int (*p2)(void *, int, char **, char **),
00072                 void *p3, char **p4);
00073     int (*finalize)(sqlite3_stmt *p0);
00074     void (*free)(void *p0);
00075     void (*free_table)(char **p0);
00076     int (*get_table)(sqlite3 *p0, const char *p1, char ***p2,
00077                      int *p3, int *p4, char **p5);
00078     void (*interrupt)(sqlite3 *p0);
00079     int (*key)(sqlite3 *p0, const void *p1, int p2);
00080     const char * (*libversion)(void);
00081     int (*load_extension)(sqlite3 *p0, const char *p1, const char *p2,
00082                           char **p3);
00083     void * (*malloc)(int p0);
00084     char * (*mprintf)(const char *p0, ...);
00085     int (*open)(const char *p0, sqlite3 **p1);
00086     int (*open16)(const void *p0, sqlite3 **p1);
00087     int (*open_v2)(const char *p0, sqlite3 **p1, int p2, const char *p3);
00088     int (*prepare)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
00089                    const char **p4);
00090     int (*prepare_v2)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
00091                       const char **p4);
00092     void * (*profile)(sqlite3 *p0,
00093                       void (*p1)(void *, const char *, sqlite3_uint64),
00094                       void *p2);
00095     void * (*realloc)(void *p0, int p1);
00096     int (*rekey)(sqlite3 *p0, const void *p1, int p2);
00097     int (*reset)(sqlite3_stmt *p0);
00098     void (*result_blob)(sqlite3_context *p0, const void *p1,
00099                         int p2, void (*p3)(void *));
00100     void (*result_error)(sqlite3_context *p0, const char *p1, int p2);
00101     void (*result_int)(sqlite3_context *p0, int p1);
00102     void (*result_null)(sqlite3_context *p0);
00103     int (*step)(sqlite3_stmt *p0);
00104     int (*xstrnicmp)(const char *p0, const char *p1, int p2);
00105     int (*table_column_metadata)(sqlite3 *p0, const char *p1,
00106                                  const char *p2, const char *p3,
00107                                  char const **p4, char const **p5,
00108                                  int *p6, int *p7, int *p8);
00109     void * (*trace)(sqlite3 *p0, void (*p1)(void *, const char *), void *p2);
00110     void * (*user_data)(sqlite3_context *p0);
00111     const void * (*value_blob)(sqlite3_value *p0);
00112     int (*value_bytes)(sqlite3_value *p0);
00113     const unsigned char * (*value_text)(sqlite3_value *p0);
00114     int (*value_type)(sqlite3_value *p0);
00115 } dls_funcs;
00116 
00117 #define sqlite3_activate_see          dls_funcs.activate_see
00118 #define sqlite3_bind_blob             dls_funcs.bind_blob
00119 #define sqlite3_bind_double           dls_funcs.bind_double
00120 #define sqlite3_bind_int              dls_funcs.bind_int
00121 #define sqlite3_bind_int64            dls_funcs.bind_int64
00122 #define sqlite3_bind_null             dls_funcs.bind_null
00123 #define sqlite3_bind_parameter_count  dls_funcs.bind_parameter_count
00124 #define sqlite3_bind_text             dls_funcs.bind_text
00125 #define sqlite3_busy_handler          dls_funcs.busy_handler
00126 #define sqlite3_changes               dls_funcs.changes
00127 #define sqlite3_close                 dls_funcs.close
00128 #define sqlite3_column_blob           dls_funcs.column_blob
00129 #define sqlite3_column_bytes          dls_funcs.column_bytes
00130 #define sqlite3_column_count          dls_funcs.column_count
00131 #define sqlite3_column_database_name  dls_funcs.column_database_name
00132 #define sqlite3_column_decltype       dls_funcs.column_decltype
00133 #define sqlite3_column_name           dls_funcs.column_name
00134 #define sqlite3_column_origin_name    dls_funcs.column_origin_name
00135 #define sqlite3_column_table_name     dls_funcs.column_table_name
00136 #define sqlite3_column_text           dls_funcs.column_text
00137 #define sqlite3_column_type           dls_funcs.column_type
00138 #define sqlite3_create_function       dls_funcs.create_function
00139 #define sqlite3_enable_load_extension dls_funcs.enable_load_extension
00140 #define sqlite3_errcode               dls_funcs.errcode
00141 #define sqlite3_errmsg                dls_funcs.errmsg
00142 #define sqlite3_exec                  dls_funcs.exec
00143 #define sqlite3_finalize              dls_funcs.finalize
00144 #define sqlite3_free                  dls_funcs.free
00145 #define sqlite3_free_table            dls_funcs.free_table
00146 #define sqlite3_get_table             dls_funcs.get_table
00147 #define sqlite3_interrupt             dls_funcs.interrupt
00148 #define sqlite3_key                   dls_funcs.key
00149 #define sqlite3_libversion            dls_funcs.libversion
00150 #define sqlite3_load_extension        dls_funcs.load_extension
00151 #define sqlite3_malloc                dls_funcs.malloc
00152 #define sqlite3_mprintf               dls_funcs.mprintf
00153 #define sqlite3_open                  dls_funcs.open
00154 #define sqlite3_open16                dls_funcs.open16
00155 #define sqlite3_open_v2               dls_funcs.open_v2
00156 #define sqlite3_prepare               dls_funcs.prepare
00157 #define sqlite3_prepare_v2            dls_funcs.prepare_v2
00158 #define sqlite3_profile               dls_funcs.profile
00159 #define sqlite3_realloc               dls_funcs.realloc
00160 #define sqlite3_rekey                 dls_funcs.rekey
00161 #define sqlite3_reset                 dls_funcs.reset
00162 #define sqlite3_result_blob           dls_funcs.result_blob
00163 #define sqlite3_result_error          dls_funcs.result_error
00164 #define sqlite3_result_int            dls_funcs.result_int
00165 #define sqlite3_result_null           dls_funcs.result_null
00166 #define sqlite3_step                  dls_funcs.step
00167 #define sqlite3_strnicmp              dls_funcs.xstrnicmp
00168 #define sqlite3_table_column_metadata dls_funcs.table_column_metadata
00169 #define sqlite3_trace                 dls_funcs.trace
00170 #define sqlite3_user_data             dls_funcs.user_data
00171 #define sqlite3_value_blob            dls_funcs.value_blob
00172 #define sqlite3_value_bytes           dls_funcs.value_bytes
00173 #define sqlite3_value_text            dls_funcs.value_text
00174 #define sqlite3_value_type            dls_funcs.value_type
00175 
00176 #endif
00177 
00178 #ifndef WITHOUT_WINTERFACE
00179 #define WINTERFACE
00180 #define WCHARSUPPORT
00181 #endif
00182 
00183 #if !defined(_WIN32) && !defined(_WIN64)
00184 #if !defined(WCHARSUPPORT) && defined(HAVE_SQLWCHAR) && (HAVE_SQLWCHAR)
00185 #define WCHARSUPPORT
00186 #endif
00187 #endif
00188 
00189 #if defined(WINTERFACE)
00190 #include <sqlucode.h>
00191 #endif
00192 
00193 #if defined(_WIN32) || defined(_WIN64)
00194 #include "resource3.h"
00195 #define ODBC_INI "ODBC.INI"
00196 #ifndef DRIVER_VER_INFO
00197 #define DRIVER_VER_INFO VERSION
00198 #endif
00199 #else
00200 #define ODBC_INI ".odbc.ini"
00201 #endif
00202 
00203 #ifndef DRIVER_VER_INFO
00204 #define DRIVER_VER_INFO "0.0"
00205 #endif
00206 
00207 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
00208 #ifdef _WIN64
00209 #define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
00210 #else
00211 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
00212 #endif
00213 #endif
00214 
00215 #ifndef SETSTMTOPTION_LAST_ARG_TYPE
00216 #define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
00217 #endif
00218 
00219 #undef min
00220 #define min(a, b) ((a) < (b) ? (a) : (b))
00221 #undef max
00222 #define max(a, b) ((a) < (b) ? (b) : (a))
00223 
00224 #ifndef PTRDIFF_T
00225 #define PTRDIFF_T int
00226 #endif
00227 
00228 #define array_size(x) (sizeof (x) / sizeof (x[0]))
00229 
00230 #define stringify1(s) #s
00231 #define stringify(s) stringify1(s)
00232 
00233 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
00234 
00235 /* Column types for static string column descriptions (SQLTables etc.) */
00236 
00237 #if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
00238 #define SCOL_VARCHAR SQL_WVARCHAR
00239 #define SCOL_CHAR SQL_WCHAR
00240 #else
00241 #define SCOL_VARCHAR SQL_VARCHAR
00242 #define SCOL_CHAR SQL_CHAR
00243 #endif
00244 
00245 #define ENV_MAGIC  0x53544145
00246 #define DBC_MAGIC  0x53544144
00247 #define DEAD_MAGIC 0xdeadbeef
00248 
00249 static const char *xdigits = "0123456789ABCDEFabcdef";
00250 
00251 #ifdef MEMORY_DEBUG
00252 
00253 static void *
00254 xmalloc_(int n, char *file, int line)
00255 {
00256     int nn = n + 4 * sizeof (long);
00257     long *p;
00258 
00259     p = malloc(nn);
00260     if (!p) {
00261 #if (MEMORY_DEBUG > 1)
00262         fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
00263 #endif
00264         return NULL;
00265     }
00266     p[0] = 0xdead1234;
00267     nn = nn / sizeof (long) - 1;
00268     p[1] = n;
00269     p[nn] = 0xdead5678;
00270 #if (MEMORY_DEBUG > 1)
00271     fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
00272 #endif
00273     return (void *) &p[2];
00274 }
00275 
00276 static void *
00277 xrealloc_(void *old, int n, char *file, int line)
00278 {
00279     int nn = n + 4 * sizeof (long), nnn;
00280     long *p, *pp;
00281 
00282     if (n == 0 || !old) {
00283         return xmalloc_(n, file, line);
00284     }
00285     p = &((long *) old)[-2];
00286     if (p[0] != 0xdead1234) {
00287         fprintf(stderr, "*** low end corruption @ %p\n", old);
00288         abort();
00289     }
00290     nnn = p[1] + 4 * sizeof (long);
00291     nnn = nnn / sizeof (long) - 1;
00292     if (p[nnn] != 0xdead5678) {
00293         fprintf(stderr, "*** high end corruption @ %p\n", old);
00294         abort();
00295     }
00296     pp = realloc(p, nn);
00297     if (!pp) {
00298 #if (MEMORY_DEBUG > 1)
00299         fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
00300 #endif
00301         return NULL;
00302     }
00303 #if (MEMORY_DEBUG > 1)
00304     fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
00305 #endif
00306     p = pp;
00307     p[1] = n;
00308     nn = nn / sizeof (long) - 1;
00309     p[nn] = 0xdead5678;
00310     return (void *) &p[2];
00311 }
00312 
00313 static void
00314 xfree_(void *x, char *file, int line)
00315 {
00316     long *p;
00317     int n;
00318 
00319     if (!x) {
00320         return;
00321     }
00322     p = &((long *) x)[-2];
00323     if (p[0] != 0xdead1234) {
00324         fprintf(stderr, "*** low end corruption @ %p\n", x);
00325         abort();
00326     }
00327     n = p[1] + 4 * sizeof (long);
00328     n = n / sizeof (long) - 1;
00329     if (p[n] != 0xdead5678) {
00330         fprintf(stderr, "*** high end corruption @ %p\n", x);
00331         abort();
00332     }
00333 #if (MEMORY_DEBUG > 1)
00334     fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
00335 #endif
00336     free(p);
00337 }
00338 
00339 static void
00340 xfree__(void *x)
00341 {
00342     xfree_(x, "unknown location", 0);
00343 }
00344 
00345 static char *
00346 xstrdup_(const char *str, char *file, int line)
00347 {
00348     char *p;
00349 
00350     if (!str) {
00351 #if (MEMORY_DEBUG > 1)
00352         fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
00353 #endif
00354         return NULL;
00355     }
00356     p = xmalloc_(strlen(str) + 1, file, line);
00357     if (p) {
00358         strcpy(p, str);
00359     }
00360 #if (MEMORY_DEBUG > 1)
00361     fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
00362 #endif
00363     return p;
00364 }
00365 
00366 #define xmalloc(x)    xmalloc_(x, __FILE__, __LINE__)
00367 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
00368 #define xfree(x)      xfree_(x, __FILE__, __LINE__)
00369 #define xstrdup(x)    xstrdup_(x, __FILE__, __LINE__)
00370 
00371 #else
00372 
00373 #define xmalloc(x)    sqlite3_malloc(x)
00374 #define xrealloc(x,y) sqlite3_realloc(x, y)
00375 #define xfree(x)      sqlite3_free(x)
00376 #define xstrdup(x)    strdup_(x)
00377 
00378 #endif
00379 
00380 #if defined(_WIN32) || defined(_WIN64)
00381 
00382 #define vsnprintf   _vsnprintf
00383 #define snprintf    _snprintf
00384 #define strcasecmp  _stricmp
00385 #define strncasecmp _strnicmp
00386 
00387 static HINSTANCE NEAR hModule;  /* Saved module handle for resources */
00388 
00389 #endif
00390 
00391 #ifdef HAVE_SQLITE3STRNICMP
00392 #undef  strncasecmp
00393 #define strncasecmp(A,B,C) sqlite3_strnicmp(A,B,C)
00394 #undef  strcasecmp
00395 #define strcasecmp(A,B) strcasecmp_(A,B)
00396 
00397 #if defined(__GNUC__) && (__GNUC__ >= 2)
00398 static int strcasecmp_(const char *a, const char *b)
00399     __attribute__((__unused__));
00400 #endif
00401 
00402 static int strcasecmp_(const char *a, const char *b)
00403 {
00404     int c = strlen(a), d = strlen(b);
00405 
00406     if (c > d) {
00407         return strncasecmp(a, b, c);
00408     }
00409     return strncasecmp(a, b, d);
00410 }
00411 #endif
00412 
00413 #if defined(_WIN32) || defined(_WIN64)
00414 
00415 /*
00416  * SQLHENV, SQLHDBC, and SQLHSTMT synchronization
00417  * is done using a critical section in ENV structure.
00418  */
00419 
00420 #define HDBC_LOCK(hdbc)                         \
00421 {                                               \
00422     DBC *d;                                     \
00423                                                 \
00424     if ((hdbc) == SQL_NULL_HDBC) {              \
00425         return SQL_INVALID_HANDLE;              \
00426     }                                           \
00427     d = (DBC *) (hdbc);                         \
00428     if (d->magic != DBC_MAGIC || !d->env) {     \
00429         return SQL_INVALID_HANDLE;              \
00430     }                                           \
00431     if (d->env->magic != ENV_MAGIC) {           \
00432         return SQL_INVALID_HANDLE;              \
00433     }                                           \
00434     EnterCriticalSection(&d->env->cs);          \
00435     d->env->owner = GetCurrentThreadId();       \
00436 }
00437 
00438 #define HDBC_UNLOCK(hdbc)                       \
00439     if ((hdbc) != SQL_NULL_HDBC) {              \
00440         DBC *d;                                 \
00441                                                 \
00442         d = (DBC *) (hdbc);                     \
00443         if (d->magic == DBC_MAGIC && d->env &&  \
00444             d->env->magic == ENV_MAGIC) {       \
00445             d->env->owner = 0;                  \
00446             LeaveCriticalSection(&d->env->cs);  \
00447         }                                       \
00448     }
00449 
00450 #define HSTMT_LOCK(hstmt)                       \
00451 {                                               \
00452     DBC *d;                                     \
00453                                                 \
00454     if ((hstmt) == SQL_NULL_HSTMT) {            \
00455         return SQL_INVALID_HANDLE;              \
00456     }                                           \
00457     d = (DBC *) ((STMT *) (hstmt))->dbc;        \
00458     if (d->magic != DBC_MAGIC || !d->env) {     \
00459         return SQL_INVALID_HANDLE;              \
00460     }                                           \
00461     if (d->env->magic != ENV_MAGIC) {           \
00462         return SQL_INVALID_HANDLE;              \
00463     }                                           \
00464     EnterCriticalSection(&d->env->cs);          \
00465     d->env->owner = GetCurrentThreadId();       \
00466 }
00467 
00468 #define HSTMT_UNLOCK(hstmt)                     \
00469     if ((hstmt) != SQL_NULL_HSTMT) {            \
00470         DBC *d;                                 \
00471                                                 \
00472         d = (DBC *) ((STMT *) (hstmt))->dbc;    \
00473         if (d->magic == DBC_MAGIC && d->env &&  \
00474             d->env->magic == ENV_MAGIC) {       \
00475             d->env->owner = 0;                  \
00476             LeaveCriticalSection(&d->env->cs);  \
00477         }                                       \
00478     }
00479 
00480 #else
00481 
00482 /*
00483  * On UN*X assume that we are single-threaded or
00484  * the driver manager provides serialization for us.
00485  *
00486  * In iODBC (3.52.x) serialization can be turned
00487  * on using the DSN property "ThreadManager=yes".
00488  *
00489  * In unixODBC that property is named
00490  * "Threading=0-3" and takes one of these values:
00491  *
00492  *   0 - no protection
00493  *   1 - statement level protection
00494  *   2 - connection level protection
00495  *   3 - environment level protection
00496  *
00497  * unixODBC 2.2.11 uses environment level protection
00498  * by default when it has been built with pthread
00499  * support.
00500  */
00501 
00502 #define HDBC_LOCK(hdbc)
00503 #define HDBC_UNLOCK(hdbc)
00504 #define HSTMT_LOCK(hdbc)
00505 #define HSTMT_UNLOCK(hdbc)
00506 
00507 #endif
00508 
00509 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
00510 extern void nvfs_init(void);
00511 extern const char *nvfs_makevfs(const char *);
00512 #endif
00513 
00514 /*
00515  * tolower() replacement w/o locale
00516  */
00517 
00518 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00519 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
00520 
00521 static int
00522 TOLOWER(int c)
00523 {
00524     if (c) {
00525         char *p = strchr(upper_chars, c);
00526 
00527         if (p) {
00528             c = lower_chars[p - upper_chars];
00529         }
00530     }
00531     return c;
00532 }
00533 
00534 /*
00535  * isdigit() replacement w/o ctype.h
00536  */
00537 
00538 static const char digit_chars[] = "0123456789";
00539 
00540 #define ISDIGIT(c) \
00541     ((c) && strchr(digit_chars, (c)) != NULL)
00542 
00543 /*
00544  * isspace() replacement w/o ctype.h
00545  */
00546 
00547 static const char space_chars[] = " \f\n\r\t\v";
00548 
00549 #define ISSPACE(c) \
00550     ((c) && strchr(space_chars, (c)) != NULL)
00551 
00552 
00553 /*
00554  * Forward declarations of static functions.
00555  */
00556 
00557 static void dbtraceapi(DBC *d, char *fn, const char *sql);
00558 static void freedyncols(STMT *s);
00559 static void freeresult(STMT *s, int clrcols);
00560 static void freerows(char **rowp);
00561 static void unbindcols(STMT *s);
00562 static void s3stmt_drop(STMT *s);
00563 
00564 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
00565 static SQLRETURN freestmt(HSTMT stmt);
00566 static SQLRETURN mkbindcols(STMT *s, int ncols);
00567 static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp);
00568 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
00569 static SQLRETURN starttran(STMT *s);
00570 static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
00571 
00572 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
00573 /* MS Access hack part 1 (reserved error -7748) */
00574 static COL *statSpec2P, *statSpec3P;
00575 #endif
00576 
00577 #if (MEMORY_DEBUG < 1)
00578 
00584 static char *
00585 strdup_(const char *str)
00586 {
00587     char *p = NULL;
00588 
00589     if (str) {
00590         p = xmalloc(strlen(str) + 1);
00591         if (p) {
00592             strcpy(p, str);
00593         }
00594     }
00595     return p;
00596 }
00597 #endif
00598 
00599 #ifdef WCHARSUPPORT
00600 
00607 static int
00608 uc_strlen(SQLWCHAR *str)
00609 {
00610     int len = 0;
00611 
00612     if (str) {
00613         while (*str) {
00614             ++len;
00615             ++str;
00616         }
00617     }
00618     return len;
00619 }
00620 
00629 static SQLWCHAR *
00630 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
00631 {
00632     int i = 0;
00633 
00634     while (i < len) {
00635         if (!src[i]) {
00636             break;
00637         }
00638         dest[i] = src[i];
00639         ++i;
00640     }
00641     if (i < len) {
00642         dest[i] = 0;
00643     }
00644     return dest;
00645 }
00646 
00655 static void
00656 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
00657 {
00658     ucLen = ucLen / sizeof (SQLWCHAR);
00659     if (!uc || ucLen < 0) {
00660         return;
00661     }
00662     if (len < 0) {
00663         len = ucLen * 5;
00664     }
00665     uc[0] = 0;
00666     if (str) {
00667         int i = 0;
00668 
00669         while (i < len && *str && i < ucLen) {
00670             unsigned char c = str[0];
00671 
00672             if (c < 0x80) {
00673                 uc[i++] = c;
00674                 ++str;
00675             } else if (c <= 0xc1 || c >= 0xf5) {
00676                 /* illegal, ignored */
00677                 ++str; 
00678             } else if (c < 0xe0) {
00679                 if ((str[1] & 0xc0) == 0x80) {
00680                     unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
00681 
00682                     uc[i++] = t;
00683                     str += 2;
00684                 } else {
00685                     uc[i++] = c;
00686                     ++str;
00687                 }
00688             } else if (c < 0xf0) {
00689                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
00690                     unsigned long t = ((c & 0x0f) << 12) |
00691                         ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
00692 
00693                     uc[i++] = t;
00694                     str += 3;
00695                 } else {
00696                     uc[i++] = c;
00697                     ++str;
00698                 }
00699             } else if (c < 0xf8) {
00700                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00701                     (str[3] & 0xc0) == 0x80) {
00702                     unsigned long t = ((c & 0x03) << 18) |
00703                         ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
00704                         (str[4] & 0x3f);
00705 
00706                     if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00707                         t >= 0x10000) {
00708                         t -= 0x10000;
00709                         uc[i++] = 0xd800 | (t & 0x3ff);
00710                         if (i >= ucLen) {
00711                             break;
00712                         }
00713                         t = 0xdc00 | ((t >> 10) & 0x3ff);
00714                     }
00715                     uc[i++] = t;
00716                     str += 4;
00717                 } else {
00718                     uc[i++] = c;
00719                     ++str;
00720                 }
00721             } else if (c < 0xfc) {
00722                 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00723                     (str[3] & 0xc0) == 0x80 && (str[4] & 0xc0) == 0x80) {
00724                     unsigned long t = ((c & 0x01) << 24) |
00725                         ((str[1] & 0x3f) << 18) | ((str[2] & 0x3f) << 12) |
00726                         ((str[4] & 0x3f) << 6) | (str[5] & 0x3f);
00727 
00728                     if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00729                         t >= 0x10000) {
00730                         t -= 0x10000;
00731                         uc[i++] = 0xd800 | (t & 0x3ff);
00732                         if (i >= ucLen) {
00733                             break;
00734                         }
00735                         t = 0xdc00 | ((t >> 10) & 0x3ff);
00736                     }
00737                     uc[i++] = t;
00738                     str += 5;
00739                 } else {
00740                     uc[i++] = c;
00741                     ++str;
00742                 }
00743             } else {
00744                 /* ignore */
00745                 ++str;
00746             }
00747         }
00748         if (i < ucLen) {
00749             uc[i] = 0;
00750         }
00751     }
00752 }
00753 
00761 static SQLWCHAR *
00762 uc_from_utf(unsigned char *str, int len)
00763 {
00764     SQLWCHAR *uc = NULL;
00765     int ucLen;
00766 
00767     if (str) {
00768         if (len == SQL_NTS) {
00769             len = strlen((char *) str);
00770         }
00771         ucLen = sizeof (SQLWCHAR) * (len + 1);
00772         uc = xmalloc(ucLen);
00773         if (uc) {
00774             uc_from_utf_buf(str, len, uc, ucLen);
00775         }
00776     }
00777     return uc;
00778 }
00779 
00787 static char *
00788 uc_to_utf(SQLWCHAR *str, int len)
00789 {
00790     int i;
00791     char *cp, *ret = NULL;
00792 
00793     if (!str) {
00794         return ret;
00795     }
00796     if (len == SQL_NTS) {
00797         len = uc_strlen(str);
00798     } else {
00799         len = len / sizeof (SQLWCHAR);
00800     }
00801     cp = xmalloc(len * 6 + 1);
00802     if (!cp) {
00803         return ret;
00804     }
00805     ret = cp;
00806     for (i = 0; i < len; i++) {
00807         unsigned long c = str[i];
00808 
00809         if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
00810             c &= 0xffff;
00811         }
00812         if (c < 0x80) {
00813             *cp++ = c;
00814         } else if (c < 0x800) {
00815             *cp++ = 0xc0 | ((c >> 6) & 0x1f);
00816             *cp++ = 0x80 | (c & 0x3f);
00817         } else if (c < 0x10000) {
00818             if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00819                 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
00820                 unsigned long c2 = str[i + 1] & 0xffff;
00821 
00822                 if (c2 >= 0xdc00 && c <= 0xdfff) {
00823                     c = ((c & 0x3ff) | ((c2 & 0x3ff) << 10)) + 0x10000;
00824                     *cp++ = 0xf0 | ((c >> 18) & 0x07);
00825                     *cp++ = 0x80 | ((c >> 12) & 0x3f);
00826                     *cp++ = 0x80 | ((c >> 6) & 0x3f);
00827                     *cp++ = 0x80 | (c & 0x3f);
00828                     ++i;
00829                     continue;
00830                 }
00831             }
00832             *cp++ = 0xe0 | ((c >> 12) & 0x0f);
00833             *cp++ = 0x80 | ((c >> 6) & 0x3f);
00834             *cp++ = 0x80 | (c & 0x3f);
00835         } else if (c < 0x200000) {
00836             *cp++ = 0xf0 | ((c >> 18) & 0x07);
00837             *cp++ = 0x80 | ((c >> 12) & 0x3f);
00838             *cp++ = 0x80 | ((c >> 6) & 0x3f);
00839             *cp++ = 0x80 | (c & 0x3f);
00840         } else if (c < 0x4000000) {
00841             *cp++ = 0xf8 | ((c >> 24) & 0x03);
00842             *cp++ = 0x80 | ((c >> 18) & 0x3f);
00843             *cp++ = 0x80 | ((c >> 12) & 0x3f);
00844             *cp++ = 0x80 | ((c >> 6) & 0x3f);
00845             *cp++ = 0x80 | (c & 0x3f);
00846         } else if (c < 0x80000000) {
00847             *cp++ = 0xfc | ((c >> 31) & 0x01);
00848             *cp++ = 0x80 | ((c >> 24) & 0x3f);
00849             *cp++ = 0x80 | ((c >> 18) & 0x3f);
00850             *cp++ = 0x80 | ((c >> 12) & 0x3f);
00851             *cp++ = 0x80 | ((c >> 6) & 0x3f);
00852             *cp++ = 0x80 | (c & 0x3f);
00853         }
00854     }
00855     *cp = '\0';
00856     return ret;
00857 }
00858 
00859 #endif
00860 
00861 #ifdef WINTERFACE
00862 
00870 static char *
00871 uc_to_utf_c(SQLWCHAR *str, int len)
00872 {
00873     if (len != SQL_NTS) {
00874         len = len * sizeof (SQLWCHAR);
00875     }
00876     return uc_to_utf(str, len);
00877 }
00878 
00879 #endif
00880 
00881 #if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
00882 
00888 static void
00889 uc_free(void *str)
00890 {
00891     if (str) {
00892         xfree(str);
00893     }
00894 }
00895 
00896 #endif
00897 
00898 #if defined(_WIN32) || defined(_WIN64)
00899 
00907 static char *
00908 wmb_to_utf(char *str, int len)
00909 {
00910     WCHAR *wstr;
00911     OSVERSIONINFO ovi;
00912     int nchar, is2k, cp = CP_OEMCP;
00913 
00914     ovi.dwOSVersionInfoSize = sizeof (ovi);
00915     GetVersionEx(&ovi);
00916     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
00917     if (AreFileApisANSI()) {
00918         cp = is2k ? CP_THREAD_ACP : CP_ACP;
00919     }
00920     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
00921     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
00922     if (!wstr) {
00923         return NULL;
00924     }
00925     wstr[0] = 0;
00926     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
00927     wstr[nchar] = 0;
00928     str = xmalloc((nchar + 1) * 7);
00929     if (!str) {
00930         xfree(wstr);
00931         return NULL;
00932     }
00933     str[0] = '\0';
00934     nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
00935     str[nchar] = '\0';
00936     xfree(wstr);
00937     return str;
00938 }
00939 
00940 #ifndef WINTERFACE
00941 
00949 static char *
00950 wmb_to_utf_c(char *str, int len)
00951 {
00952     if (len == SQL_NTS) {
00953         len = strlen(str);
00954     }
00955     return wmb_to_utf(str, len);
00956 }
00957 
00958 #endif
00959 
00967 static char *
00968 utf_to_wmb(char *str, int len)
00969 {
00970     WCHAR *wstr;
00971     OSVERSIONINFO ovi;
00972     int nchar, is2k, cp = CP_OEMCP;
00973 
00974     ovi.dwOSVersionInfoSize = sizeof (ovi);
00975     GetVersionEx(&ovi);
00976     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
00977     if (AreFileApisANSI()) {
00978         cp = is2k ? CP_THREAD_ACP : CP_ACP;
00979     }
00980     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
00981     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
00982     if (!wstr) {
00983         return NULL;
00984     }
00985     wstr[0] = 0;
00986     nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
00987     wstr[nchar] = 0;
00988     str = xmalloc((nchar + 1) * 7);
00989     if (!str) {
00990         xfree(wstr);
00991         return NULL;
00992     }
00993     str[0] = '\0';
00994     nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
00995     str[nchar] = '\0';
00996     xfree(wstr);
00997     return str;
00998 }
00999 
01000 #ifdef WINTERFACE
01001 
01009 static WCHAR *
01010 wmb_to_uc(char *str, int len)
01011 {
01012     WCHAR *wstr;
01013     OSVERSIONINFO ovi;
01014     int nchar, is2k, cp = CP_OEMCP;
01015 
01016     ovi.dwOSVersionInfoSize = sizeof (ovi);
01017     GetVersionEx(&ovi);
01018     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01019     if (AreFileApisANSI()) {
01020         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01021     }
01022     nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
01023     wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
01024     if (!wstr) {
01025         return NULL;
01026     }
01027     wstr[0] = 0;
01028     nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
01029     wstr[nchar] = 0;
01030     return wstr;
01031 }
01032 
01040 static char *
01041 uc_to_wmb(WCHAR *wstr, int len)
01042 {
01043     char *str;
01044     OSVERSIONINFO ovi;
01045     int nchar, is2k, cp = CP_OEMCP;
01046 
01047     ovi.dwOSVersionInfoSize = sizeof (ovi);
01048     GetVersionEx(&ovi);
01049     is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
01050     if (AreFileApisANSI()) {
01051         cp = is2k ? CP_THREAD_ACP : CP_ACP;
01052     }
01053     nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
01054     str = xmalloc((nchar + 1) * 2);
01055     if (!str) {
01056         return NULL;
01057     }
01058     str[0] = '\0';
01059     nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
01060     str[nchar] = '\0';
01061     return str;
01062 }
01063 
01064 #endif /* WINTERFACE */
01065 
01066 #endif /* _WIN32 || _WIN64 */
01067 
01068 
01069 #ifdef USE_DLOPEN_FOR_GPPS
01070 
01071 #include <dlfcn.h>
01072 
01073 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
01074 
01075 /*
01076  * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
01077  * dlopen(), in theory this makes the driver independent from the
01078  * driver manager, i.e. the same driver binary can run with iODBC
01079  * and unixODBC.
01080  */
01081 
01082 static void
01083 drvgetgpps(DBC *d)
01084 {
01085     void *lib;
01086     int (*gpps)();
01087 
01088     lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
01089     if (!lib) {
01090         lib = dlopen("libodbcinst.so", RTLD_LAZY);
01091     }
01092     if (!lib) {
01093         lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
01094     }
01095     if (!lib) {
01096         lib = dlopen("libiodbcinst.so", RTLD_LAZY);
01097     }
01098     if (lib) {
01099         gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
01100         if (!gpps) {
01101             dlclose(lib);
01102             return;
01103         }
01104         d->instlib = lib;
01105         d->gpps = gpps;
01106     }
01107 }
01108 
01109 static void
01110 drvrelgpps(DBC *d)
01111 {
01112     if (d->instlib) {
01113         dlclose(d->instlib);
01114         d->instlib = 0;
01115     }
01116 }
01117 
01118 static int
01119 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
01120         int bufsiz, char *fname)
01121 {
01122     if (d->gpps) {
01123         return d->gpps(sect, ent, def, buf, bufsiz, fname);
01124     }
01125     strncpy(buf, def, bufsiz);
01126     buf[bufsiz - 1] = '\0';
01127     return 1;
01128 }
01129 #else
01130 #include <odbcinst.h>
01131 #define drvgetgpps(d)
01132 #define drvrelgpps(d)
01133 #endif
01134 
01135 /*
01136  * Internal function to bind SQLite3 parameters.
01137  */
01138 
01139 static void
01140 s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
01141 {
01142     int i;
01143 
01144     if (stmt && p && nparams > 0) {
01145         for (i = 0; i < nparams; i++, p++) {
01146             switch (p->s3type) {
01147             default:
01148             case SQLITE_NULL:
01149                 sqlite3_bind_null(stmt, i + 1);
01150                 if (d->trace) {
01151                     fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
01152                     fflush(d->trace);
01153                 }
01154                 break;
01155             case SQLITE_TEXT:
01156                 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
01157                                   SQLITE_STATIC);
01158                 if (d->trace) {
01159                     fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
01160                             p->s3size, (char *) p->s3val);
01161                     fflush(d->trace);
01162                 }
01163                 break;
01164             case SQLITE_BLOB:
01165                 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
01166                                   SQLITE_STATIC);
01167                 if (d->trace) {
01168                     fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
01169                     fflush(d->trace);
01170                 }
01171                 break;
01172             case SQLITE_FLOAT:
01173                 sqlite3_bind_double(stmt, i + 1, p->s3dval);
01174                 if (d->trace) {
01175                     fprintf(d->trace, "-- parameter %d: %g\n",
01176                             i + 1, p->s3dval);
01177                     fflush(d->trace);
01178                 }
01179                 break;
01180             case SQLITE_INTEGER:
01181                 if (p->s3size > sizeof (int)) {
01182                     sqlite3_bind_int64(stmt, i + 1, p->s3lival);
01183                     if (d->trace) {
01184                         fprintf(d->trace,
01185 #ifdef _WIN32
01186                                 "-- parameter %d: %I64d\n",
01187 #else
01188                                 "-- parameter %d: %lld\n",
01189 #endif
01190                                 i + 1, p->s3lival);
01191                         fflush(d->trace);
01192                     }
01193                 } else {
01194                     sqlite3_bind_int(stmt, i + 1, p->s3ival);
01195                     if (d->trace) {
01196                         fprintf(d->trace, "-- parameter %d: %d\n",
01197                                 i + 1, p->s3ival);
01198                         fflush(d->trace);
01199                     }
01200                 }
01201                 break;
01202             }
01203         }
01204     }
01205 }
01206 
01207 /*
01208  * Internal structure for managing driver's
01209  * sqlite3_get_table() implementation.
01210  */
01211 
01212 typedef struct tblres {
01213     char **resarr;
01214     char *errmsg;
01215     sqlite3_stmt *stmt;
01216     STMT *s;
01217     int nres;
01218     int nalloc;
01219     int nrow;
01220     int ncol;
01221     PTRDIFF_T ndata;
01222     int rc;
01223 } TBLRES;
01224 
01225 /*
01226  * Driver's version of sqlite3_get_table() and friends which are
01227  * capable of dealing with blobs.
01228  */
01229 
01230 static int
01231 drvgettable_row(TBLRES *t, int ncol, int rc)
01232 {
01233     int need;
01234     int i;
01235     char *p;
01236 
01237     if (t->nrow == 0 && rc == SQLITE_ROW) {
01238         need = ncol * 2;
01239     } else {
01240         need = ncol;
01241     }
01242     if (t->ndata + need >= t->nalloc) {
01243         char **resnew;
01244         int nalloc = t->nalloc * 2 + need + 1;
01245 
01246         resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
01247         if (!resnew) {
01248 nomem:
01249             t->rc = SQLITE_NOMEM;
01250             return 1;
01251         }
01252         t->nalloc = nalloc;
01253         t->resarr = resnew;
01254     }
01255     /* column names when first row */
01256     if (t->nrow == 0) {
01257         t->ncol = ncol;
01258         for (i = 0; i < ncol; i++) {
01259             p = (char *) sqlite3_column_name(t->stmt, i);
01260             if (p) {
01261                 char *q = xmalloc(strlen(p) + 1);
01262 
01263                 if (!q) {
01264                     goto nomem;
01265                 }
01266                 strcpy(q, p);
01267                 p = q;
01268             }
01269             t->resarr[t->ndata++] = p;
01270         }
01271         if (t->s && t->s->guessed_types) {
01272             int ncol2 = ncol;
01273 
01274             setupdyncols(t->s, t->stmt, &ncol2);
01275             t->s->guessed_types = 0;
01276             t->s->ncols = ncol;
01277         }
01278     } else if (t->ncol != ncol) {
01279         t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
01280                                     " more incompatible queries");
01281         t->rc = SQLITE_ERROR;
01282         return 1;
01283     }
01284     /* copy row data */
01285     if (rc == SQLITE_ROW) {
01286         for (i = 0; i < ncol; i++) {
01287             int coltype = sqlite3_column_type(t->stmt, i);
01288 
01289             p = NULL;
01290             if (coltype == SQLITE_BLOB) {
01291                 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
01292                 char *qp;
01293                 unsigned const char *bp;
01294 
01295                 bp = sqlite3_column_blob(t->stmt, i);
01296                 qp = xmalloc(nbytes * 2 + 4);
01297                 if (!qp) {
01298                     goto nomem;
01299                 }
01300                 p = qp;
01301                 *qp++ = 'X';
01302                 *qp++ = '\'';
01303                 for (k = 0; k < nbytes; k++) {
01304                     *qp++ = xdigits[(bp[k] >> 4)];
01305                     *qp++ = xdigits[(bp[k] & 0xF)];
01306                 }
01307                 *qp++ = '\'';
01308                 *qp = '\0';
01309             } else if (coltype != SQLITE_NULL) {
01310                 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
01311                 if (!p) {
01312                     goto nomem;
01313                 }
01314             }
01315             t->resarr[t->ndata++] = p;
01316         }
01317         t->nrow++;
01318     }
01319     return 0;
01320 }
01321 
01322 static int
01323 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
01324             int *ncolp, char **errp, int nparam, BINDPARM *p)
01325 {
01326     DBC *d = (DBC *) s->dbc;
01327     int rc = SQLITE_OK, keep = sql == NULL;
01328     TBLRES tres;
01329     const char *sqlleft = 0;
01330     int nretry = 0, haveerr = 0;
01331 
01332     if (!resp) {
01333         return SQLITE_ERROR;
01334     }
01335     *resp = NULL;
01336     if (nrowp) {
01337         *nrowp = 0;
01338     }
01339     if (ncolp) {
01340         *ncolp = 0;
01341     }
01342     tres.errmsg = NULL;
01343     tres.nres = 0;
01344     tres.nrow = 0;
01345     tres.ncol = 0;
01346     tres.ndata = 1;
01347     tres.nalloc = 20;
01348     tres.rc = SQLITE_OK;
01349     tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
01350     tres.stmt = NULL;
01351     tres.s = s;
01352     if (!tres.resarr) {
01353         return SQLITE_NOMEM;
01354     }
01355     tres.resarr[0] = 0;
01356     if (sql == NULL) {
01357         tres.stmt = s->s3stmt;
01358         if (tres.stmt == NULL) {
01359             return SQLITE_NOMEM;
01360         }
01361         goto retrieve;
01362     }
01363     while (sql && *sql && (rc == SQLITE_OK ||
01364                            (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
01365         int ncol;
01366 
01367         tres.stmt = NULL;
01368 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
01369         dbtraceapi(d, "sqlite3_prepare_v2", sql);
01370         rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01371 #else
01372         dbtraceapi(d, "sqlite3_prepare", sql);
01373         rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01374 #endif
01375         if (rc != SQLITE_OK) {
01376             if (tres.stmt) {
01377                 dbtraceapi(d, "sqlite3_finalize", 0);
01378                 sqlite3_finalize(tres.stmt);
01379                 tres.stmt = NULL;
01380             }
01381             continue;
01382         }
01383         if (!tres.stmt) {
01384             /* this happens for a comment or white-space */
01385             sql = sqlleft;
01386             continue;
01387         }
01388 retrieve:
01389         if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
01390             if (errp) {
01391                 *errp =
01392                     sqlite3_mprintf("%s", "parameter marker count incorrect");
01393             }
01394             haveerr = 1;
01395             rc = SQLITE_ERROR;
01396             goto tbldone;
01397         }
01398         s3bind(d, tres.stmt, nparam, p);
01399         ncol = sqlite3_column_count(tres.stmt);
01400         while (1) {
01401             if (s->max_rows && tres.nrow >= s->max_rows) {
01402                 rc = SQLITE_OK;
01403                 break;
01404             }
01405             rc = sqlite3_step(tres.stmt);
01406             if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
01407                 if (drvgettable_row(&tres, ncol, rc)) {
01408                     rc = SQLITE_ABORT;
01409                     goto tbldone;
01410                 }
01411             }
01412             if (rc != SQLITE_ROW) {
01413                 if (keep) {
01414                     dbtraceapi(d, "sqlite3_reset", 0);
01415                     rc = sqlite3_reset(tres.stmt);
01416                     s->s3stmt_noreset = 1;
01417                 } else {
01418                     dbtraceapi(d, "sqlite3_finalize", 0);
01419                     rc = sqlite3_finalize(tres.stmt);
01420                 }
01421                 tres.stmt = 0;
01422                 if (rc != SQLITE_SCHEMA) {
01423                     nretry = 0;
01424                     sql = sqlleft;
01425                     while (sql && ISSPACE(*sql)) {
01426                         sql++;
01427                     }
01428                 }
01429                 if (rc == SQLITE_DONE) {
01430                     rc = SQLITE_OK;
01431                 }
01432                 break;
01433             }
01434         }
01435     }
01436 tbldone:
01437     if (tres.stmt) {
01438         if (keep) {
01439             if (!s->s3stmt_noreset) {
01440                 dbtraceapi(d, "sqlite3_reset", 0);
01441                 sqlite3_reset(tres.stmt);
01442                 s->s3stmt_noreset = 1;
01443             }
01444         } else {
01445             dbtraceapi(d, "sqlite3_finalize", 0);
01446             sqlite3_finalize(tres.stmt);
01447         }
01448     }
01449     if (haveerr) {
01450         /* message already in *errp if any */
01451     } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
01452         *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
01453     } else if (errp) {
01454         *errp = NULL;
01455     }
01456     if (tres.resarr) {
01457         tres.resarr[0] = (char *) (tres.ndata - 1);
01458     }
01459     if (rc == SQLITE_ABORT) {
01460         freerows(&tres.resarr[1]);
01461         if (tres.errmsg) {
01462             if (errp) {
01463                 if (*errp) {
01464                     sqlite3_free(*errp);
01465                 }
01466                 *errp = tres.errmsg;
01467             } else {
01468                 sqlite3_free(tres.errmsg);
01469             }
01470         }
01471         return tres.rc;
01472     }
01473     sqlite3_free(tres.errmsg);
01474     if (rc != SQLITE_OK) {
01475         freerows(&tres.resarr[1]);
01476         return rc;
01477     }
01478     *resp = &tres.resarr[1];
01479     if (ncolp) {
01480         *ncolp = tres.ncol;
01481     }
01482     if (nrowp) {
01483         *nrowp = tres.nrow;
01484     }
01485     return rc;
01486 }
01487 
01496 #if defined(__GNUC__) && (__GNUC__ >= 2)
01497 static void setstatd(DBC *, int, char *, char *, ...)
01498     __attribute__((format (printf, 3, 5)));
01499 #endif
01500 
01501 static void
01502 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
01503 {
01504     va_list ap;
01505 
01506     if (!d) {
01507         return;
01508     }
01509     d->naterr = naterr;
01510     d->logmsg[0] = '\0';
01511     if (msg) {
01512         int count;
01513 
01514         va_start(ap, st);
01515         count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
01516         va_end(ap);
01517         if (count < 0) {
01518             d->logmsg[sizeof (d->logmsg) - 1] = '\0';
01519         }
01520     }
01521     if (!st) {
01522         st = "?????";
01523     }
01524     strncpy(d->sqlstate, st, 5);
01525     d->sqlstate[5] = '\0';
01526 }
01527 
01536 #if defined(__GNUC__) && (__GNUC__ >= 2)
01537 static void setstat(STMT *, int, char *, char *, ...)
01538     __attribute__((format (printf, 3, 5)));
01539 #endif
01540 
01541 static void
01542 setstat(STMT *s, int naterr, char *msg, char *st, ...)
01543 {
01544     va_list ap;
01545 
01546     if (!s) {
01547         return;
01548     }
01549     s->naterr = naterr;
01550     s->logmsg[0] = '\0';
01551     if (msg) {
01552         int count;
01553 
01554         va_start(ap, st);
01555         count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
01556         va_end(ap);
01557         if (count < 0) {
01558             s->logmsg[sizeof (s->logmsg) - 1] = '\0';
01559         }
01560     }
01561     if (!st) {
01562         st = "?????";
01563     }
01564     strncpy(s->sqlstate, st, 5);
01565     s->sqlstate[5] = '\0';
01566 }
01567 
01574 static SQLRETURN
01575 drvunimpldbc(HDBC dbc)
01576 {
01577     DBC *d;
01578 
01579     if (dbc == SQL_NULL_HDBC) {
01580         return SQL_INVALID_HANDLE;
01581     }
01582     d = (DBC *) dbc;
01583     setstatd(d, -1, "not supported", "IM001");
01584     return SQL_ERROR;
01585 }
01586 
01593 static SQLRETURN
01594 drvunimplstmt(HSTMT stmt)
01595 {
01596     STMT *s;
01597 
01598     if (stmt == SQL_NULL_HSTMT) {
01599         return SQL_INVALID_HANDLE;
01600     }
01601     s = (STMT *) stmt;
01602     setstat(s, -1, "not supported", "IM001");
01603     return SQL_ERROR;
01604 }
01605 
01611 static void
01612 freep(void *x)
01613 {
01614     if (x && ((char **) x)[0]) {
01615         xfree(((char **) x)[0]);
01616         ((char **) x)[0] = NULL;
01617     }
01618 }
01619 
01626 static SQLRETURN
01627 nomem(STMT *s)
01628 {
01629     setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
01630     return SQL_ERROR;
01631 }
01632 
01639 static SQLRETURN
01640 noconn(STMT *s)
01641 {
01642     setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
01643     return SQL_ERROR;
01644 }
01645 
01653 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
01654 
01655 static double
01656 ln_strtod(const char *data, char **endp)
01657 {
01658     struct lconv *lc;
01659     char buf[128], *p, *end;
01660     double value;
01661 
01662     lc = localeconv();
01663     if (lc && lc->decimal_point && lc->decimal_point[0] &&
01664         lc->decimal_point[0] != '.') {
01665         strncpy(buf, data, sizeof (buf) - 1);
01666         buf[sizeof (buf) - 1] = '\0';
01667         p = strchr(buf, '.');
01668         if (p) {
01669             *p = lc->decimal_point[0];
01670         }
01671         p = buf;
01672     } else {
01673         p = (char *) data;
01674     }
01675     value = strtod(p, &end);
01676     end = (char *) data + (end - p);
01677     if (endp) {
01678         *endp = end;
01679     }
01680     return value;
01681 }
01682 
01683 #else
01684 
01685 #define ln_strtod(A,B) strtod(A,B)
01686 
01687 #endif
01688 
01694 static char *
01695 unquote(char *str)
01696 {
01697     if (str) {
01698         int len = strlen(str);
01699 
01700         if (len > 1) {
01701             if ((str[0] == '\'' && str[len - 1] == '\'') ||
01702                 (str[0] == '"' && str[len - 1] == '"') ||
01703                 (str[0] == '[' && str[len - 1] == ']')) {
01704                 str[len - 1] = '\0';
01705                 strcpy(str, str + 1);
01706             }
01707         }
01708     }
01709     return str;
01710 }
01711 
01719 static int
01720 unescpat(char *str)
01721 {
01722     char *p, *q;
01723     int count = 0;
01724 
01725     p = str;
01726     while ((q = strchr(p, '_')) != NULL) {
01727         if (q == str || q[-1] != '\\') {
01728             count++;
01729         }
01730         p = q + 1;
01731     }
01732     p = str;
01733     while ((q = strchr(p, '%')) != NULL) {
01734         if (q == str || q[-1] != '\\') {
01735             count++;
01736         }
01737         p = q + 1;
01738     }
01739     p = str;
01740     while ((q = strchr(p, '\\')) != NULL) {
01741         if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
01742             strcpy(q, q + 1);
01743         }
01744         p = q + 1;
01745     }
01746     return count;
01747 }
01748 
01757 static int
01758 namematch(char *str, char *pat, int esc)
01759 {
01760     int cp, ch;
01761 
01762     while (1) {
01763         cp = TOLOWER(*pat);
01764         if (cp == '\0') {
01765             if (*str != '\0') {
01766                 goto nomatch;
01767             }
01768             break;
01769         }
01770         if (*str == '\0' && cp != '%') {
01771             goto nomatch;
01772         }
01773         if (cp == '%') {
01774             while (*pat == '%') {
01775                 ++pat;
01776             }
01777             cp = TOLOWER(*pat);
01778             if (cp == '\0') {
01779                 break;
01780             }
01781             while (1) {
01782                 if (cp != '_' && cp != '\\') {
01783                     while (*str) {
01784                         ch = TOLOWER(*str);
01785                         if (ch == cp) {
01786                             break;
01787                         }
01788                         ++str;
01789                     }
01790                 }
01791                 if (namematch(str, pat, esc)) {
01792                     goto match;
01793                 }
01794                 if (*str == '\0') {
01795                     goto nomatch;
01796                 }
01797                 ch = TOLOWER(*str);
01798                 ++str;
01799             }
01800         }
01801         if (cp == '_') {
01802             pat++;
01803             str++;
01804             continue;
01805         }
01806         if (esc && cp == '\\' &&
01807             (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
01808             ++pat;
01809             cp = TOLOWER(*pat);
01810         }
01811         ch = TOLOWER(*str++);
01812         ++pat;
01813         if (ch != cp) {
01814             goto nomatch;
01815         }
01816     }
01817 match:
01818     return 1;
01819 nomatch:
01820     return 0;
01821 }
01822 
01830 static int
01831 busy_handler(void *udata, int count)
01832 {
01833     DBC *d = (DBC *) udata;
01834     long t1;
01835     int ret = 0;
01836 #if !defined(_WIN32) && !defined(_WIN64)
01837     struct timeval tv;
01838 #ifdef HAVE_NANOSLEEP
01839     struct timespec ts;
01840 #endif
01841 #endif
01842 
01843     if (d->busyint) {
01844         d->busyint = 0;
01845         return ret;
01846     }
01847     if (d->timeout <= 0) {
01848         return ret;
01849     }
01850     if (count <= 1) {
01851 #if defined(_WIN32) || defined(_WIN64)
01852         d->t0 = GetTickCount();
01853 #else
01854         gettimeofday(&tv, NULL);
01855         d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
01856 #endif
01857     }
01858 #if defined(_WIN32) || defined(_WIN64)
01859     t1 = GetTickCount();
01860 #else
01861     gettimeofday(&tv, NULL);
01862     t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
01863 #endif
01864     if (t1 - d->t0 > d->timeout) {
01865         goto done;
01866     }
01867 #if defined(_WIN32) || defined(_WIN64)
01868     Sleep(10);
01869 #else
01870 #ifdef HAVE_NANOSLEEP
01871     ts.tv_sec = 0;
01872     ts.tv_nsec = 10000000;
01873     do {
01874         ret = nanosleep(&ts, &ts);
01875         if (ret < 0 && errno != EINTR) {
01876             ret = 0;
01877         }
01878     } while (ret); 
01879 #else
01880 #ifdef HAVE_USLEEP
01881     usleep(10000);
01882 #else
01883     tv.tv_sec = 0;
01884     tv.tv_usec = 10000;
01885     select(0, NULL, NULL, NULL, &tv);
01886 #endif
01887 #endif
01888 #endif
01889     ret = 1;
01890 done:
01891     return ret;
01892 }
01893 
01905 static int
01906 setsqliteopts(sqlite3 *x, DBC *d)
01907 {
01908     int count = 0, step = 0, max, rc = SQLITE_ERROR;
01909 
01910 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
01911     max = d->longnames ? 3 : 1;
01912 #else
01913     max = 3;
01914 #endif
01915     if (d->shortnames) {
01916         max = 3;
01917     }
01918     while (step < max) {
01919         if (step < 1) {
01920             rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
01921                               NULL, NULL, NULL);
01922             if (rc == SQLITE_OK) {
01923                 rc = sqlite3_exec(x, d->fksupport ?
01924                                   "PRAGMA foreign_keys = on;" :
01925                                   "PRAGMA foreign_keys = off;",
01926                                   NULL, NULL, NULL);
01927             }
01928         } else if (step < 2) {
01929             rc = sqlite3_exec(x, d->shortnames ?
01930                               "PRAGMA full_column_names = off;" :
01931                               "PRAGMA full_column_names = on;",
01932                               NULL, NULL, NULL);
01933         } else if (step < 3) {
01934             rc = sqlite3_exec(x, d->shortnames ?
01935                               "PRAGMA short_column_names = on;" :
01936                               "PRAGMA short_column_names = off;",
01937                               NULL, NULL, NULL);
01938         }
01939         if (rc != SQLITE_OK) {
01940             if (rc != SQLITE_BUSY ||
01941                 !busy_handler((void *) d, ++count)) {
01942                 return rc;
01943             }
01944             continue;
01945         }
01946         count = 0;
01947         ++step;
01948     }
01949     sqlite3_busy_handler(x, busy_handler, (void *) d);
01950     return SQLITE_OK;
01951 }
01952 
01962 static void
01963 freerows(char **rowp)
01964 {
01965     PTRDIFF_T size, i;
01966 
01967     if (!rowp) {
01968         return;
01969     }
01970     --rowp;
01971     size = (PTRDIFF_T) rowp[0];
01972     for (i = 1; i <= size; i++) {
01973         freep(&rowp[i]);
01974     }
01975     freep(&rowp);
01976 }
01977 
01988 static int
01989 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
01990            int dobigint)
01991 {
01992     char *p, *q;
01993     int testsign = 0, result;
01994 
01995 #ifdef WINTERFACE
01996     result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
01997 #else
01998     result = SQL_VARCHAR;
01999 #endif
02000     if (!typename) {
02001         return result;
02002     }
02003     q = p = xmalloc(strlen(typename) + 1);
02004     if (!p) {
02005         return result;
02006     }
02007     strcpy(p, typename);
02008     while (*q) {
02009         *q = TOLOWER(*q);
02010         ++q;
02011     }
02012     if (strncmp(p, "inter", 5) == 0) {
02013     } else if (strncmp(p, "int", 3) == 0 ||
02014         strncmp(p, "mediumint", 9) == 0) {
02015         testsign = 1;
02016         result = SQL_INTEGER;
02017     } else if (strncmp(p, "numeric", 7) == 0) {
02018         result = SQL_DOUBLE;
02019     } else if (strncmp(p, "tinyint", 7) == 0) {
02020         testsign = 1;
02021         result = SQL_TINYINT;
02022     } else if (strncmp(p, "smallint", 8) == 0) {
02023         testsign = 1;
02024         result = SQL_SMALLINT;
02025     } else if (strncmp(p, "float", 5) == 0) {
02026         result = SQL_DOUBLE;
02027     } else if (strncmp(p, "double", 6) == 0 ||
02028         strncmp(p, "real", 4) == 0) {
02029         result = SQL_DOUBLE;
02030     } else if (strncmp(p, "timestamp", 9) == 0) {
02031 #ifdef SQL_TYPE_TIMESTAMP
02032         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02033 #else
02034         result = SQL_TIMESTAMP;
02035 #endif
02036     } else if (strncmp(p, "datetime", 8) == 0) {
02037 #ifdef SQL_TYPE_TIMESTAMP
02038         result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
02039 #else
02040         result = SQL_TIMESTAMP;
02041 #endif
02042     } else if (strncmp(p, "time", 4) == 0) {
02043 #ifdef SQL_TYPE_TIME
02044         result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
02045 #else
02046         result = SQL_TIME;
02047 #endif
02048     } else if (strncmp(p, "date", 4) == 0) {
02049 #ifdef SQL_TYPE_DATE
02050         result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
02051 #else
02052         result = SQL_DATE;
02053 #endif
02054 #ifdef SQL_LONGVARCHAR
02055     } else if (strncmp(p, "text", 4) == 0 ||
02056                strncmp(p, "memo", 4) == 0 ||
02057                strncmp(p, "longvarchar", 11) == 0) {
02058 #ifdef WINTERFACE
02059         result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
02060 #else
02061         result = SQL_LONGVARCHAR;
02062 #endif
02063 #ifdef WINTERFACE
02064     } else if (strncmp(p, "wtext", 5) == 0 ||
02065                strncmp(p, "wvarchar", 8) == 0 ||
02066                strncmp(p, "longwvarchar", 12) == 0) {
02067         result = SQL_WLONGVARCHAR;
02068 #endif
02069 #endif
02070 #ifdef SQL_BIT
02071     } else if (strncmp(p, "bool", 4) == 0 ||
02072                strncmp(p, "bit", 3) == 0) {
02073         result = SQL_BIT;
02074 #endif
02075 #ifdef SQL_BIGINT
02076     } else if (strncmp(p, "bigint", 6) == 0) {
02077         testsign = 1;
02078         result = SQL_BIGINT;
02079 #endif
02080     } else if (strncmp(p, "blob", 4) == 0) {
02081         result = SQL_BINARY;
02082     } else if (strncmp(p, "varbinary", 9) == 0) {
02083         result = SQL_VARBINARY;
02084     } else if (strncmp(p, "longvarbinary", 13) == 0) {
02085         result = SQL_LONGVARBINARY;
02086     }
02087     if (nosign) {
02088         if (testsign) {
02089             *nosign = strstr(p, "unsigned") != NULL;
02090         } else {
02091             *nosign = 1;
02092         }
02093     }
02094 #ifdef SQL_BIGINT
02095     if (dobigint && result == SQL_INTEGER) {
02096         result = SQL_BIGINT;
02097     }
02098 #endif
02099     xfree(p);
02100     return result;
02101 }
02102 
02112 static void
02113 getmd(const char *typename, int sqltype, int *mp, int *dp)
02114 {
02115     int m = 0, d = 0;
02116 
02117     switch (sqltype) {
02118     case SQL_INTEGER:       m = 10; d = 9; break;
02119     case SQL_TINYINT:       m = 4; d = 3; break;
02120     case SQL_SMALLINT:      m = 6; d = 5; break;
02121     case SQL_FLOAT:         m = 25; d = 24; break;
02122     case SQL_DOUBLE:        m = 54; d = 53; break;
02123     case SQL_VARCHAR:       m = 255; d = 0; break;
02124 #ifdef WINTERFACE
02125 #ifdef SQL_WVARCHAR
02126     case SQL_WVARCHAR:      m = 255; d = 0; break;
02127 #endif
02128 #endif
02129 #ifdef SQL_TYPE_DATE
02130     case SQL_TYPE_DATE:
02131 #endif
02132     case SQL_DATE:          m = 10; d = 0; break;
02133 #ifdef SQL_TYPE_TIME
02134     case SQL_TYPE_TIME:
02135 #endif
02136     case SQL_TIME:          m = 8; d = 0; break;
02137 #ifdef SQL_TYPE_TIMESTAMP
02138     case SQL_TYPE_TIMESTAMP:
02139 #endif
02140     case SQL_TIMESTAMP:     m = 32; d = 3; break;
02141 #ifdef SQL_LONGVARCHAR
02142     case SQL_LONGVARCHAR :  m = 65536; d = 0; break;
02143 #endif
02144 #ifdef WINTERFACE
02145 #ifdef SQL_WLONGVARCHAR
02146     case SQL_WLONGVARCHAR:  m = 65536; d = 0; break;
02147 #endif
02148 #endif
02149     case SQL_VARBINARY:     m = 255; d = 0; break;
02150     case SQL_LONGVARBINARY: m = 65536; d = 0; break;
02151 #ifdef SQL_BIGINT
02152     case SQL_BIGINT:        m = 20; d = 19; break;
02153 #endif
02154 #ifdef SQL_BIT
02155     case SQL_BIT:           m = 1; d = 1; break;
02156 #endif
02157     }
02158     if (m && typename) {
02159         int mm, dd;
02160 
02161         if (sscanf(typename, "%*[^(](%d)", &mm) == 1) {
02162             if (sqltype == SQL_TIMESTAMP) {
02163                 d = mm;
02164             }
02165 #ifdef SQL_TYPE_TIMESTAMP
02166             else if (sqltype == SQL_TYPE_TIMESTAMP) {
02167                 d = mm;
02168             }
02169 #endif
02170             else {
02171                 m = d = mm;
02172             }
02173         } else if (sscanf(typename, "%*[^(](%d,%d)", &mm, &dd) == 2) {
02174             m = mm;
02175             d = dd;
02176         }
02177     }
02178     if (mp) {
02179         *mp = m;
02180     }
02181     if (dp) {
02182         *dp = d;
02183     }
02184 }
02185 
02195 static int
02196 mapdeftype(int type, int stype, int nosign, int nowchar)
02197 {
02198     if (type == SQL_C_DEFAULT) {
02199         switch (stype) {
02200         case SQL_INTEGER:
02201             type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
02202             break;
02203         case SQL_TINYINT:
02204             type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
02205             break;
02206         case SQL_SMALLINT:
02207             type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
02208             break;
02209         case SQL_FLOAT:
02210             type = SQL_C_FLOAT;
02211             break;
02212         case SQL_DOUBLE:
02213             type = SQL_C_DOUBLE;
02214             break;
02215         case SQL_TIMESTAMP:
02216             type = SQL_C_TIMESTAMP;
02217             break;
02218         case SQL_TIME:
02219             type = SQL_C_TIME;
02220             break;
02221         case SQL_DATE:
02222             type = SQL_C_DATE;
02223             break;
02224 #ifdef SQL_C_TYPE_TIMESTAMP
02225         case SQL_TYPE_TIMESTAMP:
02226             type = SQL_C_TYPE_TIMESTAMP;
02227             break;
02228 #endif
02229 #ifdef SQL_C_TYPE_TIME
02230         case SQL_TYPE_TIME:
02231             type = SQL_C_TYPE_TIME;
02232             break;
02233 #endif
02234 #ifdef SQL_C_TYPE_DATE
02235         case SQL_TYPE_DATE:
02236             type = SQL_C_TYPE_DATE;
02237             break;
02238 #endif
02239 #ifdef WINTERFACE
02240         case SQL_WVARCHAR:
02241         case SQL_WCHAR:
02242 #ifdef SQL_WLONGVARCHAR
02243         case SQL_WLONGVARCHAR:
02244 #endif
02245             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02246             break;
02247 #endif
02248         case SQL_BINARY:
02249         case SQL_VARBINARY:
02250         case SQL_LONGVARBINARY:
02251             type = SQL_C_BINARY;
02252             break;
02253 #ifdef SQL_BIT
02254         case SQL_BIT:
02255             type = SQL_C_BIT;
02256             break;
02257 #endif
02258 #ifdef SQL_BIGINT
02259         case SQL_BIGINT:
02260             type = SQL_C_CHAR;
02261             break;
02262 #endif
02263         default:
02264 #ifdef WINTERFACE
02265             type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02266 #else
02267             type = SQL_C_CHAR;
02268 #endif
02269             break;
02270         }
02271     }
02272     return type;
02273 }
02274 
02285 static char *
02286 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg)
02287 {
02288     char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
02289     int np = 0, isddl = -1, size;
02290 
02291     *errmsg = NULL;
02292     if (sqlLen != SQL_NTS) {
02293         qz = q = xmalloc(sqlLen + 1);
02294         if (!qz) {
02295             return NULL;
02296         }
02297         memcpy(q, sql, sqlLen);
02298         q[sqlLen] = '\0';
02299         size = sqlLen * 4;
02300     } else {
02301         size = strlen(sql) * 4;
02302     }
02303     size += sizeof (char *) - 1;
02304     size &= ~(sizeof (char *) - 1);
02305     p = xmalloc(size);
02306     if (!p) {
02307 errout:
02308         freep(&qz);
02309         return NULL;
02310     }
02311     memset(p, 0, size);
02312     out = p;
02313     while (*q) {
02314         switch (*q) {
02315         case '\'':
02316         case '\"':
02317             if (q == inq) {
02318                 inq = NULL;
02319             } else if (!inq) {
02320                 inq = q + 1;
02321 
02322                 while (*inq) {
02323                     if (*inq == *q) {
02324                         if (inq[1] == *q) {
02325                             inq++;
02326                         } else {
02327                             break;
02328                         }
02329                     }
02330                     inq++;
02331                 }
02332             }
02333             *p++ = *q;
02334             break;
02335         case '?':
02336             *p++ = *q;
02337             if (!inq) {
02338                 np++;
02339             }
02340             break;
02341         case ';':
02342             if (!inq) {
02343                 if (isddl < 0) {
02344                     char *qq = out;
02345 
02346                     while (*qq && ISSPACE(*qq)) {
02347                         ++qq;
02348                     }
02349                     if (*qq && *qq != ';') {
02350                         size = strlen(qq);
02351                         if ((size >= 5) &&
02352                             (strncasecmp(qq, "create", 5) == 0)) {
02353                             isddl = 1;
02354                         } else if ((size >= 4) &&
02355                                    (strncasecmp(qq, "drop", 4) == 0)) {
02356                             isddl = 1;
02357                         } else {
02358                             isddl = 0;
02359                         }
02360                     }
02361                 }
02362                 if (isddl == 0) {
02363                     char *qq = q;
02364 
02365                     do {
02366                         ++qq;
02367                     } while (*qq && ISSPACE(*qq));
02368                     if (*qq && *qq != ';') {
02369                         freep(&out);
02370                         *errmsg = "only one SQL statement allowed";
02371                         goto errout;
02372                     }
02373                 }
02374             }
02375             *p++ = *q;
02376             break;
02377         case '{':
02378             /*
02379              * Deal with escape sequences:
02380              * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
02381              * {oj ...}, {fn ...} etc.
02382              */
02383             if (!inq) {
02384                 int ojfn = 0;
02385                 char *inq2 = NULL, *end = q + 1;
02386 
02387                 if (*end != 'd' && *end != 'D' &&
02388                     *end != 't' && *end != 'T') {
02389                     ojfn = 1;
02390                 }
02391                 while (*end) {
02392                     if (inq2 && *end == *inq2) {
02393                         inq2 = NULL;
02394                     } else if (inq2 == NULL && *end == '}') {
02395                         break;
02396                     } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
02397                         inq2 = end;
02398                     }
02399                     ++end;
02400                 }
02401                 if (*end == '}') {
02402                     char *start = q + 1;
02403                     char *end2 = end - 1;
02404 
02405                     if (ojfn) {
02406                         while (start < end) {
02407                             if (ISSPACE(*start)) {
02408                                 break;
02409                             }
02410                             ++start;
02411                         }
02412                         while (start < end) {
02413                             *p++ = *start;
02414                             ++start;
02415                         }
02416                         q = end;
02417                         break;
02418                     } else {
02419                         while (start < end2 && *start != '\'') {
02420                             ++start;
02421                         }
02422                         while (end2 > start && *end2 != '\'') {
02423                             --end2;
02424                         }
02425                         if (*start == '\'' && *end2 == '\'') {
02426                             while (start <= end2) {
02427                                 *p++ = *start;
02428                                 ++start;
02429                             }
02430                             q = end;
02431                             break;
02432                         }
02433                     }
02434                 }
02435             }
02436             /* FALL THROUGH */
02437         default:
02438             *p++ = *q;
02439         }
02440         ++q;
02441     }
02442     freep(&qz);
02443     *p = '\0';
02444     if (nparam) {
02445         *nparam = np;
02446     }
02447     if (isselect) {
02448         if (isddl > 0) {
02449             *isselect = 0;
02450         } else {
02451             int incom = 0;
02452 
02453             p = out;
02454             while (*p) {
02455                 switch (*p) {
02456                 case '-':
02457                     if (!incom && p[1] == '-') {
02458                         incom = -1;
02459                     }
02460                     break;
02461                 case '\n':
02462                     if (incom < 0) {
02463                         incom = 0;
02464                     }
02465                     break;
02466                 case '/':
02467                     if (incom > 0 && p[-1] == '*') {
02468                         incom = 0;
02469                         p++;
02470                         continue;
02471                     } else if (!incom && p[1] == '*') {
02472                         incom = 1;
02473                     }
02474                     break;
02475                 }
02476                 if (!incom && !ISSPACE(*p)) {
02477                     break;
02478                 }
02479                 p++;
02480             }
02481             size = strlen(p);
02482             *isselect = (size >= 6) && (strncasecmp(p, "select", 6) == 0);
02483         }
02484     }
02485     return out;
02486 }
02487 
02496 static int
02497 findcol(char **cols, int ncols, char *name)
02498 {
02499     int i;
02500 
02501     if (cols) {
02502         for (i = 0; i < ncols; i++) {
02503             if (strcmp(cols[i], name) == 0) {
02504                 return i;
02505             }
02506         }
02507     }
02508     return -1;
02509 }
02510 
02527 static void
02528 fixupdyncols(STMT *s, DBC *d)
02529 {
02530     int i;
02531 #if !defined(HAVE_SQLITE3TABLECOLUMNMETADATA) || !(HAVE_SQLITE3TABLECOLUMNMETADATA)
02532     int k, pk, nn, t, r, nrows, ncols;
02533     char **rowp, *flagp, flags[128];
02534 #endif
02535 
02536     if (!s->dyncols) {
02537         return;
02538     }
02539     /* fixup labels */
02540     if (!s->longnames) {
02541         if (s->dcols > 1) {
02542             char *table = s->dyncols[0].table;
02543 
02544             for (i = 1; table[0] && i < s->dcols; i++) {
02545                 if (strcmp(s->dyncols[i].table, table)) {
02546                     break;
02547                 }
02548             }
02549             if (i >= s->dcols) {
02550                 for (i = 0; i < s->dcols; i++) {
02551                     s->dyncols[i].label = s->dyncols[i].column;
02552                 }
02553             }
02554         } else if (s->dcols == 1) {
02555             s->dyncols[0].label = s->dyncols[0].column;
02556         }
02557     }
02558     for (i = 0; i < s->dcols; i++) {
02559         s->dyncols[i].type =
02560             mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
02561                        s->nowchar[0] || s->nowchar[1], s->dobigint);
02562         getmd(s->dyncols[i].typename, s->dyncols[i].type,
02563               &s->dyncols[i].size, &s->dyncols[i].prec);
02564 #ifdef SQL_LONGVARCHAR
02565         if (s->dyncols[i].type == SQL_VARCHAR &&
02566             s->dyncols[i].size > 255) {
02567             s->dyncols[i].type = SQL_LONGVARCHAR;
02568         }
02569 #endif
02570 #ifdef WINTERFACE
02571 #ifdef SQL_WLONGVARCHAR
02572         if (s->dyncols[i].type == SQL_WVARCHAR &&
02573             s->dyncols[i].size > 255) {
02574             s->dyncols[i].type = SQL_WLONGVARCHAR;
02575         }
02576 #endif
02577 #endif
02578         if (s->dyncols[i].type == SQL_VARBINARY &&
02579             s->dyncols[i].size > 255) {
02580             s->dyncols[i].type = SQL_LONGVARBINARY;
02581         }
02582     }
02583 #if !defined(HAVE_SQLITE3TABLECOLUMNMETADATA) || !(HAVE_SQLITE3TABLECOLUMNMETADATA)
02584     if (s->dcols > array_size(flags)) {
02585         flagp = xmalloc(sizeof (flags[0]) * s->dcols);
02586         if (flagp == NULL) {
02587             return;
02588         }
02589     } else {
02590         flagp = flags;
02591     }
02592     memset(flagp, 0, sizeof (flags[0]) * s->dcols);
02593     for (i = 0; i < s->dcols; i++) {
02594         s->dyncols[i].autoinc = SQL_FALSE;
02595         s->dyncols[i].notnull = SQL_NULLABLE;
02596     }
02597     for (i = 0; i < s->dcols; i++) {
02598         int ret, lastpk = -1, autoinccount = 0;
02599         char *sql;
02600 
02601         if (!s->dyncols[i].table[0]) {
02602             continue;
02603         }
02604         if (flagp[i]) {
02605             continue;
02606         }
02607         sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
02608         if (!sql) {
02609             continue;
02610         }
02611         dbtraceapi(d, "sqlite3_get_table", sql);
02612         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
02613         sqlite3_free(sql);
02614         if (ret != SQLITE_OK) {
02615             continue;
02616         }
02617         k = findcol(rowp, ncols, "name");
02618         t = findcol(rowp, ncols, "type");
02619         pk = findcol(rowp, ncols, "pk");
02620         nn = findcol(rowp, ncols, "notnull");
02621         if (k < 0 || t < 0) {
02622             goto freet;
02623         }
02624         for (r = 1; r <= nrows; r++) {
02625             int m;
02626 
02627             for (m = i; m < s->dcols; m++) {
02628                 char *colname = s->dyncols[m].column;
02629 
02630                 if (s->longnames) {
02631                     char *dotp = strchr(colname, '.');
02632 
02633                     if (dotp) {
02634                         colname = dotp + 1;
02635                     }
02636                 }
02637                 if (!flagp[m] &&
02638                     strcmp(colname, rowp[r * ncols + k]) == 0 &&
02639                     strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
02640                     char *typename = rowp[r * ncols + t];
02641 
02642                     flagp[m] = 1;
02643                     freep(&s->dyncols[m].typename);
02644                     s->dyncols[m].typename = xstrdup(typename);
02645                     s->dyncols[m].type =
02646                         mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
02647                                    s->nowchar[0] || s->nowchar[1],
02648                                    s->dobigint);
02649                     getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
02650                           &s->dyncols[m].prec);
02651 #ifdef SQL_LONGVARCHAR
02652                     if (s->dyncols[m].type == SQL_VARCHAR &&
02653                         s->dyncols[m].size > 255) {
02654                         s->dyncols[m].type = SQL_LONGVARCHAR;
02655                     }
02656 #endif
02657 #ifdef WINTERFACE
02658 #ifdef SQL_WLONGVARCHAR
02659                     if (s->dyncols[i].type == SQL_WVARCHAR &&
02660                         s->dyncols[i].size > 255) {
02661                         s->dyncols[i].type = SQL_WLONGVARCHAR;
02662                     }
02663 #endif
02664 #endif
02665                     if (s->dyncols[i].type == SQL_VARBINARY &&
02666                         s->dyncols[i].size > 255) {
02667                         s->dyncols[i].type = SQL_LONGVARBINARY;
02668                     }
02669                     if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
02670                         if (++autoinccount > 1) {
02671                             if (lastpk >= 0) {
02672                                 s->dyncols[lastpk].autoinc = SQL_FALSE;
02673                                 lastpk = -1;
02674                             }
02675                         } else {
02676                             lastpk = m;
02677                             if (strlen(typename) == 7 &&
02678                                 strncasecmp(typename, "integer", 7) == 0) {
02679                                 s->dyncols[m].autoinc = SQL_TRUE;
02680                             }
02681                         }
02682                     }
02683                     if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
02684                         s->dyncols[m].notnull = SQL_NO_NULLS;
02685                     }
02686                 }
02687             }
02688         }
02689 freet:
02690         sqlite3_free_table(rowp);
02691     }
02692     if (flagp != flags) {
02693         freep(&flagp);
02694     }
02695 #endif
02696 }
02697 
02705 static int
02706 getmdays(int year, int month)
02707 {
02708     static const int mdays[] = {
02709         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
02710     };
02711     int mday;
02712 
02713     if (month < 1) {
02714         return 0;
02715     }
02716     mday = mdays[(month - 1) % 12];
02717     if (mday == 28 && year % 4 == 0 &&
02718         (!(year % 100 == 0) || year % 400 == 0)) {
02719         mday++;
02720     }
02721     return mday;
02722 }
02723 
02735 static int
02736 str2date(char *str, DATE_STRUCT *ds)
02737 {
02738     int i, err = 0;
02739     char *p, *q, sepc = '\0';
02740 
02741     ds->year = ds->month = ds->day = 0;
02742     p = str;
02743     while (*p && !ISDIGIT(*p)) {
02744         ++p;
02745     }
02746     q = p;
02747     i = 0;
02748     while (*q && !ISDIGIT(*q)) {
02749         ++i;
02750         ++q;
02751     }
02752     if (i >= 8) {
02753         char buf[8];
02754 
02755         strncpy(buf, p + 0, 4); buf[4] = '\0';
02756         ds->year = strtol(buf, NULL, 10);
02757         strncpy(buf, p + 4, 2); buf[2] = '\0';
02758         ds->month = strtol(buf, NULL, 10);
02759         strncpy(buf, p + 6, 2); buf[2] = '\0';
02760         ds->day = strtol(buf, NULL, 10);
02761         goto done;
02762     }
02763     i = 0;
02764     while (i < 3) {
02765         int n;
02766 
02767         q = NULL; 
02768         n = strtol(p, &q, 10);
02769         if (!q || q == p) {
02770             if (*q == '\0') {
02771                 if (i == 0) {
02772                     err = 1;
02773                 }
02774                 goto done;
02775             }
02776         }
02777         if (!sepc) {
02778             sepc = *q;
02779         }
02780         if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
02781             switch (i) {
02782             case 0: ds->year = n; break;
02783             case 1: ds->month = n; break;
02784             case 2: ds->day = n; break;
02785             }
02786             ++i;
02787             if (*q) {
02788                 ++q;
02789             }
02790         } else {
02791             i = 0;
02792             while (*q && !ISDIGIT(*q)) {
02793                 ++q;
02794             }
02795         }
02796         p = q;
02797     }
02798 done:
02799     /* final check for overflow */
02800     if (err ||
02801         ds->month < 1 || ds->month > 12 ||
02802         ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
02803         if (sepc == '/') {
02804             /* Try MM/DD/YYYY format */
02805             int t[3];
02806 
02807             t[0] = ds->year;
02808             t[1] = ds->month;
02809             t[2] = ds->day;
02810             ds->year = t[2];
02811             ds->day = t[1];
02812             ds->month = t[0];
02813             if (ds->month >= 1 && ds->month <= 12 &&
02814                 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
02815                 return 0;
02816             }
02817         }
02818         return -1;
02819     }
02820     return 0;
02821 }
02822 
02833 static int
02834 str2time(char *str, TIME_STRUCT *ts)
02835 {
02836     int i, err = 0, ampm = -1;
02837     char *p, *q;
02838 
02839     ts->hour = ts->minute = ts->second = 0;
02840     p = str;
02841     while (*p && !ISDIGIT(*p)) {
02842         ++p;
02843     }
02844     q = p;
02845     i = 0;
02846     while (*q && ISDIGIT(*q)) {
02847         ++i;
02848         ++q;
02849     }
02850     if (i >= 6) {
02851         char buf[4];
02852 
02853         strncpy(buf, p + 0, 2); buf[2] = '\0';
02854         ts->hour = strtol(buf, NULL, 10);
02855         strncpy(buf, p + 2, 2); buf[2] = '\0';
02856         ts->minute = strtol(buf, NULL, 10);
02857         strncpy(buf, p + 4, 2); buf[2] = '\0';
02858         ts->second = strtol(buf, NULL, 10);
02859         goto done;
02860     }
02861     i = 0;
02862     while (i < 3) {
02863         int n;
02864 
02865         q = NULL; 
02866         n = strtol(p, &q, 10);
02867         if (!q || q == p) {
02868             if (*q == '\0') {
02869                 if (i == 0) {
02870                     err = 1;
02871                 }
02872                 goto done;
02873             }
02874         }
02875         if (*q == ':' || *q == '\0' || i == 2) {
02876             switch (i) {
02877             case 0: ts->hour = n; break;
02878             case 1: ts->minute = n; break;
02879             case 2: ts->second = n; break;
02880             }
02881             ++i;
02882             if (*q) {
02883                 ++q;
02884             }
02885         } else {
02886             i = 0;
02887             while (*q && !ISDIGIT(*q)) {
02888                 ++q;
02889             }
02890         }
02891         p = q;
02892     }
02893     if (!err) {
02894         while (*p) {
02895             if ((p[0] == 'p' || p[0] == 'P') &&
02896                 (p[1] == 'm' || p[1] == 'M')) {
02897                 ampm = 1;
02898             } else if ((p[0] == 'a' || p[0] == 'A') &&
02899                 (p[1] == 'm' || p[1] == 'M')) {
02900                 ampm = 0;
02901             }
02902             ++p;
02903         }
02904         if (ampm > 0) {
02905             if (ts->hour < 12) {
02906                 ts->hour += 12;
02907             }
02908         } else if (ampm == 0) {
02909             if (ts->hour == 12) {
02910                 ts->hour = 0;
02911             }
02912         }
02913     }
02914 done:
02915     /* final check for overflow */
02916     if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
02917         return -1;
02918     }
02919     return 0;
02920 }
02921 
02937 static int
02938 str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
02939 {
02940     int i, m, n, err = 0, ampm = -1;
02941     char *p, *q, in = '\0', sepc = '\0';
02942 
02943     tss->year = tss->month = tss->day = 0;
02944     tss->hour = tss->minute = tss->second = 0;
02945     tss->fraction = 0;
02946     p = str;
02947     while (*p && !ISDIGIT(*p)) {
02948         ++p;
02949     }
02950     q = p;
02951     i = 0;
02952     while (*q && ISDIGIT(*q)) {
02953         ++i;
02954         ++q;
02955     }
02956     if (i >= 14) {
02957         char buf[16];
02958 
02959         strncpy(buf, p + 0, 4); buf[4] = '\0';
02960         tss->year = strtol(buf, NULL, 10);
02961         strncpy(buf, p + 4, 2); buf[2] = '\0';
02962         tss->month = strtol(buf, NULL, 10);
02963         strncpy(buf, p + 6, 2); buf[2] = '\0';
02964         tss->day = strtol(buf, NULL, 10);
02965         strncpy(buf, p + 8, 2); buf[2] = '\0';
02966         tss->hour = strtol(buf, NULL, 10);
02967         strncpy(buf, p + 10, 2); buf[2] = '\0';
02968         tss->minute = strtol(buf, NULL, 10);
02969         strncpy(buf, p + 12, 2); buf[2] = '\0';
02970         tss->second = strtol(buf, NULL, 10);
02971         if (i > 14) {
02972             m = i - 14;
02973             strncpy(buf, p + 14, m);
02974             while (m < 9) {
02975                 buf[m] = '0';
02976                 ++m;
02977             }
02978             buf[m] = '\0';
02979             tss->fraction = strtol(buf, NULL, 10);
02980         }
02981         m = 7;
02982         goto done;
02983     }
02984     m = i = 0;
02985     while ((m & 7) != 7) {
02986         q = NULL; 
02987         n = strtol(p, &q, 10);
02988         if (!q || q == p) {
02989             if (*q == '\0') {
02990                 if (m < 1) {
02991                     err = 1;
02992                 }
02993                 goto done;
02994             }
02995         }
02996         if (in == '\0') {
02997             switch (*q) {
02998             case '-':
02999             case '/':
03000                 if ((m & 1) == 0) {
03001                     in = *q;
03002                     i = 0;
03003                 }
03004                 break;
03005             case ':':
03006                 if ((m & 2) == 0) {
03007                     in = *q;
03008                     i = 0;
03009                 }
03010                 break;
03011             case ' ':
03012             case '.':
03013                 break;
03014             default:
03015                 in = '\0';
03016                 i = 0;
03017                 break;
03018             }
03019         }
03020         switch (in) {
03021         case '-':
03022         case '/':
03023             if (!sepc) {
03024                 sepc = in;
03025             }
03026             switch (i) {
03027             case 0: tss->year = n; break;
03028             case 1: tss->month = n; break;
03029             case 2: tss->day = n; break;
03030             }
03031             if (++i >= 3) {
03032                 i = 0;
03033                 m |= 1;
03034                 if (!(m & 2)) {
03035                     m |= 8;
03036                 }
03037                 goto skip;
03038             } else {
03039                 ++q;
03040             }
03041             break;
03042         case ':':
03043             switch (i) {
03044             case 0: tss->hour = n; break;
03045             case 1: tss->minute = n; break;
03046             case 2: tss->second = n; break;
03047             }
03048             if (++i >= 3) {
03049                 i = 0;
03050                 m |= 2;
03051                 if (*q == '.') {
03052                     in = '.';
03053                     goto skip2;
03054                 }
03055                 if (*q == ' ') {
03056                     if ((m & 1) == 0) {
03057                         char *e = NULL;
03058                         int dummy;
03059 
03060                         dummy = strtol(q + 1, &e, 10);
03061                         if (e && *e == '-') {
03062                             goto skip;
03063                         }
03064                     }
03065                     in = '.';
03066                     goto skip2;
03067                 }
03068                 goto skip;
03069             } else {
03070                 ++q;
03071             }
03072             break;
03073         case '.':
03074             if (++i >= 1) {
03075                 int ndig = q - p;
03076 
03077                 if (p[0] == '+' || p[0] == '-') {
03078                     ndig--;
03079                 }
03080                 while (ndig < 9) {
03081                     n = n * 10;
03082                     ++ndig;
03083                 }
03084                 tss->fraction = n;
03085                 m |= 4;
03086                 i = 0;
03087             }
03088         default:
03089         skip:
03090             in = '\0';
03091         skip2:
03092             while (*q && !ISDIGIT(*q)) {
03093                 if ((q[0] == 'a' || q[0] == 'A') &&
03094                     (q[1] == 'm' || q[1] == 'M')) {
03095                     ampm = 0;
03096                     ++q;
03097                 } else if ((q[0] == 'p' || q[0] == 'P') &&
03098                            (q[1] == 'm' || q[1] == 'M')) {
03099                     ampm = 1;
03100                     ++q;
03101                 }
03102                 ++q;
03103             }
03104         }
03105         p = q;
03106     }
03107     if ((m & 7) > 1 && (m & 8)) {
03108         /* ISO8601 timezone */
03109         if (p > str && ISDIGIT(*p)) {
03110             int nn, sign;
03111 
03112             q = p - 1;
03113             if (*q != '+' && *q != '-') {
03114                 goto done;
03115             }
03116             sign = (*q == '+') ? -1 : 1;
03117             q = NULL;
03118             n = strtol(p, &q, 10);
03119             if (!q || *q++ != ':' || !ISDIGIT(*q)) {
03120                 goto done;
03121             }
03122             p = q;
03123             q = NULL;
03124             nn = strtol(p, &q, 10);
03125             tss->minute += nn * sign;
03126             if ((SQLSMALLINT) tss->minute < 0) {
03127                 tss->hour -= 1;
03128                 tss->minute += 60;
03129             } else if (tss->minute >= 60) {
03130                 tss->hour += 1;
03131                 tss->minute -= 60;
03132             }
03133             tss->hour += n * sign;
03134             if ((SQLSMALLINT) tss->hour < 0) {
03135                 tss->day -= 1;
03136                 tss->hour += 24;
03137             } else if (tss->hour >= 24) {
03138                 tss->day += 1;
03139                 tss->hour -= 24;
03140             }
03141             if ((short) tss->day < 1 || tss->day >= 28) {
03142                 int mday, pday, pmon;
03143 
03144                 mday = getmdays(tss->year, tss->month);
03145                 pmon = tss->month - 1;
03146                 if (pmon < 1) {
03147                     pmon = 12;
03148                 }
03149                 pday = getmdays(tss->year, pmon);
03150                 if ((SQLSMALLINT) tss->day < 1) {
03151                     tss->month -= 1;
03152                     tss->day = pday;
03153                 } else if (tss->day > mday) {
03154                     tss->month += 1;
03155                     tss->day = 1;
03156                 }
03157                 if ((SQLSMALLINT) tss->month < 1) {
03158                     tss->year -= 1;
03159                     tss->month = 12;
03160                 } else if (tss->month > 12) {
03161                     tss->year += 1;
03162                     tss->month = 1;
03163                 }
03164             }
03165         }
03166     }
03167 done:
03168     if ((m & 1) &&
03169         (tss->month < 1 || tss->month > 12 ||
03170          tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
03171         if (sepc == '/') {
03172             /* Try MM/DD/YYYY format */
03173             int t[3];
03174 
03175             t[0] = tss->year;
03176             t[1] = tss->month;
03177             t[2] = tss->day;
03178             tss->year = t[2];
03179             tss->day = t[1];
03180             tss->month = t[0];
03181         }
03182     }
03183     /* Replace missing year/month/day with current date */
03184     if (!err && (m & 1) == 0) {
03185 #ifdef _WIN32
03186         SYSTEMTIME t;
03187 
03188         GetLocalTime(&t);
03189         tss->year = t.wYear;
03190         tss->month = t.wMonth;
03191         tss->day = t.wDay;
03192 #else
03193         struct timeval tv;
03194         struct tm tm;
03195 
03196         gettimeofday(&tv, NULL);
03197         tm = *localtime(&tv.tv_sec);
03198         tss->year = tm.tm_year + 1900;
03199         tss->month = tm.tm_mon + 1;
03200         tss->day = tm.tm_mday;
03201 #endif
03202     }
03203     /* Normalize fraction */
03204     if (tss->fraction < 0) {
03205         tss->fraction = 0;
03206     }
03207     /* Final check for overflow */
03208     if (err ||
03209         tss->month < 1 || tss->month > 12 ||
03210         tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
03211         tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
03212         return -1;
03213     }
03214     if ((m & 7) > 1) {
03215         if (ampm > 0) {
03216             if (tss->hour < 12) {
03217                 tss->hour += 12;
03218             }
03219         } else if (ampm == 0) {
03220             if (tss->hour == 12) {
03221                 tss->hour = 0;
03222             }
03223         }
03224     }
03225     return ((m & 7) < 1) ? -1 : 0;
03226 }
03227 
03234 static int
03235 getbool(char *string)
03236 {
03237     if (string) {
03238         return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
03239     }
03240     return 0;
03241 }
03242 
03250 static void
03251 blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03252 {
03253 #if 0
03254     DBC *d = (DBC *) sqlite3_user_data(ctx);
03255 #endif
03256     char *filename = 0;
03257 
03258     if (nargs > 0) {
03259         if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
03260             filename = (char *) sqlite3_value_text(args[0]);
03261         }
03262     }
03263     if (filename) {
03264 #ifdef _WIN32
03265         char *wname = utf_to_wmb(filename, -1);
03266         FILE *f;
03267 #else
03268         FILE *f = fopen(filename, "r");
03269 #endif
03270         char *p;
03271         long n, nn;
03272 
03273 #ifdef _WIN32
03274         if (wname) {
03275             f = fopen(wname, "rb");
03276         } else {
03277             sqlite3_result_error(ctx, "out of memory", -1);
03278             return;
03279         }
03280         uc_free(wname);
03281 #endif
03282         if (f) {
03283             if (fseek(f, 0, SEEK_END) == 0) {
03284                 n = ftell(f);
03285                 if (fseek(f, 0, SEEK_SET) == 0) {
03286                     p = sqlite3_malloc(n);
03287                     if (p) {
03288                         nn = fread(p, 1, n, f);
03289                         if (nn != n) {
03290                             sqlite3_result_error(ctx, "read error", -1);
03291                             sqlite3_free(p);
03292                         } else {
03293                             sqlite3_result_blob(ctx, p, n, sqlite3_free);
03294                         }
03295                     } else {
03296                         sqlite3_result_error(ctx, "out of memory", -1);
03297                     }
03298                 } else {
03299                     sqlite3_result_error(ctx, "seek error", -1);
03300                 }
03301             } else {
03302                 sqlite3_result_error(ctx, "seek error", -1);
03303             }
03304             fclose(f);
03305         } else {
03306             sqlite3_result_error(ctx, "cannot open file", -1);
03307         }
03308     } else {
03309         sqlite3_result_error(ctx, "no filename given", -1);
03310     }
03311 }
03312 
03320 static void
03321 blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
03322 {
03323 #if 0
03324     DBC *d = (DBC *) sqlite3_user_data(ctx);
03325 #endif
03326     char *filename = 0;
03327     char *p = 0;
03328     int n = 0;
03329 
03330     if (nargs > 0) {
03331         p = (char *) sqlite3_value_blob(args[0]);
03332         n = sqlite3_value_bytes(args[0]);
03333     }
03334     if (nargs > 1) {
03335         if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
03336             filename = (char *) sqlite3_value_text(args[1]);
03337         }
03338     }
03339     if (p) {
03340         if (filename) {
03341 #ifdef _WIN32
03342             char *wname = utf_to_wmb(filename, -1);
03343             FILE *f;
03344 #else
03345             FILE *f = fopen(filename, "w");
03346 #endif
03347             int nn;
03348 
03349 #ifdef _WIN32
03350             if (wname) {
03351                 f = fopen(wname, "wb");
03352             } else {
03353                 sqlite3_result_error(ctx, "out of memory", -1);
03354                 return;
03355             }
03356             uc_free(wname);
03357 #endif
03358             if (f) {
03359                 nn = fwrite(p, 1, n, f);
03360                 if (nn != n) {
03361                     sqlite3_result_error(ctx, "write error", -1);
03362                 } else {
03363                     sqlite3_result_int(ctx, nn);
03364                 }
03365             } else {
03366                 sqlite3_result_error(ctx, "cannot open file", -1);
03367             }
03368         } else {
03369             sqlite3_result_error(ctx, "no filename given", -1);
03370         }
03371     } else {
03372         sqlite3_result_null(ctx);
03373     }
03374 }
03375 
03383 static void
03384 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03385 dbtrace(void *arg, const char *msg, sqlite_uint64 et)
03386 #else
03387 dbtrace(void *arg, const char *msg)
03388 #endif
03389 {
03390     DBC *d = (DBC *) arg;
03391 
03392     if (msg && d->trace) {
03393         int len = strlen(msg);
03394 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03395         unsigned long s, f;
03396 #endif
03397 
03398         if (len > 0) {
03399             char *end = "\n";
03400 
03401             if (msg[len - 1] != ';') {
03402                 end = ";\n";
03403             }
03404             fprintf(d->trace, "%s%s", msg, end);
03405 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03406             s = et / 1000000000LL;
03407             f = et % 1000000000LL;
03408             fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
03409 #endif
03410             fflush(d->trace);
03411         }
03412     }
03413 }
03414 
03422 static void
03423 dbtraceapi(DBC *d, char *fn, const char *sql)
03424 {
03425     if (fn && d->trace) {
03426         if (sql) {
03427             fprintf(d->trace, "-- %s: %s\n", fn, sql);
03428         } else {
03429             fprintf(d->trace, "-- %s\n", fn);
03430         }
03431         fflush(d->trace);
03432     }
03433 }
03434 
03442 static void
03443 dbtracerc(DBC *d, int rc, char *err)
03444 {
03445     if (rc != SQLITE_OK && d->trace) {
03446         fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
03447         fprintf(d->trace, err ? ": %s\n" : "\n", err);
03448         fflush(d->trace);
03449     }
03450 }
03451 
03466 static SQLRETURN
03467 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
03468        char *spflag, char *ntflag, char *jmode, char *busy)
03469 {
03470     char *endp = NULL;
03471     int rc, tmp, busyto = 100000;
03472 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03473     int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
03474     char *uname = name;
03475     const char *vfs_name = NULL;
03476 #endif
03477 
03478     if (d->sqlite) {
03479         if (d->trace) {
03480             fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
03481                     d->dbname);
03482             fflush(d->trace);
03483         }
03484         sqlite3_close(d->sqlite);
03485         d->sqlite = NULL;
03486     }
03487 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
03488     if (d->nocreat) {
03489         flags &= ~ SQLITE_OPEN_CREATE;
03490     }
03491 #if defined(_WIN32) || defined(_WIN64)
03492     if (!isu) {
03493         uname = wmb_to_utf(name, -1);
03494         if (!uname) {
03495             rc = SQLITE_NOMEM;
03496             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
03497             return SQL_ERROR;
03498         }
03499     }
03500 #endif
03501 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
03502     vfs_name = nvfs_makevfs(uname);
03503 #endif
03504 #ifdef SQLITE_OPEN_URI
03505     flags |= SQLITE_OPEN_URI;
03506 #endif
03507     rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
03508 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
03509     if (uname != name) {
03510         uc_free(uname);
03511     }
03512 #endif
03513 #else
03514 #if defined(_WIN32) || defined(_WIN64)
03515     if (d->nocreat) {
03516         char *cname = NULL;
03517 
03518         if (isu) {
03519             cname = utf_to_wmb(name, -1);
03520         }
03521         if (GetFileAttributesA(cname ? cname : name) ==
03522             INVALID_FILE_ATTRIBUTES) {
03523             uc_free(cname);
03524             rc = SQLITE_CANTOPEN;
03525             setstatd(d, rc, "cannot open database",
03526                      (*d->ov3) ? "HY000" : "S1000");
03527             return SQL_ERROR;
03528         }
03529         uc_free(cname);
03530     }
03531 #else
03532     if (d->nocreat && access(name, 004) < 0) {
03533         rc = SQLITE_CANTOPEN;
03534         setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
03535         return SQL_ERROR;
03536     }
03537 #endif
03538 #if defined(_WIN32) || defined(_WIN64)
03539     if (!isu) {
03540         WCHAR *wname = wmb_to_uc(name, -1);
03541 
03542         if (!wname) {
03543             rc = SQLITE_NOMEM;
03544             setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
03545             return SQL_ERROR;
03546         }
03547         rc = sqlite3_open16(wname, &d->sqlite);
03548         uc_free(wname);
03549     } else
03550 #endif
03551     rc = sqlite3_open(name, &d->sqlite);
03552 #endif /* !HAVE_SQLITE3VFS */
03553     if (rc != SQLITE_OK) {
03554 connfail:
03555         setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
03556         if (d->sqlite) {
03557             sqlite3_close(d->sqlite);
03558             d->sqlite = NULL;
03559         }
03560         return SQL_ERROR;
03561     }
03562 #if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
03563     if (d->pwd) {
03564         sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
03565     }
03566 #endif
03567     d->pwd = NULL;
03568     d->pwdLen = 0;
03569     if (d->trace) {
03570 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
03571         sqlite3_profile(d->sqlite, dbtrace, d);
03572 #else
03573         sqlite3_trace(d->sqlite, dbtrace, d);
03574 #endif
03575     }
03576     d->step_enable = getbool(sflag);
03577     d->trans_disable = getbool(ntflag);
03578     d->curtype = d->step_enable ?
03579         SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
03580     tmp = strtol(busy, &endp, 0);
03581     if (endp && *endp == '\0' && endp != busy) {
03582         busyto = tmp;
03583     }
03584     if (busyto < 1 || busyto > 1000000) {
03585         busyto = 1000000;
03586     }
03587     d->timeout = busyto;
03588     if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
03589         if (d->trace) {
03590             fprintf(d->trace, "-- sqlite3_close: '%s'\n",
03591                     d->dbname);
03592             fflush(d->trace);
03593         }
03594         sqlite3_close(d->sqlite);
03595         d->sqlite = NULL;
03596         goto connfail;
03597     }
03598     if (!spflag || spflag[0] == '\0') {
03599         spflag = "NORMAL";
03600     }
03601     if (spflag[0] != '\0') {
03602         char syncp[128];
03603 
03604         sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
03605         sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
03606     }
03607     if (jmode[0] != '\0') {
03608         char jourp[128];
03609 
03610         sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
03611         sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
03612     }
03613     freep(&d->dbname);
03614     d->dbname = xstrdup(name);
03615     freep(&d->dsn);
03616     d->dsn = xstrdup(dsn);
03617     if (d->trace) {
03618         fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
03619         fflush(d->trace);
03620     }
03621 #if defined(_WIN32) || defined(_WIN64)
03622     {
03623         char pname[MAX_PATH];
03624         HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
03625                                FALSE, GetCurrentProcessId());
03626 
03627         pname[0] = '\0';
03628         if (h) {
03629             HMODULE m = NULL, l = LoadLibrary("psapi.dll");
03630             DWORD need;
03631             typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
03632             typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
03633             epmfunc epm;
03634             gmbfunc gmb;
03635 
03636             if (l) {
03637                 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
03638                 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
03639                 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
03640                     gmb(h, m, pname, sizeof (pname));
03641                 }
03642                 FreeLibrary(l);
03643             }
03644             CloseHandle(h);
03645         }
03646         d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
03647                      strncasecmp(pname, "MSQRY", 5) == 0;
03648         if (d->trace && d->xcelqrx) {
03649             fprintf(d->trace, "-- enabled EXCEL quirks\n");
03650             fflush(d->trace);
03651         }
03652     }
03653 #endif
03654     sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
03655                             d, blob_import, 0, 0);
03656     sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
03657                             d, blob_export, 0, 0);
03658     return SQL_SUCCESS;
03659 }
03660 
03667 static void
03668 dbloadext(DBC *d, char *exts)
03669 {
03670 #if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
03671     char *p;
03672     char path[SQL_MAX_MESSAGE_LENGTH];
03673     int plen = 0;
03674 
03675     if (!d->sqlite) {
03676         return;
03677     }
03678     sqlite3_enable_load_extension(d->sqlite, 1);
03679 #if defined(_WIN32) || defined(_WIN64)
03680     GetModuleFileName(hModule, path, sizeof (path));
03681     p = strrchr(path, '\\');
03682     plen = p ? ((p + 1) - path) : 0;
03683 #endif
03684     do {
03685         p = strchr(exts, ',');
03686         if (p) {
03687             strncpy(path + plen, exts, p - exts);
03688             path[plen + (p - exts)] = '\0';
03689         } else {
03690             strcpy(path + plen, exts);
03691         }
03692         if (exts[0]) {
03693             char *errmsg = NULL;
03694             int rc;
03695 #if defined(_WIN32) || defined(_WIN64)
03696             char *q;
03697 
03698             q = path + plen;
03699             if (!(q[0] &&
03700                   ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
03701                    q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
03702                 q = path;
03703             }
03704             rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
03705 #else
03706             rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
03707 #endif
03708             if (rc != SQLITE_OK) {
03709 #if defined(_WIN32) || defined(_WIN64)
03710                 char buf[512], msg[512];
03711 
03712                 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
03713                 wsprintf(msg, buf, q, errmsg ?
03714                          errmsg : "no error info available");
03715                 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
03716                 MessageBox(NULL, msg, buf,
03717                            MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
03718                            MB_SETFOREGROUND);
03719 #else
03720                 fprintf(stderr, "extension '%s' did not load%s%s\n",
03721                         path, errmsg ? ": " : "", errmsg ? errmsg : "");
03722 #endif
03723             }
03724         }
03725         if (p) {
03726             exts = p + 1;
03727         }
03728     } while (p);
03729 #endif /* HAVE_SQLITE3LOADEXTENSION */
03730 }
03731 
03741 static char *
03742 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
03743 {
03744     char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
03745     char guess[64];
03746 
03747     guess[0] = '\0';
03748     if (!typename) {
03749         int coltype = sqlite3_column_type(s3stmt, col);
03750 
03751         if (guessed_types) {
03752             guessed_types[0]++;
03753         }
03754         if (d->trace) {
03755             sprintf(guess, " (guessed from %d)", coltype);
03756         }
03757         switch (coltype) {
03758         case SQLITE_INTEGER: typename = "integer"; break;
03759         case SQLITE_FLOAT:   typename = "double";  break;
03760         default:
03761         case SQLITE_TEXT:    typename = "varchar"; break;
03762         case SQLITE_BLOB:    typename = "blob";    break;
03763 #if 0
03764         case SQLITE_NULL:    typename = "null";    break;
03765 #endif
03766         }
03767     }
03768     if (d->trace) {
03769         fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
03770                 guess, typename);
03771         fflush(d->trace);
03772     }
03773     return typename;
03774 }
03775 
03776 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
03777 
03786 static void
03787 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
03788 {
03789     int nn = 0, pk = 0, ai = 0;
03790     const char *dn, *tn, *cn, *dummy1, *dummy2;
03791 
03792     dn = sqlite3_column_database_name(s3stmt, col);
03793     tn = sqlite3_column_table_name(s3stmt, col);
03794     cn = sqlite3_column_origin_name(s3stmt, col);
03795     sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
03796                                   &dummy1, &dummy2,
03797                                   &nn, &pk, &ai);
03798     ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
03799     ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
03800     if (d->trace) {
03801         fprintf(d->trace, "-- column %d %s\n",
03802                 col + 1, nn ? "notnull" : "nullable");
03803         if (ai) {
03804             fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
03805         }
03806         fflush(d->trace);
03807     }
03808 }
03809 
03810 #endif
03811 
03818 static int
03819 s3stmt_step(STMT *s)
03820 {
03821     DBC *d = (DBC *) s->dbc;
03822     char **rowd = NULL;
03823     const char *errp = NULL;
03824     int i, ncols, rc;
03825 
03826     if (s != d->cur_s3stmt || !s->s3stmt) {
03827         setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
03828         return SQL_ERROR;
03829     }
03830     rc = sqlite3_step(s->s3stmt);
03831     if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
03832         ++s->s3stmt_rownum;
03833         ncols = sqlite3_column_count(s->s3stmt);
03834         if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
03835             PTRDIFF_T size;
03836             char *p;
03837             COL *dyncols;
03838             const char *colname, *typename;
03839 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03840             char *tblname;
03841 #endif
03842 
03843             for (i = size = 0; i < ncols; i++) {
03844                 colname = sqlite3_column_name(s->s3stmt, i);
03845                 size += 3 + 3 * strlen(colname);
03846             }
03847 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03848             tblname = (char *) size;
03849             for (i = 0; i < ncols; i++) {
03850                 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
03851                 size += 2 + (p ? strlen(p) : 0);
03852             }
03853 #endif
03854             dyncols = xmalloc(ncols * sizeof (COL) + size);
03855             if (!dyncols) {
03856                 freedyncols(s);
03857                 s->ncols = 0;
03858                 dbtraceapi(d, "sqlite3_finalize", 0);
03859                 sqlite3_finalize(s->s3stmt);
03860                 s->s3stmt = NULL;
03861                 d->cur_s3stmt = NULL;
03862                 return nomem(s);
03863             }
03864             p = (char *) (dyncols + ncols);
03865 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03866             tblname = p + (PTRDIFF_T) tblname;    
03867 #endif
03868             for (i = 0; i < ncols; i++) {
03869                 char *q;
03870 
03871                 colname = sqlite3_column_name(s->s3stmt, i);
03872                 if (d->trace) {
03873                     fprintf(d->trace, "-- column %d name: '%s'\n",
03874                             i + 1, colname);
03875                     fflush(d->trace);
03876                 }
03877 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03878                 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
03879                 strcpy(tblname, q ? q : "");
03880                 if (d->trace) {
03881                     fprintf(d->trace, "-- table %d name: '%s'\n",
03882                             i + 1, tblname);
03883                     fflush(d->trace);
03884                 }
03885                 dyncols[i].table = tblname;
03886                 tblname += strlen(tblname) + 1;
03887 #endif
03888                 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
03889                 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
03890                 strcpy(p, colname);
03891                 dyncols[i].label = p;
03892                 p += strlen(p) + 1;
03893                 q = strchr(colname, '.');
03894                 if (q) {
03895                     char *q2 = strchr(q + 1, '.');
03896 
03897                     /* SQLite 3.3.4 produces view.table.column sometimes */
03898                     if (q2) {
03899                         q = q2;
03900                     }
03901                 }
03902                 if (q) {
03903 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
03904                     dyncols[i].table = p;
03905 #endif
03906                     strncpy(p, colname, q - colname);
03907                     p[q - colname] = '\0';
03908                     p += strlen(p) + 1;
03909                     strcpy(p, q + 1);
03910                     dyncols[i].column = p;
03911                     p += strlen(p) + 1;
03912                 } else {
03913 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
03914                     dyncols[i].table = "";
03915 #endif
03916                     strcpy(p, colname);
03917                     dyncols[i].column = p;
03918                     p += strlen(p) + 1;
03919                 }
03920                 if (s->longnames) {
03921                     dyncols[i].column = dyncols[i].label;
03922                 }
03923 #ifdef SQL_LONGVARCHAR
03924                 dyncols[i].type = SQL_LONGVARCHAR;
03925                 dyncols[i].size = 65535;
03926 #else
03927                 dyncols[i].type = SQL_VARCHAR;
03928                 dyncols[i].size = 255;
03929 #endif
03930                 dyncols[i].index = i;
03931                 dyncols[i].scale = 0;
03932                 dyncols[i].prec = 0;
03933                 dyncols[i].nosign = 1;
03934 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
03935                 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
03936 #else
03937                 dyncols[i].autoinc = SQL_FALSE;
03938                 dyncols[i].notnull = SQL_NULLABLE;
03939 #endif
03940                 dyncols[i].typename = xstrdup(typename);
03941             }
03942             freedyncols(s);
03943             s->ncols = s->dcols = ncols;
03944             s->dyncols = s->cols = dyncols;
03945             fixupdyncols(s, d);
03946             mkbindcols(s, s->ncols);
03947             d->s3stmt_needmeta = 0;
03948         }
03949         if (ncols <= 0) {
03950             goto killstmt;
03951         }
03952         if (rc == SQLITE_DONE) {
03953             freeresult(s, 0);
03954             s->nrows = 0;
03955             dbtraceapi(d, "sqlite3_finalize", 0);
03956             sqlite3_finalize(s->s3stmt);
03957             s->s3stmt = NULL;
03958             d->cur_s3stmt = NULL;
03959             return SQL_SUCCESS;
03960         }
03961         rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
03962         if (rowd) {
03963             const unsigned char *value;
03964 
03965             rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
03966             ++rowd;
03967             for (i = 0; i < ncols; i++) {
03968                 int coltype = sqlite3_column_type(s->s3stmt, i);
03969 
03970                 rowd[i] = rowd[i + ncols] = NULL;
03971                 if (coltype == SQLITE_BLOB) {
03972                     int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
03973                     char *qp;
03974                     unsigned const char *bp;
03975 
03976                     bp = sqlite3_column_blob(s->s3stmt, i);
03977                     qp = xmalloc(nbytes * 2 + 4);
03978                     if (qp) {
03979                         rowd[i + ncols] = qp;
03980                         *qp++ = 'X';
03981                         *qp++ = '\'';
03982                         for (k = 0; k < nbytes; k++) {
03983                             *qp++ = xdigits[(bp[k] >> 4)];
03984                             *qp++ = xdigits[(bp[k] & 0xF)];
03985                         }
03986                         *qp++ = '\'';
03987                         *qp = '\0';
03988                     }
03989                 } else if (coltype != SQLITE_NULL) {
03990                     value = sqlite3_column_text(s->s3stmt, i);
03991                     rowd[i + ncols] = xstrdup((char *) value);
03992                 }
03993             }
03994             for (i = 0; i < ncols; i++) {
03995                 int coltype = sqlite3_column_type(s->s3stmt, i);
03996 
03997                 value = NULL;
03998                 if (coltype == SQLITE_BLOB) {
03999                     value = sqlite3_column_blob(s->s3stmt, i);
04000                 } else if (coltype != SQLITE_NULL) {
04001                     value = sqlite3_column_text(s->s3stmt, i);
04002                 }
04003                 if (value && !rowd[i + ncols]) {
04004                     freerows(rowd);
04005                     rowd = 0;
04006                     break;
04007                 }
04008             }
04009         }
04010         if (rowd) {
04011             freeresult(s, 0);
04012             s->nrows = 1;
04013             s->rows = rowd;
04014             s->rowfree = freerows;
04015             if (rc == SQLITE_DONE) {
04016                 dbtraceapi(d, "sqlite3_finalize", 0);
04017                 sqlite3_finalize(s->s3stmt);
04018                 s->s3stmt = NULL;
04019                 d->cur_s3stmt = NULL;
04020             }
04021             return SQL_SUCCESS;
04022         }
04023     }
04024 killstmt:
04025     dbtraceapi(d, "sqlite3_reset", 0);
04026     rc = sqlite3_reset(s->s3stmt);
04027     s->s3stmt_noreset = 1;
04028     errp = sqlite3_errmsg(d->sqlite);
04029     if (d->cur_s3stmt == s) {
04030         d->cur_s3stmt = NULL;
04031     }
04032     setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04033             errp ? errp : "unknown error", rc);
04034     return SQL_ERROR;   
04035 }
04036 
04042 static void
04043 s3stmt_end(STMT *s)
04044 {
04045     DBC *d;
04046 
04047     if (!s || !s->s3stmt) {
04048         return;
04049     }
04050     d = (DBC *) s->dbc;
04051     if (d) {
04052         d->busyint = 0;
04053     }
04054     if (!s->s3stmt_noreset) {
04055         dbtraceapi(d, "sqlite3_reset", 0);
04056         sqlite3_reset(s->s3stmt);
04057         s->s3stmt_noreset = 1;
04058         s->s3stmt_rownum = -1;
04059     }
04060     if (d->cur_s3stmt == s) {
04061         d->cur_s3stmt = NULL;
04062     }
04063 }
04064 
04070 static void
04071 s3stmt_end_if(STMT *s)
04072 {
04073     DBC *d = (DBC *) s->dbc;
04074 
04075     if (d) {
04076         d->busyint = 0;
04077     }
04078     if (d && d->cur_s3stmt == s) {
04079         s3stmt_end(s);
04080     }
04081 }
04082 
04088 static void
04089 s3stmt_drop(STMT *s)
04090 {
04091     if (s->s3stmt) {
04092         DBC *d = (DBC *) s->dbc;
04093 
04094         if (d) {
04095             dbtraceapi(d, "sqlite3_finalize", 0);
04096         }
04097         sqlite3_finalize(s->s3stmt);
04098         s->s3stmt = NULL;
04099         s->s3stmt_rownum = 0;
04100     }
04101 }
04102 
04109 static SQLRETURN
04110 s3stmt_start(STMT *s)
04111 {
04112     DBC *d = (DBC *) s->dbc;
04113     const char *endp;
04114     sqlite3_stmt *s3stmt = NULL;
04115     int rc, nretry = 0;
04116 
04117     d->s3stmt_needmeta = 0;
04118     if (!s->s3stmt) {
04119 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04120         dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
04121 #else
04122         dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
04123 #endif
04124         do {
04125             s3stmt = NULL;
04126 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
04127             rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
04128                                     &s3stmt, &endp);
04129 #else
04130             rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
04131                                  &s3stmt, &endp);
04132 #endif
04133             if (rc != SQLITE_OK) {
04134                 if (s3stmt) {
04135                     sqlite3_finalize(s3stmt);
04136                     s3stmt = NULL;
04137                 }
04138             }
04139         } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
04140         dbtracerc(d, rc, NULL);
04141         if (rc != SQLITE_OK) {
04142             if (s3stmt) {
04143                 dbtraceapi(d, "sqlite3_finalize", NULL);
04144                 sqlite3_finalize(s3stmt);
04145             }
04146             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04147                     sqlite3_errmsg(d->sqlite), rc);
04148             return SQL_ERROR;
04149         }
04150         if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
04151             dbtraceapi(d, "sqlite3_finalize", 0);
04152             sqlite3_finalize(s3stmt);
04153             setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
04154                     (*s->ov3) ? "HY000" : "S1000");
04155             return SQL_ERROR;
04156         }
04157         s->s3stmt = s3stmt;
04158         s->s3stmt_noreset = 1;
04159         d->s3stmt_needmeta = 1;
04160     }
04161     d->cur_s3stmt = s;
04162     s->s3stmt_rownum = -1;
04163     s3bind(d, s->s3stmt, s->nparams, s->bindparms);
04164     return SQL_SUCCESS;
04165 }
04166 
04171 SQLRETURN SQL_API
04172 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
04173 {
04174     SQLRETURN ret;
04175 
04176     HSTMT_LOCK(stmt);
04177     ret = drvunimplstmt(stmt);
04178     HSTMT_UNLOCK(stmt);
04179     return ret;
04180 }
04181 
04182 #ifndef WINTERFACE
04183 
04187 SQLRETURN SQL_API
04188 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
04189                SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04190                SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04191 {
04192     if (env == SQL_NULL_HENV) {
04193         return SQL_INVALID_HANDLE;
04194     }
04195     return SQL_ERROR;
04196 }
04197 #endif
04198 
04199 #ifdef WINTERFACE
04200 
04204 SQLRETURN SQL_API
04205 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
04206                 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
04207                 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
04208 {
04209     if (env == SQL_NULL_HENV) {
04210         return SQL_INVALID_HANDLE;
04211     }
04212     return SQL_ERROR;
04213 }
04214 #endif
04215 
04216 #ifndef WINTERFACE
04217 
04221 SQLRETURN SQL_API
04222 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
04223            SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04224            SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04225 {
04226     if (env == SQL_NULL_HENV) {
04227         return SQL_INVALID_HANDLE;
04228     }
04229     return SQL_ERROR;
04230 }
04231 #endif
04232 
04233 #ifdef WINTERFACE
04234 
04238 SQLRETURN SQL_API
04239 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
04240             SQLSMALLINT descmax, SQLSMALLINT *desclenp,
04241             SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
04242 {
04243     if (env == SQL_NULL_HENV) {
04244         return SQL_INVALID_HANDLE;
04245     }
04246     return SQL_ERROR;
04247 }
04248 #endif
04249 
04250 #ifndef WINTERFACE
04251 
04255 SQLRETURN SQL_API
04256 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
04257                  SQLCHAR *connout, SQLSMALLINT connoutMax,
04258                  SQLSMALLINT *connoutLen)
04259 {
04260     SQLRETURN ret;
04261 
04262     HDBC_LOCK(dbc);
04263     ret = drvunimpldbc(dbc);
04264     HDBC_UNLOCK(dbc);
04265     return ret;
04266 }
04267 #endif
04268 
04269 #ifdef WINTERFACE
04270 
04274 SQLRETURN SQL_API
04275 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
04276                   SQLWCHAR *connout, SQLSMALLINT connoutMax,
04277                   SQLSMALLINT *connoutLen)
04278 {
04279     SQLRETURN ret;
04280 
04281     HDBC_LOCK(dbc);
04282     ret = drvunimpldbc(dbc);
04283     HDBC_UNLOCK(dbc);
04284     return ret;
04285 }
04286 #endif
04287 
04296 static SQLRETURN
04297 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
04298 {
04299     STMT *s;
04300     int i, dlen, done = 0;
04301     BINDPARM *p;
04302 
04303     if (stmt == SQL_NULL_HSTMT) {
04304         return SQL_INVALID_HANDLE;
04305     }
04306     s = (STMT *) stmt;
04307     if (!s->query || s->nparams <= 0) {
04308 seqerr:
04309         setstat(s, -1, "sequence error", "HY010");
04310         return SQL_ERROR;
04311     }
04312     for (i = 0; i < s->nparams; i++) {
04313         p = &s->bindparms[i];
04314         if (p->need > 0) {
04315             int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
04316 
04317             if (len == SQL_NULL_DATA) {
04318                 freep(&p->parbuf);
04319                 p->param = NULL;
04320                 p->len = SQL_NULL_DATA;
04321                 p->need = -1;
04322             } else if (type != SQL_C_CHAR
04323 #ifdef WCHARSUPPORT
04324                        && type != SQL_C_WCHAR
04325 #endif
04326                        && type != SQL_C_BINARY) {
04327                 int size = 0;
04328 
04329                 switch (type) {
04330                 case SQL_C_TINYINT:
04331                 case SQL_C_UTINYINT:
04332                 case SQL_C_STINYINT:
04333 #ifdef SQL_BIT
04334                 case SQL_C_BIT:
04335 #endif
04336                     size = sizeof (char);
04337                     break;
04338                 case SQL_C_SHORT:
04339                 case SQL_C_USHORT:
04340                 case SQL_C_SSHORT:
04341                     size = sizeof (short);
04342                     break;
04343                 case SQL_C_LONG:
04344                 case SQL_C_ULONG:
04345                 case SQL_C_SLONG:
04346                     size = sizeof (long);
04347                     break;
04348 #ifdef SQL_BIGINT
04349                 case SQL_C_UBIGINT:
04350                 case SQL_C_SBIGINT:
04351                     size = sizeof (SQLBIGINT);
04352                     break;
04353 #endif
04354                 case SQL_C_FLOAT:
04355                     size = sizeof (float);
04356                     break;
04357                 case SQL_C_DOUBLE:
04358                     size = sizeof (double);
04359                     break;
04360 #ifdef SQL_C_TYPE_DATE
04361                 case SQL_C_TYPE_DATE:
04362 #endif
04363                 case SQL_C_DATE:
04364                     size = sizeof (DATE_STRUCT);
04365                     break;
04366 #ifdef SQL_C_TYPE_DATE
04367                 case SQL_C_TYPE_TIME:
04368 #endif
04369                 case SQL_C_TIME:
04370                     size = sizeof (TIME_STRUCT);
04371                     break;
04372 #ifdef SQL_C_TYPE_DATE
04373                 case SQL_C_TYPE_TIMESTAMP:
04374 #endif
04375                 case SQL_C_TIMESTAMP:
04376                     size = sizeof (TIMESTAMP_STRUCT);
04377                     break;
04378                 }
04379                 freep(&p->parbuf);
04380                 p->parbuf = xmalloc(size);
04381                 if (!p->parbuf) {
04382                     return nomem(s);
04383                 }
04384                 p->param = p->parbuf;
04385                 memcpy(p->param, data, size);
04386                 p->len = size;
04387                 p->need = -1;
04388             } else if (len == SQL_NTS && (
04389                        type == SQL_C_CHAR
04390 #ifdef WCHARSUPPORT
04391                        || type == SQL_C_WCHAR
04392 #endif
04393                       )) {
04394                 char *dp = data;
04395 
04396 #ifdef WCHARSUPPORT
04397                 if (type == SQL_C_WCHAR) {
04398                     dp = uc_to_utf(data, len);
04399                     if (!dp) {
04400                         return nomem(s);
04401                     }
04402                 }
04403 #endif
04404 #if defined(_WIN32) || defined(_WIN64)
04405                 if (*s->oemcp) {
04406                     dp = wmb_to_utf(data, strlen (data));
04407                     if (!dp) {
04408                         return nomem(s);
04409                     }
04410                 }
04411 #endif
04412                 dlen = strlen(dp);
04413                 freep(&p->parbuf);
04414                 p->parbuf = xmalloc(dlen + 1);
04415                 if (!p->parbuf) {
04416                     if (dp != data) {
04417                         uc_free(dp);
04418                     }
04419                     return nomem(s);
04420                 }
04421                 p->param = p->parbuf;
04422                 strcpy(p->param, dp);
04423                 if (dp != data) {
04424                     uc_free(dp);
04425                 }
04426                 p->len = dlen;
04427                 p->need = -1;
04428             } else if (len < 0) {
04429                 setstat(s, -1, "invalid length", "HY090");
04430                 return SQL_ERROR;
04431             } else {
04432                 dlen = min(p->len - p->offs, len);
04433                 if (!p->param) {
04434                     setstat(s, -1, "no memory for parameter", "HY013");
04435                     return SQL_ERROR;
04436                 }
04437                 memcpy((char *) p->param + p->offs, data, dlen);
04438                 p->offs += dlen;
04439                 if (p->offs >= p->len) {
04440 #ifdef WCHARSUPPORT
04441                     if (type == SQL_C_WCHAR) {
04442                         char *dp = uc_to_utf(p->param, p->len);
04443                         char *np;
04444                         int nlen;
04445 
04446                         if (!dp) {
04447                             return nomem(s);
04448                         }
04449                         nlen = strlen(dp);
04450                         np = xmalloc(nlen + 1);
04451                         if (!np) {
04452                             uc_free(dp);
04453                             return nomem(s);
04454                         }
04455                         strcpy(np, dp);
04456                         uc_free(dp);
04457                         if (p->param == p->parbuf) {
04458                             freep(&p->parbuf);
04459                         }
04460                         p->parbuf = p->param = np;
04461                         p->len = nlen;
04462                     } else {
04463                         *((char *) p->param + p->len) = '\0';
04464                     }
04465                     p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
04466                             ? -1 : 0;
04467 #else
04468                     *((char *) p->param + p->len) = '\0';
04469                     p->need = (type == SQL_C_CHAR) ? -1 : 0;
04470 #endif
04471 #if defined(_WIN32) || defined(_WIN64)
04472                     if (type == SQL_C_CHAR && *s->oemcp) {
04473                         char *dp = wmb_to_utf(p->param, p->len);
04474 
04475                         if (!dp) {
04476                             return nomem(s);
04477                         }
04478                         if (p->param == p->parbuf) {
04479                             freep(&p->parbuf);
04480                         }
04481                         p->parbuf = p->param = dp;
04482                         p->len = strlen(dp);
04483                     }
04484                     if (p->type == SQL_C_WCHAR &&
04485                         (p->stype == SQL_VARCHAR ||
04486                          p->stype == SQL_LONGVARCHAR) &&
04487                          p->len == p->coldef * sizeof (SQLWCHAR)) {
04488                         /* fix for MS-Access */
04489                         p->len = p->coldef;
04490                     }
04491 #endif
04492                 }
04493             }
04494             done = 1;
04495             break;
04496         }
04497     }
04498     if (!done) {
04499         goto seqerr;
04500     }
04501     return SQL_SUCCESS;
04502 }
04503 
04512 SQLRETURN SQL_API
04513 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
04514 {
04515     SQLRETURN ret;
04516 
04517     HSTMT_LOCK(stmt);
04518     ret = drvputdata(stmt, data, len);
04519     HSTMT_UNLOCK(stmt);
04520     return ret;
04521 }
04522 
04528 static SQLRETURN
04529 freeparams(STMT *s)
04530 {
04531     if (s->bindparms) {
04532         int n;
04533 
04534         for (n = 0; n < s->nbindparms; n++) {
04535             freep(&s->bindparms[n].parbuf);
04536             memset(&s->bindparms[n], 0, sizeof (BINDPARM));
04537         }
04538     }
04539     return SQL_SUCCESS;
04540 }
04541 
04553 static SQLRETURN
04554 setupparam(STMT *s, char *sql, int pnum)
04555 {
04556     int type, len = 0, needalloc = 0;
04557     BINDPARM *p;
04558 
04559     if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
04560         goto error;
04561     }
04562     p = &s->bindparms[pnum];
04563     type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
04564 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
04565     /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
04566     if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
04567         type = SQL_C_CHAR;
04568     }
04569 #endif
04570     if (p->need > 0) {
04571         return setupparbuf(s, p);      
04572     }
04573     p->strbuf[0] = '\0';
04574     if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
04575         p->s3type = SQLITE_NULL;
04576         p->s3size = 0;
04577         return SQL_SUCCESS;
04578     }
04579     switch (type) {
04580     case SQL_C_BINARY:
04581         p->s3type = SQLITE_BLOB;
04582         p->s3size = p->len;
04583         p->s3val = p->param;
04584         if (p->need < 0) {
04585             break;
04586         }
04587         if (!p->lenp) {
04588             len = p->len;
04589         } else {
04590             len = *p->lenp;
04591             if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
04592                 len = SQL_LEN_DATA_AT_EXEC(len);
04593             }
04594         }
04595         if (len < 0) {
04596             setstat(s, -1, "invalid length", "HY009");
04597             return SQL_ERROR;
04598         }
04599         p->len = len;
04600         p->max = p->len;
04601         p->need = -1;
04602         p->s3size = len;
04603         break;
04604 #ifdef WCHARSUPPORT
04605     case SQL_C_WCHAR:
04606 #endif
04607     case SQL_C_CHAR:
04608         p->s3type = SQLITE_TEXT;
04609         p->s3size = -1;
04610         p->s3val = p->param;
04611         if (!p->parbuf && p->lenp) {
04612 #ifdef WCHARSUPPORT
04613             if (type == SQL_C_WCHAR) {
04614                 if (*p->lenp == SQL_NTS) {
04615                     p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
04616                 } else if (*p->lenp >= 0) {
04617                     p->max = *p->lenp;
04618                 }
04619             } else
04620 #endif
04621             if (type == SQL_C_CHAR) {
04622                 if (*p->lenp == SQL_NTS) {
04623                     p->len = p->max = strlen(p->param);
04624 #if defined(_WIN32) || defined(_WIN64)
04625                     needalloc = 1;
04626 #endif
04627                 } else if (*p->lenp >= 0) {
04628                     p->len = p->max = *p->lenp;
04629                     needalloc = 1;
04630                 }
04631             }
04632         }
04633         if (p->need < 0 && p->parbuf == p->param) {
04634             break;
04635         }
04636 #ifdef WCHARSUPPORT
04637         if (type == SQL_C_WCHAR) {
04638             char *dp = uc_to_utf(p->param, p->max);
04639 
04640             if (!dp) {
04641                 return nomem(s);
04642             }
04643             if (p->param == p->parbuf) {
04644                 freep(&p->parbuf);
04645             }
04646             p->parbuf = p->param = dp;
04647             p->need = -1;
04648             p->len = strlen(p->param);
04649             p->s3val = p->param;
04650             p->s3size = p->len;
04651         } else
04652 #endif
04653         if (type == SQL_C_CHAR) {
04654             p->s3val = p->param;
04655             if (needalloc) {
04656                 char *dp;
04657 
04658 #if defined(_WIN32) || defined(_WIN64)
04659                 if (*s->oemcp) {
04660                     dp = wmb_to_utf(p->param, p->len);
04661                 } else {
04662                     dp = xmalloc(p->len + 1);
04663                 }
04664 #else
04665                 dp = xmalloc(p->len + 1);
04666 #endif
04667                 if (!dp) {
04668                     return nomem(s);
04669                 }
04670 #if defined(_WIN32) || defined(_WIN64)
04671                 if (*s->oemcp) {
04672                     p->len = strlen(dp);
04673                 } else {
04674                     memcpy(dp, p->param, p->len);
04675                     dp[p->len] = '\0';
04676                 }
04677 #else
04678                 memcpy(dp, p->param, p->len);
04679                 dp[p->len] = '\0';
04680 #endif
04681                 if (p->param == p->parbuf) {
04682                     freep(&p->parbuf);
04683                 }
04684                 p->parbuf = p->param = dp;
04685                 p->need = -1;
04686                 p->s3val = p->param;
04687                 p->s3size = p->len;
04688             }
04689         }
04690         break;
04691     case SQL_C_UTINYINT:
04692         p->s3type = SQLITE_INTEGER;
04693         p->s3size = sizeof (int);
04694         p->s3ival = *((SQLCHAR *) p->param);
04695         break;
04696     case SQL_C_TINYINT:
04697     case SQL_C_STINYINT:
04698         p->s3type = SQLITE_INTEGER;
04699         p->s3size = sizeof (int);
04700         p->s3ival = *((SQLCHAR *) p->param);
04701         break;
04702     case SQL_C_USHORT:
04703         p->s3type = SQLITE_INTEGER;
04704         p->s3size = sizeof (int);
04705         p->s3ival = *((SQLUSMALLINT *) p->param);
04706         break;
04707     case SQL_C_SHORT:
04708     case SQL_C_SSHORT:
04709         p->s3type = SQLITE_INTEGER;
04710         p->s3size = sizeof (int);
04711         p->s3ival = *((SQLSMALLINT *) p->param);
04712         break;
04713     case SQL_C_ULONG:
04714         p->s3type = SQLITE_INTEGER;
04715         p->s3size = sizeof (int);
04716         p->s3ival = *((SQLUINTEGER *) p->param);
04717         break;
04718     case SQL_C_LONG:
04719     case SQL_C_SLONG:
04720         p->s3type = SQLITE_INTEGER;
04721         p->s3size = sizeof (int);
04722         p->s3ival = *((SQLINTEGER *) p->param);
04723         break;
04724 #ifdef SQL_BIT
04725     case SQL_C_BIT:
04726         p->s3type = SQLITE_INTEGER;
04727         p->s3size = sizeof (int);
04728         p->s3ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
04729         break;
04730 #endif
04731 #ifdef SQL_BIGINT
04732     case SQL_C_SBIGINT:
04733         p->s3type = SQLITE_INTEGER;
04734         p->s3size = sizeof (sqlite_int64);
04735         p->s3lival = *((sqlite_int64 *) p->param);
04736         break;
04737     case SQL_C_UBIGINT:
04738         p->s3type = SQLITE_INTEGER;
04739         p->s3size = sizeof (sqlite_int64);
04740         p->s3lival = *((sqlite_uint64 *) p->param);
04741         break;
04742 #endif
04743     case SQL_C_FLOAT:
04744         p->s3type = SQLITE_FLOAT;
04745         p->s3size = sizeof (double);
04746         p->s3dval = *((float *) p->param);
04747         break;
04748     case SQL_C_DOUBLE:
04749         p->s3type = SQLITE_FLOAT;
04750         p->s3size = sizeof (double);
04751         p->s3dval = *((double *) p->param);
04752         break;
04753 #ifdef SQL_C_TYPE_DATE
04754     case SQL_C_TYPE_DATE:
04755 #endif
04756     case SQL_C_DATE:
04757         sprintf(p->strbuf, "%04d-%02d-%02d",
04758                 ((DATE_STRUCT *) p->param)->year,
04759                 ((DATE_STRUCT *) p->param)->month,
04760                 ((DATE_STRUCT *) p->param)->day);
04761         p->s3type = SQLITE_TEXT;
04762         p->s3size = -1;
04763         p->s3val = p->strbuf;
04764         break;
04765 #ifdef SQL_C_TYPE_TIME
04766     case SQL_C_TYPE_TIME:
04767 #endif
04768     case SQL_C_TIME:
04769         sprintf(p->strbuf, "%02d:%02d:%02d",
04770                 ((TIME_STRUCT *) p->param)->hour,
04771                 ((TIME_STRUCT *) p->param)->minute,
04772                 ((TIME_STRUCT *) p->param)->second);
04773         p->s3type = SQLITE_TEXT;
04774         p->s3size = -1;
04775         p->s3val = p->strbuf;
04776         break;
04777 #ifdef SQL_C_TYPE_TIMESTAMP
04778     case SQL_C_TYPE_TIMESTAMP:
04779 #endif
04780     case SQL_C_TIMESTAMP:
04781         len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
04782         len /= 1000000;
04783         len = len % 1000;
04784         if (len < 0) {
04785             len = 0;
04786         }
04787         if (p->coldef && p->coldef <= 16) {
04788             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
04789                     ((TIMESTAMP_STRUCT *) p->param)->year,
04790                     ((TIMESTAMP_STRUCT *) p->param)->month,
04791                     ((TIMESTAMP_STRUCT *) p->param)->day,
04792                     ((TIMESTAMP_STRUCT *) p->param)->hour,
04793                     ((TIMESTAMP_STRUCT *) p->param)->minute);
04794         } else if (p->coldef && p->coldef <= 19) {
04795             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
04796                     ((TIMESTAMP_STRUCT *) p->param)->year,
04797                     ((TIMESTAMP_STRUCT *) p->param)->month,
04798                     ((TIMESTAMP_STRUCT *) p->param)->day,
04799                     ((TIMESTAMP_STRUCT *) p->param)->hour,
04800                     ((TIMESTAMP_STRUCT *) p->param)->minute,
04801                     ((TIMESTAMP_STRUCT *) p->param)->second);
04802         } else {
04803             sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
04804                     ((TIMESTAMP_STRUCT *) p->param)->year,
04805                     ((TIMESTAMP_STRUCT *) p->param)->month,
04806                     ((TIMESTAMP_STRUCT *) p->param)->day,
04807                     ((TIMESTAMP_STRUCT *) p->param)->hour,
04808                     ((TIMESTAMP_STRUCT *) p->param)->minute,
04809                     ((TIMESTAMP_STRUCT *) p->param)->second,
04810                     len);
04811         }
04812         p->s3type = SQLITE_TEXT;
04813         p->s3size = -1;
04814         p->s3val = p->strbuf;
04815         break;
04816     default:
04817     error:
04818         setstat(s, -1, "unsupported parameter type",
04819                 (*s->ov3) ? "07009" : "S1093");
04820         return SQL_ERROR;
04821     }
04822     return SQL_SUCCESS;
04823 }
04824 
04840 static SQLRETURN
04841 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
04842              SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
04843              SQLSMALLINT scale,
04844              SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
04845 {
04846     STMT *s;
04847     BINDPARM *p;
04848 
04849     if (stmt == SQL_NULL_HSTMT) {
04850         return SQL_INVALID_HANDLE;
04851     }
04852     s = (STMT *) stmt;
04853     if (pnum == 0) {
04854         setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
04855         return SQL_ERROR;
04856     }
04857     if (!data && !len) {
04858         setstat(s, -1, "invalid buffer", "HY003");
04859         return SQL_ERROR;
04860     }
04861     --pnum;
04862     if (s->bindparms) {
04863         if (pnum >= s->nbindparms) {
04864             BINDPARM *newparms;
04865             
04866             newparms = xrealloc(s->bindparms,
04867                                 (pnum + 1) * sizeof (BINDPARM));
04868             if (!newparms) {
04869 outofmem:
04870                 return nomem(s);
04871             }
04872             s->bindparms = newparms;
04873             memset(&s->bindparms[s->nbindparms], 0,
04874                    (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
04875             s->nbindparms = pnum + 1;
04876         }
04877     } else {
04878         int npar = max(10, pnum + 1);
04879 
04880         s->bindparms = xmalloc(npar * sizeof (BINDPARM));
04881         if (!s->bindparms) {
04882             goto outofmem;
04883         }
04884         memset(s->bindparms, 0, npar * sizeof (BINDPARM));
04885         s->nbindparms = npar;
04886     }
04887     switch (buftype) {
04888     case SQL_C_STINYINT:
04889     case SQL_C_UTINYINT:
04890     case SQL_C_TINYINT:
04891 #ifdef SQL_C_BIT
04892     case SQL_C_BIT:
04893 #endif
04894         buflen = sizeof (SQLCHAR);
04895         break;
04896     case SQL_C_SHORT:
04897     case SQL_C_USHORT:
04898     case SQL_C_SSHORT:
04899         buflen = sizeof (SQLSMALLINT);
04900         break;
04901     case SQL_C_SLONG:
04902     case SQL_C_ULONG:
04903     case SQL_C_LONG:
04904         buflen = sizeof (SQLINTEGER);
04905         break;
04906     case SQL_C_FLOAT:
04907         buflen = sizeof (float);
04908         break;
04909     case SQL_C_DOUBLE:
04910         buflen = sizeof (double);
04911         break;
04912     case SQL_C_TIMESTAMP:
04913 #ifdef SQL_C_TYPE_TIMESTAMP
04914     case SQL_C_TYPE_TIMESTAMP:
04915 #endif
04916         buflen = sizeof (TIMESTAMP_STRUCT);
04917         break;
04918     case SQL_C_TIME:
04919 #ifdef SQL_C_TYPE_TIME
04920     case SQL_C_TYPE_TIME:
04921 #endif
04922         buflen = sizeof (TIME_STRUCT);
04923         break;
04924     case SQL_C_DATE:
04925 #ifdef SQL_C_TYPE_DATE
04926     case SQL_C_TYPE_DATE:
04927 #endif
04928         buflen = sizeof (DATE_STRUCT);
04929         break;
04930 #ifdef SQL_C_UBIGINT
04931     case SQL_C_UBIGINT:
04932         buflen = sizeof (SQLBIGINT);
04933         break;
04934 #endif
04935 #ifdef SQL_C_SBIGINT
04936     case SQL_C_SBIGINT:
04937         buflen = sizeof (SQLBIGINT);
04938         break;
04939 #endif
04940 #ifdef SQL_C_BIGINT
04941     case SQL_C_BIGINT:
04942         buflen = sizeof (SQLBIGINT);
04943         break;
04944 #endif
04945     }
04946     p = &s->bindparms[pnum];
04947     p->type = buftype;
04948     p->stype = ptype;
04949     p->coldef = coldef;
04950     p->scale = scale;
04951     p->max = buflen;
04952     p->inc = buflen;
04953     p->lenp = p->lenp0 = len;
04954     p->offs = 0;
04955     p->len = 0;
04956     p->param0 = data;
04957     freep(&p->parbuf);
04958     p->param = p->param0;
04959     p->bound = 1;
04960     p->need = 0;
04961     return SQL_SUCCESS;
04962 }
04963 
04979 SQLRETURN SQL_API
04980 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
04981                  SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
04982                  SQLSMALLINT scale,
04983                  SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
04984 {
04985     SQLRETURN ret;
04986 
04987     HSTMT_LOCK(stmt);
04988     ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
04989                        scale, data, buflen, len);
04990     HSTMT_UNLOCK(stmt);
04991     return ret;
04992 }
04993 
04994 #ifndef HAVE_IODBC
04995 
05008 SQLRETURN SQL_API
05009 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
05010              SQLSMALLINT ptype, SQLULEN lenprec,
05011              SQLSMALLINT scale, SQLPOINTER val,
05012              SQLLEN *lenp)
05013 {
05014     SQLRETURN ret;
05015 
05016     HSTMT_LOCK(stmt);
05017     ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
05018                        lenprec, scale, val, 0, lenp);
05019     HSTMT_UNLOCK(stmt);
05020     return ret;
05021 }
05022 #endif
05023 
05031 SQLRETURN SQL_API
05032 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
05033 {
05034     STMT *s;
05035     SQLSMALLINT dummy;
05036 
05037     HSTMT_LOCK(stmt);
05038     if (stmt == SQL_NULL_HSTMT) {
05039         return SQL_INVALID_HANDLE;
05040     }
05041     s = (STMT *) stmt;
05042     if (!nparam) {
05043         nparam = &dummy;
05044     }
05045     *nparam = s->nparams;
05046     HSTMT_UNLOCK(stmt);
05047     return SQL_SUCCESS;
05048 }
05049 
05057 static SQLRETURN
05058 setupparbuf(STMT *s, BINDPARM *p)
05059 {
05060     if (!p->parbuf) {
05061         p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
05062         if (p->len < 0 && p->len != SQL_NTS &&
05063             p->len != SQL_NULL_DATA) {
05064             setstat(s, -1, "invalid length", "HY009");
05065             return SQL_ERROR;
05066         }
05067         if (p->len >= 0) {
05068             p->parbuf = xmalloc(p->len + 1);
05069             if (!p->parbuf) {
05070                 return nomem(s);
05071             }
05072             p->param = p->parbuf;
05073         } else {
05074             p->param = NULL;
05075         }
05076     }
05077     return SQL_NEED_DATA;
05078 }
05079 
05087 SQLRETURN SQL_API
05088 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
05089 {
05090     STMT *s;
05091     int i;
05092     SQLPOINTER dummy;
05093     SQLRETURN ret;
05094 
05095     HSTMT_LOCK(stmt);
05096     if (stmt == SQL_NULL_HSTMT) {
05097         return SQL_INVALID_HANDLE;
05098     }
05099     s = (STMT *) stmt;
05100     if (!pind) {
05101         pind = &dummy;
05102     }
05103     for (i = 0; i < s->nparams; i++) {
05104         BINDPARM *p = &s->bindparms[i];
05105 
05106         if (p->need > 0) {
05107             *pind = (SQLPOINTER) p->param0;
05108             ret = setupparbuf(s, p);
05109             goto done;
05110         }
05111     }
05112     ret = drvexecute(stmt, 0);
05113 done:
05114     HSTMT_UNLOCK(stmt);
05115     return ret;
05116 }
05117 
05129 SQLRETURN SQL_API
05130 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
05131                  SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
05132 {
05133     STMT *s;
05134     SQLRETURN ret = SQL_ERROR;
05135 
05136     HSTMT_LOCK(stmt);
05137     if (stmt == SQL_NULL_HSTMT) {
05138         return SQL_INVALID_HANDLE;
05139     }
05140     s = (STMT *) stmt;
05141     --pnum;
05142     if (pnum >= s->nparams) {
05143         setstat(s, -1, "invalid parameter index",
05144                 (*s->ov3) ? "HY000" : "S1000");
05145         goto done;
05146     }
05147     if (dtype) {
05148 #ifdef SQL_LONGVARCHAR
05149 #ifdef WINTERFACE
05150         *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
05151 #else   
05152         *dtype = SQL_LONGVARCHAR;
05153 #endif
05154 #else
05155 #ifdef WINTERFACE
05156         *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
05157 #else
05158         *dtype = SQL_VARCHAR;
05159 #endif
05160 #endif
05161     }
05162     if (size) {
05163 #ifdef SQL_LONGVARCHAR
05164         *size = 65536;
05165 #else
05166         *size = 255;
05167 #endif
05168     }
05169     if (decdigits) {
05170         *decdigits = 0;
05171     }
05172     if (nullable) {
05173         *nullable = SQL_NULLABLE;
05174     }
05175     ret = SQL_SUCCESS;
05176 done:
05177     HSTMT_UNLOCK(stmt);
05178     return ret;
05179 }
05180 
05194 SQLRETURN SQL_API
05195 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
05196             SQLSMALLINT sqltype, SQLULEN coldef,
05197             SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
05198 {
05199     SQLRETURN ret;
05200 
05201     HSTMT_LOCK(stmt);
05202     ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
05203                        type, sqltype, coldef, scale, val,
05204                        SQL_SETPARAM_VALUE_MAX, nval);
05205     HSTMT_UNLOCK(stmt);
05206     return ret;
05207 }
05208 
05213 SQLRETURN SQL_API
05214 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
05215 {
05216     SQLRETURN ret;
05217 
05218     HSTMT_LOCK(stmt);
05219     ret = drvunimplstmt(stmt);
05220     HSTMT_UNLOCK(stmt);
05221     return ret;
05222 }
05223 
05224 #ifndef WINTERFACE
05225 
05229 SQLRETURN SQL_API
05230 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
05231                 SQLSMALLINT fieldid, SQLPOINTER value,
05232                 SQLINTEGER buflen, SQLINTEGER *strlen)
05233 {
05234     return SQL_ERROR;
05235 }
05236 #endif
05237 
05238 #ifdef WINTERFACE
05239 
05243 SQLRETURN SQL_API
05244 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05245                  SQLSMALLINT fieldid, SQLPOINTER value,
05246                  SQLINTEGER buflen, SQLINTEGER *strlen)
05247 {
05248     return SQL_ERROR;
05249 }
05250 #endif
05251 
05252 #ifndef WINTERFACE
05253 
05257 SQLRETURN SQL_API
05258 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
05259                 SQLSMALLINT fieldid, SQLPOINTER value,
05260                 SQLINTEGER buflen)
05261 {
05262     return SQL_ERROR;
05263 }
05264 #endif
05265 
05266 #ifdef WINTERFACE
05267 
05271 SQLRETURN SQL_API
05272 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
05273                  SQLSMALLINT fieldid, SQLPOINTER value,
05274                  SQLINTEGER buflen)
05275 {
05276     return SQL_ERROR;
05277 }
05278 #endif
05279 
05280 #ifndef WINTERFACE
05281 
05285 SQLRETURN SQL_API
05286 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05287               SQLCHAR *name, SQLSMALLINT buflen,
05288               SQLSMALLINT *strlen, SQLSMALLINT *type,
05289               SQLSMALLINT *subtype, SQLLEN *len,
05290               SQLSMALLINT *prec, SQLSMALLINT *scale,
05291               SQLSMALLINT *nullable)
05292 {
05293     return SQL_ERROR;
05294 }
05295 #endif
05296 
05297 #ifdef WINTERFACE
05298 
05302 SQLRETURN SQL_API
05303 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
05304                SQLWCHAR *name, SQLSMALLINT buflen,
05305                SQLSMALLINT *strlen, SQLSMALLINT *type,
05306                SQLSMALLINT *subtype, SQLLEN *len,
05307                SQLSMALLINT *prec, SQLSMALLINT *scale,
05308                SQLSMALLINT *nullable)
05309 {
05310     return SQL_ERROR;
05311 }
05312 #endif
05313 
05318 SQLRETURN SQL_API
05319 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
05320               SQLSMALLINT type, SQLSMALLINT subtype,
05321               SQLLEN len, SQLSMALLINT prec,
05322               SQLSMALLINT scale, SQLPOINTER data,
05323               SQLLEN *strlen, SQLLEN *indicator)
05324 {
05325     return SQL_ERROR;
05326 }
05327 
05339 static SQLRETURN
05340 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
05341             int ncols3, int *nret)
05342 {
05343     STMT *s;
05344     DBC *d;
05345 
05346     if (stmt == SQL_NULL_HSTMT) {
05347         return SQL_INVALID_HANDLE;
05348     }
05349     s = (STMT *) stmt;
05350     if (s->dbc == SQL_NULL_HDBC) {
05351 noconn:
05352         return noconn(s);
05353     }
05354     d = (DBC *) s->dbc;
05355     if (!d->sqlite) {
05356         goto noconn;
05357     }
05358     s3stmt_end_if(s);
05359     freeresult(s, 0);
05360     if (colspec3 && *s->ov3) {
05361         s->ncols = ncols3;
05362         s->cols = colspec3;
05363     } else {
05364         s->ncols = ncols;
05365         s->cols = colspec;
05366     }
05367     mkbindcols(s, s->ncols);
05368     s->nowchar[1] = 1;
05369     s->nrows = 0;
05370     s->rowp = -1;
05371     s->isselect = -1;
05372     if (nret) {
05373         *nret = s->ncols;
05374     }
05375     return SQL_SUCCESS;
05376 }
05377 
05382 static COL tablePrivSpec2[] = {
05383     { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05384     { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
05385     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05386     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05387     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05388     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05389     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05390 };
05391 
05392 static COL tablePrivSpec3[] = {
05393     { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
05394     { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
05395     { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05396     { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05397     { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05398     { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
05399     { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
05400 };
05401 
05414 static SQLRETURN
05415 drvtableprivileges(SQLHSTMT stmt,
05416                    SQLCHAR *cat, SQLSMALLINT catLen,
05417                    SQLCHAR *schema, SQLSMALLINT schemaLen,
05418                    SQLCHAR *table, SQLSMALLINT tableLen)
05419 {
05420     SQLRETURN ret;
05421     STMT *s;
05422     DBC *d;
05423     int ncols, rc, size, npatt;
05424     char *errp = NULL, *sql, tname[512];
05425 
05426     ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
05427                       tablePrivSpec3, array_size(tablePrivSpec3), NULL);
05428     if (ret != SQL_SUCCESS) {
05429         return ret;
05430     }
05431     s = (STMT *) stmt;
05432     d = (DBC *) s->dbc;
05433     if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
05434         table = NULL;
05435         goto doit;
05436     }
05437     if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
05438         schema[0] == '%') {
05439         if ((!cat || catLen == 0 || !cat[0]) &&
05440             (!table || tableLen == 0 || !table[0])) {
05441             table = NULL;
05442             goto doit;
05443         }
05444     }
05445 doit:
05446     if (!table) {
05447         size = 1;
05448         tname[0] = '%';
05449     } else {
05450         if (tableLen == SQL_NTS) {
05451             size = sizeof (tname) - 1;
05452         } else {
05453             size = min(sizeof (tname) - 1, tableLen);
05454         }
05455         strncpy(tname, (char *) table, size);
05456     }
05457     tname[size] = '\0';
05458     npatt = unescpat(tname);
05459 #if defined(_WIN32) || defined(_WIN64)
05460     sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
05461                           "%s as 'TABLE_OWNER', "
05462                           "tbl_name as 'TABLE_NAME', "
05463                           "'' as 'GRANTOR', "
05464                           "'' as 'GRANTEE', "
05465                           "'SELECT' AS 'PRIVILEGE', "
05466                           "NULL as 'IS_GRANTABLE' "
05467                           "from sqlite_master where "
05468                           "(type = 'table' or type = 'view') "
05469                           "and tbl_name %s %Q "
05470                           "UNION "
05471                           "select %s as 'TABLE_QUALIFIER', "
05472                           "%s as 'TABLE_OWNER', "
05473                           "tbl_name as 'TABLE_NAME', "
05474                           "'' as 'GRANTOR', "
05475                           "'' as 'GRANTEE', "
05476                           "'UPDATE' AS 'PRIVILEGE', "
05477                           "NULL as 'IS_GRANTABLE' "
05478                           "from sqlite_master where "
05479                           "(type = 'table' or type = 'view') "
05480                           "and tbl_name %s %Q "
05481                           "UNION "
05482                           "select %s as 'TABLE_QUALIFIER', "
05483                           "%s as 'TABLE_OWNER', "
05484                           "tbl_name as 'TABLE_NAME', "
05485                           "'' as 'GRANTOR', "
05486                           "'' as 'GRANTEE', "
05487                           "'DELETE' AS 'PRIVILEGE', "
05488                           "NULL as 'IS_GRANTABLE' "
05489                           "from sqlite_master where "
05490                           "(type = 'table' or type = 'view') "
05491                           "and tbl_name %s %Q "
05492                           "UNION "
05493                           "select %s as 'TABLE_QUALIFIER', "
05494                           "%s as 'TABLE_OWNER', "
05495                           "tbl_name as 'TABLE_NAME', "
05496                           "'' as 'GRANTOR', "
05497                           "'' as 'GRANTEE', "
05498                           "'INSERT' AS 'PRIVILEGE', "
05499                           "NULL as 'IS_GRANTABLE' "
05500                           "from sqlite_master where "
05501                           "(type = 'table' or type = 'view') "
05502                           "and tbl_name %s %Q "
05503                           "UNION "
05504                           "select %s as 'TABLE_QUALIFIER', "
05505                           "%s as 'TABLE_OWNER', "
05506                           "tbl_name as 'TABLE_NAME', "
05507                           "'' as 'GRANTOR', "
05508                           "'' as 'GRANTEE', "
05509                           "'REFERENCES' AS 'PRIVILEGE', "
05510                           "NULL as 'IS_GRANTABLE' "
05511                           "from sqlite_master where "
05512                           "(type = 'table' or type = 'view') "
05513                           "and tbl_name %s %Q",
05514                           d->xcelqrx ? "''" : "NULL",
05515                           d->xcelqrx ? "'main'" : "NULL",
05516                           npatt ? "like" : "=", tname,
05517                           d->xcelqrx ? "''" : "NULL",
05518                           d->xcelqrx ? "'main'" : "NULL",
05519                           npatt ? "like" : "=", tname,
05520                           d->xcelqrx ? "''" : "NULL",
05521                           d->xcelqrx ? "'main'" : "NULL",
05522                           npatt ? "like" : "=", tname,
05523                           d->xcelqrx ? "''" : "NULL",
05524                           d->xcelqrx ? "'main'" : "NULL",
05525                           npatt ? "like" : "=", tname,
05526                           d->xcelqrx ? "''" : "NULL",
05527                           d->xcelqrx ? "'main'" : "NULL",
05528                           npatt ? "like" : "=", tname);
05529 #else
05530     sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
05531                           "NULL as 'TABLE_OWNER', "
05532                           "tbl_name as 'TABLE_NAME', "
05533                           "'' as 'GRANTOR', "
05534                           "'' as 'GRANTEE', "
05535                           "'SELECT' AS 'PRIVILEGE', "
05536                           "NULL as 'IS_GRANTABLE' "
05537                           "from sqlite_master where "
05538                           "(type = 'table' or type = 'view') "
05539                           "and tbl_name %s %Q "
05540                           "UNION "
05541                           "select NULL as 'TABLE_QUALIFIER', "
05542                           "NULL as 'TABLE_OWNER', "
05543                           "tbl_name as 'TABLE_NAME', "
05544                           "'' as 'GRANTOR', "
05545                           "'' as 'GRANTEE', "
05546                           "'UPDATE' AS 'PRIVILEGE', "
05547                           "NULL as 'IS_GRANTABLE' "
05548                           "from sqlite_master where "
05549                           "(type = 'table' or type = 'view') "
05550                           "and tbl_name %s %Q "
05551                           "UNION "
05552                           "select NULL as 'TABLE_QUALIFIER', "
05553                           "NULL as 'TABLE_OWNER', "
05554                           "tbl_name as 'TABLE_NAME', "
05555                           "'' as 'GRANTOR', "
05556                           "'' as 'GRANTEE', "
05557                           "'DELETE' AS 'PRIVILEGE', "
05558                           "NULL as 'IS_GRANTABLE' "
05559                           "from sqlite_master where "
05560                           "(type = 'table' or type = 'view') "
05561                           "and tbl_name %s %Q "
05562                           "UNION "
05563                           "select NULL as 'TABLE_QUALIFIER', "
05564                           "NULL as 'TABLE_OWNER', "
05565                           "tbl_name as 'TABLE_NAME', "
05566                           "'' as 'GRANTOR', "
05567                           "'' as 'GRANTEE', "
05568                           "'INSERT' AS 'PRIVILEGE', "
05569                           "NULL as 'IS_GRANTABLE' "
05570                           "from sqlite_master where "
05571                           "(type = 'table' or type = 'view') "
05572                           "and tbl_name %s %Q "
05573                           "UNION "
05574                           "select NULL as 'TABLE_QUALIFIER', "
05575                           "NULL as 'TABLE_OWNER', "
05576                           "tbl_name as 'TABLE_NAME', "
05577                           "'' as 'GRANTOR', "
05578                           "'' as 'GRANTEE', "
05579                           "'REFERENCES' AS 'PRIVILEGE', "
05580                           "NULL as 'IS_GRANTABLE' "
05581                           "from sqlite_master where "
05582                           "(type = 'table' or type = 'view') "
05583                           "and tbl_name %s %Q",
05584                           npatt ? "like" : "=", tname,
05585                           npatt ? "like" : "=", tname,
05586                           npatt ? "like" : "=", tname,
05587                           npatt ? "like" : "=", tname,
05588                           npatt ? "like" : "=", tname);
05589 #endif
05590     if (!sql) {
05591         return nomem(s);
05592     }
05593     ret = starttran(s);
05594     if (ret != SQL_SUCCESS) {
05595         sqlite3_free(sql);
05596         return ret;
05597     }
05598     dbtraceapi(d, "sqlite3_get_table", sql);
05599     rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
05600     sqlite3_free(sql);
05601     if (rc == SQLITE_OK) {
05602         if (ncols != s->ncols) {
05603             freeresult(s, 0);
05604             s->nrows = 0;
05605         } else {
05606             s->rowfree = sqlite3_free_table;
05607         }
05608     } else {
05609         s->nrows = 0;
05610         s->rows = NULL;
05611         s->rowfree = NULL;
05612     }
05613     if (errp) {
05614         sqlite3_free(errp);
05615         errp = NULL;
05616     }
05617     s->rowp = -1;
05618     return SQL_SUCCESS;
05619 }
05620 
05621 
05622 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
05623 
05635 SQLRETURN SQL_API
05636 SQLTablePrivileges(SQLHSTMT stmt,
05637                    SQLCHAR *catalog, SQLSMALLINT catalogLen,
05638                    SQLCHAR *schema, SQLSMALLINT schemaLen,
05639                    SQLCHAR *table, SQLSMALLINT tableLen)
05640 {
05641 #if defined(_WIN32) || defined(_WIN64)
05642     char *c = NULL, *s = NULL, *t = NULL;
05643 #endif
05644     SQLRETURN ret;
05645 
05646     HSTMT_LOCK(stmt);
05647 #if defined(_WIN32) || defined(_WIN64)
05648     if (!((STMT *) stmt)->oemcp[0]) {
05649         ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
05650                                  table, tableLen);
05651         goto done2;
05652     }
05653     if (catalog) {
05654         c = wmb_to_utf_c((char *) catalog, catalogLen);
05655         if (!c) {
05656             ret = nomem((STMT *) stmt);
05657             goto done;
05658         }
05659     }
05660     if (schema) {
05661         s = wmb_to_utf_c((char *) schema, schemaLen);
05662         if (!s) {
05663             ret = nomem((STMT *) stmt);
05664             goto done;
05665         }
05666     }
05667     if (table) {
05668         t = wmb_to_utf_c((char *) table, tableLen);
05669         if (!t) {
05670             ret = nomem((STMT *) stmt);
05671             goto done;
05672         }
05673     }
05674     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
05675                              (SQLCHAR *) s, SQL_NTS,
05676                              (SQLCHAR *) t, SQL_NTS);
05677 #else
05678     ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
05679                              table, tableLen);
05680 #endif
05681 #if defined(_WIN32) || defined(_WIN64)
05682 done:
05683     uc_free(t);
05684     uc_free(s);
05685     uc_free(c);
05686 done2:
05687     ;
05688 #endif
05689     HSTMT_UNLOCK(stmt);
05690     return ret;
05691 }
05692 #endif
05693 
05694 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
05695 #ifdef WINTERFACE
05696 
05708 SQLRETURN SQL_API
05709 SQLTablePrivilegesW(SQLHSTMT stmt,
05710                     SQLWCHAR *catalog, SQLSMALLINT catalogLen,
05711                     SQLWCHAR *schema, SQLSMALLINT schemaLen,
05712                     SQLWCHAR *table, SQLSMALLINT tableLen)
05713 {
05714     char *c = NULL, *s = NULL, *t = NULL;
05715     SQLRETURN ret;
05716 
05717     HSTMT_LOCK(stmt);
05718     if (catalog) {
05719         c = uc_to_utf_c(catalog, catalogLen);
05720         if (!c) {
05721             ret = nomem((STMT *) stmt);
05722             goto done;
05723         }
05724     }
05725     if (schema) {
05726         s = uc_to_utf_c(schema, schemaLen);
05727         if (!s) {
05728             ret = nomem((STMT *) stmt);
05729             goto done;
05730         }
05731     }
05732     if (table) {
05733         t = uc_to_utf_c(table, tableLen);
05734         if (!t) {
05735             ret = nomem((STMT *) stmt);
05736             goto done;
05737         }
05738     }
05739     ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
05740                              (SQLCHAR *) s, SQL_NTS,
05741                              (SQLCHAR *) t, SQL_NTS);
05742 done:
05743     uc_free(t);
05744     uc_free(s);
05745     uc_free(c);
05746     HSTMT_UNLOCK(stmt);
05747     return ret;
05748 }
05749 #endif
05750 #endif
05751 
05756 static COL colPrivSpec2[] = {
05757     { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05758     { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
05759     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05760     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
05761     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05762     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05763     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
05764 };
05765 
05766 static COL colPrivSpec3[] = {
05767     { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
05768     { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
05769     { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
05770     { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
05771     { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
05772     { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
05773     { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
05774 };
05775 
05776 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
05777 
05791 SQLRETURN SQL_API
05792 SQLColumnPrivileges(SQLHSTMT stmt,
05793                     SQLCHAR *catalog, SQLSMALLINT catalogLen,
05794                     SQLCHAR *schema, SQLSMALLINT schemaLen,
05795                     SQLCHAR *table, SQLSMALLINT tableLen,
05796                     SQLCHAR *column, SQLSMALLINT columnLen)
05797 {
05798     SQLRETURN ret;
05799 
05800     HSTMT_LOCK(stmt);
05801     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
05802                       colPrivSpec3, array_size(colPrivSpec3), NULL);
05803     HSTMT_UNLOCK(stmt);
05804     return ret;
05805 }
05806 #endif
05807 
05808 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
05809 #ifdef WINTERFACE
05810 
05824 SQLRETURN SQL_API
05825 SQLColumnPrivilegesW(SQLHSTMT stmt,
05826                      SQLWCHAR *catalog, SQLSMALLINT catalogLen,
05827                      SQLWCHAR *schema, SQLSMALLINT schemaLen,
05828                      SQLWCHAR *table, SQLSMALLINT tableLen,
05829                      SQLWCHAR *column, SQLSMALLINT columnLen)
05830 {
05831     SQLRETURN ret;
05832 
05833     HSTMT_LOCK(stmt);
05834     ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
05835                       colPrivSpec3, array_size(colPrivSpec3), NULL);
05836     HSTMT_UNLOCK(stmt);
05837     return ret;
05838 }
05839 #endif
05840 #endif
05841 
05846 static COL pkeySpec2[] = {
05847     { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05848     { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
05849     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
05850     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
05851     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
05852     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
05853 };
05854 
05855 static COL pkeySpec3[] = {
05856     { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
05857     { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
05858     { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
05859     { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
05860     { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
05861     { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
05862 };
05863 
05876 static SQLRETURN
05877 drvprimarykeys(SQLHSTMT stmt,
05878                SQLCHAR *cat, SQLSMALLINT catLen,
05879                SQLCHAR *schema, SQLSMALLINT schemaLen,
05880                SQLCHAR *table, SQLSMALLINT tableLen)
05881 {
05882     STMT *s;
05883     DBC *d;
05884     SQLRETURN sret;
05885     int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
05886     int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
05887     PTRDIFF_T size;
05888     char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
05889 
05890     sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
05891                        pkeySpec3, array_size(pkeySpec3), &asize);
05892     if (sret != SQL_SUCCESS) {
05893         return sret;
05894     }
05895     s = (STMT *) stmt;
05896     d = (DBC *) s->dbc;
05897     if (!table || table[0] == '\0' || table[0] == '%') {
05898         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
05899         return SQL_ERROR;
05900     }
05901     if (tableLen == SQL_NTS) {
05902         size = sizeof (tname) - 1;
05903     } else {
05904         size = min(sizeof (tname) - 1, tableLen);
05905     }
05906     strncpy(tname, (char *) table, size);
05907     tname[size] = '\0';
05908     unescpat(tname);
05909     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
05910     if (!sql) {
05911         return nomem(s);
05912     }
05913     sret = starttran(s);
05914     if (sret != SQL_SUCCESS) {
05915         sqlite3_free(sql);
05916         return sret;
05917     }
05918     dbtraceapi(d, "sqlite3_get_table", sql);
05919     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
05920     sqlite3_free(sql);
05921     if (ret != SQLITE_OK) {
05922         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
05923                 errp ? errp : "unknown error", ret);
05924         if (errp) {
05925             sqlite3_free(errp);
05926             errp = NULL;
05927         }
05928         return SQL_ERROR;
05929     }
05930     if (errp) {
05931         sqlite3_free(errp);
05932         errp = NULL;
05933     }
05934     size = 0;
05935     if (ncols * nrows > 0) {
05936         int typec;
05937 
05938         namec = findcol(rowp, ncols, "name");
05939         uniquec = findcol(rowp, ncols, "pk");
05940         typec = findcol(rowp, ncols, "type");
05941         if (namec >= 0 && uniquec >= 0 && typec >= 0) {
05942             for (i = 1; i <= nrows; i++) {
05943                 if (*rowp[i * ncols + uniquec] != '0') {
05944                     size++;
05945                 }
05946             }
05947         }
05948     }
05949     if (size == 0) {
05950         sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
05951         if (!sql) {
05952             sqlite3_free_table(rowp);
05953             return nomem(s);
05954         }
05955         dbtraceapi(d, "sqlite3_get_table", sql);
05956         ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
05957                                 &errp);
05958         sqlite3_free(sql);
05959         if (ret != SQLITE_OK) {
05960             sqlite3_free_table(rowp);
05961             sqlite3_free_table(rowp2);
05962             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
05963                     errp ? errp : "unknown error", ret);
05964             if (errp) {
05965                 sqlite3_free(errp);
05966                 errp = NULL;
05967             }
05968             return SQL_ERROR;
05969         }
05970         if (errp) {
05971             sqlite3_free(errp);
05972             errp = NULL;
05973         }
05974     }
05975     if (ncols2 * nrows2 > 0) {
05976         namec2 = findcol(rowp2, ncols2, "name");
05977         uniquec2 = findcol(rowp2, ncols2, "unique");
05978         if (namec2 >= 0 && uniquec2 >=  0) {
05979             for (i = 1; i <= nrows2; i++) {
05980                 int nnrows, nncols, nlen = 0;
05981                 char **rowpp;
05982 
05983                 if (rowp2[i * ncols2 + namec2]) {
05984                     nlen = strlen(rowp2[i * ncols2 + namec2]);
05985                 }
05986                 if (nlen < 17 ||
05987                     strncmp(rowp2[i * ncols2 + namec2],
05988                             "sqlite_autoindex_", 17)) {
05989                     continue;
05990                 }
05991                 if (*rowp2[i * ncols2 + uniquec2] != '0') {
05992                     ret = SQLITE_ERROR;
05993                     sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
05994                                           rowp2[i * ncols2 + namec2]);
05995                     if (sql) {
05996                         dbtraceapi(d, "sqlite3_get_table", sql);
05997                         ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
05998                                                 &nnrows, &nncols, NULL);
05999                         sqlite3_free(sql);
06000                     }
06001                     if (ret == SQLITE_OK) {
06002                         size += nnrows;
06003                         sqlite3_free_table(rowpp);
06004                     }
06005                 }
06006             }
06007         }
06008     }
06009     if (size == 0) {
06010         sqlite3_free_table(rowp);
06011         sqlite3_free_table(rowp2);
06012         return SQL_SUCCESS;
06013     }
06014     s->nrows = size;
06015     size = (size + 1) * asize;
06016     s->rows = xmalloc((size + 1) * sizeof (char *));
06017     if (!s->rows) {
06018         s->nrows = 0;
06019         sqlite3_free_table(rowp);
06020         sqlite3_free_table(rowp2);
06021         return nomem(s);
06022     }
06023     s->rows[0] = (char *) size;
06024     s->rows += 1;
06025     memset(s->rows, 0, sizeof (char *) * size);
06026     s->rowfree = freerows;
06027     offs = s->ncols;
06028     if (rowp) {
06029         for (i = 1; i <= nrows; i++) {
06030             if (*rowp[i * ncols + uniquec] != '0') {
06031                 char buf[32];
06032 
06033                 s->rows[offs + 0] = xstrdup("");
06034 #if defined(_WIN32) || defined(_WIN64)
06035                 s->rows[offs + 1] = xstrdup(d->xcelqrx ? "main" : "");
06036 #else
06037                 s->rows[offs + 1] = xstrdup("");
06038 #endif
06039                 s->rows[offs + 2] = xstrdup(tname);
06040                 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
06041                 sprintf(buf, "%d", seq++);
06042                 s->rows[offs + 4] = xstrdup(buf);
06043                 offs += s->ncols;
06044             }
06045         }
06046     }
06047     if (rowp2) {
06048         for (i = 1; i <= nrows2; i++) {
06049             int nnrows, nncols, nlen = 0;
06050             char **rowpp;
06051 
06052             if (rowp2[i * ncols2 + namec2]) {
06053                 nlen = strlen(rowp2[i * ncols2 + namec2]);
06054             }
06055             if (nlen < 17 ||
06056                 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
06057                 continue;
06058             }
06059             if (*rowp2[i * ncols2 + uniquec2] != '0') {
06060                 int k;
06061 
06062                 ret = SQLITE_ERROR;
06063                 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06064                                       rowp2[i * ncols2 + namec2]);
06065                 if (sql) {
06066                     dbtraceapi(d, "sqlite3_get_table", sql);
06067                     ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06068                                             &nnrows, &nncols, NULL);
06069                     sqlite3_free(sql);
06070                 }
06071                 if (ret != SQLITE_OK) {
06072                     continue;
06073                 }
06074                 for (k = 0; nnrows && k < nncols; k++) {
06075                     if (strcmp(rowpp[k], "name") == 0) {
06076                         int m;
06077 
06078                         for (m = 1; m <= nnrows; m++) {
06079                             int roffs = offs + (m - 1) * s->ncols;
06080 
06081                             s->rows[roffs + 0] = xstrdup("");
06082 #if defined(_WIN32) || defined(_WIN64)
06083                             s->rows[roffs + 1] = 
06084                                 xstrdup(d->xcelqrx ? "main" : "");
06085 #else
06086                             s->rows[roffs + 1] = xstrdup("");
06087 #endif
06088                             s->rows[roffs + 2] = xstrdup(tname);
06089                             s->rows[roffs + 3] =
06090                                 xstrdup(rowpp[m * nncols + k]);
06091                             s->rows[roffs + 5] =
06092                                 xstrdup(rowp2[i * ncols2 + namec2]);
06093                         }
06094                     } else if (strcmp(rowpp[k], "seqno") == 0) {
06095                         int m;
06096 
06097                         for (m = 1; m <= nnrows; m++) {
06098                             int roffs = offs + (m - 1) * s->ncols;
06099                             int pos = m - 1;
06100                             char buf[32];
06101 
06102                             sscanf(rowpp[m * nncols + k], "%d", &pos);
06103                             sprintf(buf, "%d", pos + 1);
06104                             s->rows[roffs + 4] = xstrdup(buf);
06105                         }
06106                     }
06107                 }
06108                 offs += nnrows * s->ncols;
06109                 sqlite3_free_table(rowpp);
06110             }
06111         }
06112     }
06113     sqlite3_free_table(rowp);
06114     sqlite3_free_table(rowp2);
06115     return SQL_SUCCESS;
06116 }
06117 
06118 #ifndef WINTERFACE
06119 
06131 SQLRETURN SQL_API
06132 SQLPrimaryKeys(SQLHSTMT stmt,
06133                SQLCHAR *cat, SQLSMALLINT catLen,
06134                SQLCHAR *schema, SQLSMALLINT schemaLen,
06135                SQLCHAR *table, SQLSMALLINT tableLen)
06136 {
06137 #if defined(_WIN32) || defined(_WIN64)
06138     char *c = NULL, *s = NULL, *t = NULL;
06139 #endif
06140     SQLRETURN ret;
06141 
06142     HSTMT_LOCK(stmt);
06143 #if defined(_WIN32) || defined(_WIN64)
06144     if (!((STMT *) stmt)->oemcp[0]) {
06145         ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06146                              table, tableLen);
06147         goto done2;
06148     }
06149     if (cat) {
06150         c = wmb_to_utf_c((char *) cat, catLen);
06151         if (!c) {
06152             ret = nomem((STMT *) stmt);
06153             goto done;
06154         }
06155     }
06156     if (schema) {
06157         s = wmb_to_utf_c((char *) schema, schemaLen);
06158         if (!s) {
06159             ret = nomem((STMT *) stmt);
06160             goto done;
06161         }
06162     }
06163     if (table) {
06164         t = wmb_to_utf_c((char *) table, tableLen);
06165         if (!t) {
06166             ret = nomem((STMT *) stmt);
06167             goto done;
06168         }
06169     }
06170     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06171                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06172 #else
06173     ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
06174                          table, tableLen);
06175 #endif
06176 #if defined(_WIN32) || defined(_WIN64)
06177 done:
06178     uc_free(t);
06179     uc_free(s);
06180     uc_free(c);
06181 done2:
06182     ;
06183 #endif
06184     HSTMT_UNLOCK(stmt);
06185     return ret;
06186 }
06187 #endif
06188 
06189 #ifdef WINTERFACE
06190 
06202 SQLRETURN SQL_API
06203 SQLPrimaryKeysW(SQLHSTMT stmt,
06204                 SQLWCHAR *cat, SQLSMALLINT catLen,
06205                 SQLWCHAR *schema, SQLSMALLINT schemaLen,
06206                 SQLWCHAR *table, SQLSMALLINT tableLen)
06207 {
06208     char *c = NULL, *s = NULL, *t = NULL;
06209     SQLRETURN ret;
06210 
06211     HSTMT_LOCK(stmt);
06212     if (cat) {
06213         c = uc_to_utf_c(cat, catLen);
06214         if (!c) {
06215             ret = nomem((STMT *) stmt);
06216             goto done;
06217         }
06218     }
06219     if (schema) {
06220         s = uc_to_utf_c(schema, schemaLen);
06221         if (!s) {
06222             ret = nomem((STMT *) stmt);
06223             goto done;
06224         }
06225     }
06226     if (table) {
06227         t = uc_to_utf_c(table, tableLen);
06228         if (!t) {
06229             ret = nomem((STMT *) stmt);
06230             goto done;
06231         }
06232     }
06233     ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
06234                          (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
06235 done:
06236     uc_free(t);
06237     uc_free(s);
06238     uc_free(c);
06239     HSTMT_UNLOCK(stmt);
06240     return ret;
06241 }
06242 #endif
06243 
06248 static COL scolSpec2[] = {
06249     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06250     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06251     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06252     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06253     { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
06254     { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
06255     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06256     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06257     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06258 };
06259 
06260 static COL scolSpec3[] = {
06261     { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
06262     { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06263     { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
06264     { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
06265     { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
06266     { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
06267     { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
06268     { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
06269     { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
06270 };
06271 
06287 static SQLRETURN
06288 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
06289                   SQLCHAR *cat, SQLSMALLINT catLen,
06290                   SQLCHAR *schema, SQLSMALLINT schemaLen,
06291                   SQLCHAR *table, SQLSMALLINT tableLen,
06292                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
06293 {
06294     STMT *s;
06295     DBC *d;
06296     SQLRETURN sret;
06297     int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
06298     PTRDIFF_T size;
06299     int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
06300     int notnullcc = -1, mkrowid = 0;
06301     char *errp = NULL, *sql, tname[512];
06302     char **rowp = NULL, **rowppp = NULL;
06303 
06304     sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
06305                        scolSpec3, array_size(scolSpec3), &asize);
06306     if (sret != SQL_SUCCESS) {
06307         return sret;
06308     }
06309     s = (STMT *) stmt;
06310     d = (DBC *) s->dbc;
06311     if (!table || table[0] == '\0' || table[0] == '%') {
06312         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06313         return SQL_ERROR;
06314     }
06315     if (tableLen == SQL_NTS) {
06316         size = sizeof (tname) - 1;
06317     } else {
06318         size = min(sizeof (tname) - 1, tableLen);
06319     }
06320     strncpy(tname, (char *) table, size);
06321     tname[size] = '\0';
06322     unescpat(tname);
06323     if (id != SQL_BEST_ROWID) {
06324         return SQL_SUCCESS;
06325     }
06326     sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
06327     if (!sql) {
06328         return nomem(s);
06329     }
06330     sret = starttran(s);
06331     if (sret != SQL_SUCCESS) {
06332         sqlite3_free(sql);
06333         return sret;
06334     }
06335     dbtraceapi(d, "sqlite3_get_table", sql);
06336     ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06337     sqlite3_free(sql);
06338     if (ret != SQLITE_OK) {
06339 doerr:
06340         setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06341                 errp ? errp : "unknown error", ret);
06342         if (errp) {
06343             sqlite3_free(errp);
06344             errp = NULL;
06345         }
06346         return SQL_ERROR;       
06347     }
06348     if (errp) {
06349         sqlite3_free(errp);
06350         errp = NULL;
06351     }
06352     size = 0; /* number result rows */
06353     if (ncols * nrows <= 0) {
06354         goto nodata_but_rowid;
06355     }
06356     sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
06357     if (!sql) {
06358         return nomem(s);
06359     }
06360     dbtraceapi(d, "sqlite3_get_table", sql);
06361     ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
06362                             &errp);
06363     sqlite3_free(sql);
06364     if (ret != SQLITE_OK) {
06365         sqlite3_free_table(rowp);
06366         goto doerr;
06367     }
06368     if (errp) {
06369         sqlite3_free(errp);
06370         errp = NULL;
06371     }
06372     namec = findcol(rowp, ncols, "name");
06373     uniquec = findcol(rowp, ncols, "unique");
06374     if (namec < 0 || uniquec < 0) {
06375         goto nodata_but_rowid;
06376     }
06377     namecc = findcol(rowppp, nnncols, "name");
06378     typecc = findcol(rowppp, nnncols, "type");
06379     notnullcc = findcol(rowppp, nnncols, "notnull");
06380     for (i = 1; i <= nrows; i++) {
06381         int nnrows, nncols;
06382         char **rowpp = NULL;
06383 
06384         if (*rowp[i * ncols + uniquec] != '0') {
06385             ret = SQLITE_ERROR;
06386             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06387                                   rowp[i * ncols + namec]);
06388             if (sql) {
06389                 dbtraceapi(d, "sqlite3_get_table", sql);
06390                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06391                                         &nnrows, &nncols, NULL);
06392                 sqlite3_free(sql);
06393             }
06394             if (ret == SQLITE_OK) {
06395                 size += nnrows;
06396                 sqlite3_free_table(rowpp);
06397             }
06398         }
06399     }
06400 nodata_but_rowid:
06401     if (size == 0) {
06402         size = 1;
06403         mkrowid = 1;
06404     }
06405     s->nrows = size;
06406     size = (size + 1) * asize;
06407     s->rows = xmalloc((size + 1) * sizeof (char *));
06408     if (!s->rows) {
06409         s->nrows = 0;
06410         sqlite3_free_table(rowp);
06411         sqlite3_free_table(rowppp);
06412         return nomem(s);
06413     }
06414     s->rows[0] = (char *) size;
06415     s->rows += 1;
06416     memset(s->rows, 0, sizeof (char *) * size);
06417     s->rowfree = freerows;
06418     if (mkrowid) {
06419         s->nrows = 0;
06420         goto mkrowid;
06421     }
06422     offs = 0;
06423     for (i = 1; i <= nrows; i++) {
06424         int nnrows, nncols;
06425         char **rowpp = NULL;
06426 
06427         if (*rowp[i * ncols + uniquec] != '0') {
06428             int k;
06429 
06430             ret = SQLITE_ERROR;
06431             sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
06432                                   rowp[i * ncols + namec]);
06433             if (sql) {
06434                 dbtraceapi(d, "sqlite3_get_table", sql);
06435                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06436                                         &nnrows, &nncols, NULL);
06437                 sqlite3_free(sql);
06438             }
06439             if (ret != SQLITE_OK) {
06440                 continue;
06441             }
06442             for (k = 0; nnrows && k < nncols; k++) {
06443                 if (strcmp(rowpp[k], "name") == 0) {
06444                     int m;
06445 
06446                     for (m = 1; m <= nnrows; m++) {
06447                         int roffs = (offs + m) * s->ncols;
06448 
06449                         s->rows[roffs + 0] =
06450                             xstrdup(stringify(SQL_SCOPE_SESSION));
06451                         s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
06452                         s->rows[roffs + 4] = xstrdup("0");
06453                         s->rows[roffs + 7] =
06454                             xstrdup(stringify(SQL_PC_NOT_PSEUDO));
06455                         if (namecc >= 0 && typecc >= 0) {
06456                             int ii;
06457 
06458                             for (ii = 1; ii <= nnnrows; ii++) {
06459                                 if (strcmp(rowppp[ii * nnncols + namecc],
06460                                            rowpp[m * nncols + k]) == 0) {
06461                                     char *typen = rowppp[ii * nnncols + typecc];
06462                                     int sqltype, mm, dd, isnullable = 0;
06463                                     char buf[32];
06464                                         
06465                                     s->rows[roffs + 3] = xstrdup(typen);
06466                                     sqltype = mapsqltype(typen, NULL, *s->ov3,
06467                                                          s->nowchar[0],
06468                                                          s->dobigint);
06469                                     getmd(typen, sqltype, &mm, &dd);
06470 #ifdef SQL_LONGVARCHAR
06471                                     if (sqltype == SQL_VARCHAR && mm > 255) {
06472                                         sqltype = SQL_LONGVARCHAR;
06473                                     }
06474 #endif
06475 #ifdef WINTERFACE
06476 #ifdef SQL_WLONGVARCHAR
06477                                     if (sqltype == SQL_WVARCHAR && mm > 255) {
06478                                         sqltype = SQL_WLONGVARCHAR;
06479                                     }
06480 #endif
06481 #endif
06482                                     if (sqltype == SQL_VARBINARY && mm > 255) {
06483                                         sqltype = SQL_LONGVARBINARY;
06484                                     }
06485                                     sprintf(buf, "%d", sqltype);
06486                                     s->rows[roffs + 2] = xstrdup(buf);
06487                                     sprintf(buf, "%d", mm);
06488                                     s->rows[roffs + 5] = xstrdup(buf);
06489                                     sprintf(buf, "%d", dd);
06490                                     s->rows[roffs + 6] = xstrdup(buf);
06491                                     if (notnullcc >= 0) {
06492                                         char *inp =
06493                                            rowppp[ii * nnncols + notnullcc];
06494 
06495                                         isnullable = inp[0] != '0';
06496                                     }
06497                                     sprintf(buf, "%d", isnullable);
06498                                     s->rows[roffs + 8] = xstrdup(buf);
06499                                 }
06500                             }
06501                         }
06502                     }
06503                 }
06504             }
06505             offs += nnrows;
06506             sqlite3_free_table(rowpp);
06507         }
06508     }
06509     if (nullable == SQL_NO_NULLS) {
06510         for (i = 1; i < s->nrows; i++) {
06511             if (s->rows[i * s->ncols + 8][0] == '0') {
06512                 int m, i1 = i + 1;
06513 
06514                 for (m = 0; m < s->ncols; m++) {
06515                     freep(&s->rows[i * s->ncols + m]);
06516                 }
06517                 size = s->ncols * sizeof (char *) * (s->nrows - i1);
06518                 if (size > 0) {
06519                     memmove(s->rows + i * s->ncols,
06520                             s->rows + i1 * s->ncols,
06521                             size);
06522                     memset(s->rows + s->nrows * s->ncols, 0,
06523                            s->ncols * sizeof (char *));
06524                 }
06525                 s->nrows--;
06526                 --i;
06527             }
06528         }
06529     }
06530 mkrowid:
06531     sqlite3_free_table(rowp);
06532     sqlite3_free_table(rowppp);
06533     if (s->nrows == 0) {
06534         s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
06535         s->rows[s->ncols + 1] = xstrdup("_ROWID_");
06536         s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
06537         s->rows[s->ncols + 3] = xstrdup("integer");
06538         s->rows[s->ncols + 4] = xstrdup("0");
06539         s->rows[s->ncols + 5] = xstrdup("10");
06540         s->rows[s->ncols + 6] = xstrdup("9");
06541         s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
06542         s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
06543         s->nrows = 1;
06544     }
06545     return SQL_SUCCESS;
06546 }
06547 
06548 #ifndef WINTERFACE
06549 
06564 SQLRETURN SQL_API
06565 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
06566                   SQLCHAR *cat, SQLSMALLINT catLen,
06567                   SQLCHAR *schema, SQLSMALLINT schemaLen,
06568                   SQLCHAR *table, SQLSMALLINT tableLen,
06569                   SQLUSMALLINT scope, SQLUSMALLINT nullable)
06570 {
06571 #if defined(_WIN32) || defined(_WIN64)
06572     char *c = NULL, *s = NULL, *t = NULL;
06573 #endif
06574     SQLRETURN ret;
06575 
06576     HSTMT_LOCK(stmt);
06577 #if defined(_WIN32) || defined(_WIN64)
06578     if (!((STMT *) stmt)->oemcp[0]) {
06579         ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
06580                                 table, tableLen, scope, nullable);
06581         goto done2;
06582     }
06583     if (cat) {
06584         c = wmb_to_utf_c((char *) cat, catLen);
06585         if (!c) {
06586             ret = nomem((STMT *) stmt);
06587             goto done;
06588         }
06589     }
06590     if (schema) {
06591         s = wmb_to_utf_c((char *) schema, schemaLen);
06592         if (!s) {
06593             ret = nomem((STMT *) stmt);
06594             goto done;
06595         }
06596     }
06597     if (table) {
06598         t = wmb_to_utf_c((char *) table, tableLen);
06599         if (!t) {
06600             ret = nomem((STMT *) stmt);
06601             goto done;
06602         }
06603     }
06604     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
06605                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
06606                             scope, nullable);
06607 #else
06608     ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
06609                             table, tableLen, scope, nullable);
06610 #endif
06611 #if defined(_WIN32) || defined(_WIN64)
06612 done:
06613     uc_free(t);
06614     uc_free(s);
06615     uc_free(c);
06616 done2:
06617     ;
06618 #endif
06619     HSTMT_UNLOCK(stmt);
06620     return ret;
06621 }
06622 #endif
06623 
06624 #ifdef WINTERFACE
06625 
06640 SQLRETURN SQL_API
06641 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
06642                    SQLWCHAR *cat, SQLSMALLINT catLen,
06643                    SQLWCHAR *schema, SQLSMALLINT schemaLen,
06644                    SQLWCHAR *table, SQLSMALLINT tableLen,
06645                    SQLUSMALLINT scope, SQLUSMALLINT nullable)
06646 {
06647     char *c = NULL, *s = NULL, *t = NULL;
06648     SQLRETURN ret;
06649 
06650     HSTMT_LOCK(stmt);
06651     if (cat) {
06652         c = uc_to_utf_c(cat, catLen);
06653         if (!c) {
06654             ret = nomem((STMT *) stmt);
06655             goto done;
06656         }
06657     }
06658     if (schema) {
06659         s = uc_to_utf_c(schema, schemaLen);
06660         if (!s) {
06661             ret = nomem((STMT *) stmt);
06662             goto done;
06663         }
06664     }
06665     if (table) {
06666         t = uc_to_utf_c(table, tableLen);
06667         if (!t) {
06668             ret = nomem((STMT *) stmt);
06669             goto done;
06670         }
06671     }
06672     ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
06673                             (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
06674                             scope, nullable);
06675 done:
06676     uc_free(t);
06677     uc_free(s);
06678     uc_free(c);
06679     HSTMT_UNLOCK(stmt);
06680     return ret;
06681 }
06682 #endif
06683 
06688 static COL fkeySpec2[] = {
06689     { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06690     { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
06691     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
06692     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
06693     { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
06694     { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
06695     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
06696     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
06697     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
06698     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
06699     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
06700     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
06701     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
06702     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
06703 };
06704 
06705 static COL fkeySpec3[] = {
06706     { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
06707     { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
06708     { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
06709     { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
06710     { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
06711     { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
06712     { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
06713     { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
06714     { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
06715     { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
06716     { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
06717     { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
06718     { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
06719     { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
06720 };
06721 
06740 static SQLRETURN SQL_API
06741 drvforeignkeys(SQLHSTMT stmt,
06742                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
06743                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
06744                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
06745                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
06746                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
06747                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
06748 {
06749     STMT *s;
06750     DBC *d;
06751     SQLRETURN sret;
06752     int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
06753     int onu, ond;
06754     PTRDIFF_T size;
06755     char **rowp, *errp = NULL, *sql, pname[512], fname[512];
06756 
06757     sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
06758                        fkeySpec3, array_size(fkeySpec3), &asize);
06759     if (sret != SQL_SUCCESS) {
06760         return sret;
06761     }
06762     s = (STMT *) stmt;
06763     sret = starttran(s);
06764     if (sret != SQL_SUCCESS) {
06765         return sret;
06766     }
06767     d = (DBC *) s->dbc;
06768     if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
06769         (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
06770         setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
06771         return SQL_ERROR;
06772     }
06773     size = 0;
06774     if (PKtable) {
06775         if (PKtableLen == SQL_NTS) {
06776             size = sizeof (pname) - 1;
06777         } else {
06778             size = min(sizeof (pname) - 1, PKtableLen);
06779         }
06780         strncpy(pname, (char *) PKtable, size);
06781     }
06782     pname[size] = '\0';
06783     size = 0;
06784     if (FKtable) {
06785 
06786         if (FKtableLen == SQL_NTS) {
06787             size = sizeof (fname) - 1;
06788         } else {
06789             size = min(sizeof (fname) - 1, FKtableLen);
06790         }
06791         strncpy(fname, (char *) FKtable, size);
06792     }
06793     fname[size] = '\0';
06794     if (fname[0] != '\0') {
06795         int plen;
06796 
06797         ret = SQLITE_ERROR;
06798         sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
06799         if (sql) {
06800             dbtraceapi(d, "sqlite3_get_table", sql);
06801             ret = sqlite3_get_table(d->sqlite, sql, &rowp,
06802                                     &nrows, &ncols, &errp);
06803             sqlite3_free(sql);
06804         }
06805         if (ret != SQLITE_OK) {
06806             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06807                     errp ? errp : "unknown error", ret);
06808             if (errp) {
06809                 sqlite3_free(errp);
06810                 errp = NULL;
06811             }
06812             return SQL_ERROR;
06813         }
06814         if (errp) {
06815             sqlite3_free(errp);
06816             errp = NULL;
06817         }
06818         if (ncols * nrows <= 0) {
06819 nodata:
06820             sqlite3_free_table(rowp);
06821             return SQL_SUCCESS;
06822         }
06823         size = 0;
06824         namec = findcol(rowp, ncols, "table");
06825         seqc = findcol(rowp, ncols, "seq");
06826         fromc = findcol(rowp, ncols, "from");
06827         toc = findcol(rowp, ncols, "to");
06828         onu = findcol(rowp, ncols, "on_update");
06829         ond = findcol(rowp, ncols, "on_delete");
06830         if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
06831             goto nodata;
06832         }
06833         plen = strlen(pname);
06834         for (i = 1; i <= nrows; i++) {
06835             char *ptab = unquote(rowp[i * ncols + namec]);
06836 
06837             if (plen && ptab) {
06838                 int len = strlen(ptab);
06839 
06840                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
06841                     continue;
06842                 }
06843             }
06844             size++;
06845         }
06846         if (size == 0) {
06847             goto nodata;
06848         }
06849         s->nrows = size;
06850         size = (size + 1) * asize;
06851         s->rows = xmalloc((size + 1) * sizeof (char *));
06852         if (!s->rows) {
06853             s->nrows = 0;
06854             return nomem(s);
06855         }
06856         s->rows[0] = (char *) size;
06857         s->rows += 1;
06858         memset(s->rows, 0, sizeof (char *) * size);
06859         s->rowfree = freerows;
06860         offs = 0;
06861         for (i = 1; i <= nrows; i++) {
06862             int pos = 0, roffs = (offs + 1) * s->ncols;
06863             char *ptab = rowp[i * ncols + namec];
06864             char buf[32];
06865 
06866             if (plen && ptab) {
06867                 int len = strlen(ptab);
06868 
06869                 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
06870                     continue;
06871                 }
06872             }
06873             s->rows[roffs + 0] = xstrdup("");
06874 #if defined(_WIN32) || defined(_WIN64)
06875             s->rows[roffs + 1] = xstrdup(d->xcelqrx ? "main" : "");
06876 #else
06877             s->rows[roffs + 1] = xstrdup("");
06878 #endif
06879             s->rows[roffs + 2] = xstrdup(ptab);
06880             s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
06881             s->rows[roffs + 4] = xstrdup("");
06882             s->rows[roffs + 5] = xstrdup("");
06883             s->rows[roffs + 6] = xstrdup(fname);
06884             s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
06885             sscanf(rowp[i * ncols + seqc], "%d", &pos);
06886             sprintf(buf, "%d", pos + 1);
06887             s->rows[roffs + 8] = xstrdup(buf);
06888             if (onu < 0) {
06889                 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
06890             } else {
06891                 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
06892                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
06893                 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
06894                     s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
06895                 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
06896                     s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
06897                 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
06898                     s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
06899                 } else {
06900                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
06901                 }
06902             }
06903             if (ond < 0) {
06904                 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
06905             } else {
06906                 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
06907                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
06908                 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
06909                     s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
06910                 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
06911                     s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
06912                 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
06913                     s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
06914                 } else {
06915                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
06916                 }
06917             }
06918             s->rows[roffs + 11] = NULL;
06919             s->rows[roffs + 12] = NULL;
06920             s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
06921             offs++;
06922         }
06923         sqlite3_free_table(rowp);
06924     } else {
06925         int nnrows, nncols, plen = strlen(pname);
06926         char **rowpp;
06927 
06928         sql = "select name from sqlite_master where type='table'";
06929         dbtraceapi(d, "sqlite3_get_table", sql);
06930         ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
06931         if (ret != SQLITE_OK) {
06932             setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06933                     errp ? errp : "unknown error", ret);
06934             if (errp) {
06935                 sqlite3_free(errp);
06936                 errp = NULL;
06937             }
06938             return SQL_ERROR;
06939         }
06940         if (errp) {
06941             sqlite3_free(errp);
06942             errp = NULL;
06943         }
06944         if (ncols * nrows <= 0) {
06945             goto nodata;
06946         }
06947         size = 0;
06948         for (i = 1; i <= nrows; i++) {
06949             int k;
06950 
06951             if (!rowp[i]) {
06952                 continue;
06953             }
06954             rowpp = NULL;
06955             ret = SQLITE_ERROR;
06956             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
06957             if (sql) {
06958                 dbtraceapi(d, "sqlite3_get_table", sql);
06959                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
06960                                       &nnrows, &nncols, NULL);
06961                 sqlite3_free(sql);
06962             }
06963             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
06964                 sqlite3_free_table(rowpp);
06965                 continue;
06966             }
06967             namec = findcol(rowpp, nncols, "table");
06968             seqc = findcol(rowpp, nncols, "seq");
06969             fromc = findcol(rowpp, nncols, "from");
06970             toc = findcol(rowpp, nncols, "to");
06971             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
06972                 sqlite3_free_table(rowpp);
06973                 continue;
06974             }
06975             for (k = 1; k <= nnrows; k++) {
06976                 char *ptab = unquote(rowpp[k * nncols + namec]);
06977 
06978                 if (plen && ptab) {
06979                     int len = strlen(ptab);
06980 
06981                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
06982                         continue;
06983                     }
06984                 }
06985                 size++;
06986             }
06987             sqlite3_free_table(rowpp);
06988         }
06989         if (size == 0) {
06990             goto nodata;
06991         }
06992         s->nrows = size;
06993         size = (size + 1) * asize;
06994         s->rows = xmalloc((size + 1) * sizeof (char *));
06995         if (!s->rows) {
06996             s->nrows = 0;
06997             return nomem(s);
06998         }
06999         s->rows[0] = (char *) size;
07000         s->rows += 1;
07001         memset(s->rows, 0, sizeof (char *) * size);
07002         s->rowfree = freerows;
07003         offs = 0;
07004         for (i = 1; i <= nrows; i++) {
07005             int k;
07006 
07007             if (!rowp[i]) {
07008                 continue;
07009             }
07010             rowpp = NULL;
07011             ret = SQLITE_ERROR;
07012             sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
07013             if (sql) {
07014                 dbtraceapi(d, "sqlite3_get_table", sql);
07015                 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
07016                                         &nnrows, &nncols, NULL);
07017                 sqlite3_free(sql);
07018             }
07019             if (ret != SQLITE_OK || nncols * nnrows <= 0) {
07020                 sqlite3_free_table(rowpp);
07021                 continue;
07022             }
07023             namec = findcol(rowpp, nncols, "table");
07024             seqc = findcol(rowpp, nncols, "seq");
07025             fromc = findcol(rowpp, nncols, "from");
07026             toc = findcol(rowpp, nncols, "to");
07027             onu = findcol(rowpp, nncols, "on_update");
07028             ond = findcol(rowpp, nncols, "on_delete");
07029             if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
07030                 sqlite3_free_table(rowpp);
07031                 continue;
07032             }
07033             for (k = 1; k <= nnrows; k++) {
07034                 int pos = 0, roffs = (offs + 1) * s->ncols;
07035                 char *ptab = unquote(rowpp[k * nncols + namec]);
07036                 char buf[32];
07037 
07038                 if (plen && ptab) {
07039                     int len = strlen(ptab);
07040 
07041                     if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
07042                         continue;
07043                     }
07044                 }
07045                 s->rows[roffs + 0] = xstrdup("");
07046 #if defined(_WIN32) || defined(_WIN64)
07047                 s->rows[roffs + 1] = xstrdup(d->xcelqrx ? "main" : "");
07048 #else
07049                 s->rows[roffs + 1] = xstrdup("");
07050 #endif
07051                 s->rows[roffs + 2] = xstrdup(ptab);
07052                 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
07053                 s->rows[roffs + 4] = xstrdup("");
07054                 s->rows[roffs + 5] = xstrdup("");
07055                 s->rows[roffs + 6] = xstrdup(rowp[i]);
07056                 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
07057                 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
07058                 sprintf(buf, "%d", pos + 1);
07059                 s->rows[roffs + 8] = xstrdup(buf);
07060                 if (onu < 0) {
07061                     s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
07062                 } else {
07063                     if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
07064                         s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
07065                     } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
07066                                == 0) {
07067                         s->rows[roffs + 9] =
07068                             xstrdup(stringify(SQL_SET_DEFAULT));
07069                     } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
07070                                == 0) {
07071                         s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
07072                     } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
07073                                == 0) {
07074                         s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
07075                     } else {
07076                         s->rows[roffs + 9] =
07077                             xstrdup(stringify(SQL_NO_ACTION));
07078                     }
07079                 }
07080                 if (ond < 0) {
07081                     s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
07082                 } else {
07083                     if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
07084                         s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
07085                     } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
07086                                == 0) {
07087                         s->rows[roffs + 10] =
07088                             xstrdup(stringify(SQL_SET_DEFAULT));
07089                     } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
07090                                == 0) {
07091                         s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
07092                     } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
07093                                == 0) {
07094                         s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
07095                     } else {
07096                         s->rows[roffs + 10] =
07097                             xstrdup(stringify(SQL_NO_ACTION));
07098                     }
07099                 }
07100                 s->rows[roffs + 11] = NULL;
07101                 s->rows[roffs + 12] = NULL;
07102                 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
07103                 offs++;
07104             }
07105             sqlite3_free_table(rowpp);
07106         }
07107         sqlite3_free_table(rowp);
07108     }
07109     return SQL_SUCCESS;
07110 }
07111 
07112 #ifndef WINTERFACE
07113 
07131 SQLRETURN SQL_API
07132 SQLForeignKeys(SQLHSTMT stmt,
07133                SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07134                SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
07135                SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
07136                SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07137                SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
07138                SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
07139 {
07140 #if defined(_WIN32) || defined(_WIN64)
07141     char *pc = NULL, *ps = NULL, *pt = NULL;
07142     char *fc = NULL, *fs = NULL, *ft = NULL;
07143 #endif
07144     SQLRETURN ret;
07145 
07146     HSTMT_LOCK(stmt);
07147 #if defined(_WIN32) || defined(_WIN64)
07148     if (!((STMT *) stmt)->oemcp[0]) {
07149         ret = drvforeignkeys(stmt,
07150                              PKcatalog, PKcatalogLen,
07151                              PKschema, PKschemaLen, PKtable, PKtableLen,
07152                              FKcatalog, FKcatalogLen,
07153                              FKschema, FKschemaLen,
07154                              FKtable, FKtableLen);
07155         goto done2;
07156     }
07157     if (PKcatalog) {
07158         pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
07159         if (!pc) {
07160             ret = nomem((STMT *) stmt);
07161             goto done;
07162         }
07163     }
07164     if (PKschema) {
07165         ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
07166         if (!ps) {
07167             ret = nomem((STMT *) stmt);
07168             goto done;
07169         }
07170     }
07171     if (PKtable) {
07172         pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
07173         if (!pt) {
07174             ret = nomem((STMT *) stmt);
07175             goto done;
07176         }
07177     }
07178     if (FKcatalog) {
07179         fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
07180         if (!fc) {
07181             ret = nomem((STMT *) stmt);
07182             goto done;
07183         }
07184     }
07185     if (FKschema) {
07186         fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
07187         if (!fs) {
07188             ret = nomem((STMT *) stmt);
07189             goto done;
07190         }
07191     }
07192     if (FKtable) {
07193         ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
07194         if (!ft) {
07195             ret = nomem((STMT *) stmt);
07196             goto done;
07197         }
07198     }
07199     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
07200                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
07201                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
07202                          (SQLCHAR *) ft, SQL_NTS);
07203 #else
07204     ret = drvforeignkeys(stmt,
07205                          PKcatalog, PKcatalogLen,
07206                          PKschema, PKschemaLen, PKtable, PKtableLen,
07207                          FKcatalog, FKcatalogLen,
07208                          FKschema, FKschemaLen,
07209                          FKtable, FKtableLen);
07210 #endif
07211 #if defined(_WIN32) || defined(_WIN64)
07212 done:
07213     uc_free(ft);
07214     uc_free(fs);
07215     uc_free(fc);
07216     uc_free(pt);
07217     uc_free(ps);
07218     uc_free(pc);
07219 done2:
07220     ;
07221 #endif
07222     HSTMT_UNLOCK(stmt);
07223     return ret;
07224 }
07225 #endif
07226 
07227 #ifdef WINTERFACE
07228 
07246 SQLRETURN SQL_API
07247 SQLForeignKeysW(SQLHSTMT stmt,
07248                 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
07249                 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
07250                 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
07251                 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
07252                 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
07253                 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
07254 {
07255     char *pc = NULL, *ps = NULL, *pt = NULL;
07256     char *fc = NULL, *fs = NULL, *ft = NULL;
07257     SQLRETURN ret;
07258 
07259     HSTMT_LOCK(stmt);
07260     if (PKcatalog) {
07261         pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
07262         if (!pc) {
07263             ret = nomem((STMT *) stmt);
07264             goto done;
07265         }
07266     }
07267     if (PKschema) {
07268         ps = uc_to_utf_c(PKschema, PKschemaLen);
07269         if (!ps) {
07270             ret = nomem((STMT *) stmt);
07271             goto done;
07272         }
07273     }
07274     if (PKtable) {
07275         pt = uc_to_utf_c(PKtable, PKtableLen);
07276         if (!pt) {
07277             ret = nomem((STMT *) stmt);
07278             goto done;
07279         }
07280     }
07281     if (FKcatalog) {
07282         fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
07283         if (!fc) {
07284             ret = nomem((STMT *) stmt);
07285             goto done;
07286         }
07287     }
07288     if (FKschema) {
07289         fs = uc_to_utf_c(FKschema, FKschemaLen);
07290         if (!fs) {
07291             ret = nomem((STMT *) stmt);
07292             goto done;
07293         }
07294     }
07295     if (FKtable) {
07296         ft = uc_to_utf_c(FKtable, FKtableLen);
07297         if (!ft) {
07298             ret = nomem((STMT *) stmt);
07299             goto done;
07300         }
07301     }
07302     ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
07303                          (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
07304                          (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
07305                          (SQLCHAR *) ft, SQL_NTS);
07306 done:
07307     uc_free(ft);
07308     uc_free(fs);
07309     uc_free(fc);
07310     uc_free(pt);
07311     uc_free(ps);
07312     uc_free(pc);
07313     HSTMT_UNLOCK(stmt);
07314     return ret;
07315 }
07316 #endif
07317 
07324 static SQLRETURN
07325 starttran(STMT *s)
07326 {
07327     int ret = SQL_SUCCESS, rc, busy_count = 0;
07328     char *errp = NULL;
07329     DBC *d = (DBC *) s->dbc;
07330 
07331     if (!d->autocommit && !d->intrans && !d->trans_disable) {
07332 begin_again:
07333         rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
07334         if (rc == SQLITE_BUSY) {
07335             if (busy_handler((void *) d, ++busy_count)) {
07336                 if (errp) {
07337                     sqlite3_free(errp);
07338                     errp = NULL;
07339                 }
07340                 goto begin_again;
07341             }
07342         }
07343         dbtracerc(d, rc, errp);
07344         if (rc != SQLITE_OK) {
07345             setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07346                     errp ? errp : "unknown error", rc);
07347             ret = SQL_ERROR;
07348         } else {
07349             d->intrans = 1;
07350         }
07351         if (errp) {
07352             sqlite3_free(errp);
07353             errp = NULL;
07354         }
07355     }
07356     return ret;
07357 }
07358 
07367 static SQLRETURN
07368 endtran(DBC *d, SQLSMALLINT comptype, int force)
07369 {
07370     int ret, busy_count = 0;
07371     char *sql, *errp = NULL;
07372 
07373     if (!d->sqlite) {
07374         setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
07375         return SQL_ERROR;
07376     }
07377     if ((!force && d->autocommit) || !d->intrans) {
07378         return SQL_SUCCESS;
07379     }
07380     switch (comptype) {
07381     case SQL_COMMIT:
07382         sql = "COMMIT TRANSACTION";
07383         goto doit;
07384     case SQL_ROLLBACK:
07385         sql = "ROLLBACK TRANSACTION";
07386     doit:
07387         ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
07388         dbtracerc(d, ret, errp);
07389         if (ret == SQLITE_BUSY && busy_count < 10) {
07390             if (busy_handler((void *) d, ++busy_count)) {
07391                 if (errp) {
07392                     sqlite3_free(errp);
07393                     errp = NULL;
07394                 }
07395                 goto doit;
07396             }
07397         }
07398         d->intrans = 0;
07399         if (ret != SQLITE_OK) {
07400             setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
07401                      errp ? errp : "transaction failed");
07402             if (errp) {
07403                 sqlite3_free(errp);
07404                 errp = NULL;
07405             }
07406             return SQL_ERROR;
07407         }
07408         if (errp) {
07409             sqlite3_free(errp);
07410             errp = NULL;
07411         }
07412         return SQL_SUCCESS;
07413     }
07414     setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
07415     return SQL_ERROR;
07416 }
07417 
07426 static SQLRETURN
07427 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
07428 {
07429     DBC *d;
07430     int fail = 0;
07431     SQLRETURN ret;
07432 #if defined(_WIN32) || defined(_WIN64)
07433     ENV *e;
07434 #endif
07435 
07436     switch (type) {
07437     case SQL_HANDLE_DBC:
07438         HDBC_LOCK((SQLHDBC) handle);
07439         if (handle == SQL_NULL_HDBC) {
07440             return SQL_INVALID_HANDLE;
07441         }
07442         d = (DBC *) handle;
07443         ret = endtran(d, comptype, 0);
07444         HDBC_UNLOCK((SQLHDBC) handle);
07445         return ret;
07446     case SQL_HANDLE_ENV:
07447         if (handle == SQL_NULL_HENV) {
07448             return SQL_INVALID_HANDLE;
07449         }
07450 #if defined(_WIN32) || defined(_WIN64)
07451         e = (ENV *) handle;
07452         if (e->magic != ENV_MAGIC) {
07453             return SQL_INVALID_HANDLE;
07454         }
07455         EnterCriticalSection(&e->cs);
07456         e->owner = GetCurrentThreadId();
07457 #endif
07458         d = ((ENV *) handle)->dbcs;
07459         while (d) {
07460             ret = endtran(d, comptype, 0);
07461             if (ret != SQL_SUCCESS) {
07462                 fail++;
07463             }
07464             d = d->next;
07465         }
07466 #if defined(_WIN32) || defined(_WIN64)
07467         e->owner = 0;
07468         LeaveCriticalSection(&e->cs);
07469 #endif
07470         return fail ? SQL_ERROR : SQL_SUCCESS;
07471     }
07472     return SQL_INVALID_HANDLE;
07473 }
07474 
07483 SQLRETURN SQL_API
07484 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
07485 {
07486     return drvendtran(type, handle, comptype);
07487 }
07488 
07497 SQLRETURN SQL_API
07498 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
07499 {
07500     if (env != SQL_NULL_HENV) {
07501         return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
07502     }
07503     return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
07504 }
07505 
07510 SQLRETURN SQL_API
07511 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
07512 {
07513     return SQL_ERROR;
07514 }
07515 
07516 #ifndef WINTERFACE
07517 
07528 SQLRETURN SQL_API
07529 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
07530              SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
07531 {
07532     int outLen = 0;
07533     SQLRETURN ret = SQL_SUCCESS;
07534 
07535     HSTMT_LOCK(stmt);
07536     if (sqlinLen == SQL_NTS) {
07537         sqlinLen = strlen((char *) sqlin);
07538     }
07539     if (sql) {
07540         if (sqlMax > 0) {
07541             strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
07542             sqlin[sqlMax - 1] = '\0';
07543             outLen = min(sqlMax - 1, sqlinLen);
07544         }
07545     } else {
07546         outLen = sqlinLen;
07547     }
07548     if (sqlLen) {
07549         *sqlLen = outLen;
07550     }
07551     if (sql && outLen < sqlinLen) {
07552         setstat((STMT *) stmt, -1, "data right truncated", "01004");
07553         ret = SQL_SUCCESS_WITH_INFO;
07554     }
07555     HSTMT_UNLOCK(stmt);
07556     return ret;
07557 }
07558 #endif
07559 
07560 #ifdef WINTERFACE
07561 
07572 SQLRETURN SQL_API
07573 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
07574               SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
07575 {
07576     int outLen = 0;
07577     SQLRETURN ret = SQL_SUCCESS;
07578 
07579     HSTMT_LOCK(stmt);
07580     if (sqlinLen == SQL_NTS) {
07581         sqlinLen = uc_strlen(sqlin);
07582     }
07583     if (sql) {
07584         if (sqlMax > 0) {
07585             uc_strncpy(sql, sqlin, sqlMax - 1);
07586             sqlin[sqlMax - 1] = 0;
07587             outLen = min(sqlMax  - 1, sqlinLen);
07588         }
07589     } else {
07590         outLen = sqlinLen;
07591     }
07592     if (sqlLen) {
07593         *sqlLen = outLen;
07594     }
07595     if (sql && outLen < sqlinLen) {
07596         setstat((STMT *) stmt, -1, "data right truncated", "01004");
07597         ret = SQL_SUCCESS_WITH_INFO;
07598     }
07599     HSTMT_UNLOCK(stmt);
07600     return ret;
07601 }
07602 #endif
07603 
07608 static COL procSpec2[] = {
07609     { "SYSTEM",