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

JNI: add sqlite3_result_nio_buffer() and tests. Discover that we cannot create sensible sqlite3_column_nio_buffer() or sqlite3_value_nio_buffer() counterparts because of ByteBuffer interface limitations.

FossilOrigin-Name: 44b4df01ff86841fb85b6295cbada422c6ba8a32a420a2e840e2d607b6c90164
This commit is contained in:
stephan
2023-11-13 18:35:37 +00:00
parent 7f7d7bea01
commit 87c407da18
6 changed files with 251 additions and 69 deletions

View File

@ -882,7 +882,7 @@ static jbyte * s3jni__jbyteArray_bytes2(JNIEnv * const env, jbyteArray jBA, jsiz
** required so cannot check for that violation. The caller is required ** required so cannot check for that violation. The caller is required
** to ensure that any to-be-bind()ed range fits within SQLITE_LIMIT. ** to ensure that any to-be-bind()ed range fits within SQLITE_LIMIT.
*/ */
/*static*/ void s3jni__get_nio_buffer(JNIEnv * const env, jobject jbb, void **pBuf, jint * pN ){ static void s3jni__get_nio_buffer(JNIEnv * const env, jobject jbb, void **pBuf, jint * pN ){
*pBuf = 0; *pBuf = 0;
*pN = 0; *pN = 0;
if( jbb ){ if( jbb ){
@ -2433,32 +2433,90 @@ S3JniApi(sqlite3_bind_blob(),jint,1bind_1blob)(
return (jint)rc; return (jint)rc;
} }
/**
Helper for use with s3jni_setup_nio_args().
*/
struct S3JniNioArgs {
jobject jBuf; /* input - ByteBuffer */
jint iBegin; /* input - byte offset */
jint iN; /* input - byte count to bind */
jint nBuf; /* output - jBuf's buffer size */
void * p; /* output - jBuf's buffer memory */
const void * pStart; /* output - offset of p to bind */
int iOutLen; /* output - number of bytes from pStart to bind */
};
typedef struct S3JniNioArgs S3JniNioArgs;
static const S3JniNioArgs S3JniNioArgs_empty = {
0,0,0,0,0,0,0
};
/**
Internal helper for sqlite3_bind_nio_buffer() and
sqlite3_result_nio_buffer(). Populates pArgs and returns 0 on
success, non-0 if the operation should fail. The caller is
required to check for SJG.g.cByteBuffer!=0 before calling
this and reporting it in a way appropriate for that routine.
This function may assert() that SJG.g.cByteBuffer is not 0.
The (jBuffer, iBegin, iN) arguments are the (ByteBuffer, offset,
length) arguments to the bind/result method.
*/
static int s3jni_setup_nio_args(
JNIEnv *env, S3JniNioArgs * pArgs,
jobject jBuffer, jint iBegin, jint iN
){
jlong iEnd = 0;
*pArgs = S3JniNioArgs_empty;
pArgs->jBuf = jBuffer;
pArgs->iBegin = iBegin;
pArgs->iN = iN;
assert( SJG.g.cByteBuffer );
if( pArgs->iBegin<0 ){
return SQLITE_MISUSE;
}
s3jni_get_nio_buffer(pArgs->jBuf, &pArgs->p, &pArgs->nBuf);
if( !pArgs->p ){
return SQLITE_MISUSE;
}else if( pArgs->iBegin>=pArgs->nBuf ){
pArgs->pStart = 0;
pArgs->iOutLen = 0;
return 0;
}
assert( pArgs->nBuf > 0 );
assert( pArgs->iBegin < pArgs->nBuf );
iEnd = pArgs->iN<0 ? pArgs->nBuf - pArgs->iBegin : pArgs->iBegin + pArgs->iN;
if( iEnd>(jlong)pArgs->nBuf ) iEnd = pArgs->nBuf - pArgs->iBegin;
if( iEnd - pArgs->iBegin > (jlong)SQLITE_MAX_LENGTH ){
return SQLITE_TOOBIG;
}
assert( pArgs->iBegin >= 0 );
assert( iEnd > pArgs->iBegin );
pArgs->pStart = pArgs->p + pArgs->iBegin;
pArgs->iOutLen = (int)(iEnd - pArgs->iBegin);
assert( pArgs->iOutLen > 0 );
return 0;
}
S3JniApi(sqlite3_bind_nio_buffer(),jint,1bind_1nio_1buffer)( S3JniApi(sqlite3_bind_nio_buffer(),jint,1bind_1nio_1buffer)(
JniArgsEnvClass, jobject jpStmt, jint ndx, jobject jBuffer, JniArgsEnvClass, jobject jpStmt, jint ndx, jobject jBuffer,
jint iBegin, jint iN jint iBegin, jint iN
){ ){
sqlite3_stmt * pStmt = PtrGet_sqlite3_stmt(jpStmt); sqlite3_stmt * pStmt = PtrGet_sqlite3_stmt(jpStmt);
void * pBuf = 0; S3JniNioArgs args;
jint nBuf = 0; int rc;
jlong iEnd = 0; if( !pStmt || !SJG.g.cByteBuffer ) return SQLITE_MISUSE;
if( !SJG.g.cByteBuffer || !pStmt || iBegin<0 ){ rc = s3jni_setup_nio_args(env, &args, jBuffer, iBegin, iN);
return (jint)SQLITE_MISUSE; if(rc){
return rc;
}else if( !args.pStart || !args.iOutLen ){
return sqlite3_bind_null(pStmt, ndx);
} }
s3jni_get_nio_buffer(jBuffer, &pBuf, &nBuf); assert( args.iOutLen>0 );
if( !pBuf || iBegin>=nBuf ){ assert( args.nBuf > 0 );
return (jint)sqlite3_bind_null(pStmt, ndx); assert( args.pStart != 0 );
} assert( (args.pStart + args.iOutLen) <= (args.p + args.nBuf) );
assert( nBuf > 0 ); return sqlite3_bind_blob( pStmt, (int)ndx, args.pStart,
assert( iBegin < nBuf ); args.iOutLen, SQLITE_TRANSIENT );
iEnd = iN<0 ? nBuf - iBegin : iBegin + iN;
if( iEnd>(jlong)nBuf ) iEnd = nBuf-iBegin;
if( iEnd-iBegin >(jlong)SQLITE_MAX_LENGTH ){
return SQLITE_MISUSE;
}
assert( iBegin>=0 );
assert( iEnd > iBegin );
return (jint)sqlite3_bind_blob(pStmt, (int)ndx, pBuf + iBegin,
(int)(iEnd - iBegin), SQLITE_TRANSIENT);
} }
S3JniApi(sqlite3_bind_double(),jint,1bind_1double)( S3JniApi(sqlite3_bind_double(),jint,1bind_1double)(
@ -4470,6 +4528,40 @@ S3JniApi(sqlite3_result_java_object(),void,1result_1java_1object)(
} }
} }
S3JniApi(sqlite3_result_nio_buffer(),void,1result_1nio_1buffer)(
JniArgsEnvClass, jobject jpCtx, jobject jBuffer,
jint iBegin, jint iN
){
sqlite3_context * pCx = PtrGet_sqlite3_context(jpCtx);
int rc;
S3JniNioArgs args;
if( !pCx ){
return;
}else if( !SJG.g.cByteBuffer ){
sqlite3_result_error(
pCx, "This JVM does not support JNI access to ByteBuffers.", -1
);
return;
}
rc = s3jni_setup_nio_args(env, &args, jBuffer, iBegin, iN);
if(rc){
if( iBegin<0 ){
sqlite3_result_error(pCx, "Start index may not be negative.", -1);
}else if( SQLITE_TOOBIG==rc ){
sqlite3_result_error_toobig(pCx);
}else{
sqlite3_result_error(
pCx, "Invalid arguments to sqlite3_result_nio_buffer().", -1
);
}
}else if( !args.pStart || !args.iOutLen ){
sqlite3_result_null(pCx);
}else{
sqlite3_result_blob(pCx, args.pStart, args.iOutLen, SQLITE_TRANSIENT);
}
}
S3JniApi(sqlite3_result_null(),void,1result_1null)( S3JniApi(sqlite3_result_null(),void,1result_1null)(
JniArgsEnvClass, jobject jpCx JniArgsEnvClass, jobject jpCx
){ ){

View File

@ -1729,6 +1729,14 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1int64
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1java_1object JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1java_1object
(JNIEnv *, jclass, jobject, jobject); (JNIEnv *, jclass, jobject, jobject);
/*
* Class: org_sqlite_jni_capi_CApi
* Method: sqlite3_result_nio_buffer
* Signature: (Lorg/sqlite/jni/capi/sqlite3_context;Ljava/nio/ByteBuffer;II)V
*/
JNIEXPORT void JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1result_1nio_1buffer
(JNIEnv *, jclass, jobject, jobject, jint, jint);
/* /*
* Class: org_sqlite_jni_capi_CApi * Class: org_sqlite_jni_capi_CApi
* Method: sqlite3_result_null * Method: sqlite3_result_null

View File

@ -295,16 +295,16 @@ public final class CApi {
range is silently truncated to fit the buffer. range is silently truncated to fit the buffer.
If any of the following are true, this function behaves like If any of the following are true, this function behaves like
sqlite3_bind_null(): the buffer is null, beginPos is past the end sqlite3_bind_null(): the buffer is null, beginPos is at or past
of the buffer, howMany is 0, or the calculated slice of the blob the end of the buffer, howMany is 0, or the calculated slice of
has a length of 0. the blob has a length of 0.
If ndx is out of range, it returns SQLITE_RANGE, as documented If ndx is out of range, it returns SQLITE_RANGE, as documented
for sqlite3_bind_blob(). If any other arguments are invalid or for sqlite3_bind_blob(). If beginPos is negative or if
if sqlite3_jni_supports_nio() is false then SQLITE_MISUSE is sqlite3_jni_supports_nio() returns false then SQLITE_MISUSE is
returned. Note that this function is bound (as it were) by the returned. Note that this function is bound (as it were) by the
SQLITE_LIMIT_LENGTH constraint and SQLITE_MISUSE is returned if SQLITE_LIMIT_LENGTH constraint and SQLITE_TOOBIG is returned if
that's violated. the resulting slice of the buffer exceeds that limit.
This function does not modify the buffer's streaming-related This function does not modify the buffer's streaming-related
cursors. cursors.
@ -318,6 +318,10 @@ public final class CApi {
buffers and the only such class offered by Java is (apparently) buffers and the only such class offered by Java is (apparently)
ByteBuffer. ByteBuffer.
Design note: there are no sqlite3_column_nio_buffer() and
sqlite3_value_nio_buffer() counterparts because the ByteBuffer
interface does not enable sensible implementations of those.
@see https://docs.oracle.com/javase/8/docs/api/java/nio/Buffer.html @see https://docs.oracle.com/javase/8/docs/api/java/nio/Buffer.html
*/ */
public static native int sqlite3_bind_nio_buffer( public static native int sqlite3_bind_nio_buffer(
@ -1560,6 +1564,39 @@ public final class CApi {
@NotNull sqlite3_context cx, @NotNull Object o @NotNull sqlite3_context cx, @NotNull Object o
); );
/**
Similar to sqlite3_bind_nio_buffer(), this works like
sqlite3_result_blob() but accepts a java.nio.ByteBuffer as its
input source. See sqlite3_bind_nio_buffer() for the semantics of
the second and subsequent arguments.
If cx is null then this function will silently fail. If
sqlite3_jni_supports_nio() returns false or iBegin is negative,
an error result is set. If (begin+n) extends beyond the end of
the buffer, it is silently truncated to fit.
If any of the following apply, this function behaves like
sqlite3_result_null(): the blob is null, the resulting slice of
the blob is empty.
If the resulting slice of the buffer exceeds SQLITE_LIMIT_LENGTH
then this function behaves like sqlite3_result_error_toobig().
*/
public static native void sqlite3_result_nio_buffer(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob,
int begin, int n
);
/**
Convenience overload which uses the whole input object
as the result blob content.
*/
public static void sqlite3_result_nio_buffer(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob
){
sqlite3_result_nio_buffer(cx, blob, 0, -1);
}
public static native void sqlite3_result_null( public static native void sqlite3_result_null(
@NotNull sqlite3_context cx @NotNull sqlite3_context cx
); );
@ -1654,6 +1691,27 @@ public final class CApi {
sqlite3_result_blob(cx, blob, (int)(null==blob ? 0 : blob.length)); sqlite3_result_blob(cx, blob, (int)(null==blob ? 0 : blob.length));
} }
/**
Convenience overload which behaves like
sqlite3_result_nio_buffer().
*/
public static void sqlite3_result_blob(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob,
int begin, int n
){
sqlite3_result_nio_buffer(cx, blob, begin, n);
}
/**
Convenience overload which behaves like the two-argument overload of
sqlite3_result_nio_buffer().
*/
public static void sqlite3_result_blob(
@NotNull sqlite3_context cx, @Nullable java.nio.ByteBuffer blob
){
sqlite3_result_nio_buffer(cx, blob);
}
/** /**
Binds the given text using C's sqlite3_result_blob64() unless: Binds the given text using C's sqlite3_result_blob64() unless:

View File

@ -39,12 +39,12 @@ import java.util.concurrent.Future;
@interface SingleThreadOnly{} @interface SingleThreadOnly{}
/** /**
Annotation for Tester1 tests which must only be run if JNI-level support for Annotation for Tester1 tests which must only be run if
java.nio.Buffer is available. sqlite3_jni_supports_nio() is true.
*/ */
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
@interface RequiresNioBuffer{} @interface RequiresJniNio{}
public class Tester1 implements Runnable { public class Tester1 implements Runnable {
//! True when running in multi-threaded mode. //! True when running in multi-threaded mode.
@ -565,42 +565,65 @@ public class Tester1 implements Runnable {
sqlite3_close_v2(db); sqlite3_close_v2(db);
} }
@RequiresNioBuffer @RequiresJniNio
private void testBindByteBuffer(){ private void testBindByteBuffer(){
/* TODO: these tests need to be much more extensive to check the
begin/end range handling. */
sqlite3 db = createNewDb(); sqlite3 db = createNewDb();
execSql(db, "CREATE TABLE t(a)"); execSql(db, "CREATE TABLE t(a)");
sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(?);");
java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocateDirect(10); final java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocateDirect(10);
buf.put((byte)0x31)/*note that we'll skip this one*/ buf.put((byte)0x31)/*note that we'll skip this one*/
.put((byte)0x32) .put((byte)0x32)
.put((byte)0x33) .put((byte)0x33)
.put((byte)0x34); .put((byte)0x34)
int rc = sqlite3_bind_blob(stmt, 1, buf, -1, 0); .put((byte)0x35)/*we'll skip this one too*/;
affirm( SQLITE_MISUSE==rc );
rc = sqlite3_bind_blob(stmt, 1, buf, 1, 3); final int expectTotal = buf.get(1) + buf.get(2) + buf.get(3);
affirm( 0==rc ); sqlite3_stmt stmt = prepare(db, "INSERT INTO t(a) VALUES(?);");
rc = sqlite3_step(stmt); affirm( SQLITE_MISUSE == sqlite3_bind_blob(stmt, 1, buf, -1, 0) );
affirm(SQLITE_DONE == rc); affirm( 0 == sqlite3_bind_blob(stmt, 1, buf, 1, 3) );
affirm( SQLITE_DONE == sqlite3_step(stmt) );
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
stmt = prepare(db, "SELECT a FROM t ORDER BY a DESC;"); stmt = prepare(db, "SELECT a FROM t;");
int n = 0;
int total = 0; int total = 0;
while( SQLITE_ROW == sqlite3_step(stmt) ){ affirm( SQLITE_ROW == sqlite3_step(stmt) );
byte[] blob = sqlite3_column_blob(stmt, 0); byte blob[] = sqlite3_column_blob(stmt, 0);
affirm(3 == blob.length); affirm(3 == blob.length);
int i = 0; int i = 0;
for(byte b : blob){ for(byte b : blob){
affirm( i<=3 ); affirm( i<=3 );
affirm(b == buf.get(1 + i++)); affirm(b == buf.get(1 + i++));
total += b; total += b;
}
++n;
} }
affirm( SQLITE_DONE == sqlite3_step(stmt) );
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
affirm(1 == n); affirm(total == expectTotal);
affirm(total == 0x32 + 0x33 + 0x34);
/* TODO: these tests need to be much more extensive to check the SQLFunction func =
begin range handling. */ new ScalarFunction(){
public void xFunc(sqlite3_context cx, sqlite3_value[] args){
sqlite3_result_blob(cx, buf, 1, 3);
}
};
affirm( 0 == sqlite3_create_function(db, "myfunc", -1, SQLITE_UTF8, func) );
stmt = prepare(db, "SELECT myfunc()");
affirm( SQLITE_ROW == sqlite3_step(stmt) );
blob = sqlite3_column_blob(stmt, 0);
affirm(3 == blob.length);
i = 0;
total = 0;
for(byte b : blob){
affirm( i<=3 );
affirm(b == buf.get(1 + i++));
total += b;
}
affirm( SQLITE_DONE == sqlite3_step(stmt) );
sqlite3_finalize(stmt);
affirm(total == expectTotal);
sqlite3_close_v2(db); sqlite3_close_v2(db);
} }
@ -1924,9 +1947,10 @@ public class Tester1 implements Runnable {
if( forceFail ){ if( forceFail ){
testMethods.add(m); testMethods.add(m);
} }
}else if( m.isAnnotationPresent( RequiresNioBuffer.class ) }else if( m.isAnnotationPresent( RequiresJniNio.class )
&& !sqlite3_jni_supports_nio() ){ && !sqlite3_jni_supports_nio() ){
outln("Skipping test for lack JNI nio.Buffer support: ",name,"()\n"); outln("Skipping test for lack of JNI java.nio.ByteBuffer support: ",
name,"()\n");
++nSkipped; ++nSkipped;
}else if( !m.isAnnotationPresent( ManualTest.class ) ){ }else if( !m.isAnnotationPresent( ManualTest.class ) ){
if( nThread>1 && m.isAnnotationPresent( SingleThreadOnly.class ) ){ if( nThread>1 && m.isAnnotationPresent( SingleThreadOnly.class ) ){

View File

@ -1,5 +1,5 @@
C JNI:\sadd\ssqlite3_bind_nio_buffer()\sand\sinitial\stests\sfor\sbinding\sByteBuffer\sobjects\sas\sblobs\son\sJVMs\swhich\shave\sJNI\ssupport\sfor\snio\sbuffers. C JNI:\sadd\ssqlite3_result_nio_buffer()\sand\stests.\sDiscover\sthat\swe\scannot\screate\ssensible\ssqlite3_column_nio_buffer()\sor\ssqlite3_value_nio_buffer()\scounterparts\sbecause\sof\sByteBuffer\sinterface\slimitations.
D 2023-11-13T14:58:37.421 D 2023-11-13T18:35:37.387
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
@ -241,8 +241,8 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
F ext/jni/GNUmakefile f2f3a31923293659b95225e932a286af1f2287d75bf88ad6c0fd1b9d9cd020d4 F ext/jni/GNUmakefile f2f3a31923293659b95225e932a286af1f2287d75bf88ad6c0fd1b9d9cd020d4
F ext/jni/README.md ef9ac115e97704ea995d743b4a8334e23c659e5534c3b64065a5405256d5f2f4 F ext/jni/README.md ef9ac115e97704ea995d743b4a8334e23c659e5534c3b64065a5405256d5f2f4
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c a04d0d77e7391a69f7f8ca4b38e24de59b3a8f61610f2e91698c190c07283850 F ext/jni/src/c/sqlite3-jni.c 56ddb35bbae71123bedd003ae2bf42adae7d683717bb15ac3ed51d16e2b6c3ff
F ext/jni/src/c/sqlite3-jni.h 2848299f845d36b4b6123d360e7a4eb960d040637a10158079af49f4ded16453 F ext/jni/src/c/sqlite3-jni.h 1f28a6a2beec13a49efdb42804926d2139f6a786558ea52c121ddf0bf39af59a
F ext/jni/src/org/sqlite/jni/annotation/NotNull.java 02091a8112e33389f1c160f506cd413168c8dfacbeda608a4946c6e3557b7d5a F ext/jni/src/org/sqlite/jni/annotation/NotNull.java 02091a8112e33389f1c160f506cd413168c8dfacbeda608a4946c6e3557b7d5a
F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 0b1879852707f752512d4db9d7edd0d8db2f0c2612316ce1c832715e012ff6ba F ext/jni/src/org/sqlite/jni/annotation/Nullable.java 0b1879852707f752512d4db9d7edd0d8db2f0c2612316ce1c832715e012ff6ba
F ext/jni/src/org/sqlite/jni/annotation/package-info.java 977b374aed9d5853cbf3438ba3b0940abfa2ea4574f702a2448ee143b98ac3ca F ext/jni/src/org/sqlite/jni/annotation/package-info.java 977b374aed9d5853cbf3438ba3b0940abfa2ea4574f702a2448ee143b98ac3ca
@ -251,7 +251,7 @@ F ext/jni/src/org/sqlite/jni/capi/AggregateFunction.java 0b72cdff61533b564d65b63
F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a F ext/jni/src/org/sqlite/jni/capi/AuthorizerCallback.java c045a5b47e02bb5f1af91973814a905f12048c428a3504fbc5266d1c1be3de5a
F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759 F ext/jni/src/org/sqlite/jni/capi/AutoExtensionCallback.java 74cc4998a73d6563542ecb90804a3c4f4e828cb4bd69e61226d1a51f4646e759
F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca F ext/jni/src/org/sqlite/jni/capi/BusyHandlerCallback.java 7b8e19810c42b0ad21a04b5d8c804b32ee5905d137148703f16a75b612c380ca
F ext/jni/src/org/sqlite/jni/capi/CApi.java 5ef54290c17dca46d7f24001ac3b689559e1b37ee40d06b88fa5315d64863789 F ext/jni/src/org/sqlite/jni/capi/CApi.java 1517e1f5fc53001b2cb7229a427d33747163f8f37348368fe7c3e14edbb9c512
F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 57e2d275dcebe690b1fc1f3d34eb96879b2d7039bce30b563aee547bf45d8a8b F ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java 57e2d275dcebe690b1fc1f3d34eb96879b2d7039bce30b563aee547bf45d8a8b
F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a F ext/jni/src/org/sqlite/jni/capi/CollationCallback.java e29bcfc540fdd343e2f5cca4d27235113f2886acb13380686756d5cabdfd065a
F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java 5bfa226a8e7a92e804fd52d6e42b4c7b875fa7a94f8e2c330af8cc244a8920ab F ext/jni/src/org/sqlite/jni/capi/CollationNeededCallback.java 5bfa226a8e7a92e804fd52d6e42b4c7b875fa7a94f8e2c330af8cc244a8920ab
@ -269,7 +269,7 @@ F ext/jni/src/org/sqlite/jni/capi/SQLFunction.java 0d1e9afc9ff8a2adb94a155b72385
F ext/jni/src/org/sqlite/jni/capi/SQLTester.java 09bee15aa0eedac68d767ae21d9a6a62a31ade59182a3ccbf036d6463d9e30b1 F ext/jni/src/org/sqlite/jni/capi/SQLTester.java 09bee15aa0eedac68d767ae21d9a6a62a31ade59182a3ccbf036d6463d9e30b1
F ext/jni/src/org/sqlite/jni/capi/ScalarFunction.java 93b9700fca4c68075ccab12fe0fbbc76c91cafc9f368e835b9bd7cd7732c8615 F ext/jni/src/org/sqlite/jni/capi/ScalarFunction.java 93b9700fca4c68075ccab12fe0fbbc76c91cafc9f368e835b9bd7cd7732c8615
F ext/jni/src/org/sqlite/jni/capi/TableColumnMetadata.java addf120e0e76e5be1ff2260daa7ce305ff9b5fafd64153a7a28e9d8f000a815f F ext/jni/src/org/sqlite/jni/capi/TableColumnMetadata.java addf120e0e76e5be1ff2260daa7ce305ff9b5fafd64153a7a28e9d8f000a815f
F ext/jni/src/org/sqlite/jni/capi/Tester1.java 4ec21172917f641787767443f418854329bf9b9779807b644e000dac1ec77013 F ext/jni/src/org/sqlite/jni/capi/Tester1.java 4d460ccce50e7ef4ce8e1ab5d46ceca70834a798d8a2233c93f4bede9deb6683
F ext/jni/src/org/sqlite/jni/capi/TraceV2Callback.java 0a25e117a0daae3394a77f24713e36d7b44c67d6e6d30e9e1d56a63442eef723 F ext/jni/src/org/sqlite/jni/capi/TraceV2Callback.java 0a25e117a0daae3394a77f24713e36d7b44c67d6e6d30e9e1d56a63442eef723
F ext/jni/src/org/sqlite/jni/capi/UpdateHookCallback.java c8bdf7848e6599115d601bcc9427ff902cb33129b9be32870ac6808e04b6ae56 F ext/jni/src/org/sqlite/jni/capi/UpdateHookCallback.java c8bdf7848e6599115d601bcc9427ff902cb33129b9be32870ac6808e04b6ae56
F ext/jni/src/org/sqlite/jni/capi/ValueHolder.java 22d365746a78c5cd7ae10c39444eb7bbf1a819aad4bb7eb77b1edc47773a3950 F ext/jni/src/org/sqlite/jni/capi/ValueHolder.java 22d365746a78c5cd7ae10c39444eb7bbf1a819aad4bb7eb77b1edc47773a3950
@ -2139,8 +2139,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 0832f9a8e9f574b157c791c5cddc73aff7b2ff403509f5d78f310494d4a7f93d P b10ce1ef82d84726fbf6a8f624d6530f84fefb505f7868b4a0ea910fed7a877f
R 7292f27854539ba720bc8a8fcd0c273f R 2f05bfa531dff8515ddabab7cc0cd5f1
U stephan U stephan
Z 1881d5bf6b59348a7807616e897efc0f Z acc87a8d47162ab6fa5eb71b4d2c3712
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
b10ce1ef82d84726fbf6a8f624d6530f84fefb505f7868b4a0ea910fed7a877f 44b4df01ff86841fb85b6295cbada422c6ba8a32a420a2e840e2d607b6c90164