1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Do not pre-allocate sqlite3_aggregate_context() for Java UDFs, as it unduly complicates UDF initialization.

FossilOrigin-Name: e8308f0c6ec2d8999c8a2502fb130cb3501ba326f23f71f2cd8d452debae79b5
This commit is contained in:
stephan
2023-08-24 21:31:56 +00:00
parent 36018803d6
commit 0f0bf3ff9e
9 changed files with 118 additions and 107 deletions

View File

@@ -288,7 +288,7 @@ jar: $(package.jar)
dir.doc := $(dir.jni)/doc dir.doc := $(dir.jni)/doc
doc: $(JAVA_FILES.main) doc: $(JAVA_FILES.main)
$(bin.javadoc) -cp $(classpath) -d $(dir.doc) org.sqlite.jni $(bin.javadoc) -cp $(classpath) -d $(dir.doc) -quiet org.sqlite.jni
######################################################################## ########################################################################
# Clean up... # Clean up...

View File

@@ -1164,49 +1164,6 @@ static int S3JniAutoExtension_init(JNIEnv *const env,
return 0; return 0;
} }
/*
** Requires that jCx be a Java-side sqlite3_context wrapper for pCx.
** This function calls sqlite3_aggregate_context() to allocate a tiny
** sliver of memory, the address of which is set in
** jCx->aggregateContext. The memory is only used as a key for
** mapping client-side results of aggregate result sets across
** calls to the UDF's callbacks.
**
** isFinal must be 1 for xFinal() calls and 0 for all others, the
** difference being that the xFinal() invocation will not allocate
** new memory if it was not already, resulting in a value of 0
** for jCx->aggregateContext.
**
** Returns 0 on success. Returns SQLITE_NOMEM on allocation error,
** noting that it will not allocate when isFinal is true. It returns
** SQLITE_ERROR if there's a serious internal error in dealing with
** the JNI state.
*/
static int udf_setAggregateContext(JNIEnv * env, jobject jCx,
sqlite3_context * pCx,
int isFinal){
void * pAgg;
int rc = 0;
S3JniNphClass * const pNC =
S3JniGlobal_nph_cache(env, &S3NphRefs.sqlite3_context);
if( !pNC->fidAggCtx ){
S3JniMutex_Nph_enter;
if( !pNC->fidAggCtx ){
pNC->fidAggCtx = (*env)->GetFieldID(env, pNC->klazz, "aggregateContext", "J");
EXCEPTION_IS_FATAL("Cannot get sqlite3_contex.aggregateContext member.");
}
S3JniMutex_Nph_leave;
}
pAgg = sqlite3_aggregate_context(pCx, isFinal ? 0 : sizeof(void*));
if( pAgg || isFinal ){
(*env)->SetLongField(env, jCx, pNC->fidAggCtx, (jlong)pAgg);
}else{
assert(!pAgg);
rc = SQLITE_NOMEM;
}
return rc;
}
/* /*
** Common init for OutputPointer_set_Int32() and friends. pRef must be ** Common init for OutputPointer_set_Int32() and friends. pRef must be
** a pointer from S3NphRefs. jOut must be an instance of that ** a pointer from S3NphRefs. jOut must be an instance of that
@@ -1628,6 +1585,7 @@ static int udf_report_exception(JNIEnv * const env, int translateToErr,
(*env)->ExceptionDescribe( env ); (*env)->ExceptionDescribe( env );
S3JniExceptionClear; S3JniExceptionClear;
} }
UNREF_L(ex);
return rc; return rc;
} }
@@ -1645,10 +1603,6 @@ static int udf_xFSI(sqlite3_context* const pCx, int argc,
int rc = udf_args(env, pCx, argc, argv, &args.jcx, &args.jargv); int rc = udf_args(env, pCx, argc, argv, &args.jcx, &args.jargv);
//MARKER(("UDF::%s.%s()\n", s->zFuncName, zFuncType)); //MARKER(("UDF::%s.%s()\n", s->zFuncName, zFuncType));
if( rc ) return rc;
if( UDF_SCALAR != s->type ){
rc = udf_setAggregateContext(env, args.jcx, pCx, 0);
}
if( 0 == rc ){ if( 0 == rc ){
(*env)->CallVoidMethod(env, s->jObj, xMethodID, args.jcx, args.jargv); (*env)->CallVoidMethod(env, s->jObj, xMethodID, args.jcx, args.jargv);
S3JniIfThrew{ S3JniIfThrew{
@@ -1678,15 +1632,10 @@ static int udf_xFV(sqlite3_context* cx, S3JniUdf * s,
return SQLITE_NOMEM; return SQLITE_NOMEM;
} }
//MARKER(("UDF::%s.%s()\n", s->zFuncName, zFuncType)); //MARKER(("UDF::%s.%s()\n", s->zFuncName, zFuncType));
if( UDF_SCALAR != s->type ){ (*env)->CallVoidMethod(env, s->jObj, xMethodID, jcx);
rc = udf_setAggregateContext(env, jcx, cx, isFinal); S3JniIfThrew{
} rc = udf_report_exception(env, isFinal, cx, s->zFuncName,
if( 0 == rc ){ zFuncType);
(*env)->CallVoidMethod(env, s->jObj, xMethodID, jcx);
S3JniIfThrew{
rc = udf_report_exception(env, isFinal, cx, s->zFuncName,
zFuncType);
}
} }
UNREF_L(jcx); UNREF_L(jcx);
return rc; return rc;
@@ -1834,6 +1783,20 @@ WRAP_INT_SVALUE(1value_1type, sqlite3_value_type)
#undef WRAP_MUTF8_VOID #undef WRAP_MUTF8_VOID
#undef WRAP_STR_STMT_INT #undef WRAP_STR_STMT_INT
S3JniApi(sqlite3_aggregate_context(),jlong,1aggregate_1context)(
JniArgsEnvClass, jobject jCx, jboolean initialize
){
sqlite3_context * const pCx = PtrGet_sqlite3_context(jCx);
void * const p = pCx
? sqlite3_aggregate_context(pCx, (int)(initialize
? (int)sizeof(void*)
: 0))
: 0;
return (jlong)p / sizeof(void*);
}
/* Central auto-extension handler. */ /* Central auto-extension handler. */
static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr, static int s3jni_run_java_auto_extensions(sqlite3 *pDb, const char **pzErr,
const struct sqlite3_api_routines *ignored){ const struct sqlite3_api_routines *ignored){

View File

@@ -771,6 +771,14 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_init
JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_SQLite3Jni_uncacheJniEnv JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_SQLite3Jni_uncacheJniEnv
(JNIEnv *, jclass); (JNIEnv *, jclass);
/*
* Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_aggregate_context
* Signature: (Lorg/sqlite/jni/sqlite3_context;Z)J
*/
JNIEXPORT jlong JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1aggregate_1context
(JNIEnv *, jclass, jobject, jboolean);
/* /*
* Class: org_sqlite_jni_SQLite3Jni * Class: org_sqlite_jni_SQLite3Jni
* Method: sqlite3_auto_extension * Method: sqlite3_auto_extension

View File

@@ -55,6 +55,9 @@ public abstract class SQLFunction {
Client UDFs are free to perform such mappings using custom Client UDFs are free to perform such mappings using custom
approaches. The provided Aggregate<T> and Window<T> classes approaches. The provided Aggregate<T> and Window<T> classes
use this. use this.
<p>T must be of a type which can be legally stored as a value in
java.util.HashMap<KeyType,T>.
*/ */
public static final class PerContextState<T> { public static final class PerContextState<T> {
private final java.util.Map<Long,ValueHolder<T>> map private final java.util.Map<Long,ValueHolder<T>> map
@@ -64,20 +67,20 @@ public abstract class SQLFunction {
Should be called from a UDF's xStep(), xValue(), and xInverse() Should be called from a UDF's xStep(), xValue(), and xInverse()
methods, passing it that method's first argument and an initial methods, passing it that method's first argument and an initial
value for the persistent state. If there is currently no value for the persistent state. If there is currently no
mapping for cx.getAggregateContext() within the map, one is mapping for the given context within the map, one is created
created using the given initial value, else the existing one is using the given initial value, else the existing one is used
used and the 2nd argument is ignored. It returns a and the 2nd argument is ignored. It returns a ValueHolder<T>
ValueHolder<T> which can be used to modify that state directly which can be used to modify that state directly without
without requiring that the client update the underlying map's requiring that the client update the underlying map's entry.
entry.
<p>T must be of a type which can be legally stored as a value in <p>The caller is obligated to eventually call
java.util.HashMap<KeyType,T>. takeAggregateState() to clear the mapping.
*/ */
public ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){ public ValueHolder<T> getAggregateState(sqlite3_context cx, T initialValue){
ValueHolder<T> rc = map.get(cx.getAggregateContext()); final Long key = cx.getAggregateContext(true);
if(null == rc){ ValueHolder<T> rc = null==key ? null : map.get(key);
map.put(cx.getAggregateContext(), rc = new ValueHolder<>(initialValue)); if( null==rc ){
map.put(key, rc = new ValueHolder<>(initialValue));
} }
return rc; return rc;
} }
@@ -92,7 +95,7 @@ public abstract class SQLFunction {
rows. rows.
*/ */
public T takeAggregateState(sqlite3_context cx){ public T takeAggregateState(sqlite3_context cx){
final ValueHolder<T> h = map.remove(cx.getAggregateContext()); final ValueHolder<T> h = map.remove(cx.getAggregateContext(false));
return null==h ? null : h.value; return null==h ? null : h.value;
} }
} }

View File

@@ -126,19 +126,19 @@ public final class SQLite3Jni {
This will clean up any cached per-JNIEnv info. Calling into the This will clean up any cached per-JNIEnv info. Calling into the
library will re-initialize the cache on demand. library will re-initialize the cache on demand.
This process does not close any databases or finalize <p>This process does not close any databases or finalize
any prepared statements because their ownership does not depend on any prepared statements because their ownership does not depend on
a given thread. For proper library behavior, and to a given thread. For proper library behavior, and to
avoid C-side leaks, be sure to finalize all statements and close avoid C-side leaks, be sure to finalize all statements and close
all databases before calling this function. all databases before calling this function.
Calling this from the main application thread is not strictly <p>Calling this from the main application thread is not strictly
required but is "polite." Additional threads must call this required but is "polite." Additional threads must call this
before ending or they will leak cache entries in the C heap, before ending or they will leak cache entries in the C heap,
which in turn may keep numerous Java-side global references which in turn may keep numerous Java-side global references
active. active.
This routine returns false without side effects if the current <p>This routine returns false without side effects if the current
JNIEnv is not cached, else returns true, but this information is JNIEnv is not cached, else returns true, but this information is
primarily for testing of the JNI bindings and is not information primarily for testing of the JNI bindings and is not information
which client-level code should use to make any informed which client-level code should use to make any informed
@@ -151,22 +151,42 @@ public final class SQLite3Jni {
// alphabetized. The SQLITE_... values. on the other hand, are // alphabetized. The SQLITE_... values. on the other hand, are
// grouped by category. // grouped by category.
/**
Functions exactly like the native form except that (A) the
returned value is only intended for use as a lookup key in a
higher-level data structure and (B) the 2nd argument is a boolean
instead of an int. If passed true, it will attempt to allocate
enough memory to use as a UDF-call-local context key. If passed
false it will not allocate any memory.
<p>It is only valid for the life of the current UDF method call
and must not be retained for later use. The return value 0
indicates an allocation error unless initialize is false, in
which case it means that the given context was never passed to
this function with a true second argument so never had to
allocate.
<p>For the JNI wrapping, the value of sz is provided for API
consistency but it is ignored unless it's 0. Results are
undefined if the value is negative.
*/
public static native long sqlite3_aggregate_context(sqlite3_context cx, boolean initialize);
/** /**
Functions almost as documented for the C API, with these Functions almost as documented for the C API, with these
exceptions: exceptions:
- The callback interface is is shorter because of cross-language <p>- The callback interface is is shorter because of
differences. Specifically, 3rd argument to the C auto-extension cross-language differences. Specifically, 3rd argument to the C
callback interface is unnecessary here. auto-extension callback interface is unnecessary here.
The C API docs do not specifically say so, if the list of <p>The C API docs do not specifically say so, but if the list of
auto-extensions is manipulated from an auto-extension, it is auto-extensions is manipulated from an auto-extension, it is
undefined which, if any, auto-extensions will subsequently undefined which, if any, auto-extensions will subsequently
execute for the current database. execute for the current database.
See the AutoExtension class docs for more information. <p>See the AutoExtension class docs for more information.
*/ */
public static native int sqlite3_auto_extension(@NotNull AutoExtension callback); public static native int sqlite3_auto_extension(@NotNull AutoExtension callback);

View File

@@ -723,7 +723,9 @@ public class Tester1 implements Runnable {
SQLFunction func = new SQLFunction.Aggregate<Integer>(){ SQLFunction func = new SQLFunction.Aggregate<Integer>(){
@Override @Override
public void xStep(sqlite3_context cx, sqlite3_value[] args){ public void xStep(sqlite3_context cx, sqlite3_value[] args){
this.getAggregateState(cx, 0).value += sqlite3_value_int(args[0]); final ValueHolder<Integer> agg = this.getAggregateState(cx, 0);
agg.value += sqlite3_value_int(args[0]);
affirm( agg == this.getAggregateState(cx, 0) );
} }
@Override @Override
public void xFinal(sqlite3_context cx){ public void xFinal(sqlite3_context cx){
@@ -740,15 +742,19 @@ public class Tester1 implements Runnable {
int rc = sqlite3_create_function(db, "myfunc", 1, SQLITE_UTF8, func); int rc = sqlite3_create_function(db, "myfunc", 1, SQLITE_UTF8, func);
affirm(0 == rc); affirm(0 == rc);
sqlite3_stmt stmt = prepare(db, "select myfunc(a), myfunc(a+10) from t"); sqlite3_stmt stmt = prepare(db, "select myfunc(a), myfunc(a+10) from t");
affirm( null != stmt );
int n = 0; int n = 0;
if( SQLITE_ROW == sqlite3_step(stmt) ){ if( SQLITE_ROW == sqlite3_step(stmt) ){
final int v = sqlite3_column_int(stmt, 0); int v = sqlite3_column_int(stmt, 0);
affirm( 6 == v ); affirm( 6 == v );
int v2 = sqlite3_column_int(stmt, 1);
affirm( 30+v == v2 );
++n; ++n;
} }
affirm( 1==n );
affirm(!xFinalNull.value); affirm(!xFinalNull.value);
sqlite3_reset(stmt); sqlite3_reset(stmt);
// Ensure that the accumulator is reset... // Ensure that the accumulator is reset on subsequent calls...
n = 0; n = 0;
if( SQLITE_ROW == sqlite3_step(stmt) ){ if( SQLITE_ROW == sqlite3_step(stmt) ){
final int v = sqlite3_column_int(stmt, 0); final int v = sqlite3_column_int(stmt, 0);
@@ -767,9 +773,9 @@ public class Tester1 implements Runnable {
affirm( 6 == c0 ); affirm( 6 == c0 );
affirm( 12 == c1 ); affirm( 12 == c1 );
} }
sqlite3_finalize(stmt);
affirm( 1 == n ); affirm( 1 == n );
affirm(!xFinalNull.value); affirm(!xFinalNull.value);
sqlite3_finalize(stmt);
execSql(db, "SELECT myfunc(1) WHERE 0"); execSql(db, "SELECT myfunc(1) WHERE 0");
affirm(xFinalNull.value); affirm(xFinalNull.value);

View File

@@ -18,10 +18,7 @@ package org.sqlite.jni;
SQL functions (a.k.a. UDFs). SQL functions (a.k.a. UDFs).
*/ */
public final class sqlite3_context extends NativePointerHolder<sqlite3_context> { public final class sqlite3_context extends NativePointerHolder<sqlite3_context> {
/** private Long aggregateContext = null;
Only set by the JNI layer.
*/
private long aggregateContext = 0;
/** /**
getAggregateContext() corresponds to C's getAggregateContext() corresponds to C's
@@ -32,19 +29,29 @@ public final class sqlite3_context extends NativePointerHolder<sqlite3_context>
such that all calls into those callbacks can determine which "set" such that all calls into those callbacks can determine which "set"
of those calls they belong to. of those calls they belong to.
If this object is being used in the context of an aggregate or <p>If the argument is true and the aggregate context has not yet
been set up, it will be initialized fetched on demand, else it
won't. The intent is that xStep(), xValue(), and xInverse()
methods pass true and xFinal() methods pass false.
<p>This function treats numeric 0 as null, always returning null instead
of 0.
<p>If this object is being used in the context of an aggregate or
window UDF, this function returns a non-0 value which is distinct window UDF, this function returns a non-0 value which is distinct
for each set of UDF callbacks from a single invocation of the for each set of UDF callbacks from a single invocation of the
UDF, otherwise it returns 0. The returned value is only only UDF, otherwise it returns 0. The returned value is only only
valid within the context of execution of a single SQL statement, valid within the context of execution of a single SQL statement,
and may be re-used by future invocations of the UDF in different and must not be re-used by future invocations of the UDF in
SQL statements. different SQL statements.
Consider this SQL, where MYFUNC is a user-defined aggregate function: <p>Consider this SQL, where MYFUNC is a user-defined aggregate function:
{code
SELECT MYFUNC(A), MYFUNC(B) FROM T; SELECT MYFUNC(A), MYFUNC(B) FROM T;
}
The xStep() and xFinal() methods of the callback need to be able <p>The xStep() and xFinal() methods of the callback need to be able
to differentiate between those two invocations in order to to differentiate between those two invocations in order to
perform their work properly. The value returned by perform their work properly. The value returned by
getAggregateContext() will be distinct for each of those getAggregateContext() will be distinct for each of those
@@ -52,14 +59,18 @@ public final class sqlite3_context extends NativePointerHolder<sqlite3_context>
key for mapping callback invocations to whatever client-defined key for mapping callback invocations to whatever client-defined
state is needed by the UDF. state is needed by the UDF.
There is one case where this will return 0 in the context of an <p>There is one case where this will return 0 in the context of an
aggregate or window function: if the result set has no rows, aggregate or window function: if the result set has no rows,
the UDF's xFinal() will be called without any other x...() members the UDF's xFinal() will be called without any other x...() members
having been called. In that one case, no aggregate context key will having been called. In that one case, no aggregate context key will
have been generated. xFinal() implementations need to be prepared to have been generated. xFinal() implementations need to be prepared to
accept that condition as legal. accept that condition as legal.
*/ */
public long getAggregateContext(){ public synchronized Long getAggregateContext(boolean initIfNeeded){
return aggregateContext; if( aggregateContext==null ){
aggregateContext = SQLite3Jni.sqlite3_aggregate_context(this, initIfNeeded);
if( !initIfNeeded && null==aggregateContext ) aggregateContext = 0L;
}
return (null==aggregateContext || 0!=aggregateContext) ? aggregateContext : null;
} }
} }

View File

@@ -1,5 +1,5 @@
C Add\sdoc/testrunner.md,\sfor\sdocumenting\sthe\stestrunner.tcl\sscript. C Do\snot\spre-allocate\ssqlite3_aggregate_context()\sfor\sJava\sUDFs,\sas\sit\sunduly\scomplicates\sUDF\sinitialization.
D 2023-08-24T19:08:50.024 D 2023-08-24T21:31:56.676
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -233,11 +233,11 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9 F ext/icu/README.txt 7ab7ced8ae78e3a645b57e78570ff589d4c672b71370f5aa9e1cd7024f400fc9
F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282 F ext/icu/icu.c c074519b46baa484bb5396c7e01e051034da8884bad1a1cb7f09bbe6be3f0282
F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8 F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a32075a8
F ext/jni/GNUmakefile 6b3c0fd8d055c129735702d0b288589d25544dd404a00d46d9eb43770fe7f78f F ext/jni/GNUmakefile 6aeafa0ebcf0f0d834c814ae8b450b54135ea11a2a7868f90b6286ec1bf6020f
F ext/jni/README.md 9d3caa2e038bfe5e8356a9e8ff66f93ca0647ac278339eeea296f10017f5cf35 F ext/jni/README.md 9d3caa2e038bfe5e8356a9e8ff66f93ca0647ac278339eeea296f10017f5cf35
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c 8db2fcc05dd7749f9f4175e2654344feccac6abfd19fd9db0d116c6350e3b625 F ext/jni/src/c/sqlite3-jni.c 0d98ab3b117893904a06f0f8a350d68d4e911939b6aee4f0eb1ef707502ac23c
F ext/jni/src/c/sqlite3-jni.h 2b81cfb83933cb18e5f690487f4556591d3329538809c847d00190aa4d69aa1d F ext/jni/src/c/sqlite3-jni.h 7e9f36434b919cd8b6aa66c61e3910e9f112e252f52d1ac8a9811c52710aefcb
F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892 F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892
F ext/jni/src/org/sqlite/jni/AutoExtension.java bcc1849b2fccbe5e2d7ac9e9ac7f8d05a6d7088a8fedbaad90e39569745a61e6 F ext/jni/src/org/sqlite/jni/AutoExtension.java bcc1849b2fccbe5e2d7ac9e9ac7f8d05a6d7088a8fedbaad90e39569745a61e6
F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c
@@ -256,10 +256,10 @@ F ext/jni/src/org/sqlite/jni/PreUpdateHook.java dec00a706b58c67989f0ff56c4f0a703
F ext/jni/src/org/sqlite/jni/ProgressHandler.java 6f62053a828a572de809828b1ee495380677e87daa29a1c57a0e2c06b0a131dc F ext/jni/src/org/sqlite/jni/ProgressHandler.java 6f62053a828a572de809828b1ee495380677e87daa29a1c57a0e2c06b0a131dc
F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7ce7797f2c6c7fca2004ff12ce20f86 F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7ce7797f2c6c7fca2004ff12ce20f86
F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564 F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564
F ext/jni/src/org/sqlite/jni/SQLFunction.java 5851698d96ee29171d68930ad758d0f5a253f7575f1feb890d82b2557a8d3ef5 F ext/jni/src/org/sqlite/jni/SQLFunction.java 4d6291fa14fcca1a040609378f9f00a193145d79c3abbda98ba32c340904cbeb
F ext/jni/src/org/sqlite/jni/SQLLog.java c60610b35208416940822e834d61f08fbbe5d6e06b374b541b49e41fd56c9798 F ext/jni/src/org/sqlite/jni/SQLLog.java c60610b35208416940822e834d61f08fbbe5d6e06b374b541b49e41fd56c9798
F ext/jni/src/org/sqlite/jni/SQLite3Jni.java d96f10a097c1d614b44353e85a65368d9aca565d5ae57fae0104811594fbdfba F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 866b320e6cb089ebe96c14763575df9e2e0d5e52a0ec87a52119ff17ec59ffbf
F ext/jni/src/org/sqlite/jni/Tester1.java 76f308ad9bf0bd74374561c30c65564ed24583a465264b751d9e2333980149f1 F ext/jni/src/org/sqlite/jni/Tester1.java 239eb0133547d4a23317a6dd5bc456172cfb1f2547fd15ba8408871c2776a721
F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629 F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629
F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d
F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d
@@ -269,7 +269,7 @@ F ext/jni/src/org/sqlite/jni/fts5_extension_function.java ac825035d7d83fc7fd9603
F ext/jni/src/org/sqlite/jni/fts5_tokenizer.java e530b36e6437fcc500e95d5d75fbffe272bdea20d2fac6be2e1336c578fba98b F ext/jni/src/org/sqlite/jni/fts5_tokenizer.java e530b36e6437fcc500e95d5d75fbffe272bdea20d2fac6be2e1336c578fba98b
F ext/jni/src/org/sqlite/jni/package-info.java 1a547913d681411d65c5fe0bca840f049abe5612740154a125545ea9e2481747 F ext/jni/src/org/sqlite/jni/package-info.java 1a547913d681411d65c5fe0bca840f049abe5612740154a125545ea9e2481747
F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c388ec3bc1de547f098a0217158fc F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c388ec3bc1de547f098a0217158fc
F ext/jni/src/org/sqlite/jni/sqlite3_context.java fe7797a696978f057528a57b7a11e7797ed41fd7afcf100c5ebb67055d9f706f F ext/jni/src/org/sqlite/jni/sqlite3_context.java 42df6769ab9c8de40d24f39f49152cdaa6e0c06d1468660a95dfee9ecaeb9a63
F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 78e6d1b95ac600a9475e9db4623f69449322b0c93d1bd4e1616e76ed547ed9fc F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 78e6d1b95ac600a9475e9db4623f69449322b0c93d1bd4e1616e76ed547ed9fc
F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a
F ext/jni/src/org/sqlite/jni/tester/SQLTester.java bc3d6797a2f6cb7d443a0b72af84e5a45e0416b96af52e432d28e123db1970c3 F ext/jni/src/org/sqlite/jni/tester/SQLTester.java bc3d6797a2f6cb7d443a0b72af84e5a45e0416b96af52e432d28e123db1970c3
@@ -2096,8 +2096,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 62b404d62fd62f4d220838b59c9f38a71afa2d4a8c3af0a5c9495fa7020972cf P 9c69a28401c7273823f2c2b291fd417febeb278afb9ce085a4b944505ca13d23
R a33be9d18a7bfec02bf745dca74a3ae4 R 1c78bd3d04007fccae2264dff957535e
U dan U stephan
Z b231c489ac6e506e7affd58c17184d19 Z 6a74bde3490bcf9bf06f9dd5ecb09697
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
9c69a28401c7273823f2c2b291fd417febeb278afb9ce085a4b944505ca13d23 e8308f0c6ec2d8999c8a2502fb130cb3501ba326f23f71f2cd8d452debae79b5