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