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