1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Remove doc outdated warning about sqlite3_trace_v2() JNI binding being incompatible with MUTF-8. Use new to-string capability to simplify Fts5ExtensionApi::xColumnText() JNI binding.

FossilOrigin-Name: ebcfc2379be12f76a96f3605b734f406b3354d4c985062cdbfca0cf7e3f31379
This commit is contained in:
stephan
2023-08-06 11:05:17 +00:00
parent 57645b67fa
commit 6a9364a518
7 changed files with 43 additions and 76 deletions

View File

@ -1075,11 +1075,13 @@ static int udf_setAggregateContext(JNIEnv * env, jobject jCx,
stores it in pFieldId. Fails fatally if the property is not found,
as that presents a serious internal misuse.
Property lookups are cached on a per-class basis.
Property lookups are cached on a per-zClassName basis. Do not use
this routine with the same zClassName but different zTypeSig: it
will misbehave.
*/
static void setupOutputPointer(JNIEnv * env, const char *zClassName,
const char *zTypeSig,
jobject jOut, jfieldID * pFieldId){
static void setupOutputPointer(JNIEnv * const env, const char *zClassName,
const char * const zTypeSig,
jobject const jOut, jfieldID * const pFieldId){
jfieldID setter = 0;
struct NphCacheLine * const cacheLine =
S3Global_nph_cache(env, zClassName);
@ -1087,6 +1089,7 @@ static void setupOutputPointer(JNIEnv * env, const char *zClassName,
setter = cacheLine->fidValue;
}else{
const jclass klazz = (*env)->GetObjectClass(env, jOut);
//MARKER(("%s => %s\n", zClassName, zTypeSig));
setter = (*env)->GetFieldID(env, klazz, "value", zTypeSig);
EXCEPTION_IS_FATAL("setupOutputPointer() could not find OutputPointer.*.value");
if(cacheLine){
@ -1099,7 +1102,7 @@ static void setupOutputPointer(JNIEnv * env, const char *zClassName,
/* Sets the value property of the OutputPointer.Int32 jOut object
to v. */
static void setOutputInt32(JNIEnv * env, jobject jOut, int v){
static void setOutputInt32(JNIEnv * const env, jobject const jOut, int v){
jfieldID setter = 0;
setupOutputPointer(env, S3ClassNames.OutputPointer_Int32, "I", jOut, &setter);
(*env)->SetIntField(env, jOut, setter, (jint)v);
@ -1109,40 +1112,34 @@ static void setOutputInt32(JNIEnv * env, jobject jOut, int v){
#ifdef SQLITE_ENABLE_FTS5
/* Sets the value property of the OutputPointer.Int64 jOut object
to v. */
static void setOutputInt64(JNIEnv * env, jobject jOut, jlong v){
static void setOutputInt64(JNIEnv * const env, jobject const jOut, jlong v){
jfieldID setter = 0;
setupOutputPointer(env, S3ClassNames.OutputPointer_Int64, "J", jOut, &setter);
(*env)->SetLongField(env, jOut, setter, v);
EXCEPTION_IS_FATAL("Cannot set OutputPointer.Int64.value");
}
#if 0
/* Sets the value property of the OutputPointer.ByteArray jOut object
to v. */
static void setOutputByteArray(JNIEnv * env, jobject jOut, jbyteArray v){
static void setOutputByteArray(JNIEnv * const env, jobject const jOut,
jbyteArray const v){
jfieldID setter = 0;
setupOutputPointer(env, S3ClassNames.OutputPointer_ByteArray, "[B",
jOut, &setter);
(*env)->SetObjectField(env, jOut, setter, v);
EXCEPTION_IS_FATAL("Cannot set OutputPointer.ByteArray.value");
}
#if 0
#endif
/* Sets the value property of the OutputPointer.String jOut object
to v. */
static void setOutputString(JNIEnv * env, jobject jOut, jstring v){
static void setOutputString(JNIEnv * const env, jobject const jOut,
jstring const v){
jfieldID setter = 0;
setupOutputPointer(env, S3ClassNames.OutputPointer_String, "Ljava/lang/String",
jOut, &setter);
setupOutputPointer(env, S3ClassNames.OutputPointer_String,
"Ljava/lang/String;", jOut, &setter);
(*env)->SetObjectField(env, jOut, setter, v);
EXCEPTION_IS_FATAL("Cannot set OutputPointer.String.value");
}
//! Bad: uses MUTF-8 encoding.
static void setOutputString2(JNIEnv * env, jobject jOut, const char * zStr){
jstring const jStr = (*env)->NewStringUTF(env, zStr);
if(jStr){
setOutputString(env, jOut, jStr);
UNREF_L(jStr);
}
}
#endif
#endif /* SQLITE_ENABLE_FTS5 */
static int encodingTypeIsValid(int eTextRep){
@ -3027,32 +3024,22 @@ JDECLFtsXA(jint,xColumnSize)(JENV_JSELF,jobject jCtx, jint iIdx, jobject jOut32)
}
JDECLFtsXA(jint,xColumnText)(JENV_JSELF,jobject jCtx, jint iCol,
jobject jOutBA){
jobject jOut){
Fts5ExtDecl;
const char *pz = 0;
int pn = 0;
int rc = fext->xColumnText(PtrGet_Fts5Context(jCtx), (int)iCol,
&pz, &pn);
if( 0==rc ){
/* Two problems here:
1) JNI doesn't give us a way to create strings from standard
UTF-8. We're converting the results to MUTF-8, which may
differ for exotic text.
2) JNI's NewStringUTF() (which treats its input as MUTF-8) does
not take a _length_ - it requires the string to be
NUL-terminated, which may not the case here.
So we use a byte array and convert it to UTF-8 Java-side.
*/
jbyteArray const jba = (*env)->NewByteArray(env, (jint)pn);
if( jba ){
(*env)->SetByteArrayRegion(env, jba, 0, (jint)pn, (const jbyte*)pz);
setOutputByteArray(env, jOutBA, jba);
UNREF_L(jba)/*jOutBA has a reference*/;
}else{
rc = SQLITE_NOMEM;
JNIEnvCacheLine * const jc = S3Global_JNIEnvCache_cache(env);
jstring jstr = pz ? s3jni_string_from_utf8(jc, pz, pn) : 0;
if( pz ){
if( jstr ){
setOutputString(env, jOut, jstr);
UNREF_L(jstr)/*jOut has a reference*/;
}else{
rc = SQLITE_NOMEM;
}
}
}
return (jint)rc;

View File

@ -1675,7 +1675,7 @@ JNIEXPORT jint JNICALL Java_org_sqlite_jni_Fts5ExtensionApi_xColumnSize
/*
* Class: org_sqlite_jni_Fts5ExtensionApi
* Method: xColumnText
* Signature: (Lorg/sqlite/jni/Fts5Context;ILorg/sqlite/jni/OutputPointer/ByteArray;)I
* Signature: (Lorg/sqlite/jni/Fts5Context;ILorg/sqlite/jni/OutputPointer/String;)I
*/
JNIEXPORT jint JNICALL Java_org_sqlite_jni_Fts5ExtensionApi_xColumnText
(JNIEnv *, jobject, jobject, jint, jobject);

View File

@ -40,20 +40,7 @@ public final class Fts5ExtensionApi extends NativePointerHolder<Fts5ExtensionApi
public native int xColumnSize(@NotNull Fts5Context cx, int iCol,
@NotNull OutputPointer.Int32 pnToken);
public native int xColumnText(@NotNull Fts5Context cx, int iCol,
@NotNull OutputPointer.ByteArray txt);
/**
Convenience overload which converts the output byte array
to a UTF-8 string.
*/
public int xColumnText(@NotNull Fts5Context cx, int iCol,
@NotNull OutputPointer.String txt){
final OutputPointer.ByteArray out = new OutputPointer.ByteArray();
int rc = xColumnText(cx, iCol, out);
if( 0 == rc ){
txt.setValue( new String(out.getValue(), StandardCharsets.UTF_8) );
}
return rc;
}
@NotNull OutputPointer.String txt);
public native int xColumnTotalSize(@NotNull Fts5Context fcx, int iCol,
@NotNull OutputPointer.Int64 pnToken);
public native Object xGetAuxdata(@NotNull Fts5Context cx, boolean clearIt);

View File

@ -47,10 +47,10 @@ public final class OutputPointer {
}
public static final class ByteArray {
private byte value[];
private byte[] value;
public ByteArray(){this(null);}
public ByteArray(byte v[]){value = v;}
public ByteArray(byte[] v){value = v;}
public final byte[] getValue(){return value;}
public final void setValue(byte v[]){value = v;}
public final void setValue(byte[] v){value = v;}
}
}

View File

@ -94,13 +94,6 @@ import java.lang.annotation.ElementType;
APIs will mis-translate them on their way between languages
(possibly leading to a crash).
- sqlite3_trace_v2() is also currently affected by this, in that
it requires that traced SQL statements be compatible with
MUTF-8. The alternative would be to perform two extra layers of
conversion for that performance-sensitive function: one from
UTF-8 to a byte-array before passing the data from C to Java,
and then from byte-array to String in the tracer implementation.
- C functions which take C-style strings without a length argument
require special care when taking input from Java. In particular,
Java strings converted to byte arrays for encoding purposes are