Home | History | Annotate | Download | only in native
      1 #include "JNIHelp.h"
      2 
      3 #include <stdlib.h>
      4 #include <stdio.h>
      5 #include <string.h>
      6 
      7 #include "sqlite_jni_defs.h"
      8 
      9 #if HAVE_SQLITE2
     10 #include "sqlite.h"
     11 #endif
     12 
     13 #if HAVE_SQLITE3
     14 #include "sqlite3.h"
     15 #undef  HAVE_SQLITE_COMPILE
     16 #define HAVE_SQLITE_COMPILE 1
     17 #undef  HAVE_SQLITE_PROGRESS_HANDLER
     18 #define HAVE_SQLITE_PROGRESS_HANDLER 1
     19 #undef  HAVE_SQLITE_TRACE
     20 #define HAVE_SQLITE_TRACE 1
     21 #if !HAVE_SQLITE3_MALLOC
     22 #define sqlite3_malloc malloc
     23 #define sqlite3_free   free
     24 #endif
     25 #if !HAVE_SQLITE3_BIND_PARAMETER_COUNT
     26 #define sqlite3_bind_parameter_count(dummy) (1000)
     27 #endif
     28 #endif
     29 
     30 #if HAVE_SQLITE2 && HAVE_SQLITE3
     31 #define HAVE_BOTH_SQLITE 1
     32 #endif
     33 
     34 #define CANT_PASS_VALIST_AS_CHARPTR
     35 
     36 #include "sqlite_jni.h"
     37 
     38 #if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
     39 #define MAX_PARAMS 256
     40 #else
     41 #define MAX_PARAMS 32
     42 #endif
     43 
     44 /* free memory proc */
     45 
     46 typedef void (freemem)(void *);
     47 
     48 /* internal handle for SQLite database */
     49 
     50 typedef struct {
     51     void *sqlite;		/* SQLite handle */
     52 #if HAVE_BOTH_SQLITE
     53     int is3;			/* True for SQLITE3 handle */
     54 #endif
     55     int ver;			/* version code */
     56     jobject bh;			/* BusyHandler object */
     57     jobject cb;			/* Callback object */
     58     jobject ai;			/* Authorizer object */
     59     jobject tr;			/* Trace object */
     60     jobject ph;			/* ProgressHandler object */
     61     JNIEnv *env;		/* Java environment for callbacks */
     62     int row1;			/* true while processing first row */
     63     int haveutf;		/* true for SQLite UTF-8 support */
     64     jstring enc;		/* encoding or 0 */
     65     struct hfunc *funcs;	/* SQLite user defined function handles */
     66 #if HAVE_SQLITE_COMPILE
     67     struct hvm *vms;		/* Compiled SQLite VMs */
     68 #endif
     69 #if HAVE_SQLITE3
     70     sqlite3_stmt *stmt;		/* For callback() */
     71 #endif
     72 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
     73   struct hbl *blobs;		/* SQLite3 blob handles */
     74 #endif
     75 } handle;
     76 
     77 /* internal handle for SQLite user defined function */
     78 
     79 typedef struct hfunc {
     80     struct hfunc *next;		/* next function */
     81 #if HAVE_BOTH_SQLITE
     82     int is3;			/* True for SQLITE3 handle */
     83 #endif
     84     jobject fc;			/* FunctionContext object */
     85     jobject fi;			/* Function object */
     86     jobject db;			/* Database object */
     87     handle *h;			/* SQLite database handle */
     88     void *sf;			/* SQLite function handle */
     89     JNIEnv *env;		/* Java environment for callbacks */
     90 } hfunc;
     91 
     92 #if HAVE_SQLITE_COMPILE
     93 /* internal handle for SQLite VM (sqlite_compile()) */
     94 
     95 typedef struct hvm {
     96     struct hvm *next;		/* next vm handle */
     97 #if HAVE_BOTH_SQLITE
     98     int is3;			/* True for SQLITE3 handle */
     99 #endif
    100     void *vm;			/* SQLite 2/3 VM/statement */
    101     char *tail;			/* tail SQL string */
    102     int tail_len;		/* only for SQLite3/prepare */
    103     handle *h;			/* SQLite database handle */
    104     handle hh;			/* fake SQLite database handle */
    105 } hvm;
    106 #endif
    107 
    108 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
    109 /* internal handle for sqlite3_blob */
    110 
    111 typedef struct hbl {
    112     struct hbl *next;		/* next blob handle */
    113     sqlite3_blob *blob;		/* SQLite3 blob */
    114     handle *h;			/* SQLite database handle */
    115 } hbl;
    116 #endif
    117 
    118 /* ISO to/from UTF-8 translation */
    119 
    120 typedef struct {
    121     char *result;		/* translated C string result */
    122     char *tofree;		/* memory to be free'd, or 0 */
    123     jstring jstr;		/* resulting Java string or 0 */
    124 } transstr;
    125 
    126 /* static cached weak class refs, field and method ids */
    127 
    128 static jclass C_java_lang_String = 0;
    129 
    130 static jfieldID F_SQLite_Database_handle = 0;
    131 static jfieldID F_SQLite_Database_error_code = 0;
    132 static jfieldID F_SQLite_FunctionContext_handle = 0;
    133 static jfieldID F_SQLite_Vm_handle = 0;
    134 static jfieldID F_SQLite_Vm_error_code = 0;
    135 static jfieldID F_SQLite_Stmt_handle = 0;
    136 static jfieldID F_SQLite_Stmt_error_code = 0;
    137 static jfieldID F_SQLite_Blob_handle = 0;
    138 static jfieldID F_SQLite_Blob_size = 0;
    139 
    140 static jmethodID M_java_lang_String_getBytes = 0;
    141 static jmethodID M_java_lang_String_getBytes2 = 0;
    142 static jmethodID M_java_lang_String_initBytes = 0;
    143 static jmethodID M_java_lang_String_initBytes2 = 0;
    144 
    145 static const char xdigits[] = "0123456789ABCDEF";
    146 
    147 static void
    148 seterr(JNIEnv *env, jobject obj, int err)
    149 {
    150     jvalue v;
    151 
    152     v.j = 0;
    153     v.i = (jint) err;
    154     (*env)->SetIntField(env, obj, F_SQLite_Database_error_code, v.i);
    155 }
    156 
    157 #if HAVE_SQLITE_COMPILE
    158 static void
    159 setvmerr(JNIEnv *env, jobject obj, int err)
    160 {
    161     jvalue v;
    162 
    163     v.j = 0;
    164     v.i = (jint) err;
    165     (*env)->SetIntField(env, obj, F_SQLite_Vm_error_code, v.i);
    166 }
    167 
    168 #if HAVE_SQLITE3
    169 static void
    170 setstmterr(JNIEnv *env, jobject obj, int err)
    171 {
    172     jvalue v;
    173 
    174     v.j = 0;
    175     v.i = (jint) err;
    176     (*env)->SetIntField(env, obj, F_SQLite_Stmt_error_code, v.i);
    177 }
    178 
    179 static int
    180 jstrlen(const jchar *jstr)
    181 {
    182     int len = 0;
    183 
    184     if (jstr) {
    185         while (*jstr++) {
    186 	    len++;
    187 	}
    188     }
    189     return len;
    190 }
    191 #endif
    192 #endif
    193 
    194 static void *
    195 gethandle(JNIEnv *env, jobject obj)
    196 {
    197     jvalue v;
    198 
    199     v.j = (*env)->GetLongField(env, obj, F_SQLite_Database_handle);
    200     return (void *) v.l;
    201 }
    202 
    203 #if HAVE_SQLITE_COMPILE
    204 static void *
    205 gethvm(JNIEnv *env, jobject obj)
    206 {
    207     jvalue v;
    208 
    209     v.j = (*env)->GetLongField(env, obj, F_SQLite_Vm_handle);
    210     return (void *) v.l;
    211 }
    212 
    213 #if HAVE_SQLITE3
    214 static void *
    215 gethstmt(JNIEnv *env, jobject obj)
    216 {
    217     jvalue v;
    218 
    219     v.j = (*env)->GetLongField(env, obj, F_SQLite_Stmt_handle);
    220     return (void *) v.l;
    221 }
    222 #endif
    223 #endif
    224 
    225 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
    226 static void *
    227 gethbl(JNIEnv *env, jobject obj)
    228 {
    229     jvalue v;
    230 
    231     v.j = (*env)->GetLongField(env, obj, F_SQLite_Blob_handle);
    232     return (void *) v.l;
    233 }
    234 #endif
    235 
    236 static void
    237 delglobrefp(JNIEnv *env, jobject *obj)
    238 {
    239     if (*obj) {
    240 	(*env)->DeleteGlobalRef(env, *obj);
    241 	*obj = 0;
    242     }
    243 }
    244 
    245 static jobject
    246 globrefpop(JNIEnv *env, jobject *obj)
    247 {
    248     jobject ret = 0;
    249 
    250     if (*obj) {
    251 	ret = *obj;
    252 	*obj = 0;
    253     }
    254     return ret;
    255 }
    256 
    257 static void
    258 globrefset(JNIEnv *env, jobject obj, jobject *ref)
    259 {
    260     if (ref) {
    261 	if (obj) {
    262 	    *ref = (*env)->NewGlobalRef(env, obj);
    263 	} else {
    264 	    *ref = 0;
    265 	}
    266     }
    267 }
    268 
    269 static void
    270 freep(char **strp)
    271 {
    272     if (strp && *strp) {
    273 	free(*strp);
    274 	*strp = 0;
    275     }
    276 }
    277 
    278 static void
    279 throwex(JNIEnv *env, const char *msg)
    280 {
    281     jniThrowException(env, "SQLite/Exception", msg);
    282 }
    283 
    284 static void
    285 throwoom(JNIEnv *env, const char *msg)
    286 {
    287     jniThrowException(env, "java/lang/OutOfMemoryError", msg);
    288 }
    289 
    290 static void
    291 throwclosed(JNIEnv *env)
    292 {
    293     throwex(env, "database already closed");
    294 }
    295 
    296 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
    297 static void
    298 throwioex(JNIEnv *env, const char *msg)
    299 {
    300     jniThrowException(env, "java/io/IOException", msg);
    301 }
    302 #endif
    303 
    304 static void
    305 transfree(transstr *dest)
    306 {
    307     dest->result = 0;
    308     freep(&dest->tofree);
    309 }
    310 
    311 static char *
    312 trans2iso(JNIEnv *env, int haveutf, jstring enc, jstring src,
    313 	  transstr *dest)
    314 {
    315     jbyteArray bytes = 0;
    316     jthrowable exc;
    317 
    318     dest->result = 0;
    319     dest->tofree = 0;
    320     if (haveutf) {
    321         const jsize utfLength = (*env)->GetStringUTFLength(env, src);
    322         dest->result = dest->tofree = malloc(utfLength + 1);
    323         if (!dest->tofree) {
    324             throwoom(env, "string translation failed");
    325             return dest->result;
    326         }
    327         (*env)->GetStringUTFRegion(env, src, 0, utfLength, dest->result);
    328         return dest->result;
    329     }
    330     if (enc) {
    331 	bytes = (*env)->CallObjectMethod(env, src,
    332 					 M_java_lang_String_getBytes2, enc);
    333     } else {
    334 	bytes = (*env)->CallObjectMethod(env, src,
    335 					 M_java_lang_String_getBytes);
    336     }
    337     exc = (*env)->ExceptionOccurred(env);
    338     if (!exc) {
    339 	jint len = (*env)->GetArrayLength(env, bytes);
    340 	dest->tofree = malloc(len + 1);
    341 	if (!dest->tofree) {
    342 	    throwoom(env, "string translation failed");
    343 	    return dest->result;
    344 	}
    345 	dest->result = dest->tofree;
    346 	(*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *) dest->result);
    347 	dest->result[len] = '\0';
    348     } else {
    349 	(*env)->DeleteLocalRef(env, exc);
    350     }
    351     return dest->result;
    352 }
    353 
    354 static jstring
    355 trans2utf(JNIEnv *env, int haveutf, jstring enc, const char *src,
    356 	  transstr *dest)
    357 {
    358     jbyteArray bytes = 0;
    359     int len;
    360 
    361     dest->result = 0;
    362     dest->tofree = 0;
    363     dest->jstr = 0;
    364     if (!src) {
    365 	return dest->jstr;
    366     }
    367     if (haveutf) {
    368 	dest->jstr = (*env)->NewStringUTF(env, src);
    369 	return dest->jstr;
    370     }
    371     len = strlen(src);
    372     bytes = (*env)->NewByteArray(env, len);
    373     if (bytes) {
    374 	(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) src);
    375 	if (enc) {
    376 	    dest->jstr =
    377 		(*env)->NewObject(env, C_java_lang_String,
    378 				  M_java_lang_String_initBytes2, bytes, enc);
    379 	} else {
    380 	    dest->jstr =
    381 		(*env)->NewObject(env, C_java_lang_String,
    382 				  M_java_lang_String_initBytes, bytes);
    383 	}
    384 	(*env)->DeleteLocalRef(env, bytes);
    385 	return dest->jstr;
    386     }
    387     throwoom(env, "string translation failed");
    388     return dest->jstr;
    389 }
    390 
    391 #if HAVE_SQLITE2
    392 static int
    393 busyhandler(void *udata, const char *table, int count)
    394 {
    395     handle *h = (handle *) udata;
    396     JNIEnv *env = h->env;
    397     int ret = 0;
    398 
    399     if (env && h->bh) {
    400 	transstr tabstr;
    401 	jclass cls = (*env)->GetObjectClass(env, h->bh);
    402 	jmethodID mid = (*env)->GetMethodID(env, cls, "busy",
    403 					    "(Ljava/lang/String;I)Z");
    404 
    405 	if (mid == 0) {
    406 	    (*env)->DeleteLocalRef(env, cls);
    407 	    return ret;
    408 	}
    409 	trans2utf(env, h->haveutf, h->enc, table, &tabstr);
    410 	ret = (*env)->CallBooleanMethod(env, h->bh, mid, tabstr.jstr,
    411 					(jint) count)
    412 	      != JNI_FALSE;
    413 	(*env)->DeleteLocalRef(env, tabstr.jstr);
    414 	(*env)->DeleteLocalRef(env, cls);
    415     }
    416     return ret;
    417 }
    418 #endif
    419 
    420 #if HAVE_SQLITE3
    421 static int
    422 busyhandler3(void *udata, int count)
    423 {
    424     handle *h = (handle *) udata;
    425     JNIEnv *env = h->env;
    426     int ret = 0;
    427 
    428     if (env && h->bh) {
    429 	jclass cls = (*env)->GetObjectClass(env, h->bh);
    430 	jmethodID mid = (*env)->GetMethodID(env, cls, "busy",
    431 					    "(Ljava/lang/String;I)Z");
    432 
    433 	if (mid == 0) {
    434 	    (*env)->DeleteLocalRef(env, cls);
    435 	    return ret;
    436 	}
    437 	ret = (*env)->CallBooleanMethod(env, h->bh, mid, 0, (jint) count)
    438 	    != JNI_FALSE;
    439 	(*env)->DeleteLocalRef(env, cls);
    440     }
    441     return ret;
    442 }
    443 #endif
    444 
    445 static int
    446 progresshandler(void *udata)
    447 {
    448     handle *h = (handle *) udata;
    449     JNIEnv *env = h->env;
    450     int ret = 0;
    451 
    452     if (env && h->ph) {
    453 	jclass cls = (*env)->GetObjectClass(env, h->ph);
    454 	jmethodID mid = (*env)->GetMethodID(env, cls, "progress", "()Z");
    455 
    456 	if (mid == 0) {
    457 	    (*env)->DeleteLocalRef(env, cls);
    458 	    return ret;
    459 	}
    460 	ret = (*env)->CallBooleanMethod(env, h->ph, mid) != JNI_TRUE;
    461 	(*env)->DeleteLocalRef(env, cls);
    462     }
    463     return ret;
    464 }
    465 
    466 static int
    467 callback(void *udata, int ncol, char **data, char **cols)
    468 {
    469     handle *h = (handle *) udata;
    470     JNIEnv *env = h->env;
    471 
    472     if (env && h->cb) {
    473 	jthrowable exc;
    474 	jclass cls = (*env)->GetObjectClass(env, h->cb);
    475 	jmethodID mid;
    476 	jobjectArray arr = 0;
    477 	jint i;
    478 
    479 	if (h->row1) {
    480 	    mid = (*env)->GetMethodID(env, cls, "columns",
    481 				      "([Ljava/lang/String;)V");
    482 
    483 	    if (mid) {
    484 		arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0);
    485 		for (i = 0; i < ncol; i++) {
    486 		    if (cols[i]) {
    487 			transstr col;
    488 
    489 			trans2utf(env, h->haveutf, h->enc, cols[i], &col);
    490 			(*env)->SetObjectArrayElement(env, arr, i, col.jstr);
    491 			exc = (*env)->ExceptionOccurred(env);
    492 			if (exc) {
    493 			    (*env)->DeleteLocalRef(env, exc);
    494 			    return 1;
    495 			}
    496 			(*env)->DeleteLocalRef(env, col.jstr);
    497 		    }
    498 		}
    499 		h->row1 = 0;
    500 		(*env)->CallVoidMethod(env, h->cb, mid, arr);
    501 		exc = (*env)->ExceptionOccurred(env);
    502 		if (exc) {
    503 		    (*env)->DeleteLocalRef(env, exc);
    504 		    return 1;
    505 		}
    506 		(*env)->DeleteLocalRef(env, arr);
    507 	    }
    508 #if HAVE_BOTH_SQLITE
    509 	    if (h->is3) {
    510 		mid = (*env)->GetMethodID(env, cls, "types",
    511 					  "([Ljava/lang/String;)V");
    512 
    513 		if (mid && h->stmt) {
    514 		    arr = (*env)->NewObjectArray(env, ncol,
    515 						 C_java_lang_String, 0);
    516 		    for (i = 0; i < ncol; i++) {
    517 			const char *ctype =
    518 			    sqlite3_column_decltype(h->stmt, i);
    519 
    520 			if (!ctype) {
    521 			    switch (sqlite3_column_type(h->stmt, i)) {
    522 			    case SQLITE_INTEGER: ctype = "integer"; break;
    523 			    case SQLITE_FLOAT:   ctype = "double";  break;
    524 			    default:
    525 #if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT)
    526 			    case SQLITE_TEXT:
    527 #else
    528 #ifdef SQLITE3_TEXT
    529 			    case SQLITE3_TEXT:
    530 #endif
    531 #endif
    532 						 ctype = "text";    break;
    533 			    case SQLITE_BLOB:    ctype = "blob";    break;
    534 			    case SQLITE_NULL:    ctype = "null";    break;
    535 			    }
    536 			}
    537 			if (ctype) {
    538 			    transstr ty;
    539 
    540 			    trans2utf(env, 1, 0, ctype, &ty);
    541 			    (*env)->SetObjectArrayElement(env, arr, i,
    542 							  ty.jstr);
    543 			    exc = (*env)->ExceptionOccurred(env);
    544 			    if (exc) {
    545 				(*env)->DeleteLocalRef(env, exc);
    546 				return 1;
    547 			    }
    548 			    (*env)->DeleteLocalRef(env, ty.jstr);
    549 			}
    550 		    }
    551 		    (*env)->CallVoidMethod(env, h->cb, mid, arr);
    552 		    exc = (*env)->ExceptionOccurred(env);
    553 		    if (exc) {
    554 			(*env)->DeleteLocalRef(env, exc);
    555 			return 1;
    556 		    }
    557 		    (*env)->DeleteLocalRef(env, arr);
    558 		}
    559 	    } else {
    560 		if (h->ver >= 0x020506 && cols[ncol]) {
    561 		    mid = (*env)->GetMethodID(env, cls, "types",
    562 					      "([Ljava/lang/String;)V");
    563 
    564 		    if (mid) {
    565 			arr = (*env)->NewObjectArray(env, ncol,
    566 						     C_java_lang_String, 0);
    567 			for (i = 0; i < ncol; i++) {
    568 			    if (cols[i + ncol]) {
    569 				transstr ty;
    570 
    571 				trans2utf(env, h->haveutf, h->enc,
    572 					  cols[i + ncol], &ty);
    573 				(*env)->SetObjectArrayElement(env, arr, i,
    574 							      ty.jstr);
    575 				exc = (*env)->ExceptionOccurred(env);
    576 				if (exc) {
    577 				    (*env)->DeleteLocalRef(env, exc);
    578 				    return 1;
    579 				}
    580 				(*env)->DeleteLocalRef(env, ty.jstr);
    581 			    }
    582 			}
    583 			(*env)->CallVoidMethod(env, h->cb, mid, arr);
    584 			exc = (*env)->ExceptionOccurred(env);
    585 			if (exc) {
    586 			    (*env)->DeleteLocalRef(env, exc);
    587 			    return 1;
    588 			}
    589 			(*env)->DeleteLocalRef(env, arr);
    590 		    }
    591 		}
    592 	    }
    593 #else
    594 #if HAVE_SQLITE2
    595 	    if (h->ver >= 0x020506 && cols[ncol]) {
    596 		mid = (*env)->GetMethodID(env, cls, "types",
    597 					  "([Ljava/lang/String;)V");
    598 
    599 		if (mid) {
    600 		    arr = (*env)->NewObjectArray(env, ncol,
    601 						 C_java_lang_String, 0);
    602 		    for (i = 0; i < ncol; i++) {
    603 			if (cols[i + ncol]) {
    604 			    transstr ty;
    605 
    606 			    trans2utf(env, h->haveutf, h->enc,
    607 				      cols[i + ncol], &ty);
    608 			    (*env)->SetObjectArrayElement(env, arr, i,
    609 							  ty.jstr);
    610 			    exc = (*env)->ExceptionOccurred(env);
    611 			    if (exc) {
    612 				(*env)->DeleteLocalRef(env, exc);
    613 				return 1;
    614 			    }
    615 			    (*env)->DeleteLocalRef(env, ty.jstr);
    616 			}
    617 		    }
    618 		    (*env)->CallVoidMethod(env, h->cb, mid, arr);
    619 		    exc = (*env)->ExceptionOccurred(env);
    620 		    if (exc) {
    621 			(*env)->DeleteLocalRef(env, exc);
    622 			return 1;
    623 		    }
    624 		    (*env)->DeleteLocalRef(env, arr);
    625 		}
    626 	    }
    627 #endif
    628 #if HAVE_SQLITE3
    629 	    mid = (*env)->GetMethodID(env, cls, "types",
    630 				      "([Ljava/lang/String;)V");
    631 
    632 	    if (mid && h->stmt) {
    633 		arr = (*env)->NewObjectArray(env, ncol,
    634 					     C_java_lang_String, 0);
    635 		for (i = 0; i < ncol; i++) {
    636 		    const char *ctype = sqlite3_column_decltype(h->stmt, i);
    637 
    638 		    if (!ctype) {
    639 			switch (sqlite3_column_type(h->stmt, i)) {
    640 			case SQLITE_INTEGER: ctype = "integer"; break;
    641 			case SQLITE_FLOAT:   ctype = "double";  break;
    642 			default:
    643 #if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT)
    644 			case SQLITE_TEXT:
    645 #else
    646 #ifdef SQLITE3_TEXT
    647 			case SQLITE3_TEXT:
    648 #endif
    649 #endif
    650 					     ctype = "text";    break;
    651 			case SQLITE_BLOB:    ctype = "blob";    break;
    652 			case SQLITE_NULL:    ctype = "null";    break;
    653 			}
    654 		    }
    655 		    if (ctype) {
    656 			transstr ty;
    657 
    658 			trans2utf(env, 1, 0, ctype, &ty);
    659 			(*env)->SetObjectArrayElement(env, arr, i, ty.jstr);
    660 			exc = (*env)->ExceptionOccurred(env);
    661 			if (exc) {
    662 			    (*env)->DeleteLocalRef(env, exc);
    663 			    return 1;
    664 			}
    665 			(*env)->DeleteLocalRef(env, ty.jstr);
    666 		    }
    667 		}
    668 		(*env)->CallVoidMethod(env, h->cb, mid, arr);
    669 		exc = (*env)->ExceptionOccurred(env);
    670 		if (exc) {
    671 		    (*env)->DeleteLocalRef(env, exc);
    672 		    return 1;
    673 		}
    674 		(*env)->DeleteLocalRef(env, arr);
    675 	    }
    676 #endif
    677 #endif
    678 	}
    679 	mid = (*env)->GetMethodID(env, cls, "newrow",
    680 				  "([Ljava/lang/String;)Z");
    681 	if (mid) {
    682 	    jboolean rc;
    683 
    684 	    if (data) {
    685 		arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0);
    686 	    } else {
    687 		arr = 0;
    688 	    }
    689 	    for (i = 0; arr && i < ncol; i++) {
    690 		if (data[i]) {
    691 		    transstr dats;
    692 
    693 		    trans2utf(env, h->haveutf, h->enc, data[i], &dats);
    694 		    (*env)->SetObjectArrayElement(env, arr, i, dats.jstr);
    695 		    exc = (*env)->ExceptionOccurred(env);
    696 		    if (exc) {
    697 			(*env)->DeleteLocalRef(env, exc);
    698 			return 1;
    699 		    }
    700 		    (*env)->DeleteLocalRef(env, dats.jstr);
    701 		}
    702 	    }
    703 	    rc = (*env)->CallBooleanMethod(env, h->cb, mid, arr);
    704 	    exc = (*env)->ExceptionOccurred(env);
    705 	    if (exc) {
    706 		(*env)->DeleteLocalRef(env, exc);
    707 		return 1;
    708 	    }
    709 	    if (arr) {
    710 		(*env)->DeleteLocalRef(env, arr);
    711 	    }
    712 	    (*env)->DeleteLocalRef(env, cls);
    713 	    return rc != JNI_FALSE;
    714 	}
    715     }
    716     return 0;
    717 }
    718 
    719 static void
    720 doclose(JNIEnv *env, jobject obj, int final)
    721 {
    722     handle *h = gethandle(env, obj);
    723 
    724     if (h) {
    725 	hfunc *f;
    726 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
    727 	hbl *bl;
    728 #endif
    729 #if HAVE_SQLITE_COMPILE
    730 	hvm *v;
    731 
    732 	while ((v = h->vms)) {
    733 	    h->vms = v->next;
    734 	    v->next = 0;
    735 	    v->h = 0;
    736 	    if (v->vm) {
    737 #if HAVE_BOTH_SQLITE
    738 		if (h->is3) {
    739 		    sqlite3_finalize((sqlite3_stmt *) v->vm);
    740 		} else {
    741 		    sqlite_finalize((sqlite_vm *) v->vm, 0);
    742 		}
    743 #else
    744 #if HAVE_SQLITE2
    745 		sqlite_finalize((sqlite_vm *) v->vm, 0);
    746 #endif
    747 #if HAVE_SQLITE3
    748 		sqlite3_finalize((sqlite3_stmt *) v->vm);
    749 #endif
    750 #endif
    751 		v->vm = 0;
    752 	    }
    753 	}
    754 #endif
    755 	if (h->sqlite) {
    756 #if HAVE_BOTH_SQLITE
    757 	    if (h->is3) {
    758 		sqlite3_close((sqlite3 *) h->sqlite);
    759 	    } else {
    760 		sqlite_close((sqlite *) h->sqlite);
    761 	    }
    762 #else
    763 #if HAVE_SQLITE2
    764 	    sqlite_close((sqlite *) h->sqlite);
    765 #endif
    766 #if HAVE_SQLITE3
    767 	    sqlite3_close((sqlite3 *) h->sqlite);
    768 #endif
    769 #endif
    770 	    h->sqlite = 0;
    771 	}
    772 	while ((f = h->funcs)) {
    773 	    h->funcs = f->next;
    774 	    f->h = 0;
    775 	    f->sf = 0;
    776 	    f->env = 0;
    777 	    if (f->fc) {
    778 		(*env)->SetLongField(env, f->fc,
    779 				     F_SQLite_FunctionContext_handle, 0);
    780 	    }
    781 	    delglobrefp(env, &f->db);
    782 	    delglobrefp(env, &f->fi);
    783 	    delglobrefp(env, &f->fc);
    784 	    free(f);
    785 	}
    786 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
    787 	while ((bl = h->blobs)) {
    788 	    h->blobs = bl->next;
    789 	    bl->next = 0;
    790 	    bl->h = 0;
    791 	    if (bl->blob) {
    792 	        sqlite3_blob_close(bl->blob);
    793 	    }
    794 	    bl->blob = 0;
    795 	}
    796 #endif
    797 	delglobrefp(env, &h->bh);
    798 	delglobrefp(env, &h->cb);
    799 	delglobrefp(env, &h->ai);
    800 	delglobrefp(env, &h->tr);
    801 	delglobrefp(env, &h->ph);
    802 	delglobrefp(env, &h->enc);
    803 	free(h);
    804 	(*env)->SetLongField(env, obj, F_SQLite_Database_handle, 0);
    805 	return;
    806     }
    807     if (!final) {
    808 	throwclosed(env);
    809     }
    810 }
    811 
    812 JNIEXPORT void JNICALL
    813 Java_SQLite_Database__1close(JNIEnv *env, jobject obj)
    814 {
    815     doclose(env, obj, 0);
    816 }
    817 
    818 JNIEXPORT void JNICALL
    819 Java_SQLite_Database__1finalize(JNIEnv *env, jobject obj)
    820 {
    821     doclose(env, obj, 1);
    822 }
    823 
    824 JNIEXPORT void JNICALL
    825 Java_SQLite_Database__1busy_1timeout(JNIEnv *env, jobject obj, jint ms)
    826 {
    827     handle *h = gethandle(env, obj);
    828 
    829     if (h && h->sqlite) {
    830 #if HAVE_BOTH_SQLITE
    831 	if (h->is3) {
    832 	    sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms);
    833 	} else {
    834 	    sqlite_busy_timeout((sqlite *) h->sqlite, ms);
    835 	}
    836 #else
    837 #if HAVE_SQLITE2
    838 	sqlite_busy_timeout((sqlite *) h->sqlite, ms);
    839 #endif
    840 #if HAVE_SQLITE3
    841 	sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms);
    842 #endif
    843 #endif
    844 	return;
    845     }
    846     throwclosed(env);
    847 }
    848 
    849 JNIEXPORT jstring JNICALL
    850 Java_SQLite_Database_version(JNIEnv *env, jclass cls)
    851 {
    852     /* CHECK THIS */
    853 #if HAVE_BOTH_SQLITE
    854     return (*env)->NewStringUTF(env, sqlite_libversion());
    855 #else
    856 #if HAVE_SQLITE2
    857     return (*env)->NewStringUTF(env, sqlite_libversion());
    858 #else
    859     return (*env)->NewStringUTF(env, sqlite3_libversion());
    860 #endif
    861 #endif
    862 }
    863 
    864 JNIEXPORT jstring JNICALL
    865 Java_SQLite_Database_dbversion(JNIEnv *env, jobject obj)
    866 {
    867     handle *h = gethandle(env, obj);
    868 
    869     if (h && h->sqlite) {
    870 #if HAVE_BOTH_SQLITE
    871 	if (h->is3) {
    872 	    return (*env)->NewStringUTF(env, sqlite3_libversion());
    873 	} else {
    874 	    return (*env)->NewStringUTF(env, sqlite_libversion());
    875 	}
    876 #else
    877 #if HAVE_SQLITE2
    878 	return (*env)->NewStringUTF(env, sqlite_libversion());
    879 #else
    880 	return (*env)->NewStringUTF(env, sqlite3_libversion());
    881 #endif
    882 #endif
    883     }
    884     return (*env)->NewStringUTF(env, "unknown");
    885 }
    886 
    887 JNIEXPORT jlong JNICALL
    888 Java_SQLite_Database__1last_1insert_1rowid(JNIEnv *env, jobject obj)
    889 {
    890     handle *h = gethandle(env, obj);
    891 
    892     if (h && h->sqlite) {
    893 #if HAVE_BOTH_SQLITE
    894 	if (h->is3) {
    895 	    return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite);
    896 	} else {
    897 	    return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite);
    898 	}
    899 #else
    900 #if HAVE_SQLITE2
    901 	return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite);
    902 #endif
    903 #if HAVE_SQLITE3
    904 	return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite);
    905 #endif
    906 #endif
    907     }
    908     throwclosed(env);
    909     return (jlong) 0;
    910 }
    911 
    912 JNIEXPORT jlong JNICALL
    913 Java_SQLite_Database__1changes(JNIEnv *env, jobject obj)
    914 {
    915     handle *h = gethandle(env, obj);
    916 
    917     if (h && h->sqlite) {
    918 #if HAVE_BOTH_SQLITE
    919 	if (h->is3) {
    920 	    return (jlong) sqlite3_changes((sqlite3 *) h->sqlite);
    921 	} else {
    922 	    return (jlong) sqlite_changes((sqlite *) h->sqlite);
    923 	}
    924 #else
    925 #if HAVE_SQLITE2
    926 	return (jlong) sqlite_changes((sqlite *) h->sqlite);
    927 #endif
    928 #if HAVE_SQLITE3
    929 	return (jlong) sqlite3_changes((sqlite3 *) h->sqlite);
    930 #endif
    931 #endif
    932     }
    933     throwclosed(env);
    934     return (jlong) 0;
    935 }
    936 
    937 JNIEXPORT jboolean JNICALL
    938 Java_SQLite_Database__1complete(JNIEnv *env, jclass cls, jstring sql)
    939 {
    940     transstr sqlstr;
    941     jboolean result;
    942 
    943     if (!sql) {
    944 	return JNI_FALSE;
    945     }
    946 #if HAVE_BOTH_SQLITE || HAVE_SQLITE3
    947     /* CHECK THIS */
    948     trans2iso(env, 1, 0, sql, &sqlstr);
    949     result = sqlite3_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE;
    950 #else
    951     trans2iso(env, strcmp(sqlite_libencoding(), "UTF-8") == 0, 0,
    952 	      sql, &sqlstr);
    953     result = sqlite_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE;
    954 #endif
    955     transfree(&sqlstr);
    956     return result;
    957 }
    958 
    959 JNIEXPORT void JNICALL
    960 Java_SQLite_Database__1interrupt(JNIEnv *env, jobject obj)
    961 {
    962     handle *h = gethandle(env, obj);
    963 
    964     if (h && h->sqlite) {
    965 #if HAVE_BOTH_SQLITE
    966 	if (h->is3) {
    967 	    sqlite3_interrupt((sqlite3 *) h->sqlite);
    968 	} else {
    969 	    sqlite_interrupt((sqlite *) h->sqlite);
    970 	}
    971 #else
    972 #if HAVE_SQLITE2
    973 	sqlite_interrupt((sqlite *) h->sqlite);
    974 #endif
    975 #if HAVE_SQLITE3
    976 	sqlite3_interrupt((sqlite3 *) h->sqlite);
    977 #endif
    978 #endif
    979 	return;
    980     }
    981     throwclosed(env);
    982 }
    983 
    984 JNIEXPORT void JNICALL
    985 Java_SQLite_Database__1open(JNIEnv *env, jobject obj, jstring file, jint mode)
    986 {
    987     handle *h = gethandle(env, obj);
    988     jthrowable exc;
    989     char *err = 0;
    990     transstr filename;
    991     int maj, min, lev;
    992 
    993     if (h) {
    994 	if (h->sqlite) {
    995 #if HAVE_BOTH_SQLITE
    996 	    if (h->is3) {
    997 		sqlite3_close((sqlite3 *) h->sqlite);
    998 	    } else {
    999 		sqlite_close((sqlite *) h->sqlite);
   1000 	    }
   1001 	    h->is3 = 0;
   1002 #else
   1003 #if HAVE_SQLITE2
   1004 	    sqlite_close((sqlite *) h->sqlite);
   1005 #endif
   1006 #if HAVE_SQLITE3
   1007 	    sqlite3_close((sqlite3 *) h->sqlite);
   1008 #endif
   1009 #endif
   1010 	    h->sqlite = 0;
   1011 	}
   1012     } else {
   1013 	h = malloc(sizeof (handle));
   1014 	if (!h) {
   1015 	    throwoom(env, "unable to get SQLite handle");
   1016 	    return;
   1017 	}
   1018 	h->sqlite = 0;
   1019 	h->bh = h->cb = h->ai = h->tr = h->ph = 0;
   1020 	/* CHECK THIS */
   1021 #if HAVE_BOTH_SQLITE
   1022 	h->is3 = 0;
   1023 	h->stmt = 0;
   1024 	h->haveutf = 1;
   1025 #else
   1026 #if HAVE_SQLITE2
   1027 	h->haveutf = strcmp(sqlite_libencoding(), "UTF-8") == 0;
   1028 #endif
   1029 #if HAVE_SQLITE3
   1030 	h->stmt = 0;
   1031 	h->haveutf = 1;
   1032 #endif
   1033 #endif
   1034 	h->enc = 0;
   1035 	h->funcs = 0;
   1036 	h->ver = 0;
   1037 #if HAVE_SQLITE_COMPILE
   1038 	h->vms = 0;
   1039 #endif
   1040 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
   1041 	h->blobs = 0;
   1042 #endif
   1043     }
   1044     h->env = 0;
   1045     if (!file) {
   1046 	throwex(env, err ? err : "invalid file name");
   1047 	return;
   1048     }
   1049     trans2iso(env, h->haveutf, h->enc, file, &filename);
   1050     exc = (*env)->ExceptionOccurred(env);
   1051     if (exc) {
   1052 	(*env)->DeleteLocalRef(env, exc);
   1053 	return;
   1054     }
   1055 #if HAVE_BOTH_SQLITE
   1056     {
   1057 	FILE *f = fopen(filename.result, "rb");
   1058 	int c_0 = EOF;
   1059 
   1060 	if (f) {
   1061 	    c_0 = fgetc(f);
   1062 	    fclose(f);
   1063 	}
   1064 	if (c_0 != '*') {
   1065 	    int rc = sqlite3_open(filename.result, (sqlite3 **) &h->sqlite);
   1066 
   1067 	    if (rc == SQLITE_OK) {
   1068 		h->is3 = 1;
   1069 	    } else if (h->sqlite) {
   1070 	        sqlite3_close((sqlite3 *) h->sqlite);
   1071 		h->sqlite = 0;
   1072 	    }
   1073 	} else {
   1074 	    h->sqlite = (void *) sqlite_open(filename.result,
   1075 					     (int) mode, &err);
   1076 	}
   1077     }
   1078 #else
   1079 #if HAVE_SQLITE2
   1080     h->sqlite = (void *) sqlite_open(filename.result, (int) mode, &err);
   1081 #endif
   1082 #if HAVE_SQLITE3
   1083     if (sqlite3_open(filename.result, (sqlite3 **) &h->sqlite) != SQLITE_OK) {
   1084         if (h->sqlite) {
   1085 	    sqlite3_close((sqlite3 *) h->sqlite);
   1086 	    h->sqlite = 0;
   1087 	}
   1088     }
   1089 #endif
   1090 #endif
   1091     transfree(&filename);
   1092     exc = (*env)->ExceptionOccurred(env);
   1093     if (exc) {
   1094 	(*env)->DeleteLocalRef(env, exc);
   1095 #if HAVE_SQLITE2
   1096 	if (err) {
   1097 	    sqlite_freemem(err);
   1098 	}
   1099 #endif
   1100 	if (h->sqlite) {
   1101 #if HAVE_BOTH_SQLITE
   1102 	    if (h->is3) {
   1103 		sqlite3_close((sqlite3 *) h->sqlite);
   1104 		h->is3 = 0;
   1105 	    } else {
   1106 		sqlite_close((sqlite *) h->sqlite);
   1107 	    }
   1108 #else
   1109 #if HAVE_SQLITE2
   1110 	    sqlite_close((sqlite *) h->sqlite);
   1111 #endif
   1112 #if HAVE_SQLITE3
   1113 	    sqlite3_close((sqlite3 *) h->sqlite);
   1114 #endif
   1115 #endif
   1116 	}
   1117 	h->sqlite = 0;
   1118 	return;
   1119     }
   1120     if (h->sqlite) {
   1121 	jvalue v;
   1122 
   1123 	v.j = 0;
   1124 	v.l = (jobject) h;
   1125 	(*env)->SetLongField(env, obj, F_SQLite_Database_handle, v.j);
   1126 #if HAVE_SQLITE2
   1127 	if (err) {
   1128 	    sqlite_freemem(err);
   1129 	}
   1130 #endif
   1131 #if HAVE_BOTH_SQLITE
   1132 	if (h->is3) {
   1133 	    sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
   1134 	} else {
   1135 	    sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev);
   1136 	}
   1137 #else
   1138 #if HAVE_SQLITE2
   1139 	sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev);
   1140 #endif
   1141 #if HAVE_SQLITE3
   1142 	sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
   1143 #endif
   1144 #endif
   1145 	h->ver = ((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (lev & 0xFF);
   1146 	return;
   1147     }
   1148     throwex(env, err ? err : "unknown error in open");
   1149 #if HAVE_SQLITE2
   1150     if (err) {
   1151 	sqlite_freemem(err);
   1152     }
   1153 #endif
   1154 }
   1155 
   1156 JNIEXPORT void JNICALL
   1157 Java_SQLite_Database__1open_1aux_1file(JNIEnv *env, jobject obj, jstring file)
   1158 {
   1159     handle *h = gethandle(env, obj);
   1160 #if HAVE_SQLITE_OPEN_AUX_FILE
   1161     jboolean b;
   1162     jthrowable exc;
   1163     char *err = 0;
   1164     transstr filename;
   1165     int ret;
   1166 #endif
   1167 
   1168     if (h && h->sqlite) {
   1169 #if HAVE_SQLITE_OPEN_AUX_FILE
   1170 #if HAVE_BOTH_SQLITE
   1171 	if (h->is3) {
   1172 	    throwex(env, "unsupported");
   1173 	}
   1174 #endif
   1175 	trans2iso(env, h->haveutf, h->enc, file, &filename);
   1176 	exc = (*env)->ExceptionOccurred(env);
   1177 	if (exc) {
   1178 	    (*env)->DeleteLocalRef(env, exc);
   1179 	    return;
   1180 	}
   1181 	ret = sqlite_open_aux_file((sqlite *) h->sqlite,
   1182 				   filename.result, &err);
   1183 	transfree(&filename);
   1184 	exc = (*env)->ExceptionOccurred(env);
   1185 	if (exc) {
   1186 	    (*env)->DeleteLocalRef(env, exc);
   1187 	    if (err) {
   1188 		sqlite_freemem(err);
   1189 	    }
   1190 	    return;
   1191 	}
   1192 	if (ret != SQLITE_OK) {
   1193 	    throwex(env, err ? err : sqlite_error_string(ret));
   1194 	}
   1195 	if (err) {
   1196 	    sqlite_freemem(err);
   1197 	}
   1198 #else
   1199 	throwex(env, "unsupported");
   1200 #endif
   1201 	return;
   1202     }
   1203     throwclosed(env);
   1204 }
   1205 
   1206 JNIEXPORT void JNICALL
   1207 Java_SQLite_Database__1busy_1handler(JNIEnv *env, jobject obj, jobject bh)
   1208 {
   1209     handle *h = gethandle(env, obj);
   1210 
   1211     if (h && h->sqlite) {
   1212 	delglobrefp(env, &h->bh);
   1213 	globrefset(env, bh, &h->bh);
   1214 #if HAVE_BOTH_SQLITE
   1215 	if (h->is3) {
   1216 	    sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h);
   1217 	} else {
   1218 	    sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h);
   1219 	}
   1220 #else
   1221 #if HAVE_SQLITE2
   1222 	sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h);
   1223 #endif
   1224 #if HAVE_SQLITE3
   1225 	sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h);
   1226 #endif
   1227 #endif
   1228 	return;
   1229     }
   1230     throwclosed(env);
   1231 }
   1232 
   1233 JNIEXPORT void JNICALL
   1234 Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2
   1235     (JNIEnv *env, jobject obj, jstring sql, jobject cb)
   1236 {
   1237     handle *h = gethandle(env, obj);
   1238     freemem *freeproc;
   1239 
   1240     if (!sql) {
   1241 	throwex(env, "invalid SQL statement");
   1242 	return;
   1243     }
   1244     if (h) {
   1245 	if (h->sqlite) {
   1246 	    jthrowable exc;
   1247 	    int rc;
   1248 	    char *err = 0;
   1249 	    transstr sqlstr;
   1250 	    jobject oldcb = globrefpop(env, &h->cb);
   1251 
   1252 	    globrefset(env, cb, &h->cb);
   1253 	    h->env = env;
   1254 	    h->row1 = 1;
   1255 	    trans2iso(env, h->haveutf, h->enc, sql, &sqlstr);
   1256 	    exc = (*env)->ExceptionOccurred(env);
   1257 	    if (exc) {
   1258 		(*env)->DeleteLocalRef(env, exc);
   1259 		return;
   1260 	    }
   1261 #if HAVE_BOTH_SQLITE
   1262 	    if (h->is3) {
   1263 		rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result,
   1264 				  callback, h, &err);
   1265 		freeproc = (freemem *) sqlite3_free;
   1266 	    } else {
   1267 		rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result,
   1268 				 callback, h, &err);
   1269 		freeproc = (freemem *) sqlite_freemem;
   1270 	    }
   1271 #else
   1272 #if HAVE_SQLITE2
   1273 	    rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result,
   1274 			     callback, h, &err);
   1275 	    freeproc = (freemem *) sqlite_freemem;
   1276 #endif
   1277 #if HAVE_SQLITE3
   1278 	    rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result,
   1279 			      callback, h, &err);
   1280 	    freeproc = (freemem *) sqlite3_free;
   1281 #endif
   1282 #endif
   1283 	    transfree(&sqlstr);
   1284 	    exc = (*env)->ExceptionOccurred(env);
   1285 	    delglobrefp(env, &h->cb);
   1286 	    h->cb = oldcb;
   1287 	    if (exc) {
   1288 		(*env)->DeleteLocalRef(env, exc);
   1289 		if (err) {
   1290 		    freeproc(err);
   1291 		}
   1292 		return;
   1293 	    }
   1294 	    if (rc != SQLITE_OK) {
   1295 		char msg[128];
   1296 
   1297 		seterr(env, obj, rc);
   1298 		if (!err) {
   1299 		    sprintf(msg, "error %d in sqlite*_exec", rc);
   1300 		}
   1301 		throwex(env, err ? err : msg);
   1302 	    }
   1303 	    if (err) {
   1304 		freeproc(err);
   1305 	    }
   1306 	    return;
   1307 	}
   1308     }
   1309     throwclosed(env);
   1310 }
   1311 
   1312 JNIEXPORT void JNICALL
   1313 Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2
   1314     (JNIEnv *env, jobject obj, jstring sql, jobject cb, jobjectArray args)
   1315 {
   1316     handle *h = gethandle(env, obj);
   1317     freemem *freeproc = 0;
   1318 
   1319     if (!sql) {
   1320 	throwex(env, "invalid SQL statement");
   1321 	return;
   1322     }
   1323     if (h) {
   1324 	if (h->sqlite) {
   1325 	    jthrowable exc;
   1326 	    int rc = SQLITE_ERROR, nargs, i;
   1327 	    char *err = 0, *p;
   1328 	    const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
   1329 	    transstr sqlstr;
   1330 	    struct args {
   1331 		char *arg;
   1332 		jobject obj;
   1333 		transstr trans;
   1334 	    } *argv = 0;
   1335 	    char **cargv = 0;
   1336 	    jobject oldcb = globrefpop(env, &h->cb);
   1337 
   1338 	    globrefset(env, cb, &h->cb);
   1339 	    p = (char *) str;
   1340 	    nargs = 0;
   1341 	    while (*p) {
   1342 		if (*p == '%') {
   1343 		    ++p;
   1344 		    if (*p == 'q' || *p == 's') {
   1345 			nargs++;
   1346 			if (nargs > MAX_PARAMS) {
   1347 			    (*env)->ReleaseStringUTFChars(env, sql, str);
   1348 			    delglobrefp(env, &h->cb);
   1349 			    h->cb = oldcb;
   1350 			    throwex(env, "too much SQL parameters");
   1351 			    return;
   1352 			}
   1353 		    } else if (h->ver >= 0x020500 && *p == 'Q') {
   1354 			nargs++;
   1355 			if (nargs > MAX_PARAMS) {
   1356 			    (*env)->ReleaseStringUTFChars(env, sql, str);
   1357 			    delglobrefp(env, &h->cb);
   1358 			    h->cb = oldcb;
   1359 			    throwex(env, "too much SQL parameters");
   1360 			    return;
   1361 			}
   1362 		    } else if (*p != '%') {
   1363 			(*env)->ReleaseStringUTFChars(env, sql, str);
   1364 			delglobrefp(env, &h->cb);
   1365 			h->cb = oldcb;
   1366 			throwex(env, "bad % specification in query");
   1367 			return;
   1368 		    }
   1369 		}
   1370 		++p;
   1371 	    }
   1372 	    cargv = malloc((sizeof (*argv) + sizeof (char *))
   1373 			   * MAX_PARAMS);
   1374 	    if (!cargv) {
   1375 		(*env)->ReleaseStringUTFChars(env, sql, str);
   1376 		delglobrefp(env, &h->cb);
   1377 		h->cb = oldcb;
   1378 		throwoom(env, "unable to allocate arg vector");
   1379 		return;
   1380 	    }
   1381 	    argv = (struct args *) (cargv + MAX_PARAMS);
   1382 	    for (i = 0; i < MAX_PARAMS; i++) {
   1383 		cargv[i] = 0;
   1384 		argv[i].arg = 0;
   1385 		argv[i].obj = 0;
   1386 		argv[i].trans.result = argv[i].trans.tofree = 0;
   1387 	    }
   1388 	    exc = 0;
   1389 	    for (i = 0; i < nargs; i++) {
   1390 		jobject so = (*env)->GetObjectArrayElement(env, args, i);
   1391 
   1392 		exc = (*env)->ExceptionOccurred(env);
   1393 		if (exc) {
   1394 		    (*env)->DeleteLocalRef(env, exc);
   1395 		    break;
   1396 		}
   1397 		if (so) {
   1398 		    argv[i].obj = so;
   1399 		    argv[i].arg = cargv[i] =
   1400 			trans2iso(env, h->haveutf, h->enc, argv[i].obj,
   1401 				  &argv[i].trans);
   1402 		}
   1403 	    }
   1404 	    if (exc) {
   1405 		for (i = 0; i < nargs; i++) {
   1406 		    if (argv[i].obj) {
   1407 			transfree(&argv[i].trans);
   1408 		    }
   1409 		}
   1410 		freep((char **) &cargv);
   1411 		(*env)->ReleaseStringUTFChars(env, sql, str);
   1412 		delglobrefp(env, &h->cb);
   1413 		h->cb = oldcb;
   1414 		return;
   1415 	    }
   1416 	    h->env = env;
   1417 	    h->row1 = 1;
   1418 	    trans2iso(env, h->haveutf, h->enc, sql, &sqlstr);
   1419 	    exc = (*env)->ExceptionOccurred(env);
   1420 	    if (!exc) {
   1421 #if HAVE_BOTH_SQLITE
   1422 		if (h->is3) {
   1423 #if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
   1424 		    char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
   1425 #else
   1426 		    char *s = sqlite3_mprintf(sqlstr.result,
   1427 					      cargv[0], cargv[1],
   1428 					      cargv[2], cargv[3],
   1429 					      cargv[4], cargv[5],
   1430 					      cargv[6], cargv[7],
   1431 					      cargv[8], cargv[9],
   1432 					      cargv[10], cargv[11],
   1433 					      cargv[12], cargv[13],
   1434 					      cargv[14], cargv[15],
   1435 					      cargv[16], cargv[17],
   1436 					      cargv[18], cargv[19],
   1437 					      cargv[20], cargv[21],
   1438 					      cargv[22], cargv[23],
   1439 					      cargv[24], cargv[25],
   1440 					      cargv[26], cargv[27],
   1441 					      cargv[28], cargv[29],
   1442 					      cargv[30], cargv[31]);
   1443 #endif
   1444 
   1445 		    if (s) {
   1446 			rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
   1447 					  h, &err);
   1448 			sqlite3_free(s);
   1449 		    } else {
   1450 			rc = SQLITE_NOMEM;
   1451 		    }
   1452 		    freeproc = (freemem *) sqlite3_free;
   1453 		} else {
   1454 #if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
   1455 		    rc = sqlite_exec_vprintf((sqlite *) h->sqlite,
   1456 					     sqlstr.result, callback, h, &err,
   1457 					     (char *) cargv);
   1458 #else
   1459 		    rc = sqlite_exec_printf((sqlite *) h->sqlite,
   1460 					    sqlstr.result, callback,
   1461 					    h, &err,
   1462 					    cargv[0], cargv[1],
   1463 					    cargv[2], cargv[3],
   1464 					    cargv[4], cargv[5],
   1465 					    cargv[6], cargv[7],
   1466 					    cargv[8], cargv[9],
   1467 					    cargv[10], cargv[11],
   1468 					    cargv[12], cargv[13],
   1469 					    cargv[14], cargv[15],
   1470 					    cargv[16], cargv[17],
   1471 					    cargv[18], cargv[19],
   1472 					    cargv[20], cargv[21],
   1473 					    cargv[22], cargv[23],
   1474 					    cargv[24], cargv[25],
   1475 					    cargv[26], cargv[27],
   1476 					    cargv[28], cargv[29],
   1477 					    cargv[30], cargv[31]);
   1478 #endif
   1479 		    freeproc = (freemem *) sqlite_freemem;
   1480 		}
   1481 #else
   1482 #if HAVE_SQLITE2
   1483 #if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
   1484 		rc = sqlite_exec_vprintf((sqlite *) h->sqlite, sqlstr.result,
   1485 					 callback, h, &err, (char *) cargv);
   1486 #else
   1487 		rc = sqlite_exec_printf((sqlite *) h->sqlite, sqlstr.result,
   1488 					callback, h, &err,
   1489 					cargv[0], cargv[1],
   1490 					cargv[2], cargv[3],
   1491 					cargv[4], cargv[5],
   1492 					cargv[6], cargv[7],
   1493 					cargv[8], cargv[9],
   1494 					cargv[10], cargv[11],
   1495 					cargv[12], cargv[13],
   1496 					cargv[14], cargv[15],
   1497 					cargv[16], cargv[17],
   1498 					cargv[18], cargv[19],
   1499 					cargv[20], cargv[21],
   1500 					cargv[22], cargv[23],
   1501 					cargv[24], cargv[25],
   1502 					cargv[26], cargv[27],
   1503 					cargv[28], cargv[29],
   1504 					cargv[30], cargv[31]);
   1505 #endif
   1506 		freeproc = (freemem *) sqlite_freemem;
   1507 #endif
   1508 #if HAVE_SQLITE3
   1509 #if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
   1510 		char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
   1511 #else
   1512 		char *s = sqlite3_mprintf(sqlstr.result,
   1513 					  cargv[0], cargv[1],
   1514 					  cargv[2], cargv[3],
   1515 					  cargv[4], cargv[5],
   1516 					  cargv[6], cargv[7],
   1517 					  cargv[8], cargv[9],
   1518 					  cargv[10], cargv[11],
   1519 					  cargv[12], cargv[13],
   1520 					  cargv[14], cargv[15],
   1521 					  cargv[16], cargv[17],
   1522 					  cargv[18], cargv[19],
   1523 					  cargv[20], cargv[21],
   1524 					  cargv[22], cargv[23],
   1525 					  cargv[24], cargv[25],
   1526 					  cargv[26], cargv[27],
   1527 					  cargv[28], cargv[29],
   1528 					  cargv[30], cargv[31]);
   1529 #endif
   1530 
   1531 		if (s) {
   1532 		    rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
   1533 				      h, &err);
   1534 		    sqlite3_free(s);
   1535 		} else {
   1536 		    rc = SQLITE_NOMEM;
   1537 		}
   1538 		freeproc = (freemem *) sqlite3_free;
   1539 #endif
   1540 #endif
   1541 		exc = (*env)->ExceptionOccurred(env);
   1542 	    }
   1543 	    for (i = 0; i < nargs; i++) {
   1544 		if (argv[i].obj) {
   1545 		    transfree(&argv[i].trans);
   1546 		}
   1547 	    }
   1548 	    transfree(&sqlstr);
   1549 	    (*env)->ReleaseStringUTFChars(env, sql, str);
   1550 	    freep((char **) &cargv);
   1551 	    delglobrefp(env, &h->cb);
   1552 	    h->cb = oldcb;
   1553 	    if (exc) {
   1554 		(*env)->DeleteLocalRef(env, exc);
   1555 		if (err && freeproc) {
   1556 		    freeproc(err);
   1557 		}
   1558 		return;
   1559 	    }
   1560 	    if (rc != SQLITE_OK) {
   1561 		char msg[128];
   1562 
   1563 		seterr(env, obj, rc);
   1564 		if (!err) {
   1565 		    sprintf(msg, "error %d in sqlite*_exec", rc);
   1566 		}
   1567 		throwex(env, err ? err : msg);
   1568 	    }
   1569 	    if (err && freeproc) {
   1570 		freeproc(err);
   1571 	    }
   1572 	    return;
   1573 	}
   1574     }
   1575     throwclosed(env);
   1576 }
   1577 
   1578 static hfunc *
   1579 getfunc(JNIEnv *env, jobject obj)
   1580 {
   1581     jvalue v;
   1582 
   1583     v.j = (*env)->GetLongField(env, obj, F_SQLite_FunctionContext_handle);
   1584     return (hfunc *) v.l;
   1585 }
   1586 
   1587 #if HAVE_SQLITE2
   1588 static void
   1589 call_common(sqlite_func *sf, int isstep, int nargs, const char **args)
   1590 {
   1591     hfunc *f = (hfunc *) sqlite_user_data(sf);
   1592 
   1593     if (f && f->env && f->fi) {
   1594 	JNIEnv *env = f->env;
   1595 	jclass cls = (*env)->GetObjectClass(env, f->fi);
   1596 	jmethodID mid =
   1597 	    (*env)->GetMethodID(env, cls,
   1598 				isstep ? "step" : "function",
   1599 				"(LSQLite/FunctionContext;[Ljava/lang/String;)V");
   1600 	jobjectArray arr;
   1601 	int i;
   1602 
   1603 	if (mid == 0) {
   1604 	    (*env)->DeleteLocalRef(env, cls);
   1605 	    return;
   1606 	}
   1607 	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
   1608 	for (i = 0; i < nargs; i++) {
   1609 	    if (args[i]) {
   1610 		transstr arg;
   1611 		jthrowable exc;
   1612 
   1613 		trans2utf(env, f->h->haveutf, f->h->enc, args[i], &arg);
   1614 		(*env)->SetObjectArrayElement(env, arr, i, arg.jstr);
   1615 		exc = (*env)->ExceptionOccurred(env);
   1616 		if (exc) {
   1617 		    (*env)->DeleteLocalRef(env, exc);
   1618 		    return;
   1619 		}
   1620 		(*env)->DeleteLocalRef(env, arg.jstr);
   1621 	    }
   1622 	}
   1623 	f->sf = sf;
   1624 	(*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr);
   1625 	(*env)->DeleteLocalRef(env, arr);
   1626 	(*env)->DeleteLocalRef(env, cls);
   1627     }
   1628 }
   1629 
   1630 static void
   1631 call_func(sqlite_func *sf, int nargs, const char **args)
   1632 {
   1633     call_common(sf, 0, nargs, args);
   1634 }
   1635 
   1636 static void
   1637 call_step(sqlite_func *sf, int nargs, const char **args)
   1638 {
   1639     call_common(sf, 1, nargs, args);
   1640 }
   1641 
   1642 static void
   1643 call_final(sqlite_func *sf)
   1644 {
   1645     hfunc *f = (hfunc *) sqlite_user_data(sf);
   1646 
   1647     if (f && f->env && f->fi) {
   1648 	JNIEnv *env = f->env;
   1649 	jclass cls = (*env)->GetObjectClass(env, f->fi);
   1650 	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
   1651 					    "(LSQLite/FunctionContext;)V");
   1652 	if (mid == 0) {
   1653 	    (*env)->DeleteLocalRef(env, cls);
   1654 	    return;
   1655 	}
   1656 	f->sf = sf;
   1657 	(*env)->CallVoidMethod(env, f->fi, mid, f->fc);
   1658 	(*env)->DeleteLocalRef(env, cls);
   1659     }
   1660 }
   1661 #endif
   1662 
   1663 #if HAVE_SQLITE3
   1664 static void
   1665 call3_common(sqlite3_context *sf, int isstep, int nargs, sqlite3_value **args)
   1666 {
   1667     hfunc *f = (hfunc *) sqlite3_user_data(sf);
   1668 
   1669     if (f && f->env && f->fi) {
   1670 	JNIEnv *env = f->env;
   1671 	jclass cls = (*env)->GetObjectClass(env, f->fi);
   1672 	jmethodID mid =
   1673 	    (*env)->GetMethodID(env, cls,
   1674 				isstep ? "step" : "function",
   1675 				"(LSQLite/FunctionContext;[Ljava/lang/String;)V");
   1676 	jobjectArray arr;
   1677 	int i;
   1678 
   1679 	if (mid == 0) {
   1680 	    (*env)->DeleteLocalRef(env, cls);
   1681 	    return;
   1682 	}
   1683 	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
   1684 	for (i = 0; i < nargs; i++) {
   1685 	    if (args[i]) {
   1686 		transstr arg;
   1687 		jthrowable exc;
   1688 
   1689 		trans2utf(env, 1, 0, (char *) sqlite3_value_text(args[i]),
   1690 			  &arg);
   1691 		(*env)->SetObjectArrayElement(env, arr, i, arg.jstr);
   1692 		exc = (*env)->ExceptionOccurred(env);
   1693 		if (exc) {
   1694 		    (*env)->DeleteLocalRef(env, exc);
   1695 		    return;
   1696 		}
   1697 		(*env)->DeleteLocalRef(env, arg.jstr);
   1698 	    }
   1699 	}
   1700 	f->sf = sf;
   1701 	(*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr);
   1702 	(*env)->DeleteLocalRef(env, arr);
   1703 	(*env)->DeleteLocalRef(env, cls);
   1704     }
   1705 }
   1706 
   1707 static void
   1708 call3_func(sqlite3_context *sf, int nargs, sqlite3_value **args)
   1709 {
   1710     call3_common(sf, 0, nargs, args);
   1711 }
   1712 
   1713 static void
   1714 call3_step(sqlite3_context *sf, int nargs, sqlite3_value **args)
   1715 {
   1716     call3_common(sf, 1, nargs, args);
   1717 }
   1718 
   1719 static void
   1720 call3_final(sqlite3_context *sf)
   1721 {
   1722     hfunc *f = (hfunc *) sqlite3_user_data(sf);
   1723 
   1724     if (f && f->env && f->fi) {
   1725 	JNIEnv *env = f->env;
   1726 	jclass cls = (*env)->GetObjectClass(env, f->fi);
   1727 	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
   1728 					    "(LSQLite/FunctionContext;)V");
   1729 	if (mid == 0) {
   1730 	    (*env)->DeleteLocalRef(env, cls);
   1731 	    return;
   1732 	}
   1733 	f->sf = sf;
   1734 	(*env)->CallVoidMethod(env, f->fi, mid, f->fc);
   1735 	(*env)->DeleteLocalRef(env, cls);
   1736     }
   1737 }
   1738 #endif
   1739 
   1740 static void
   1741 mkfunc_common(JNIEnv *env, int isagg, jobject obj, jstring name,
   1742 	      jint nargs, jobject fi)
   1743 {
   1744     handle *h = gethandle(env, obj);
   1745 
   1746     if (h && h->sqlite) {
   1747 	jclass cls = (*env)->FindClass(env, "SQLite/FunctionContext");
   1748 	jobject fc;
   1749 	hfunc *f;
   1750 	int ret;
   1751 	transstr namestr;
   1752 	jvalue v;
   1753 	jthrowable exc;
   1754 
   1755 	fc = (*env)->AllocObject(env, cls);
   1756 	if (!fi) {
   1757 	    throwex(env, "null SQLite.Function not allowed");
   1758 	    return;
   1759 	}
   1760 	f = malloc(sizeof (hfunc));
   1761 	if (!f) {
   1762 	    throwoom(env, "unable to get SQLite.FunctionContext handle");
   1763 	    return;
   1764 	}
   1765 	globrefset(env, fc, &f->fc);
   1766 	globrefset(env, fi, &f->fi);
   1767 	globrefset(env, obj, &f->db);
   1768 	f->h = h;
   1769 	f->next = h->funcs;
   1770 	h->funcs = f;
   1771 	f->sf = 0;
   1772 	f->env = env;
   1773 	v.j = 0;
   1774 	v.l = (jobject) f;
   1775 	(*env)->SetLongField(env, f->fc, F_SQLite_FunctionContext_handle, v.j);
   1776 	trans2iso(env, h->haveutf, h->enc, name, &namestr);
   1777 	exc = (*env)->ExceptionOccurred(env);
   1778 	if (exc) {
   1779 	    (*env)->DeleteLocalRef(env, exc);
   1780 	    return;
   1781 	}
   1782 #if HAVE_BOTH_SQLITE
   1783 	f->is3 = h->is3;
   1784 	if (h->is3) {
   1785 	    ret = sqlite3_create_function((sqlite3 *) h->sqlite,
   1786 					  namestr.result,
   1787 					  (int) nargs,
   1788 					  SQLITE_UTF8, f,
   1789 					  isagg ? NULL : call3_func,
   1790 					  isagg ? call3_step : NULL,
   1791 					  isagg ? call3_final : NULL);
   1792 
   1793 	} else {
   1794 	    if (isagg) {
   1795 		ret = sqlite_create_aggregate((sqlite *) h->sqlite,
   1796 					      namestr.result,
   1797 					      (int) nargs,
   1798 					      call_step, call_final, f);
   1799 	    } else {
   1800 		ret = sqlite_create_function((sqlite *) h->sqlite,
   1801 					     namestr.result,
   1802 					     (int) nargs,
   1803 					     call_func, f);
   1804 	    }
   1805 	}
   1806 #else
   1807 #if HAVE_SQLITE2
   1808 	if (isagg) {
   1809 	    ret = sqlite_create_aggregate((sqlite *) h->sqlite, namestr.result,
   1810 					  (int) nargs,
   1811 					  call_step, call_final, f);
   1812 	} else {
   1813 	    ret = sqlite_create_function((sqlite *) h->sqlite, namestr.result,
   1814 					 (int) nargs,
   1815 					 call_func, f);
   1816 	}
   1817 #endif
   1818 #if HAVE_SQLITE3
   1819 	ret = sqlite3_create_function((sqlite3 *) h->sqlite,
   1820 				      namestr.result,
   1821 				      (int) nargs,
   1822 				      SQLITE_UTF8, f,
   1823 				      isagg ? NULL : call3_func,
   1824 				      isagg ? call3_step : NULL,
   1825 				      isagg ? call3_final : NULL);
   1826 #endif
   1827 #endif
   1828 	transfree(&namestr);
   1829 	if (ret != SQLITE_OK) {
   1830 	    throwex(env, "error creating function/aggregate");
   1831 	}
   1832 	return;
   1833     }
   1834     throwclosed(env);
   1835 }
   1836 
   1837 JNIEXPORT void JNICALL
   1838 Java_SQLite_Database__1create_1aggregate(JNIEnv *env, jobject obj,
   1839 					 jstring name, jint nargs, jobject fi)
   1840 {
   1841     mkfunc_common(env, 1, obj, name, nargs, fi);
   1842 }
   1843 
   1844 JNIEXPORT void JNICALL
   1845 Java_SQLite_Database__1create_1function(JNIEnv *env, jobject obj,
   1846 					jstring name, jint nargs, jobject fi)
   1847 {
   1848     mkfunc_common(env, 0, obj, name, nargs, fi);
   1849 }
   1850 
   1851 JNIEXPORT void JNICALL
   1852 Java_SQLite_Database__1function_1type(JNIEnv *env, jobject obj,
   1853 				      jstring name, jint type)
   1854 {
   1855     handle *h = gethandle(env, obj);
   1856 
   1857     if (h && h->sqlite) {
   1858 #if HAVE_BOTH_SQLITE
   1859 	if (h->is3) {
   1860 	    return;
   1861 	}
   1862 #endif
   1863 #if HAVE_SQLITE2
   1864 #if HAVE_SQLITE_FUNCTION_TYPE
   1865 	{
   1866 	    int ret;
   1867 	    transstr namestr;
   1868 	    jthrowable exc;
   1869 
   1870 	    trans2iso(env, h->haveutf, h->enc, name, &namestr);
   1871 	    exc = (*env)->ExceptionOccurred(env);
   1872 	    if (exc) {
   1873 		(*env)->DeleteLocalRef(env, exc);
   1874 		return;
   1875 	    }
   1876 	    ret = sqlite_function_type(h->sqlite, namestr.result, (int) type);
   1877 	    transfree(&namestr);
   1878 	    if (ret != SQLITE_OK) {
   1879 		throwex(env, sqlite_error_string(ret));
   1880 	    }
   1881 	}
   1882 #endif
   1883 #endif
   1884 	return;
   1885     }
   1886     throwclosed(env);
   1887 }
   1888 
   1889 JNIEXPORT jint JNICALL
   1890 Java_SQLite_FunctionContext_count(JNIEnv *env, jobject obj)
   1891 {
   1892     hfunc *f = getfunc(env, obj);
   1893     jint r = 0;
   1894 
   1895     if (f && f->sf) {
   1896 #if HAVE_SQLITE_BOTH
   1897 	if (f->is3) {
   1898 	    r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf);
   1899 	} else {
   1900 	    r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf);
   1901 	}
   1902 #else
   1903 #if HAVE_SQLITE2
   1904 	r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf);
   1905 #endif
   1906 #if HAVE_SQLITE3
   1907 	r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf);
   1908 #endif
   1909 #endif
   1910     }
   1911     return r;
   1912 }
   1913 
   1914 JNIEXPORT void JNICALL
   1915 Java_SQLite_FunctionContext_set_1error(JNIEnv *env, jobject obj, jstring err)
   1916 {
   1917     hfunc *f = getfunc(env, obj);
   1918 
   1919     if (f && f->sf) {
   1920 #if HAVE_BOTH_SQLITE
   1921 	if (!f->is3) {
   1922 	    transstr errstr;
   1923 	    jthrowable exc;
   1924 
   1925 	    trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr);
   1926 	    exc = (*env)->ExceptionOccurred(env);
   1927 	    if (exc) {
   1928 	        (*env)->DeleteLocalRef(env, exc);
   1929 		return;
   1930 	    }
   1931 	    sqlite_set_result_error((sqlite_func *) f->sf,
   1932 				    errstr.result, -1);
   1933 	    transfree(&errstr);
   1934 	} else if (err) {
   1935 	    jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar);
   1936 	    const jchar *str = (*env)->GetStringChars(env, err, 0);
   1937 
   1938 	    sqlite3_result_error16((sqlite3_context *) f->sf, str, len);
   1939 	    (*env)->ReleaseStringChars(env, err, str);
   1940 	} else {
   1941 	    sqlite3_result_error((sqlite3_context *) f->sf,
   1942 				 "null error text", -1);
   1943 	}
   1944 #else
   1945 #if HAVE_SQLITE2
   1946 	transstr errstr;
   1947 	jthrowable exc;
   1948 
   1949 	trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr);
   1950 	exc = (*env)->ExceptionOccurred(env);
   1951 	if (exc) {
   1952 	    (*env)->DeleteLocalRef(env, exc);
   1953 	    return;
   1954 	}
   1955 	sqlite_set_result_error((sqlite_func *) f->sf, errstr.result, -1);
   1956 	transfree(&errstr);
   1957 #endif
   1958 #if HAVE_SQLITE3
   1959 	if (err) {
   1960 	    jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar);
   1961 	    const jchar *str = (*env)->GetStringChars(env, err, 0);
   1962 
   1963 	    sqlite3_result_error16((sqlite3_context *) f->sf, str, len);
   1964 	    (*env)->ReleaseStringChars(env, err, str);
   1965 	} else {
   1966 	    sqlite3_result_error((sqlite3_context *) f->sf,
   1967 				 "null error text", -1);
   1968 	}
   1969 #endif
   1970 #endif
   1971     }
   1972 }
   1973 
   1974 JNIEXPORT void JNICALL
   1975 Java_SQLite_FunctionContext_set_1result__D(JNIEnv *env, jobject obj, jdouble d)
   1976 {
   1977     hfunc *f = getfunc(env, obj);
   1978 
   1979     if (f && f->sf) {
   1980 #if HAVE_BOTH_SQLITE
   1981 	if (f->is3) {
   1982 	    sqlite3_result_double((sqlite3_context *) f->sf, (double) d);
   1983 	} else {
   1984 	    sqlite_set_result_double((sqlite_func *) f->sf, (double) d);
   1985 	}
   1986 #else
   1987 #if HAVE_SQLITE2
   1988 	sqlite_set_result_double((sqlite_func *) f->sf, (double) d);
   1989 #endif
   1990 #if HAVE_SQLITE3
   1991 	sqlite3_result_double((sqlite3_context *) f->sf, (double) d);
   1992 #endif
   1993 #endif
   1994     }
   1995 }
   1996 
   1997 JNIEXPORT void JNICALL
   1998 Java_SQLite_FunctionContext_set_1result__I(JNIEnv *env, jobject obj, jint i)
   1999 {
   2000     hfunc *f = getfunc(env, obj);
   2001 
   2002     if (f && f->sf) {
   2003 #if HAVE_BOTH_SQLITE
   2004 	if (f->is3) {
   2005 	    sqlite3_result_int((sqlite3_context *) f->sf, (int) i);
   2006 	} else {
   2007 	    sqlite_set_result_int((sqlite_func *) f->sf, (int) i);
   2008 	}
   2009 #else
   2010 #if HAVE_SQLITE2
   2011 	sqlite_set_result_int((sqlite_func *) f->sf, (int) i);
   2012 #endif
   2013 #if HAVE_SQLITE3
   2014 	sqlite3_result_int((sqlite3_context *) f->sf, (int) i);
   2015 #endif
   2016 #endif
   2017     }
   2018 }
   2019 
   2020 JNIEXPORT void JNICALL
   2021 Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2(JNIEnv *env,
   2022 							     jobject obj,
   2023 							     jstring ret)
   2024 {
   2025     hfunc *f = getfunc(env, obj);
   2026 
   2027     if (f && f->sf) {
   2028 #if HAVE_BOTH_SQLITE
   2029 	if (!f->is3) {
   2030 	    transstr retstr;
   2031 	    jthrowable exc;
   2032 
   2033 	    trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr);
   2034 	    exc = (*env)->ExceptionOccurred(env);
   2035 	    if (exc) {
   2036 	        (*env)->DeleteLocalRef(env, exc);
   2037 		return;
   2038 	    }
   2039 	    sqlite_set_result_string((sqlite_func *) f->sf,
   2040 				     retstr.result, -1);
   2041 	    transfree(&retstr);
   2042 	} else if (ret) {
   2043 	    jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar);
   2044 	    const jchar *str = (*env)->GetStringChars(env, ret, 0);
   2045 
   2046 	    sqlite3_result_text16((sqlite3_context *) f->sf, str, len,
   2047 				  SQLITE_TRANSIENT);
   2048 	    (*env)->ReleaseStringChars(env, ret, str);
   2049 	} else {
   2050 	    sqlite3_result_null((sqlite3_context *) f->sf);
   2051 	}
   2052 #else
   2053 #if HAVE_SQLITE2
   2054 	transstr retstr;
   2055 	jthrowable exc;
   2056 
   2057 	trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr);
   2058 	exc = (*env)->ExceptionOccurred(env);
   2059 	if (exc) {
   2060 	    (*env)->DeleteLocalRef(env, exc);
   2061 	    return;
   2062 	}
   2063 	sqlite_set_result_string((sqlite_func *) f->sf, retstr.result, -1);
   2064 	transfree(&retstr);
   2065 #endif
   2066 #if HAVE_SQLITE3
   2067 	if (ret) {
   2068 	    jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar);
   2069 	    const jchar *str = (*env)->GetStringChars(env, ret, 0);
   2070 
   2071 	    sqlite3_result_text16((sqlite3_context *) f->sf, str, len,
   2072 				  SQLITE_TRANSIENT);
   2073 	    (*env)->ReleaseStringChars(env, ret, str);
   2074 	} else {
   2075 	    sqlite3_result_null((sqlite3_context *) f->sf);
   2076 	}
   2077 #endif
   2078 #endif
   2079     }
   2080 }
   2081 
   2082 JNIEXPORT void JNICALL
   2083 Java_SQLite_FunctionContext_set_1result___3B(JNIEnv *env, jobject obj,
   2084 					     jbyteArray b)
   2085 {
   2086 #if HAVE_SQLITE3
   2087     hfunc *f = getfunc(env, obj);
   2088 
   2089     if (f && f->sf) {
   2090 #if HAVE_BOTH_SQLITE
   2091 	if (!f->is3) {
   2092 	    /* silently ignored */
   2093 	    return;
   2094 	}
   2095 #endif
   2096 	if (b) {
   2097 	    jsize len;
   2098 	    jbyte *data;
   2099 
   2100 	    len = (*env)->GetArrayLength(env, b);
   2101 	    data = (*env)->GetByteArrayElements(env, b, 0);
   2102 	    sqlite3_result_blob((sqlite3_context *) f->sf,
   2103 				data, len, SQLITE_TRANSIENT);
   2104 	    (*env)->ReleaseByteArrayElements(env, b, data, 0);
   2105 	} else {
   2106 	    sqlite3_result_null((sqlite3_context *) f->sf);
   2107 	}
   2108     }
   2109 #endif
   2110 }
   2111 
   2112 JNIEXPORT void JNICALL
   2113 Java_SQLite_FunctionContext_set_1result_1zeroblob(JNIEnv *env, jobject obj,
   2114 						  jint n)
   2115 {
   2116 #if HAVE_SQLITE3 && HAVE_SQLITE3_RESULT_ZEROBLOB
   2117     hfunc *f = getfunc(env, obj);
   2118 
   2119     if (f && f->sf) {
   2120 #if HAVE_BOTH_SQLITE
   2121 	if (!f->is3) {
   2122 	    /* silently ignored */
   2123 	    return;
   2124 	}
   2125 #endif
   2126 	sqlite3_result_zeroblob((sqlite3_context *) f->sf, n);
   2127     }
   2128 #endif
   2129 }
   2130 
   2131 JNIEXPORT jstring JNICALL
   2132 Java_SQLite_Database_error_1string(JNIEnv *env, jclass c, jint err)
   2133 {
   2134 #if HAVE_SQLITE2
   2135     return (*env)->NewStringUTF(env, sqlite_error_string((int) err));
   2136 #else
   2137     return (*env)->NewStringUTF(env, "unkown error");
   2138 #endif
   2139 }
   2140 
   2141 JNIEXPORT jstring JNICALL
   2142 Java_SQLite_Database__1errmsg(JNIEnv *env, jobject obj)
   2143 {
   2144 #if HAVE_SQLITE3
   2145     handle *h = gethandle(env, obj);
   2146 
   2147     if (h && h->sqlite) {
   2148 #if HAVE_BOTH_SQLITE
   2149 	if (!h->is3) {
   2150 	    return 0;
   2151 	}
   2152 #endif
   2153 	return (*env)->NewStringUTF(env,
   2154 				    sqlite3_errmsg((sqlite3 *) h->sqlite));
   2155     }
   2156 #endif
   2157     return 0;
   2158 }
   2159 
   2160 JNIEXPORT void JNICALL
   2161 Java_SQLite_Database__1set_1encoding(JNIEnv *env, jobject obj, jstring enc)
   2162 {
   2163     handle *h = gethandle(env, obj);
   2164 
   2165     if (h && !h->haveutf) {
   2166 #if HAVE_BOTH_SQLITE
   2167 	if (!h->is3) {
   2168 	    delglobrefp(env, &h->enc);
   2169 	    h->enc = enc;
   2170 	    globrefset(env, enc, &h->enc);
   2171 	}
   2172 #else
   2173 #if HAVE_SQLITE2
   2174 	delglobrefp(env, &h->enc);
   2175 	h->enc = enc;
   2176 	globrefset(env, enc, &h->enc);
   2177 #endif
   2178 #endif
   2179     }
   2180 }
   2181 
   2182 #if HAVE_SQLITE_SET_AUTHORIZER
   2183 static int
   2184 doauth(void *arg, int what, const char *arg1, const char *arg2,
   2185        const char *arg3, const char *arg4)
   2186 {
   2187     handle *h = (handle *) arg;
   2188     JNIEnv *env = h->env;
   2189 
   2190     if (env && h->ai) {
   2191 	jthrowable exc;
   2192 	jclass cls = (*env)->GetObjectClass(env, h->ai);
   2193 	jmethodID mid;
   2194 	jint i = what;
   2195 
   2196 	mid = (*env)->GetMethodID(env, cls, "authorize",
   2197 				  "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I");
   2198 	if (mid) {
   2199 	    jstring s1 = 0, s2 = 0, s3 = 0, s4 = 0;
   2200 	    transstr tr;
   2201 
   2202 	    if (arg1) {
   2203 		trans2utf(env, h->haveutf, h->enc, arg1, &tr);
   2204 		s1 = tr.jstr;
   2205 	    }
   2206 	    exc = (*env)->ExceptionOccurred(env);
   2207 	    if (exc) {
   2208 		(*env)->DeleteLocalRef(env, exc);
   2209 		return SQLITE_DENY;
   2210 	    }
   2211 	    if (arg2) {
   2212 		trans2utf(env, h->haveutf, h->enc, arg2, &tr);
   2213 		s2 = tr.jstr;
   2214 	    }
   2215 	    if (arg3) {
   2216 		trans2utf(env, h->haveutf, h->enc, arg3, &tr);
   2217 		s3 = tr.jstr;
   2218 	    }
   2219 	    if (arg4) {
   2220 		trans2utf(env, h->haveutf, h->enc, arg4, &tr);
   2221 		s4 = tr.jstr;
   2222 	    }
   2223 	    exc = (*env)->ExceptionOccurred(env);
   2224 	    if (exc) {
   2225 		(*env)->DeleteLocalRef(env, exc);
   2226 		return SQLITE_DENY;
   2227 	    }
   2228 	    i = (*env)->CallIntMethod(env, h->ai, mid, i, s1, s2, s3, s4);
   2229 	    exc = (*env)->ExceptionOccurred(env);
   2230 	    if (exc) {
   2231 		(*env)->DeleteLocalRef(env, exc);
   2232 		return SQLITE_DENY;
   2233 	    }
   2234 	    (*env)->DeleteLocalRef(env, s4);
   2235 	    (*env)->DeleteLocalRef(env, s3);
   2236 	    (*env)->DeleteLocalRef(env, s2);
   2237 	    (*env)->DeleteLocalRef(env, s1);
   2238 	    if (i != SQLITE_OK && i != SQLITE_IGNORE) {
   2239 		i = SQLITE_DENY;
   2240 	    }
   2241 	    return (int) i;
   2242 	}
   2243     }
   2244     return SQLITE_DENY;
   2245 }
   2246 #endif
   2247 
   2248 JNIEXPORT void JNICALL
   2249 Java_SQLite_Database__1set_1authorizer(JNIEnv *env, jobject obj, jobject auth)
   2250 {
   2251     handle *h = gethandle(env, obj);
   2252 
   2253     if (h && h->sqlite) {
   2254 	delglobrefp(env, &h->ai);
   2255 	globrefset(env, auth, &h->ai);
   2256 #if HAVE_SQLITE_SET_AUTHORIZER
   2257 	h->env = env;
   2258 #if HAVE_BOTH_SQLITE
   2259 	if (h->is3) {
   2260 	    sqlite3_set_authorizer((sqlite3 *) h->sqlite,
   2261 				   h->ai ? doauth : 0, h);
   2262 	} else {
   2263 	    sqlite_set_authorizer((sqlite *) h->sqlite,
   2264 				  h->ai ? doauth : 0, h);
   2265 	}
   2266 #else
   2267 #if HAVE_SQLITE2
   2268 	sqlite_set_authorizer((sqlite *) h->sqlite, h->ai ? doauth : 0, h);
   2269 #endif
   2270 #if HAVE_SQLITE3
   2271 	sqlite3_set_authorizer((sqlite3 *) h->sqlite, h->ai ? doauth : 0, h);
   2272 #endif
   2273 #endif
   2274 #endif
   2275 	return;
   2276     }
   2277     throwclosed(env);
   2278 }
   2279 
   2280 #if HAVE_SQLITE_TRACE
   2281 static void
   2282 dotrace(void *arg, const char *msg)
   2283 {
   2284     handle *h = (handle *) arg;
   2285     JNIEnv *env = h->env;
   2286 
   2287     if (env && h->tr && msg) {
   2288 	jthrowable exc;
   2289 	jclass cls = (*env)->GetObjectClass(env, h->tr);
   2290 	jmethodID mid;
   2291 
   2292 	mid = (*env)->GetMethodID(env, cls, "trace", "(Ljava/lang/String;)V");
   2293 	if (mid) {
   2294 	    transstr tr;
   2295 
   2296 	    trans2utf(env, h->haveutf, h->enc, msg, &tr);
   2297 	    exc = (*env)->ExceptionOccurred(env);
   2298 	    if (exc) {
   2299 		(*env)->DeleteLocalRef(env, exc);
   2300 		(*env)->ExceptionClear(env);
   2301 		return;
   2302 	    }
   2303 	    (*env)->CallVoidMethod(env, h->tr, mid, tr.jstr);
   2304 	    (*env)->ExceptionClear(env);
   2305 	    (*env)->DeleteLocalRef(env, tr.jstr);
   2306 	    return;
   2307 	}
   2308     }
   2309     return;
   2310 }
   2311 #endif
   2312 
   2313 JNIEXPORT void JNICALL
   2314 Java_SQLite_Database__1trace(JNIEnv *env, jobject obj, jobject tr)
   2315 {
   2316     handle *h = gethandle(env, obj);
   2317 
   2318     if (h && h->sqlite) {
   2319 	delglobrefp(env, &h->tr);
   2320 	globrefset(env, tr, &h->tr);
   2321 #if HAVE_BOTH_SQLITE
   2322 	if (h->is3) {
   2323 	    sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h);
   2324 	} else {
   2325 #if HAVE_SQLITE_TRACE
   2326 	    sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h);
   2327 #endif
   2328 	}
   2329 #else
   2330 #if HAVE_SQLITE2
   2331 #if HAVE_SQLITE_TRACE
   2332 	sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h);
   2333 #endif
   2334 #endif
   2335 #if HAVE_SQLITE3
   2336 	sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h);
   2337 #endif
   2338 #endif
   2339 	return;
   2340     }
   2341     throwclosed(env);
   2342 }
   2343 
   2344 #if HAVE_SQLITE_COMPILE
   2345 static void
   2346 dovmfinal(JNIEnv *env, jobject obj, int final)
   2347 {
   2348     hvm *v = gethvm(env, obj);
   2349 
   2350     if (v) {
   2351 	if (v->h) {
   2352 	    handle *h = v->h;
   2353 	    hvm *vv, **vvp;
   2354 
   2355 	    vvp = &h->vms;
   2356 	    vv = *vvp;
   2357 	    while (vv) {
   2358 		if (vv == v) {
   2359 		    *vvp = vv->next;
   2360 		    break;
   2361 		}
   2362 		vvp = &vv->next;
   2363 		vv = *vvp;
   2364 	    }
   2365 	}
   2366 	if (v->vm) {
   2367 #if HAVE_BOTH_SQLITE
   2368 	    if (v->is3) {
   2369 		sqlite3_finalize((sqlite3_stmt *) v->vm);
   2370 	    } else {
   2371 		sqlite_finalize((sqlite_vm *) v->vm, 0);
   2372 	    }
   2373 #else
   2374 #if HAVE_SQLITE2
   2375 	    sqlite_finalize((sqlite_vm *) v->vm, 0);
   2376 #endif
   2377 #if HAVE_SQLITE3
   2378 	    sqlite3_finalize((sqlite3_stmt *) v->vm);
   2379 #endif
   2380 #endif
   2381 	    v->vm = 0;
   2382 	}
   2383 	free(v);
   2384 	(*env)->SetLongField(env, obj, F_SQLite_Vm_handle, 0);
   2385 	return;
   2386     }
   2387     if (!final) {
   2388 	throwex(env, "vm already closed");
   2389     }
   2390 }
   2391 #endif
   2392 
   2393 #if HAVE_SQLITE3
   2394 static void
   2395 dostmtfinal(JNIEnv *env, jobject obj)
   2396 {
   2397     hvm *v = gethstmt(env, obj);
   2398 
   2399     if (v) {
   2400 	if (v->h) {
   2401 	    handle *h = v->h;
   2402 	    hvm *vv, **vvp;
   2403 
   2404 	    vvp = &h->vms;
   2405 	    vv = *vvp;
   2406 	    while (vv) {
   2407 		if (vv == v) {
   2408 		    *vvp = vv->next;
   2409 		    break;
   2410 		}
   2411 		vvp = &vv->next;
   2412 		vv = *vvp;
   2413 	    }
   2414 	}
   2415 	if (v->vm) {
   2416 	    sqlite3_finalize((sqlite3_stmt *) v->vm);
   2417 	}
   2418 	v->vm = 0;
   2419 	free(v);
   2420 	(*env)->SetLongField(env, obj, F_SQLite_Stmt_handle, 0);
   2421     }
   2422 }
   2423 #endif
   2424 
   2425 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
   2426 static void
   2427 doblobfinal(JNIEnv *env, jobject obj)
   2428 {
   2429     hbl *bl = gethbl(env, obj);
   2430 
   2431     if (bl) {
   2432 	if (bl->h) {
   2433 	    handle *h = bl->h;
   2434 	    hbl *blc, **blp;
   2435 
   2436 	    blp = &h->blobs;
   2437 	    blc = *blp;
   2438 	    while (blc) {
   2439 		if (blc == bl) {
   2440 		    *blp = blc->next;
   2441 		    break;
   2442 		}
   2443 		blp = &blc->next;
   2444 		blc = *blp;
   2445 	    }
   2446 	}
   2447 	if (bl->blob) {
   2448 	    sqlite3_blob_close(bl->blob);
   2449 	}
   2450 	bl->blob = 0;
   2451 	free(bl);
   2452 	(*env)->SetLongField(env, obj, F_SQLite_Blob_handle, 0);
   2453 	(*env)->SetIntField(env, obj, F_SQLite_Blob_size, 0);
   2454     }
   2455 }
   2456 #endif
   2457 
   2458 JNIEXPORT void JNICALL
   2459 Java_SQLite_Vm_stop(JNIEnv *env, jobject obj)
   2460 {
   2461 #if HAVE_SQLITE_COMPILE
   2462     dovmfinal(env, obj, 0);
   2463 #else
   2464     throwex(env, "unsupported");
   2465 #endif
   2466 }
   2467 
   2468 JNIEXPORT void JNICALL
   2469 Java_SQLite_Vm_finalize(JNIEnv *env, jobject obj)
   2470 {
   2471 #if HAVE_SQLITE_COMPILE
   2472     dovmfinal(env, obj, 1);
   2473 #endif
   2474 }
   2475 
   2476 #if HAVE_SQLITE_COMPILE
   2477 #if HAVE_SQLITE3
   2478 static void
   2479 free_tab(void *mem)
   2480 {
   2481     char **p = (char **) mem;
   2482     int i, n;
   2483 
   2484     if (!p) {
   2485 	return;
   2486     }
   2487     p -= 1;
   2488     mem = (void *) p;
   2489     n = ((int *) p)[0];
   2490     p += n * 2 + 2 + 1;
   2491     for (i = 0; i < n; i++) {
   2492 	if (p[i]) {
   2493 	    free(p[i]);
   2494 	}
   2495     }
   2496     free(mem);
   2497 }
   2498 #endif
   2499 #endif
   2500 
   2501 JNIEXPORT jboolean JNICALL
   2502 Java_SQLite_Vm_step(JNIEnv *env, jobject obj, jobject cb)
   2503 {
   2504 #if HAVE_SQLITE_COMPILE
   2505     hvm *v = gethvm(env, obj);
   2506 
   2507     if (v && v->vm && v->h) {
   2508 	jthrowable exc;
   2509 	int ret, ncol = 0;
   2510 #if HAVE_SQLITE3
   2511 	freemem *freeproc = 0;
   2512 	const char **blob = 0;
   2513 #endif
   2514 	const char **data = 0, **cols = 0;
   2515 
   2516 	v->h->env = env;
   2517 #if HAVE_BOTH_SQLITE
   2518 	if (v->is3) {
   2519 	    ret = sqlite3_step((sqlite3_stmt *) v->vm);
   2520 	    if (ret == SQLITE_ROW) {
   2521 		ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   2522 		if (ncol > 0) {
   2523 		    data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
   2524 		    if (data) {
   2525 			data[0] = (const char *) ncol;
   2526 			++data;
   2527 			cols = data + ncol + 1;
   2528 			blob = cols + ncol + 1;
   2529 			freeproc = free_tab;
   2530 		    } else {
   2531 			ret = SQLITE_NOMEM;
   2532 		    }
   2533 		}
   2534 		if (ret != SQLITE_NOMEM) {
   2535 		    int i;
   2536 
   2537 		    for (i = 0; i < ncol; i++) {
   2538 			cols[i] =
   2539 			    sqlite3_column_name((sqlite3_stmt *) v->vm, i);
   2540 			if (sqlite3_column_type((sqlite3_stmt *) v->vm, i)
   2541 			    == SQLITE_BLOB) {
   2542 			    unsigned char *src = (unsigned char *)
   2543 				sqlite3_column_blob((sqlite3_stmt *) v->vm, i);
   2544 			    int n =
   2545 				sqlite3_column_bytes((sqlite3_stmt *) v->vm,
   2546 						     i);
   2547 
   2548 			    if (src) {
   2549 				data[i] = malloc(n * 2 + 4);
   2550 				if (data[i]) {
   2551 				    int k;
   2552 				    char *p = (char *) data[i];
   2553 
   2554 				    blob[i] = data[i];
   2555 				    *p++ = 'X';
   2556 				    *p++ = '\'';
   2557 				    for (k = 0; k < n; k++) {
   2558 					*p++ = xdigits[src[k] >> 4];
   2559 					*p++ = xdigits[src[k] & 0x0F];
   2560 				    }
   2561 				    *p++ = '\'';
   2562 				    *p++ = '\0';
   2563 				}
   2564 			    }
   2565 			} else {
   2566 			    data[i] = (const char *)
   2567 				sqlite3_column_text((sqlite3_stmt *) v->vm, i);
   2568 			}
   2569 		    }
   2570 		}
   2571 	    }
   2572 	} else {
   2573 	    ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
   2574 	}
   2575 #else
   2576 #if HAVE_SQLITE2
   2577 	ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
   2578 #endif
   2579 #if HAVE_SQLITE3
   2580 	ret = sqlite3_step((sqlite3_stmt *) v->vm);
   2581 	if (ret == SQLITE_ROW) {
   2582 	    ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   2583 	    if (ncol > 0) {
   2584 		data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
   2585 		if (data) {
   2586 		    data[0] = (const char *) ncol;
   2587 		    ++data;
   2588 		    cols = data + ncol + 1;
   2589 		    blob = cols + ncol + 1;
   2590 		    freeproc = free_tab;
   2591 		} else {
   2592 		    ret = SQLITE_NOMEM;
   2593 		}
   2594 	    }
   2595 	    if (ret != SQLITE_NOMEM) {
   2596 		int i;
   2597 
   2598 		for (i = 0; i < ncol; i++) {
   2599 		    cols[i] = sqlite3_column_name((sqlite3_stmt *) v->vm, i);
   2600 		    if (sqlite3_column_type((sqlite3_stmt *) v->vm, i)
   2601 			== SQLITE_BLOB) {
   2602 			unsigned char *src = (unsigned char *)
   2603 			    sqlite3_column_blob((sqlite3_stmt *) v->vm, i);
   2604 			int n =
   2605 			    sqlite3_column_bytes((sqlite3_stmt *) v->vm, i);
   2606 
   2607 			if (src) {
   2608 			    data[i] = malloc(n * 2 + 4);
   2609 			    if (data[i]) {
   2610 				int k;
   2611 				char *p = (char *) data[i];
   2612 
   2613 				blob[i] = data[i];
   2614 				*p++ = 'X';
   2615 				*p++ = '\'';
   2616 				for (k = 0; k < n; k++) {
   2617 				    *p++ = xdigits[src[k] >> 4];
   2618 				    *p++ = xdigits[src[k] & 0x0F];
   2619 				}
   2620 				*p++ = '\'';
   2621 				*p++ = '\0';
   2622 			    }
   2623 			}
   2624 		    } else {
   2625 			data[i] = (char *)
   2626 			    sqlite3_column_text((sqlite3_stmt *) v->vm, i);
   2627 		    }
   2628 		}
   2629 	    }
   2630 	}
   2631 #endif
   2632 #endif
   2633 	if (ret == SQLITE_ROW) {
   2634 	    v->hh.cb = cb;
   2635 	    v->hh.env = env;
   2636 #if HAVE_BOTH_SQLITE
   2637 	    if (v->is3) {
   2638 		v->hh.stmt = (sqlite3_stmt *) v->vm;
   2639 	    }
   2640 #else
   2641 #if HAVE_SQLITE3
   2642 	    v->hh.stmt = (sqlite3_stmt *) v->vm;
   2643 #endif
   2644 #endif
   2645 	    callback((void *) &v->hh, ncol, (char **) data, (char **) cols);
   2646 #if HAVE_SQLITE3
   2647 	    if (data && freeproc) {
   2648 		freeproc((void *) data);
   2649 	    }
   2650 #endif
   2651 	    exc = (*env)->ExceptionOccurred(env);
   2652 	    if (exc) {
   2653 		(*env)->DeleteLocalRef(env, exc);
   2654 		goto dofin;
   2655 	    }
   2656 	    return JNI_TRUE;
   2657 	} else if (ret == SQLITE_DONE) {
   2658 dofin:
   2659 #if HAVE_BOTH_SQLITE
   2660 	    if (v->is3) {
   2661 		sqlite3_finalize((sqlite3_stmt *) v->vm);
   2662 	    } else {
   2663 		sqlite_finalize((sqlite_vm *) v->vm, 0);
   2664 	    }
   2665 #else
   2666 #if HAVE_SQLITE2
   2667 	    sqlite_finalize((sqlite_vm *) v->vm, 0);
   2668 #endif
   2669 #if HAVE_SQLITE3
   2670 	    sqlite3_finalize((sqlite3_stmt *) v->vm);
   2671 #endif
   2672 #endif
   2673 	    v->vm = 0;
   2674 	    return JNI_FALSE;
   2675 	}
   2676 #if HAVE_BOTH_SQLITE
   2677 	if (v->is3) {
   2678 	    sqlite3_finalize((sqlite3_stmt *) v->vm);
   2679 	} else {
   2680 	    sqlite_finalize((sqlite_vm *) v->vm, 0);
   2681 	}
   2682 #else
   2683 #if HAVE_SQLITE2
   2684 	sqlite_finalize((sqlite_vm *) v->vm, 0);
   2685 #endif
   2686 #if HAVE_SQLITE3
   2687 	sqlite3_finalize((sqlite3_stmt *) v->vm);
   2688 #endif
   2689 #endif
   2690 	setvmerr(env, obj, ret);
   2691 	v->vm = 0;
   2692 	throwex(env, "error in step");
   2693 	return JNI_FALSE;
   2694     }
   2695     throwex(env, "vm already closed");
   2696 #else
   2697     throwex(env, "unsupported");
   2698 #endif
   2699     return JNI_FALSE;
   2700 }
   2701 
   2702 JNIEXPORT jboolean JNICALL
   2703 Java_SQLite_Vm_compile(JNIEnv *env, jobject obj)
   2704 {
   2705 #if HAVE_SQLITE_COMPILE
   2706     hvm *v = gethvm(env, obj);
   2707     void *svm = 0;
   2708     char *err = 0;
   2709     const char *tail;
   2710     int ret;
   2711 
   2712     if (v && v->vm) {
   2713 #if HAVE_BOTH_SQLITE
   2714 	if (v->is3) {
   2715 	    sqlite3_finalize((sqlite3_stmt *) v->vm);
   2716 	} else {
   2717 	    sqlite_finalize((sqlite_vm *) v->vm, 0);
   2718 	}
   2719 #else
   2720 #if HAVE_SQLITE2
   2721 	sqlite_finalize((sqlite_vm *) v->vm, 0);
   2722 #endif
   2723 #if HAVE_SQLITE3
   2724 	sqlite3_finalize((sqlite3_stmt *) v->vm);
   2725 #endif
   2726 #endif
   2727 	v->vm = 0;
   2728     }
   2729     if (v && v->h && v->h->sqlite) {
   2730 	if (!v->tail) {
   2731 	    return JNI_FALSE;
   2732 	}
   2733 	v->h->env = env;
   2734 #if HAVE_BOTH_SQLITE
   2735 	if (v->is3) {
   2736 #if HAVE_SQLITE3_PREPARE_V2
   2737 	    ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite, v->tail, -1,
   2738 				     (sqlite3_stmt **) &svm, &tail);
   2739 #else
   2740 	    ret = sqlite3_prepare((sqlite3 *) v->h->sqlite, v->tail, -1,
   2741 				  (sqlite3_stmt **) &svm, &tail);
   2742 #endif
   2743 	    if (ret != SQLITE_OK) {
   2744 		if (svm) {
   2745 		    sqlite3_finalize((sqlite3_stmt *) svm);
   2746 		    svm = 0;
   2747 		}
   2748 	    }
   2749 	} else {
   2750 	    ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
   2751 				 &tail, (sqlite_vm **) &svm, &err);
   2752 	    if (ret != SQLITE_OK) {
   2753 		if (svm) {
   2754 		    sqlite_finalize((sqlite_vm *) svm, 0);
   2755 		    svm = 0;
   2756 		}
   2757 	    }
   2758 	}
   2759 #else
   2760 #if HAVE_SQLITE2
   2761 	ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
   2762 			     &tail, (sqlite_vm **) &svm, &err);
   2763 	if (ret != SQLITE_OK) {
   2764 	    if (svm) {
   2765 		sqlite_finalize((sqlite_vm *) svm, 0);
   2766 		svm = 0;
   2767 	    }
   2768 	}
   2769 #endif
   2770 #if HAVE_SQLITE3
   2771 #if HAVE_SQLITE3_PREPARE_V2
   2772 	ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite,
   2773 				 v->tail, -1, (sqlite3_stmt **) &svm, &tail);
   2774 #else
   2775 	ret = sqlite3_prepare((sqlite3 *) v->h->sqlite,
   2776 			      v->tail, -1, (sqlite3_stmt **) &svm, &tail);
   2777 #endif
   2778 	if (ret != SQLITE_OK) {
   2779 	    if (svm) {
   2780 		sqlite3_finalize((sqlite3_stmt *) svm);
   2781 		svm = 0;
   2782 	    }
   2783 	}
   2784 #endif
   2785 #endif
   2786 	if (ret != SQLITE_OK) {
   2787 	    setvmerr(env, obj, ret);
   2788 	    v->tail = 0;
   2789 	    throwex(env, err ? err : "error in compile/prepare");
   2790 #if HAVE_SQLITE2
   2791 	    if (err) {
   2792 		sqlite_freemem(err);
   2793 	    }
   2794 #endif
   2795 	    return JNI_FALSE;
   2796 	}
   2797 #if HAVE_SQLITE2
   2798 	if (err) {
   2799 	    sqlite_freemem(err);
   2800 	}
   2801 #endif
   2802 	if (!svm) {
   2803 	    v->tail = 0;
   2804 	    return JNI_FALSE;
   2805 	}
   2806 	v->vm = svm;
   2807 	v->tail = (char *) tail;
   2808 	v->hh.row1 = 1;
   2809 	return JNI_TRUE;
   2810     }
   2811     throwex(env, "vm already closed");
   2812 #else
   2813     throwex(env, "unsupported");
   2814 #endif
   2815     return JNI_FALSE;
   2816 }
   2817 
   2818 JNIEXPORT void JNICALL
   2819 Java_SQLite_Database_vm_1compile(JNIEnv *env, jobject obj, jstring sql,
   2820 				 jobject vm)
   2821 {
   2822 #if HAVE_SQLITE_COMPILE
   2823     handle *h = gethandle(env, obj);
   2824     void *svm = 0;
   2825     hvm *v;
   2826     char *err = 0;
   2827     const char *tail;
   2828     transstr tr;
   2829     jvalue vv;
   2830     int ret;
   2831     jthrowable exc;
   2832 
   2833     if (!h) {
   2834 	throwclosed(env);
   2835 	return;
   2836     }
   2837     if (!vm) {
   2838 	throwex(env, "null vm");
   2839 	return;
   2840     }
   2841     if (!sql) {
   2842 	throwex(env, "null sql");
   2843 	return;
   2844     }
   2845     trans2iso(env, h->haveutf, h->enc, sql, &tr);
   2846     exc = (*env)->ExceptionOccurred(env);
   2847     if (exc) {
   2848 	(*env)->DeleteLocalRef(env, exc);
   2849 	return;
   2850     }
   2851     h->env = env;
   2852 #if HAVE_BOTH_SQLITE
   2853     if (h->is3) {
   2854 #if HAVE_SQLITE3_PREPARE_V2
   2855 	ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1,
   2856 				 (sqlite3_stmt **) &svm, &tail);
   2857 #else
   2858 	ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1,
   2859 			      (sqlite3_stmt **) &svm, &tail);
   2860 #endif
   2861 	if (ret != SQLITE_OK) {
   2862 	    if (svm) {
   2863 		sqlite3_finalize((sqlite3_stmt *) svm);
   2864 		svm = 0;
   2865 	    }
   2866 	}
   2867     } else {
   2868 	ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
   2869 			     (sqlite_vm **) &svm, &err);
   2870 	if (ret != SQLITE_OK) {
   2871 	    if (svm) {
   2872 		sqlite_finalize((sqlite_vm *) svm, 0);
   2873 	    }
   2874 	}
   2875     }
   2876 #else
   2877 #if HAVE_SQLITE2
   2878     ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
   2879 			 (sqlite_vm **) &svm, &err);
   2880     if (ret != SQLITE_OK) {
   2881 	if (svm) {
   2882 	    sqlite_finalize((sqlite_vm *) svm, 0);
   2883 	    svm = 0;
   2884 	}
   2885     }
   2886 #endif
   2887 #if HAVE_SQLITE3
   2888 #if HAVE_SQLITE3_PREPARE_V2
   2889     ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1,
   2890 			     (sqlite3_stmt **) &svm, &tail);
   2891 #else
   2892     ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1,
   2893 			  (sqlite3_stmt **) &svm, &tail);
   2894 #endif
   2895     if (ret != SQLITE_OK) {
   2896 	if (svm) {
   2897 	    sqlite3_finalize((sqlite3_stmt *) svm);
   2898 	    svm = 0;
   2899 	}
   2900     }
   2901 #endif
   2902 #endif
   2903     if (ret != SQLITE_OK) {
   2904 	transfree(&tr);
   2905 	setvmerr(env, vm, ret);
   2906 	throwex(env, err ? err : "error in prepare/compile");
   2907 #if HAVE_SQLITE2
   2908 	if (err) {
   2909 	    sqlite_freemem(err);
   2910 	}
   2911 #endif
   2912 	return;
   2913     }
   2914 #if HAVE_SQLITE2
   2915     if (err) {
   2916 	sqlite_freemem(err);
   2917     }
   2918 #endif
   2919     if (!svm) {
   2920 	transfree(&tr);
   2921 	return;
   2922     }
   2923     v = malloc(sizeof (hvm) + strlen(tail) + 1);
   2924     if (!v) {
   2925 	transfree(&tr);
   2926 #if HAVE_BOTH_SQLITE
   2927 	if (h->is3) {
   2928 	    sqlite3_finalize((sqlite3_stmt *) svm);
   2929 	} else {
   2930 	    sqlite_finalize((sqlite_vm *) svm, 0);
   2931 	}
   2932 #else
   2933 #if HAVE_SQLITE2
   2934 	sqlite_finalize((sqlite_vm *) svm, 0);
   2935 #endif
   2936 #if HAVE_SQLITE3
   2937 	sqlite3_finalize((sqlite3_stmt *) svm);
   2938 #endif
   2939 #endif
   2940 	throwoom(env, "unable to get SQLite handle");
   2941 	return;
   2942     }
   2943     v->next = h->vms;
   2944     h->vms = v;
   2945     v->vm = svm;
   2946     v->h = h;
   2947     v->tail = (char *) (v + 1);
   2948 #if HAVE_BOTH_SQLITE
   2949     v->is3 = v->hh.is3 = h->is3;
   2950 #endif
   2951     strcpy(v->tail, tail);
   2952     v->hh.sqlite = 0;
   2953     v->hh.haveutf = h->haveutf;
   2954     v->hh.ver = h->ver;
   2955     v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
   2956     v->hh.row1 = 1;
   2957     v->hh.enc = h->enc;
   2958     v->hh.funcs = 0;
   2959     v->hh.vms = 0;
   2960     v->hh.env = 0;
   2961     vv.j = 0;
   2962     vv.l = (jobject) v;
   2963     (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
   2964 #else
   2965     throwex(env, "unsupported");
   2966 #endif
   2967 }
   2968 
   2969 JNIEXPORT void JNICALL
   2970 Java_SQLite_Database_vm_1compile_1args(JNIEnv *env,
   2971 				       jobject obj, jstring sql,
   2972 				       jobject vm, jobjectArray args)
   2973 {
   2974 #if HAVE_SQLITE_COMPILE
   2975 #if HAVE_SQLITE3
   2976     handle *h = gethandle(env, obj);
   2977 #endif
   2978 
   2979 #if HAVE_BOTH_SQLITE
   2980     if (h && !h->is3) {
   2981 	throwex(env, "unsupported");
   2982 	return;
   2983     }
   2984 #else
   2985 #if HAVE_SQLITE2
   2986     throwex(env, "unsupported");
   2987 #endif
   2988 #endif
   2989 #if HAVE_SQLITE3
   2990     if (!h || !h->sqlite) {
   2991 	throwclosed(env);
   2992 	return;
   2993     }
   2994     if (!vm) {
   2995 	throwex(env, "null vm");
   2996 	return;
   2997     }
   2998     if (!sql) {
   2999 	throwex(env, "null sql");
   3000 	return;
   3001     } else {
   3002 	void *svm = 0;
   3003 	hvm *v;
   3004 	jvalue vv;
   3005 	jthrowable exc;
   3006 	int rc = SQLITE_ERROR, nargs, i;
   3007 	char *p;
   3008 	const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
   3009 	const char *tail;
   3010 	transstr sqlstr;
   3011 	struct args {
   3012 	    char *arg;
   3013 	    jobject obj;
   3014 	    transstr trans;
   3015 	} *argv = 0;
   3016 	char **cargv = 0;
   3017 
   3018 	p = (char *) str;
   3019 	nargs = 0;
   3020 	while (*p) {
   3021 	    if (*p == '%') {
   3022 		++p;
   3023 		if (*p == 'q' || *p == 'Q' || *p == 's') {
   3024 		    nargs++;
   3025 		    if (nargs > MAX_PARAMS) {
   3026 			(*env)->ReleaseStringUTFChars(env, sql, str);
   3027 			throwex(env, "too much SQL parameters");
   3028 			return;
   3029 		    }
   3030 		} else if (*p != '%') {
   3031 		    (*env)->ReleaseStringUTFChars(env, sql, str);
   3032 		    throwex(env, "bad % specification in query");
   3033 		    return;
   3034 		}
   3035 	    }
   3036 	    ++p;
   3037 	}
   3038 	cargv = malloc((sizeof (*argv) + sizeof (char *)) * MAX_PARAMS);
   3039 	if (!cargv) {
   3040 	    (*env)->ReleaseStringUTFChars(env, sql, str);
   3041 	    throwoom(env, "unable to allocate arg vector");
   3042 	    return;
   3043 	}
   3044 	argv = (struct args *) (cargv + MAX_PARAMS);
   3045 	for (i = 0; i < MAX_PARAMS; i++) {
   3046 	    cargv[i] = 0;
   3047 	    argv[i].arg = 0;
   3048 	    argv[i].obj = 0;
   3049 	    argv[i].trans.result = argv[i].trans.tofree = 0;
   3050 	}
   3051 	exc = 0;
   3052 	for (i = 0; i < nargs; i++) {
   3053 	    jobject so = (*env)->GetObjectArrayElement(env, args, i);
   3054 
   3055 	    exc = (*env)->ExceptionOccurred(env);
   3056 	    if (exc) {
   3057 		(*env)->DeleteLocalRef(env, exc);
   3058 		break;
   3059 	    }
   3060 	    if (so) {
   3061 		argv[i].obj = so;
   3062 		argv[i].arg = cargv[i] =
   3063 		    trans2iso(env, 1, 0, argv[i].obj, &argv[i].trans);
   3064 	    }
   3065 	}
   3066 	if (exc) {
   3067 	    for (i = 0; i < nargs; i++) {
   3068 		if (argv[i].obj) {
   3069 		    transfree(&argv[i].trans);
   3070 		}
   3071 	    }
   3072 	    freep((char **) &cargv);
   3073 	    (*env)->ReleaseStringUTFChars(env, sql, str);
   3074 	    return;
   3075 	}
   3076 	h->row1 = 1;
   3077 	trans2iso(env, 1, 0, sql, &sqlstr);
   3078 	exc = (*env)->ExceptionOccurred(env);
   3079 	if (!exc) {
   3080 #if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
   3081 	    char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
   3082 #else
   3083 	    char *s = sqlite3_mprintf(sqlstr.result,
   3084 				      cargv[0], cargv[1],
   3085 				      cargv[2], cargv[3],
   3086 				      cargv[4], cargv[5],
   3087 				      cargv[6], cargv[7],
   3088 				      cargv[8], cargv[9],
   3089 				      cargv[10], cargv[11],
   3090 				      cargv[12], cargv[13],
   3091 				      cargv[14], cargv[15],
   3092 				      cargv[16], cargv[17],
   3093 				      cargv[18], cargv[19],
   3094 				      cargv[20], cargv[21],
   3095 				      cargv[22], cargv[23],
   3096 				      cargv[24], cargv[25],
   3097 				      cargv[26], cargv[27],
   3098 				      cargv[28], cargv[29],
   3099 				      cargv[30], cargv[31]);
   3100 #endif
   3101 	    if (!s) {
   3102 		rc = SQLITE_NOMEM;
   3103 	    } else {
   3104 #if HAVE_SQLITE3_PREPARE_V2
   3105 		rc = sqlite3_prepare_v2((sqlite3 *) h->sqlite, s, -1,
   3106 					(sqlite3_stmt **) &svm, &tail);
   3107 #else
   3108 		rc = sqlite3_prepare((sqlite3 *) h->sqlite, s, -1,
   3109 				      (sqlite3_stmt **) &svm, &tail);
   3110 #endif
   3111 		if (rc != SQLITE_OK) {
   3112 		    if (svm) {
   3113 			sqlite3_finalize((sqlite3_stmt *) svm);
   3114 			svm = 0;
   3115 		    }
   3116 		}
   3117 	    }
   3118 	    if (rc != SQLITE_OK) {
   3119 		sqlite3_free(s);
   3120 		for (i = 0; i < nargs; i++) {
   3121 		    if (argv[i].obj) {
   3122 			transfree(&argv[i].trans);
   3123 		    }
   3124 		}
   3125 		freep((char **) &cargv);
   3126 		transfree(&sqlstr);
   3127 		(*env)->ReleaseStringUTFChars(env, sql, str);
   3128 		setvmerr(env, vm, rc);
   3129 		throwex(env, "error in prepare");
   3130 		return;
   3131 	    }
   3132 	    v = malloc(sizeof (hvm) + strlen(tail) + 1);
   3133 	    if (!v) {
   3134 		sqlite3_free(s);
   3135 		for (i = 0; i < nargs; i++) {
   3136 		    if (argv[i].obj) {
   3137 			transfree(&argv[i].trans);
   3138 		    }
   3139 		}
   3140 		freep((char **) &cargv);
   3141 		transfree(&sqlstr);
   3142 		(*env)->ReleaseStringUTFChars(env, sql, str);
   3143 		sqlite3_finalize((sqlite3_stmt *) svm);
   3144 		setvmerr(env, vm, SQLITE_NOMEM);
   3145 		throwoom(env, "unable to get SQLite handle");
   3146 		return;
   3147 	    }
   3148 	    v->next = h->vms;
   3149 	    h->vms = v;
   3150 	    v->vm = svm;
   3151 	    v->h = h;
   3152 	    v->tail = (char *) (v + 1);
   3153 #if HAVE_BOTH_SQLITE
   3154 	    v->is3 = v->hh.is3 = h->is3;
   3155 #endif
   3156 	    strcpy(v->tail, tail);
   3157 	    sqlite3_free(s);
   3158 	    v->hh.sqlite = 0;
   3159 	    v->hh.haveutf = h->haveutf;
   3160 	    v->hh.ver = h->ver;
   3161 	    v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
   3162 	    v->hh.row1 = 1;
   3163 	    v->hh.enc = h->enc;
   3164 	    v->hh.funcs = 0;
   3165 	    v->hh.vms = 0;
   3166 	    v->hh.env = 0;
   3167 	    vv.j = 0;
   3168 	    vv.l = (jobject) v;
   3169 	    (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
   3170 	}
   3171 	for (i = 0; i < nargs; i++) {
   3172 	    if (argv[i].obj) {
   3173 		transfree(&argv[i].trans);
   3174 	    }
   3175 	}
   3176 	freep((char **) &cargv);
   3177 	transfree(&sqlstr);
   3178 	(*env)->ReleaseStringUTFChars(env, sql, str);
   3179 	if (exc) {
   3180 	    (*env)->DeleteLocalRef(env, exc);
   3181 	}
   3182     }
   3183 #endif
   3184 #else
   3185     throwex(env, "unsupported");
   3186 #endif
   3187 }
   3188 
   3189 JNIEXPORT void JNICALL
   3190 Java_SQLite_FunctionContext_internal_1init(JNIEnv *env, jclass cls)
   3191 {
   3192     F_SQLite_FunctionContext_handle =
   3193 	(*env)->GetFieldID(env, cls, "handle", "J");
   3194 }
   3195 
   3196 JNIEXPORT void JNICALL
   3197 Java_SQLite_Database__1progress_1handler(JNIEnv *env, jobject obj, jint n,
   3198 					 jobject ph)
   3199 {
   3200     handle *h = gethandle(env, obj);
   3201 
   3202     if (h && h->sqlite) {
   3203 	/* CHECK THIS */
   3204 #if HAVE_SQLITE_PROGRESS_HANDLER
   3205 	delglobrefp(env, &h->ph);
   3206 #if HAVE_BOTH_SQLITE
   3207 	if (h->is3) {
   3208 	    if (ph) {
   3209 		globrefset(env, ph, &h->ph);
   3210 		sqlite3_progress_handler((sqlite3 *) h->sqlite,
   3211 					 n, progresshandler, h);
   3212 	    } else {
   3213 		sqlite3_progress_handler((sqlite3 *) h->sqlite,
   3214 					 0, 0, 0);
   3215 	    }
   3216 	} else {
   3217 	    if (ph) {
   3218 		globrefset(env, ph, &h->ph);
   3219 		sqlite_progress_handler((sqlite *) h->sqlite,
   3220 					n, progresshandler, h);
   3221 	    } else {
   3222 		sqlite_progress_handler((sqlite *) h->sqlite,
   3223 					0, 0, 0);
   3224 	    }
   3225 	}
   3226 #else
   3227 #if HAVE_SQLITE2
   3228 	if (ph) {
   3229 	    globrefset(env, ph, &h->ph);
   3230 	    sqlite_progress_handler((sqlite *) h->sqlite,
   3231 				    n, progresshandler, h);
   3232 	} else {
   3233 	    sqlite_progress_handler((sqlite *) h->sqlite,
   3234 				    0, 0, 0);
   3235 	}
   3236 #endif
   3237 #if HAVE_SQLITE3
   3238 	if (ph) {
   3239 	    globrefset(env, ph, &h->ph);
   3240 	    sqlite3_progress_handler((sqlite3 *) h->sqlite,
   3241 				     n, progresshandler, h);
   3242 	} else {
   3243 	    sqlite3_progress_handler((sqlite3 *) h->sqlite,
   3244 				     0, 0, 0);
   3245 	}
   3246 #endif
   3247 #endif
   3248 	return;
   3249 #else
   3250 	throwex(env, "unsupported");
   3251 	return;
   3252 #endif
   3253     }
   3254     throwclosed(env);
   3255 }
   3256 
   3257 JNIEXPORT jboolean JNICALL
   3258 Java_SQLite_Database_is3(JNIEnv *env, jobject obj)
   3259 {
   3260 #if HAVE_BOTH_SQLITE
   3261     handle *h = gethandle(env, obj);
   3262 
   3263     if (h) {
   3264 	return h->is3 ? JNI_TRUE : JNI_FALSE;
   3265     }
   3266     return JNI_FALSE;
   3267 #else
   3268 #if HAVE_SQLITE2
   3269     return JNI_FALSE;
   3270 #endif
   3271 #if HAVE_SQLITE3
   3272     return JNI_TRUE;
   3273 #endif
   3274 #endif
   3275 }
   3276 
   3277 JNIEXPORT jboolean JNICALL
   3278 Java_SQLite_Stmt_prepare(JNIEnv *env, jobject obj)
   3279 {
   3280 #if HAVE_SQLITE3
   3281     hvm *v = gethstmt(env, obj);
   3282     void *svm = 0;
   3283     char *tail;
   3284     int ret;
   3285 
   3286     if (v && v->vm) {
   3287 	sqlite3_finalize((sqlite3_stmt *) v->vm);
   3288 	v->vm = 0;
   3289     }
   3290     if (v && v->h && v->h->sqlite) {
   3291 	if (!v->tail) {
   3292 	    return JNI_FALSE;
   3293 	}
   3294 	v->h->env = env;
   3295 #if HAVE_SQLITE3_PREPARE16_V2
   3296 	ret = sqlite3_prepare16_v2((sqlite3 *) v->h->sqlite,
   3297 				   v->tail, -1, (sqlite3_stmt **) &svm,
   3298 				   (const void **) &tail);
   3299 #else
   3300 	ret = sqlite3_prepare16((sqlite3 *) v->h->sqlite,
   3301 				v->tail, -1, (sqlite3_stmt **) &svm,
   3302 				(const void **) &tail);
   3303 #endif
   3304 	if (ret != SQLITE_OK) {
   3305 	    if (svm) {
   3306 		sqlite3_finalize((sqlite3_stmt *) svm);
   3307 		svm = 0;
   3308 	    }
   3309 	}
   3310 	if (ret != SQLITE_OK) {
   3311 	    const char *err = sqlite3_errmsg(v->h->sqlite);
   3312 
   3313 	    setstmterr(env, obj, ret);
   3314 	    v->tail = 0;
   3315 	    throwex(env, err ? err : "error in compile/prepare");
   3316 	    return JNI_FALSE;
   3317 	}
   3318 	if (!svm) {
   3319 	    v->tail = 0;
   3320 	    return JNI_FALSE;
   3321 	}
   3322 	v->vm = svm;
   3323 	v->tail = (char *) tail;
   3324 	v->hh.row1 = 1;
   3325 	return JNI_TRUE;
   3326     }
   3327     throwex(env, "stmt already closed");
   3328 #else
   3329     throwex(env, "unsupported");
   3330 #endif
   3331     return JNI_FALSE;
   3332 }
   3333 
   3334 JNIEXPORT void JNICALL
   3335 Java_SQLite_Database_stmt_1prepare(JNIEnv *env, jobject obj, jstring sql,
   3336 				   jobject stmt)
   3337 {
   3338 #if HAVE_SQLITE3
   3339     handle *h = gethandle(env, obj);
   3340     void *svm = 0;
   3341     hvm *v;
   3342     jvalue vv;
   3343     jsize len16;
   3344     const jchar *sql16, *tail = 0;
   3345     int ret;
   3346 
   3347     if (!h) {
   3348 	throwclosed(env);
   3349 	return;
   3350     }
   3351     if (!stmt) {
   3352 	throwex(env, "null stmt");
   3353 	return;
   3354     }
   3355     if (!sql) {
   3356 	throwex(env, "null sql");
   3357 	return;
   3358     }
   3359 #ifdef HAVE_BOTH_SQLITE
   3360     if (!h->is3) {
   3361 	throwex(env, "only on SQLite3 database");
   3362 	return;
   3363     }
   3364 #endif
   3365     len16 = (*env)->GetStringLength(env, sql) * sizeof (jchar);
   3366     if (len16 < 1) {
   3367         return;
   3368     }
   3369     h->env = env;
   3370     sql16 = (*env)->GetStringChars(env, sql, 0);
   3371 #if HAVE_SQLITE3_PREPARE16_V2
   3372     ret = sqlite3_prepare16_v2((sqlite3 *) h->sqlite, sql16, len16,
   3373 			       (sqlite3_stmt **) &svm, (const void **) &tail);
   3374 #else
   3375     ret = sqlite3_prepare16((sqlite3 *) h->sqlite, sql16, len16,
   3376 			    (sqlite3_stmt **) &svm, (const void **) &tail);
   3377 #endif
   3378     if (ret != SQLITE_OK) {
   3379 	if (svm) {
   3380 	    sqlite3_finalize((sqlite3_stmt *) svm);
   3381 	    svm = 0;
   3382 	}
   3383     }
   3384     if (ret != SQLITE_OK) {
   3385 	const char *err = sqlite3_errmsg(h->sqlite);
   3386 
   3387         (*env)->ReleaseStringChars(env, sql, sql16);
   3388 	setstmterr(env, stmt, ret);
   3389 	throwex(env, err ? err : "error in prepare");
   3390 	return;
   3391     }
   3392     if (!svm) {
   3393         (*env)->ReleaseStringChars(env, sql, sql16);
   3394 	return;
   3395     }
   3396     len16 = len16 + sizeof (jchar) - ((char *) tail - (char *) sql16);
   3397     if (len16 < (jsize) sizeof (jchar)) {
   3398         len16 = sizeof (jchar);
   3399     }
   3400     v = malloc(sizeof (hvm) + len16);
   3401     if (!v) {
   3402         (*env)->ReleaseStringChars(env, sql, sql16);
   3403 	sqlite3_finalize((sqlite3_stmt *) svm);
   3404 	throwoom(env, "unable to get SQLite handle");
   3405 	return;
   3406     }
   3407     v->next = h->vms;
   3408     h->vms = v;
   3409     v->vm = svm;
   3410     v->h = h;
   3411     v->tail = (char *) (v + 1);
   3412 #if HAVE_BOTH_SQLITE
   3413     v->is3 = v->hh.is3 = 1;
   3414 #endif
   3415     memcpy(v->tail, tail, len16);
   3416     len16 /= sizeof (jchar);
   3417     ((jchar *) v->tail)[len16 - 1] = 0;
   3418     (*env)->ReleaseStringChars(env, sql, sql16);
   3419     v->hh.sqlite = 0;
   3420     v->hh.haveutf = h->haveutf;
   3421     v->hh.ver = h->ver;
   3422     v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
   3423     v->hh.row1 = 1;
   3424     v->hh.enc = h->enc;
   3425     v->hh.funcs = 0;
   3426     v->hh.vms = 0;
   3427     v->hh.env = 0;
   3428     vv.j = 0;
   3429     vv.l = (jobject) v;
   3430     (*env)->SetLongField(env, stmt, F_SQLite_Stmt_handle, vv.j);
   3431 #else
   3432     throwex(env, "unsupported");
   3433 #endif
   3434 }
   3435 
   3436 JNIEXPORT jboolean JNICALL
   3437 Java_SQLite_Stmt_step(JNIEnv *env, jobject obj)
   3438 {
   3439 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3440     hvm *v = gethstmt(env, obj);
   3441 
   3442     if (v && v->vm && v->h) {
   3443 	int ret;
   3444 
   3445 	ret = sqlite3_step((sqlite3_stmt *) v->vm);
   3446 	if (ret == SQLITE_ROW) {
   3447 	    return JNI_TRUE;
   3448 	}
   3449 	if (ret != SQLITE_DONE) {
   3450 	    const char *err = sqlite3_errmsg(v->h->sqlite);
   3451 
   3452 	    setstmterr(env, obj, ret);
   3453 	    throwex(env, err ? err : "error in step");
   3454 	}
   3455 	return JNI_FALSE;
   3456     }
   3457     throwex(env, "stmt already closed");
   3458 #else
   3459     throwex(env, "unsupported");
   3460 #endif
   3461     return JNI_FALSE;
   3462 }
   3463 
   3464 JNIEXPORT void JNICALL
   3465 Java_SQLite_Stmt_close(JNIEnv *env, jobject obj)
   3466 {
   3467 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3468     hvm *v = gethstmt(env, obj);
   3469 
   3470     if (v && v->vm && v->h) {
   3471 	int ret;
   3472 
   3473 	ret = sqlite3_finalize((sqlite3_stmt *) v->vm);
   3474 	v->vm = 0;
   3475 	if (ret != SQLITE_OK) {
   3476 	    const char *err = sqlite3_errmsg(v->h->sqlite);
   3477 
   3478 	    setstmterr(env, obj, ret);
   3479 	    throwex(env, err ? err : "error in close");
   3480 	}
   3481 	return;
   3482     }
   3483     throwex(env, "stmt already closed");
   3484 #else
   3485     throwex(env, "unsupported");
   3486 #endif
   3487     return;
   3488 }
   3489 
   3490 JNIEXPORT void JNICALL
   3491 Java_SQLite_Stmt_reset(JNIEnv *env, jobject obj)
   3492 {
   3493 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3494     hvm *v = gethstmt(env, obj);
   3495 
   3496     if (v && v->vm && v->h) {
   3497 	sqlite3_reset((sqlite3_stmt *) v->vm);
   3498     } else {
   3499 	throwex(env, "stmt already closed");
   3500     }
   3501 #else
   3502     throwex(env, "unsupported");
   3503 #endif
   3504 }
   3505 
   3506 JNIEXPORT void JNICALL
   3507 Java_SQLite_Stmt_clear_1bindings(JNIEnv *env, jobject obj)
   3508 {
   3509 #if HAVE_SQLITE3 && HAVE_SQLITE3_CLEAR_BINDINGS
   3510     hvm *v = gethstmt(env, obj);
   3511 
   3512     if (v && v->vm && v->h) {
   3513 	sqlite3_clear_bindings((sqlite3_stmt *) v->vm);
   3514     } else {
   3515 	throwex(env, "stmt already closed");
   3516     }
   3517 #else
   3518     throwex(env, "unsupported");
   3519 #endif
   3520 }
   3521 
   3522 JNIEXPORT void JNICALL
   3523 Java_SQLite_Stmt_bind__II(JNIEnv *env, jobject obj, jint pos, jint val)
   3524 {
   3525 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3526     hvm *v = gethstmt(env, obj);
   3527 
   3528     if (v && v->vm && v->h) {
   3529 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3530 	int ret;
   3531 
   3532 	if (pos < 1 || pos > npar) {
   3533 	    throwex(env, "parameter position out of bounds");
   3534 	    return;
   3535 	}
   3536 	ret = sqlite3_bind_int((sqlite3_stmt *) v->vm, pos, val);
   3537 	if (ret != SQLITE_OK) {
   3538 	    setstmterr(env, obj, ret);
   3539 	    throwex(env, "bind failed");
   3540 	}
   3541     } else {
   3542         throwex(env, "stmt already closed");
   3543     }
   3544 #else
   3545     throwex(env, "unsupported");
   3546 #endif
   3547 }
   3548 
   3549 JNIEXPORT void JNICALL
   3550 Java_SQLite_Stmt_bind__IJ(JNIEnv *env, jobject obj, jint pos, jlong val)
   3551 {
   3552 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3553     hvm *v = gethstmt(env, obj);
   3554 
   3555     if (v && v->vm && v->h) {
   3556 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3557 	int ret;
   3558 
   3559 	if (pos < 1 || pos > npar) {
   3560 	    throwex(env, "parameter position out of bounds");
   3561 	    return;
   3562 	}
   3563 	ret = sqlite3_bind_int64((sqlite3_stmt *) v->vm, pos, val);
   3564 	if (ret != SQLITE_OK) {
   3565 	    setstmterr(env, obj, ret);
   3566 	    throwex(env, "bind failed");
   3567 	}
   3568     } else {
   3569         throwex(env, "stmt already closed");
   3570     }
   3571 #else
   3572     throwex(env, "unsupported");
   3573 #endif
   3574 }
   3575 
   3576 JNIEXPORT void JNICALL
   3577 Java_SQLite_Stmt_bind__ID(JNIEnv *env, jobject obj, jint pos, jdouble val)
   3578 {
   3579 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3580     hvm *v = gethstmt(env, obj);
   3581 
   3582     if (v && v->vm && v->h) {
   3583 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3584 	int ret;
   3585 
   3586 	if (pos < 1 || pos > npar) {
   3587 	    throwex(env, "parameter position out of bounds");
   3588 	    return;
   3589 	}
   3590 	ret = sqlite3_bind_double((sqlite3_stmt *) v->vm, pos, val);
   3591 	if (ret != SQLITE_OK) {
   3592 	    setstmterr(env, obj, ret);
   3593 	    throwex(env, "bind failed");
   3594 	}
   3595     } else {
   3596         throwex(env, "stmt already closed");
   3597     }
   3598 #else
   3599     throwex(env, "unsupported");
   3600 #endif
   3601 }
   3602 
   3603 JNIEXPORT void JNICALL
   3604 Java_SQLite_Stmt_bind__I_3B(JNIEnv *env, jobject obj, jint pos, jbyteArray val)
   3605 {
   3606 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3607     hvm *v = gethstmt(env, obj);
   3608 
   3609     if (v && v->vm && v->h) {
   3610 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3611 	int ret;
   3612 	jint len;
   3613 	char *data = 0;
   3614 
   3615 	if (pos < 1 || pos > npar) {
   3616 	    throwex(env, "parameter position out of bounds");
   3617 	    return;
   3618 	}
   3619 	if (val) {
   3620 	    len = (*env)->GetArrayLength(env, val);
   3621 	    if (len > 0) {
   3622 	        data = sqlite3_malloc(len);
   3623 		if (!data) {
   3624 		    throwoom(env, "unable to get blob parameter");
   3625 		    return;
   3626 		}
   3627 		(*env)->GetByteArrayRegion(env, val, 0, len, (jbyte *) data);
   3628 		ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm,
   3629 					pos, data, len, sqlite3_free);
   3630 	    } else {
   3631 		ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm,
   3632 					pos, "", 0, SQLITE_STATIC);
   3633 	    }
   3634 	} else {
   3635 	    ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
   3636 	}
   3637 	if (ret != SQLITE_OK) {
   3638 	    if (data) {
   3639 	        sqlite3_free(data);
   3640 	    }
   3641 	    setstmterr(env, obj, ret);
   3642 	    throwex(env, "bind failed");
   3643 	}
   3644     } else {
   3645         throwex(env, "stmt already closed");
   3646     }
   3647 #else
   3648     throwex(env, "unsupported");
   3649 #endif
   3650 }
   3651 
   3652 JNIEXPORT void JNICALL
   3653 Java_SQLite_Stmt_bind__ILjava_lang_String_2(JNIEnv *env, jobject obj,
   3654 					    jint pos, jstring val)
   3655 {
   3656 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3657     hvm *v = gethstmt(env, obj);
   3658 
   3659     if (v && v->vm && v->h) {
   3660 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3661 	int ret;
   3662 	jsize len;
   3663 	char *data = 0;
   3664 
   3665 	if (pos < 1 || pos > npar) {
   3666 	    throwex(env, "parameter position out of bounds");
   3667 	    return;
   3668 	}
   3669 	if (val) {
   3670 	    const jsize charCount = (*env)->GetStringLength(env, val);
   3671 	    len = charCount * sizeof(jchar);
   3672 	    if (len > 0) {
   3673 		data = sqlite3_malloc(len);
   3674 		if (!data) {
   3675 		    throwoom(env, "unable to get blob parameter");
   3676 		    return;
   3677 		}
   3678 
   3679 		(*env)->GetStringRegion(env, val, 0, charCount, (jchar*) data);
   3680 		ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm,
   3681 					  pos, data, len, sqlite3_free);
   3682 	    } else {
   3683 	        ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm, pos, "", 0,
   3684 					  SQLITE_STATIC);
   3685 	    }
   3686 	} else {
   3687 	    ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
   3688 	}
   3689 	if (ret != SQLITE_OK) {
   3690 	    if (data) {
   3691 	        sqlite3_free(data);
   3692 	    }
   3693 	    setstmterr(env, obj, ret);
   3694 	    throwex(env, "bind failed");
   3695 	}
   3696     } else {
   3697         throwex(env, "stmt already closed");
   3698     }
   3699 #else
   3700     throwex(env, "unsupported");
   3701 #endif
   3702 }
   3703 
   3704 JNIEXPORT void JNICALL
   3705 Java_SQLite_Stmt_bind__I(JNIEnv *env, jobject obj, jint pos)
   3706 {
   3707 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3708     hvm *v = gethstmt(env, obj);
   3709 
   3710     if (v && v->vm && v->h) {
   3711 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3712 	int ret;
   3713 
   3714 	if (pos < 1 || pos > npar) {
   3715 	    throwex(env, "parameter position out of bounds");
   3716 	    return;
   3717 	}
   3718 	ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
   3719 	if (ret != SQLITE_OK) {
   3720 	    setstmterr(env, obj, ret);
   3721 	    throwex(env, "bind failed");
   3722 	}
   3723     } else {
   3724         throwex(env, "stmt already closed");
   3725     }
   3726 #else
   3727     throwex(env, "unsupported");
   3728 #endif
   3729 }
   3730 
   3731 JNIEXPORT void JNICALL
   3732 Java_SQLite_Stmt_bind_1zeroblob(JNIEnv *env, jobject obj, jint pos, jint len)
   3733 {
   3734 #if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_ZEROBLOB
   3735     hvm *v = gethstmt(env, obj);
   3736 
   3737     if (v && v->vm && v->h) {
   3738 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3739 	int ret;
   3740 
   3741 	if (pos < 1 || pos > npar) {
   3742 	    throwex(env, "parameter position out of bounds");
   3743 	    return;
   3744 	}
   3745 	ret = sqlite3_bind_zeroblob((sqlite3_stmt *) v->vm, pos, len);
   3746 	if (ret != SQLITE_OK) {
   3747 	    setstmterr(env, obj, ret);
   3748 	    throwex(env, "bind failed");
   3749 	}
   3750     } else {
   3751         throwex(env, "stmt already closed");
   3752     }
   3753 #else
   3754     throwex(env, "unsupported");
   3755 #endif
   3756 }
   3757 
   3758 JNIEXPORT jint JNICALL
   3759 Java_SQLite_Stmt_bind_1parameter_1count(JNIEnv *env, jobject obj)
   3760 {
   3761 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3762     hvm *v = gethstmt(env, obj);
   3763 
   3764     if (v && v->vm && v->h) {
   3765 	return sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3766     }
   3767     throwex(env, "stmt already closed");
   3768 #else
   3769     throwex(env, "unsupported");
   3770 #endif
   3771     return 0;
   3772 }
   3773 
   3774 JNIEXPORT jstring JNICALL
   3775 Java_SQLite_Stmt_bind_1parameter_1name(JNIEnv *env, jobject obj, jint pos)
   3776 {
   3777 #if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_NAME
   3778     hvm *v = gethstmt(env, obj);
   3779 
   3780     if (v && v->vm && v->h) {
   3781 	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
   3782 	const char *name;
   3783 
   3784 	if (pos < 1 || pos > npar) {
   3785 	    throwex(env, "parameter position out of bounds");
   3786 	    return 0;
   3787 	}
   3788 	name = sqlite3_bind_parameter_name((sqlite3_stmt *) v->vm, pos);
   3789 	if (name) {
   3790 	    return (*env)->NewStringUTF(env, name);
   3791 	}
   3792     } else {
   3793         throwex(env, "stmt already closed");
   3794     }
   3795 #else
   3796     throwex(env, "unsupported");
   3797 #endif
   3798     return 0;
   3799 }
   3800 
   3801 JNIEXPORT jint JNICALL
   3802 Java_SQLite_Stmt_bind_1parameter_1index(JNIEnv *env, jobject obj,
   3803 					jstring name)
   3804 {
   3805 #if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_INDEX
   3806     hvm *v = gethstmt(env, obj);
   3807 
   3808     if (v && v->vm && v->h) {
   3809         int pos;
   3810 	const char *n;
   3811 	transstr namestr;
   3812 	jthrowable exc;
   3813 
   3814 	n = trans2iso(env, 1, 0, name, &namestr);
   3815 	exc = (*env)->ExceptionOccurred(env);
   3816 	if (exc) {
   3817 	    (*env)->DeleteLocalRef(env, exc);
   3818 	    return -1;
   3819 	}
   3820         pos = sqlite3_bind_parameter_index((sqlite3_stmt *) v->vm, n);
   3821 	transfree(&namestr);
   3822 	return pos;
   3823     } else {
   3824         throwex(env, "stmt already closed");
   3825     }
   3826 #else
   3827     throwex(env, "unsupported");
   3828 #endif
   3829     return -1;
   3830 }
   3831 
   3832 JNIEXPORT jint JNICALL
   3833 Java_SQLite_Stmt_column_1int(JNIEnv *env, jobject obj, jint col)
   3834 {
   3835 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3836     hvm *v = gethstmt(env, obj);
   3837 
   3838     if (v && v->vm && v->h) {
   3839 	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   3840 
   3841 	if (col < 0 || col >= ncol) {
   3842 	    throwex(env, "column out of bounds");
   3843 	    return 0;
   3844 	}
   3845 	return sqlite3_column_int((sqlite3_stmt *) v->vm, col);
   3846     }
   3847     throwex(env, "stmt already closed");
   3848 #else
   3849     throwex(env, "unsupported");
   3850 #endif
   3851     return 0;
   3852 }
   3853 
   3854 JNIEXPORT jlong JNICALL
   3855 Java_SQLite_Stmt_column_1long(JNIEnv *env, jobject obj, jint col)
   3856 {
   3857 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3858     hvm *v = gethstmt(env, obj);
   3859 
   3860     if (v && v->vm && v->h) {
   3861 	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   3862 
   3863 	if (col < 0 || col >= ncol) {
   3864 	    throwex(env, "column out of bounds");
   3865 	    return 0;
   3866 	}
   3867 	return sqlite3_column_int64((sqlite3_stmt *) v->vm, col);
   3868     }
   3869     throwex(env, "stmt already closed");
   3870 #else
   3871     throwex(env, "unsupported");
   3872 #endif
   3873     return 0;
   3874 }
   3875 
   3876 JNIEXPORT jdouble JNICALL
   3877 Java_SQLite_Stmt_column_1double(JNIEnv *env, jobject obj, jint col)
   3878 {
   3879 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3880     hvm *v = gethstmt(env, obj);
   3881 
   3882     if (v && v->vm && v->h) {
   3883 	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   3884 
   3885 	if (col < 0 || col >= ncol) {
   3886 	    throwex(env, "column out of bounds");
   3887 	    return 0;
   3888 	}
   3889 	return sqlite3_column_double((sqlite3_stmt *) v->vm, col);
   3890     }
   3891     throwex(env, "stmt already closed");
   3892 #else
   3893     throwex(env, "unsupported");
   3894 #endif
   3895     return 0;
   3896 }
   3897 
   3898 JNIEXPORT jbyteArray JNICALL
   3899 Java_SQLite_Stmt_column_1bytes(JNIEnv *env, jobject obj, jint col)
   3900 {
   3901 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3902     hvm *v = gethstmt(env, obj);
   3903 
   3904     if (v && v->vm && v->h) {
   3905 	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   3906 	int nbytes;
   3907 	const jbyte *data;
   3908 	jbyteArray b = 0;
   3909 
   3910 	if (col < 0 || col >= ncol) {
   3911 	    throwex(env, "column out of bounds");
   3912 	    return 0;
   3913 	}
   3914 	data = sqlite3_column_blob((sqlite3_stmt *) v->vm, col);
   3915 	if (data) {
   3916 	    nbytes = sqlite3_column_bytes((sqlite3_stmt *) v->vm, col);
   3917 	} else {
   3918 	    return 0;
   3919 	}
   3920 	b = (*env)->NewByteArray(env, nbytes);
   3921 	if (!b) {
   3922 	    throwoom(env, "unable to get blob column data");
   3923 	    return 0;
   3924 	}
   3925 	(*env)->SetByteArrayRegion(env, b, 0, nbytes, data);
   3926 	return b;
   3927     }
   3928     throwex(env, "stmt already closed");
   3929 #else
   3930     throwex(env, "unsupported");
   3931 #endif
   3932     return 0;
   3933 }
   3934 
   3935 JNIEXPORT jstring JNICALL
   3936 Java_SQLite_Stmt_column_1string(JNIEnv *env, jobject obj, jint col)
   3937 {
   3938 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3939     hvm *v = gethstmt(env, obj);
   3940 
   3941     if (v && v->vm && v->h) {
   3942 	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   3943 	int nbytes;
   3944 	const jchar *data;
   3945 	jstring b = 0;
   3946 
   3947 	if (col < 0 || col >= ncol) {
   3948 	    throwex(env, "column out of bounds");
   3949 	    return 0;
   3950 	}
   3951 	data = sqlite3_column_text16((sqlite3_stmt *) v->vm, col);
   3952 	if (data) {
   3953 	    nbytes = sqlite3_column_bytes16((sqlite3_stmt *) v->vm, col);
   3954 	} else {
   3955 	    return 0;
   3956 	}
   3957 	nbytes /= sizeof (jchar);
   3958 	b = (*env)->NewString(env, data, nbytes);
   3959 	if (!b) {
   3960 	    throwoom(env, "unable to get string column data");
   3961 	    return 0;
   3962 	}
   3963 	return b;
   3964     }
   3965     throwex(env, "stmt already closed");
   3966 #else
   3967     throwex(env, "unsupported");
   3968 #endif
   3969     return 0;
   3970 }
   3971 
   3972 JNIEXPORT jint JNICALL
   3973 Java_SQLite_Stmt_column_1type(JNIEnv *env, jobject obj, jint col)
   3974 {
   3975 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3976     hvm *v = gethstmt(env, obj);
   3977 
   3978     if (v && v->vm && v->h) {
   3979 	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
   3980 
   3981 	if (col < 0 || col >= ncol) {
   3982 	    throwex(env, "column out of bounds");
   3983 	    return 0;
   3984 	}
   3985 	return sqlite3_column_type((sqlite3_stmt *) v->vm, col);
   3986     }
   3987     throwex(env, "stmt already closed");
   3988 #else
   3989     throwex(env, "unsupported");
   3990 #endif
   3991     return 0;
   3992 }
   3993 
   3994 JNIEXPORT jint JNICALL
   3995 Java_SQLite_Stmt_column_1count(JNIEnv *env, jobject obj)
   3996 {
   3997 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   3998     hvm *v = gethstmt(env, obj);
   3999 
   4000     if (v && v->vm && v->h) {
   4001 	return sqlite3_column_count((sqlite3_stmt *) v->vm);
   4002     }
   4003     throwex(env, "stmt already closed");
   4004 #else
   4005     throwex(env, "unsupported");
   4006 #endif
   4007     return 0;
   4008 }
   4009 
   4010 JNIEXPORT jstring JNICALL
   4011 Java_SQLite_Stmt_column_1table_1name(JNIEnv *env, jobject obj, jint col)
   4012 {
   4013 #if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_TABLE_NAME16
   4014     hvm *v = gethstmt(env, obj);
   4015 
   4016     if (v && v->vm && v->h) {
   4017 	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
   4018         const jchar *str;
   4019 
   4020 	if (col < 0 || col >= ncol) {
   4021 	    throwex(env, "column out of bounds");
   4022 	    return 0;
   4023 	}
   4024 	str = sqlite3_column_table_name16((sqlite3_stmt *) v->vm, col);
   4025 	if (str) {
   4026 	    return (*env)->NewString(env, str, jstrlen(str));
   4027 	}
   4028 	return 0;
   4029     }
   4030     throwex(env, "stmt already closed");
   4031 #else
   4032     throwex(env, "unsupported");
   4033 #endif
   4034     return 0;
   4035 }
   4036 
   4037 JNIEXPORT jstring JNICALL
   4038 Java_SQLite_Stmt_column_1database_1name(JNIEnv *env, jobject obj, jint col)
   4039 {
   4040 #if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_DATABASE_NAME16
   4041     hvm *v = gethstmt(env, obj);
   4042 
   4043     if (v && v->vm && v->h) {
   4044 	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
   4045         const jchar *str;
   4046 
   4047 	if (col < 0 || col >= ncol) {
   4048 	    throwex(env, "column out of bounds");
   4049 	    return 0;
   4050 	}
   4051 	str = sqlite3_column_database_name16((sqlite3_stmt *) v->vm, col);
   4052 	if (str) {
   4053 	    return (*env)->NewString(env, str, jstrlen(str));
   4054 	}
   4055 	return 0;
   4056     }
   4057     throwex(env, "stmt already closed");
   4058 #else
   4059     throwex(env, "unsupported");
   4060 #endif
   4061     return 0;
   4062 }
   4063 
   4064 JNIEXPORT jstring JNICALL
   4065 Java_SQLite_Stmt_column_1decltype(JNIEnv *env, jobject obj, jint col)
   4066 {
   4067 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   4068     hvm *v = gethstmt(env, obj);
   4069 
   4070     if (v && v->vm && v->h) {
   4071 	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
   4072         const jchar *str;
   4073 
   4074 	if (col < 0 || col >= ncol) {
   4075 	    throwex(env, "column out of bounds");
   4076 	    return 0;
   4077 	}
   4078 	str = sqlite3_column_decltype16((sqlite3_stmt *) v->vm, col);
   4079 	if (str) {
   4080 	    return (*env)->NewString(env, str, jstrlen(str));
   4081 	}
   4082 	return 0;
   4083     }
   4084     throwex(env, "stmt already closed");
   4085 #else
   4086     throwex(env, "unsupported");
   4087 #endif
   4088     return 0;
   4089 }
   4090 
   4091 JNIEXPORT jstring JNICALL
   4092 Java_SQLite_Stmt_column_1origin_1name(JNIEnv *env, jobject obj, jint col)
   4093 {
   4094 #if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_ORIGIN_NAME16
   4095     hvm *v = gethstmt(env, obj);
   4096 
   4097     if (v && v->vm && v->h) {
   4098 	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
   4099         const jchar *str;
   4100 
   4101 	if (col < 0 || col >= ncol) {
   4102 	    throwex(env, "column out of bounds");
   4103 	    return 0;
   4104 	}
   4105 	str = sqlite3_column_origin_name16((sqlite3_stmt *) v->vm, col);
   4106 	if (str) {
   4107 	    return (*env)->NewString(env, str, jstrlen(str));
   4108 	}
   4109 	return 0;
   4110     }
   4111     throwex(env, "stmt already closed");
   4112 #else
   4113     throwex(env, "unsupported");
   4114 #endif
   4115     return 0;
   4116 }
   4117 
   4118 JNIEXPORT void JNICALL
   4119 Java_SQLite_Stmt_finalize(JNIEnv *env, jobject obj)
   4120 {
   4121 #if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
   4122     dostmtfinal(env, obj);
   4123 #endif
   4124 }
   4125 
   4126 JNIEXPORT void JNICALL
   4127 Java_SQLite_Database__1open_1blob(JNIEnv *env, jobject obj,
   4128 				  jstring dbname, jstring table,
   4129 				  jstring column, jlong row,
   4130 				  jboolean rw, jobject blobj)
   4131 {
   4132 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
   4133     handle *h = gethandle(env, obj);
   4134     hbl *bl;
   4135     jthrowable exc;
   4136     transstr dbn, tbl, col;
   4137     sqlite3_blob *blob;
   4138     jvalue vv;
   4139     int ret;
   4140 
   4141     if (!blobj) {
   4142 	throwex(env, "null blob");
   4143 	return;
   4144     }
   4145     if (h && h->sqlite) {
   4146         trans2iso(env, h->haveutf, h->enc, dbname, &dbn);
   4147 	exc = (*env)->ExceptionOccurred(env);
   4148 	if (exc) {
   4149 	    (*env)->DeleteLocalRef(env, exc);
   4150 	    return;
   4151 	}
   4152         trans2iso(env, h->haveutf, h->enc, table, &tbl);
   4153 	exc = (*env)->ExceptionOccurred(env);
   4154 	if (exc) {
   4155 	    transfree(&dbn);
   4156 	    (*env)->DeleteLocalRef(env, exc);
   4157 	    return;
   4158 	}
   4159         trans2iso(env, h->haveutf, h->enc, column, &col);
   4160 	exc = (*env)->ExceptionOccurred(env);
   4161 	if (exc) {
   4162 	    transfree(&tbl);
   4163 	    transfree(&dbn);
   4164 	    (*env)->DeleteLocalRef(env, exc);
   4165 	    return;
   4166 	}
   4167 	ret = sqlite3_blob_open(h->sqlite,
   4168 				dbn.result, tbl.result, col.result,
   4169 				row, rw, &blob);
   4170 	transfree(&col);
   4171 	transfree(&tbl);
   4172 	transfree(&dbn);
   4173 	if (ret != SQLITE_OK) {
   4174 	    const char *err = sqlite3_errmsg(h->sqlite);
   4175 
   4176 	    seterr(env, obj, ret);
   4177 	    throwex(env, err ? err : "error in blob open");
   4178 	    return;
   4179 	}
   4180 	bl = malloc(sizeof (hbl));
   4181 	if (!bl) {
   4182 	    sqlite3_blob_close(blob);
   4183 	    throwoom(env, "unable to get SQLite blob handle");
   4184 	    return;
   4185 	}
   4186 	bl->next = h->blobs;
   4187 	h->blobs = bl;
   4188 	bl->blob = blob;
   4189 	bl->h = h;
   4190 	vv.j = 0;
   4191 	vv.l = (jobject) bl;
   4192 	(*env)->SetLongField(env, blobj, F_SQLite_Blob_handle, vv.j);
   4193 	(*env)->SetIntField(env, blobj, F_SQLite_Blob_size,
   4194 			    sqlite3_blob_bytes(blob));
   4195 	return;
   4196     }
   4197     throwex(env, "not an open database");
   4198 #else
   4199     throwex(env, "unsupported");
   4200 #endif
   4201 }
   4202 
   4203 JNIEXPORT jint JNICALL
   4204 Java_SQLite_Blob_write(JNIEnv *env , jobject obj, jbyteArray b, jint off,
   4205 		       jint pos, jint len)
   4206 {
   4207 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
   4208     hbl *bl = gethbl(env, obj);
   4209 
   4210     if (bl && bl->h && bl->blob) {
   4211         jbyte *buf;
   4212 	jthrowable exc;
   4213 	int ret;
   4214 
   4215 	if (len <= 0) {
   4216 	    return 0;
   4217 	}
   4218 	buf = malloc(len);
   4219 	if (!buf) {
   4220 	    throwoom(env, "out of buffer space for blob");
   4221 	    return 0;
   4222 	}
   4223 	(*env)->GetByteArrayRegion(env, b, off, len, buf);
   4224 	exc = (*env)->ExceptionOccurred(env);
   4225 	if (exc) {
   4226 	    free(buf);
   4227 	    return 0;
   4228 	}
   4229 	ret = sqlite3_blob_write(bl->blob, buf, len, pos);
   4230 	free(buf);
   4231 	if (ret != SQLITE_OK) {
   4232 	    throwioex(env, "blob write error");
   4233 	    return 0;
   4234 	}
   4235 	return len;
   4236     }
   4237     throwex(env, "blob already closed");
   4238 #else
   4239     throwex(env, "unsupported");
   4240 #endif
   4241     return 0;
   4242 }
   4243 
   4244 JNIEXPORT jint JNICALL
   4245 Java_SQLite_Blob_read(JNIEnv *env , jobject obj, jbyteArray b, jint off,
   4246 		      jint pos, jint len)
   4247 {
   4248 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
   4249     hbl *bl = gethbl(env, obj);
   4250 
   4251     if (bl && bl->h && bl->blob) {
   4252         jbyte *buf;
   4253 	jthrowable exc;
   4254 	int ret;
   4255 
   4256 	if (len <= 0) {
   4257 	    return 0;
   4258 	}
   4259 	buf = malloc(len);
   4260 	if (!buf) {
   4261 	    throwoom(env, "out of buffer space for blob");
   4262 	    return 0;
   4263 	}
   4264 	ret = sqlite3_blob_read(bl->blob, buf, len, pos);
   4265 	if (ret != SQLITE_OK) {
   4266 	    free(buf);
   4267 	    throwioex(env, "blob read error");
   4268 	    return 0;
   4269 	}
   4270 	(*env)->SetByteArrayRegion(env, b, off, len, buf);
   4271 	free(buf);
   4272 	exc = (*env)->ExceptionOccurred(env);
   4273 	if (exc) {
   4274 	    return 0;
   4275 	}
   4276 	return len;
   4277     }
   4278     throwex(env, "blob already closed");
   4279 #else
   4280     throwex(env, "unsupported");
   4281 #endif
   4282     return 0;
   4283 }
   4284 
   4285 JNIEXPORT void JNICALL
   4286 Java_SQLite_Blob_close(JNIEnv *env, jobject obj)
   4287 {
   4288 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
   4289     doblobfinal(env, obj);
   4290 #endif
   4291 }
   4292 
   4293 JNIEXPORT void JNICALL
   4294 Java_SQLite_Blob_finalize(JNIEnv *env, jobject obj)
   4295 {
   4296 #if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
   4297     doblobfinal(env, obj);
   4298 #endif
   4299 }
   4300 
   4301 JNIEXPORT void JNICALL
   4302 Java_SQLite_Stmt_internal_1init(JNIEnv *env, jclass cls)
   4303 {
   4304     F_SQLite_Stmt_handle =
   4305 	(*env)->GetFieldID(env, cls, "handle", "J");
   4306     F_SQLite_Stmt_error_code =
   4307 	(*env)->GetFieldID(env, cls, "error_code", "I");
   4308 }
   4309 
   4310 JNIEXPORT void JNICALL
   4311 Java_SQLite_Vm_internal_1init(JNIEnv *env, jclass cls)
   4312 {
   4313     F_SQLite_Vm_handle =
   4314 	(*env)->GetFieldID(env, cls, "handle", "J");
   4315     F_SQLite_Vm_error_code =
   4316 	(*env)->GetFieldID(env, cls, "error_code", "I");
   4317 }
   4318 
   4319 JNIEXPORT void JNICALL
   4320 Java_SQLite_Blob_internal_1init(JNIEnv *env, jclass cls)
   4321 {
   4322     F_SQLite_Blob_handle =
   4323 	(*env)->GetFieldID(env, cls, "handle", "J");
   4324     F_SQLite_Blob_size =
   4325 	(*env)->GetFieldID(env, cls, "size", "I");
   4326 }
   4327 
   4328 JNIEXPORT void JNICALL
   4329 Java_SQLite_Database_internal_1init(JNIEnv *env, jclass cls)
   4330 {
   4331 //#ifndef JNI_VERSION_1_2
   4332     jclass jls = (*env)->FindClass(env, "java/lang/String");
   4333 
   4334     C_java_lang_String = (*env)->NewGlobalRef(env, jls);
   4335 //#endif
   4336     F_SQLite_Database_handle =
   4337 	(*env)->GetFieldID(env, cls, "handle", "J");
   4338     F_SQLite_Database_error_code =
   4339 	(*env)->GetFieldID(env, cls, "error_code", "I");
   4340     M_java_lang_String_getBytes =
   4341 	(*env)->GetMethodID(env, C_java_lang_String, "getBytes", "()[B");
   4342     M_java_lang_String_getBytes2 =
   4343 	(*env)->GetMethodID(env, C_java_lang_String, "getBytes",
   4344 			    "(Ljava/lang/String;)[B");
   4345     M_java_lang_String_initBytes =
   4346 	(*env)->GetMethodID(env, C_java_lang_String, "<init>", "([B)V");
   4347     M_java_lang_String_initBytes2 =
   4348 	(*env)->GetMethodID(env, C_java_lang_String, "<init>",
   4349 			    "([BLjava/lang/String;)V");
   4350 }
   4351 
   4352 #ifdef JNI_VERSION_1_2
   4353 JNIEXPORT jint JNICALL
   4354 JNI_OnLoad(JavaVM *vm, void *reserved)
   4355 {
   4356     JNIEnv *env;
   4357     jclass cls;
   4358 
   4359 #ifndef _WIN32
   4360 #if HAVE_SQLITE2
   4361     if (strcmp(sqlite_libencoding(), "UTF-8") != 0) {
   4362 	fprintf(stderr, "WARNING: using non-UTF SQLite2 engine\n");
   4363     }
   4364 #endif
   4365 #endif
   4366     if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
   4367 	return JNI_ERR;
   4368     }
   4369     cls = (*env)->FindClass(env, "java/lang/String");
   4370     if (!cls) {
   4371 	return JNI_ERR;
   4372     }
   4373     C_java_lang_String = (*env)->NewWeakGlobalRef(env, cls);
   4374     return JNI_VERSION_1_2;
   4375 }
   4376 
   4377 JNIEXPORT void JNICALL
   4378 JNI_OnUnload(JavaVM *vm, void *reserved)
   4379 {
   4380     JNIEnv *env;
   4381 
   4382     if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
   4383 	return;
   4384     }
   4385     if (C_java_lang_String) {
   4386 	(*env)->DeleteWeakGlobalRef(env, C_java_lang_String);
   4387 	C_java_lang_String = 0;
   4388     }
   4389 }
   4390 #endif
   4391