SQLite

Check-in [ab00af4e48]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:JNI: part 1 of typos and Java style tweaks suggested in forum post 99ac7961d82f57f3.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: ab00af4e48501b0413650df31147866a805c34b7ecf506d1e208bc3ae6c2ef28
User & Date: stephan 2025-04-14 11:31:10.823
Context
2025-04-14
12:09
JNI: part 2 of typos and Java style tweaks suggested in forum post 99ac7961d82f57f3. (check-in: 5e6e9aee5b user: stephan tags: trunk)
11:31
JNI: part 1 of typos and Java style tweaks suggested in forum post 99ac7961d82f57f3. (check-in: ab00af4e48 user: stephan tags: trunk)
10:20
Doc/help text tweaks in autoconf/tea. (check-in: d6889f6b9a user: stephan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/jni/GNUmakefile.
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
		-subpackages org.sqlite.jni $(javadoc.exclude)
	@echo "javadoc output is in $@"

.PHONY: doc javadoc docserve
.FORCE: doc
doc: $(doc.index)
javadoc: $(doc.index)
# Force rebild of docs
redoc:
	@rm -f $(doc.index)
	@$(MAKE) doc
docserve: $(doc.index)
	cd $(dir.doc) && althttpd -max-age 1 -page index.html
########################################################################
# Clean up...







|







425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
		-subpackages org.sqlite.jni $(javadoc.exclude)
	@echo "javadoc output is in $@"

.PHONY: doc javadoc docserve
.FORCE: doc
doc: $(doc.index)
javadoc: $(doc.index)
# Force rebuild of docs
redoc:
	@rm -f $(doc.index)
	@$(MAKE) doc
docserve: $(doc.index)
	cd $(dir.doc) && althttpd -max-age 1 -page index.html
########################################################################
# Clean up...
Changes to ext/jni/src/c/sqlite3-jni.c.
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#endif


/*
** Which sqlite3.c we're using needs to be configurable to enable
** building against a custom copy, e.g. the SEE variant. We have to
** include sqlite3.c, as opposed to sqlite3.h, in order to get access
** to some interal details like SQLITE_MAX_... and friends. This
** increases the rebuild time considerably but we need this in order
** to access some internal functionality and keep the to-Java-exported
** values of SQLITE_MAX_... and SQLITE_LIMIT_... in sync with the C
** build.
*/
#ifndef SQLITE_C
# define SQLITE_C sqlite3.c







|







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#endif


/*
** Which sqlite3.c we're using needs to be configurable to enable
** building against a custom copy, e.g. the SEE variant. We have to
** include sqlite3.c, as opposed to sqlite3.h, in order to get access
** to some internal details like SQLITE_MAX_... and friends. This
** increases the rebuild time considerably but we need this in order
** to access some internal functionality and keep the to-Java-exported
** values of SQLITE_MAX_... and SQLITE_LIMIT_... in sync with the C
** build.
*/
#ifndef SQLITE_C
# define SQLITE_C sqlite3.c
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
  return NativePointerHolder_new(env, S3JniNph(fts5_api), sv);
}

/*
** Returns a per-JNIEnv global ref to the Fts5ExtensionApi singleton
** instance, or NULL on OOM.
*/
static jobject s3jni_getFts5ExensionApi(JNIEnv * const env){
  if( !SJG.fts5.jExt ){
    S3JniGlobal_mutex_enter;
    if( !SJG.fts5.jExt ){
      jobject const pNPH = NativePointerHolder_new(
        env, S3JniNph(Fts5ExtensionApi), s3jni_ftsext()
      );
      if( pNPH ){







|







5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
  return NativePointerHolder_new(env, S3JniNph(fts5_api), sv);
}

/*
** Returns a per-JNIEnv global ref to the Fts5ExtensionApi singleton
** instance, or NULL on OOM.
*/
static jobject s3jni_getFts5ExtensionApi(JNIEnv * const env){
  if( !SJG.fts5.jExt ){
    S3JniGlobal_mutex_enter;
    if( !SJG.fts5.jExt ){
      jobject const pNPH = NativePointerHolder_new(
        env, S3JniNph(Fts5ExtensionApi), s3jni_ftsext()
      );
      if( pNPH ){
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
  }
  return ps ? ps->fts.jApi : 0;
#endif
}


JniDeclFtsXA(jobject,getInstance)(JniArgsEnvClass){
  return s3jni_getFts5ExensionApi(env);
}

JniDeclFtsXA(jint,xColumnCount)(JniArgsEnvObj,jobject jCtx){
  Fts5ExtDecl;
  return (jint)ext->xColumnCount(PtrGet_Fts5Context(jCtx));
}








|







5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
  }
  return ps ? ps->fts.jApi : 0;
#endif
}


JniDeclFtsXA(jobject,getInstance)(JniArgsEnvClass){
  return s3jni_getFts5ExtensionApi(env);
}

JniDeclFtsXA(jint,xColumnCount)(JniArgsEnvObj,jobject jCtx){
  Fts5ExtDecl;
  return (jint)ext->xColumnCount(PtrGet_Fts5Context(jCtx));
}

5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
  jobjectArray jArgv = 0;
  jobject jpFts = 0;
  jobject jFXA;
  int rc;
  S3JniDeclLocal_env;

  assert(pAux);
  jFXA = s3jni_getFts5ExensionApi(env);
  if( !jFXA ) goto error_oom;
  jpFts = new_java_Fts5Context(env, pFts);
  if( !jpFts ) goto error_oom;
  rc = udf_args(env, pCx, argc, argv, &jpCx, &jArgv);
  if( rc ) goto error_oom;
  (*env)->CallVoidMethod(env, pAux->jObj, pAux->jmid,
                         jFXA, jpFts, jpCx, jArgv);







|







5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
  jobjectArray jArgv = 0;
  jobject jpFts = 0;
  jobject jFXA;
  int rc;
  S3JniDeclLocal_env;

  assert(pAux);
  jFXA = s3jni_getFts5ExtensionApi(env);
  if( !jFXA ) goto error_oom;
  jpFts = new_java_Fts5Context(env, pFts);
  if( !jpFts ) goto error_oom;
  rc = udf_args(env, pCx, argc, argv, &jpCx, &jArgv);
  if( rc ) goto error_oom;
  (*env)->CallVoidMethod(env, pAux->jObj, pAux->jmid,
                         jFXA, jpFts, jpCx, jArgv);
Changes to ext/jni/src/c/sqlite3-jni.h.
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
  (JNIEnv *, jclass, jlong);

/*
 * Class:     org_sqlite_jni_capi_CApi
 * Method:    sqlite3_db_config
 * Signature: (Lorg/sqlite/jni/capi/sqlite3;IILorg/sqlite/jni/capi/OutputPointer/Int32;)I
 */
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1db_1config__Lorg_sqlite_jni_capi_sqlite3_2IILorg_sqlite_jni_capi_OutputPointer_Int32_2
  (JNIEnv *, jclass, jobject, jint, jint, jobject);

/*
 * Class:     org_sqlite_jni_capi_CApi
 * Method:    sqlite3_db_config
 * Signature: (Lorg/sqlite/jni/capi/sqlite3;ILjava/lang/String;)I
 */







|







1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
  (JNIEnv *, jclass, jlong);

/*
 * Class:     org_sqlite_jni_capi_CApi
 * Method:    sqlite3_db_config
 * Signature: (Lorg/sqlite/jni/capi/sqlite3;IILorg/sqlite/jni/capi/OutputPointer/Int32;)I
 */
JNIEXPORT jint JNICALL Java_org_sqlite_jni_capi_CApi_sqlite3_1db_1config__Lorg_sqlite_jni_capi_sqlite3_2IILorg_sqlite_jni_capi_OutputPointer_00024Int32_2
  (JNIEnv *, jclass, jobject, jint, jint, jobject);

/*
 * Class:     org_sqlite_jni_capi_CApi
 * Method:    sqlite3_db_config
 * Signature: (Lorg/sqlite/jni/capi/sqlite3;ILjava/lang/String;)I
 */
Changes to ext/jni/src/org/sqlite/jni/annotation/NotNull.java.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   is passed.</p>

   <p>When used in the context of Java interfaces which are called
   from the C APIs, this annotation communicates that the C API will
   never pass a null value to the callback for that parameter.</p>

   <p>Passing a null, for this annotation's definition of null, for
   any parameter marked with this annoation specifically invokes
   undefined behavior (see below).</p>

   <p>Passing 0 (i.e. C NULL) or a negative value for any long-type
   parameter marked with this annoation specifically invokes undefined
   behavior (see below). Such values are treated as C pointers in the
   JNI layer.</p>

   <p><b>Undefined behaviour:</b> the JNI build uses the {@code
   SQLITE_ENABLE_API_ARMOR} build flag, meaning that the C code
   invoked with invalid NULL pointers and the like will not invoke
   undefined behavior in the conventional C sense, but may, for







|



|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   is passed.</p>

   <p>When used in the context of Java interfaces which are called
   from the C APIs, this annotation communicates that the C API will
   never pass a null value to the callback for that parameter.</p>

   <p>Passing a null, for this annotation's definition of null, for
   any parameter marked with this annotation specifically invokes
   undefined behavior (see below).</p>

   <p>Passing 0 (i.e. C NULL) or a negative value for any long-type
   parameter marked with this annotation specifically invokes undefined
   behavior (see below). Such values are treated as C pointers in the
   JNI layer.</p>

   <p><b>Undefined behaviour:</b> the JNI build uses the {@code
   SQLITE_ENABLE_API_ARMOR} build flag, meaning that the C code
   invoked with invalid NULL pointers and the like will not invoke
   undefined behavior in the conventional C sense, but may, for
Changes to ext/jni/src/org/sqlite/jni/capi/CApi.java.
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file declares the main JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;

import java.nio.charset.StandardCharsets;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import org.sqlite.jni.annotation.*;
import java.util.Arrays;

/**
  This class contains the entire C-style sqlite3 JNI API binding,
  minus a few bits and pieces declared in other files. For client-side
  use, a static import is recommended:

  <pre>{@code







>

<
<
<
<
<

<







8
9
10
11
12
13
14
15
16





17

18
19
20
21
22
23
24
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file declares the main JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
import java.util.Arrays;
import java.nio.charset.StandardCharsets;





import org.sqlite.jni.annotation.*;


/**
  This class contains the entire C-style sqlite3 JNI API binding,
  minus a few bits and pieces declared in other files. For client-side
  use, a static import is recommended:

  <pre>{@code
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
     <p>Passing a true second argument is analogous to passing some
     unspecified small, non-0 positive value to the C API and passing
     false is equivalent to passing 0 to the C API.

     <p>Like the C API, it returns 0 if allocation fails or if
     initialize is false and no prior aggregate context was allocated
     for cx.  If initialize is true then it returns 0 only on
     allocation error. In all casses, 0 is considered the sentinel
     "not a key" value.
  */
  public static native long sqlite3_aggregate_context(sqlite3_context cx, boolean initialize);

  /**
     Functions almost as documented for the C API, with these
     exceptions:







|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
     <p>Passing a true second argument is analogous to passing some
     unspecified small, non-0 positive value to the C API and passing
     false is equivalent to passing 0 to the C API.

     <p>Like the C API, it returns 0 if allocation fails or if
     initialize is false and no prior aggregate context was allocated
     for cx.  If initialize is true then it returns 0 only on
     allocation error. In all cases, 0 is considered the sentinel
     "not a key" value.
  */
  public static native long sqlite3_aggregate_context(sqlite3_context cx, boolean initialize);

  /**
     Functions almost as documented for the C API, with these
     exceptions:
559
560
561
562
563
564
565
566

567
568
569
570
571
572
573
    @NotNull sqlite3 db, @NotNull String dbName,
    @NotNull String tableName, @NotNull String columnName,
    long iRow, int flags ){
    final OutputPointer.sqlite3_blob out = new OutputPointer.sqlite3_blob();
    sqlite3_blob_open(db.getNativePointer(), dbName, tableName, columnName,
                      iRow, flags, out);
    return out.take();
  };


  private static native int sqlite3_blob_read(
    @NotNull long ptrToBlob, @NotNull byte[] target, int srcOffset
  );

  /**
     As per C's sqlite3_blob_read(), but writes its output to the







<
>







554
555
556
557
558
559
560

561
562
563
564
565
566
567
568
    @NotNull sqlite3 db, @NotNull String dbName,
    @NotNull String tableName, @NotNull String columnName,
    long iRow, int flags ){
    final OutputPointer.sqlite3_blob out = new OutputPointer.sqlite3_blob();
    sqlite3_blob_open(db.getNativePointer(), dbName, tableName, columnName,
                      iRow, flags, out);
    return out.take();

  }

  private static native int sqlite3_blob_read(
    @NotNull long ptrToBlob, @NotNull byte[] target, int srcOffset
  );

  /**
     As per C's sqlite3_blob_read(), but writes its output to the
1294
1295
1296
1297
1298
1299
1300
1301

1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317

1318
1319
1320
1321
1322
1323
1324
     <p>Ownership of the returned value is passed to the caller, who must eventually
     pass it to sqlite3_close() or sqlite3_close_v2().
  */
  public static sqlite3 sqlite3_open(@Nullable String filename){
    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
    sqlite3_open(filename, out);
    return out.take();
  };


  public static native int sqlite3_open_v2(
    @Nullable String filename, @NotNull OutputPointer.sqlite3 ppDb,
    int flags, @Nullable String zVfs
  );

  /**
     Has the same semantics as the sqlite3-returning sqlite3_open()
     but uses sqlite3_open_v2() instead of sqlite3_open().
  */
  public static sqlite3 sqlite3_open_v2(@Nullable String filename, int flags,
                                        @Nullable String zVfs){
    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
    sqlite3_open_v2(filename, out, flags, zVfs);
    return out.take();
  };


  /**
     The sqlite3_prepare() family of functions require slightly
     different signatures than their native counterparts, but (A) they
     retain functionally equivalent semantics and (B) overloading
     allows us to install several convenience forms.








<
>















<
>







1289
1290
1291
1292
1293
1294
1295

1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311

1312
1313
1314
1315
1316
1317
1318
1319
     <p>Ownership of the returned value is passed to the caller, who must eventually
     pass it to sqlite3_close() or sqlite3_close_v2().
  */
  public static sqlite3 sqlite3_open(@Nullable String filename){
    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
    sqlite3_open(filename, out);
    return out.take();

  }

  public static native int sqlite3_open_v2(
    @Nullable String filename, @NotNull OutputPointer.sqlite3 ppDb,
    int flags, @Nullable String zVfs
  );

  /**
     Has the same semantics as the sqlite3-returning sqlite3_open()
     but uses sqlite3_open_v2() instead of sqlite3_open().
  */
  public static sqlite3 sqlite3_open_v2(@Nullable String filename, int flags,
                                        @Nullable String zVfs){
    final OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
    sqlite3_open_v2(filename, out, flags, zVfs);
    return out.take();

  }

  /**
     The sqlite3_prepare() family of functions require slightly
     different signatures than their native counterparts, but (A) they
     retain functionally equivalent semantics and (B) overloading
     allows us to install several convenience forms.

1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
    @NotNull long ptrToDb, @NotNull byte[] sqlUtf8, int maxBytes,
    @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  );

  /**
     Works like the canonical sqlite3_prepare_v2() but its "tail"
     output paramter is returned as the index offset into the given
     byte array at which SQL parsing stopped.
  */
  public static int sqlite3_prepare_v2(
    @NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
    @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  ){







|







1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
    @NotNull long ptrToDb, @NotNull byte[] sqlUtf8, int maxBytes,
    @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  );

  /**
     Works like the canonical sqlite3_prepare_v2() but its "tail"
     output parameter is returned as the index offset into the given
     byte array at which SQL parsing stopped.
  */
  public static int sqlite3_prepare_v2(
    @NotNull sqlite3 db, @NotNull byte[] sqlUtf8,
    @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  ){
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
    @NotNull long ptrToDb, @NotNull byte[] sqlUtf8, int maxBytes,
    int prepFlags, @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  );

  /**
     Works like the canonical sqlite3_prepare_v2() but its "tail"
     output paramter is returned as the index offset into the given
     byte array at which SQL parsing stopped.
  */
  public static int sqlite3_prepare_v3(
    @NotNull sqlite3 db, @NotNull byte[] sqlUtf8, int prepFlags,
    @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  ){







|







1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
    @NotNull long ptrToDb, @NotNull byte[] sqlUtf8, int maxBytes,
    int prepFlags, @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  );

  /**
     Works like the canonical sqlite3_prepare_v2() but its "tail"
     output parameter is returned as the index offset into the given
     byte array at which SQL parsing stopped.
  */
  public static int sqlite3_prepare_v3(
    @NotNull sqlite3 db, @NotNull byte[] sqlUtf8, int prepFlags,
    @NotNull OutputPointer.sqlite3_stmt outStmt,
    @Nullable OutputPointer.Int32 pTailOffset
  ){
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
    @NotNull PrepareMultiCallback p){
    final OutputPointer.Int32 oTail = new OutputPointer.Int32();
    int pos = 0, n = 1;
    byte[] sqlChunk = sqlUtf8;
    int rc = 0;
    final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
    while( 0==rc && pos<sqlChunk.length ){
      sqlite3_stmt stmt = null;
      if( pos>0 ){
        sqlChunk = Arrays.copyOfRange(sqlChunk, pos,
                                      sqlChunk.length);
      }
      if( 0==sqlChunk.length ) break;
      rc = sqlite3_prepare_v3(db, sqlChunk, prepFlags, outStmt, oTail);
      if( 0!=rc ) break;







|







1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
    @NotNull PrepareMultiCallback p){
    final OutputPointer.Int32 oTail = new OutputPointer.Int32();
    int pos = 0, n = 1;
    byte[] sqlChunk = sqlUtf8;
    int rc = 0;
    final OutputPointer.sqlite3_stmt outStmt = new OutputPointer.sqlite3_stmt();
    while( 0==rc && pos<sqlChunk.length ){
      sqlite3_stmt stmt;
      if( pos>0 ){
        sqlChunk = Arrays.copyOfRange(sqlChunk, pos,
                                      sqlChunk.length);
      }
      if( 0==sqlChunk.length ) break;
      rc = sqlite3_prepare_v3(db, sqlChunk, prepFlags, outStmt, oTail);
      if( 0!=rc ) break;
Changes to ext/jni/src/org/sqlite/jni/capi/CallbackProxy.java.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
   This marker interface exists soley for use as a documentation and
   class-grouping tool. It should be applied to interfaces or
   classes which have a call() method implementing some specific
   callback interface on behalf of the C library.

   <p>Unless very explicitly documented otherwise, callbacks must
   never throw. Any which do throw but should not might trigger debug
   output regarding the error, but the exception will not be
   propagated.  For callback interfaces which support returning error
   info to the core, the JNI binding will convert any exceptions to
   C-level error information. For callback interfaces which do not
   support returning error information, all exceptions will
   necessarily be suppressed in order to retain the C-style no-throw
   semantics and avoid invoking undefined behavior in the C layer.

   <p>Callbacks of this style follow a common naming convention:

   <p>1) They use the UpperCamelCase form of the C function they're
   proxying for, minus the {@code sqlite3_} prefix, plus a {@code
   Callback} suffix. e.g. {@code sqlite3_busy_handler()}'s callback is
   named {@code BusyHandlerCallback}. Exceptions are made where that
   would potentially be ambiguous, e.g. {@link ConfigSqllogCallback}
   instead of {@code ConfigCallback} because the {@code
   sqlite3_config()} interface may need to support more callback types
   in the future.

   <p>2) They all have a {@code call()} method but its signature is
   callback-specific.
*/
public interface CallbackProxy {}







|




















|








9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file is part of the JNI bindings for the sqlite3 C API.
*/
package org.sqlite.jni.capi;
/**
   This marker interface exists solely for use as a documentation and
   class-grouping tool. It should be applied to interfaces or
   classes which have a call() method implementing some specific
   callback interface on behalf of the C library.

   <p>Unless very explicitly documented otherwise, callbacks must
   never throw. Any which do throw but should not might trigger debug
   output regarding the error, but the exception will not be
   propagated.  For callback interfaces which support returning error
   info to the core, the JNI binding will convert any exceptions to
   C-level error information. For callback interfaces which do not
   support returning error information, all exceptions will
   necessarily be suppressed in order to retain the C-style no-throw
   semantics and avoid invoking undefined behavior in the C layer.

   <p>Callbacks of this style follow a common naming convention:

   <p>1) They use the UpperCamelCase form of the C function they're
   proxying for, minus the {@code sqlite3_} prefix, plus a {@code
   Callback} suffix. e.g. {@code sqlite3_busy_handler()}'s callback is
   named {@code BusyHandlerCallback}. Exceptions are made where that
   would potentially be ambiguous, e.g. {@link ConfigSqlLogCallback}
   instead of {@code ConfigCallback} because the {@code
   sqlite3_config()} interface may need to support more callback types
   in the future.

   <p>2) They all have a {@code call()} method but its signature is
   callback-specific.
*/
public interface CallbackProxy {}
Changes to ext/jni/src/org/sqlite/jni/capi/OutputPointer.java.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
   Helper classes for handling JNI output pointers.

   <p>We do not use a generic OutputPointer<T> because working with those
   from the native JNI code is unduly quirky due to a lack of
   autoboxing at that level.

   <p>The usage is similar for all of thes types:

   <pre>{@code
   OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
   assert( null==out.get() );
   int rc = sqlite3_open(":memory:", out);
   if( 0!=rc ) ... error;
   assert( null!=out.get() );







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
   Helper classes for handling JNI output pointers.

   <p>We do not use a generic OutputPointer<T> because working with those
   from the native JNI code is unduly quirky due to a lack of
   autoboxing at that level.

   <p>The usage is similar for all of these types:

   <pre>{@code
   OutputPointer.sqlite3 out = new OutputPointer.sqlite3();
   assert( null==out.get() );
   int rc = sqlite3_open(":memory:", out);
   if( 0!=rc ) ... error;
   assert( null!=out.get() );
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  public static final class sqlite3 {
    private org.sqlite.jni.capi.sqlite3 value;
    /** Initializes with a null value. */
    public sqlite3(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public final org.sqlite.jni.capi.sqlite3 get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public final org.sqlite.jni.capi.sqlite3 take(){
      final org.sqlite.jni.capi.sqlite3 v = value;
      value = null;
      return v;
    }
  }

  /**
     Output pointer for sqlite3_blob_open(). These
     pointers can only be set by the JNI layer, not by client-level
     code.
  */
  public static final class sqlite3_blob {
    private org.sqlite.jni.capi.sqlite3_blob value;
    /** Initializes with a null value. */
    public sqlite3_blob(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public final org.sqlite.jni.capi.sqlite3_blob get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public final org.sqlite.jni.capi.sqlite3_blob take(){
      final org.sqlite.jni.capi.sqlite3_blob v = value;
      value = null;
      return v;
    }
  }

  /**
     Output pointer for use with routines, such as sqlite3_prepare(),
     which return a statement handle via an output pointer. These
     pointers can only be set by the JNI layer, not by client-level
     code.
  */
  public static final class sqlite3_stmt {
    private org.sqlite.jni.capi.sqlite3_stmt value;
    /** Initializes with a null value. */
    public sqlite3_stmt(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public final org.sqlite.jni.capi.sqlite3_stmt get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public final org.sqlite.jni.capi.sqlite3_stmt take(){
      final org.sqlite.jni.capi.sqlite3_stmt v = value;
      value = null;
      return v;
    }
  }

  /**
     Output pointer for use with routines, such as sqlite3_prepupdate_new(),
     which return a sqlite3_value handle via an output pointer. These
     pointers can only be set by the JNI layer, not by client-level
     code.
  */
  public static final class sqlite3_value {
    private org.sqlite.jni.capi.sqlite3_value value;
    /** Initializes with a null value. */
    public sqlite3_value(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public final org.sqlite.jni.capi.sqlite3_value get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public final org.sqlite.jni.capi.sqlite3_value take(){
      final org.sqlite.jni.capi.sqlite3_value v = value;
      value = null;
      return v;
    }
  }

  /**







|

|


















|

|



















|

|



















|

|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  public static final class sqlite3 {
    private org.sqlite.jni.capi.sqlite3 value;
    /** Initializes with a null value. */
    public sqlite3(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public org.sqlite.jni.capi.sqlite3 get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public org.sqlite.jni.capi.sqlite3 take(){
      final org.sqlite.jni.capi.sqlite3 v = value;
      value = null;
      return v;
    }
  }

  /**
     Output pointer for sqlite3_blob_open(). These
     pointers can only be set by the JNI layer, not by client-level
     code.
  */
  public static final class sqlite3_blob {
    private org.sqlite.jni.capi.sqlite3_blob value;
    /** Initializes with a null value. */
    public sqlite3_blob(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public org.sqlite.jni.capi.sqlite3_blob get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public org.sqlite.jni.capi.sqlite3_blob take(){
      final org.sqlite.jni.capi.sqlite3_blob v = value;
      value = null;
      return v;
    }
  }

  /**
     Output pointer for use with routines, such as sqlite3_prepare(),
     which return a statement handle via an output pointer. These
     pointers can only be set by the JNI layer, not by client-level
     code.
  */
  public static final class sqlite3_stmt {
    private org.sqlite.jni.capi.sqlite3_stmt value;
    /** Initializes with a null value. */
    public sqlite3_stmt(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public org.sqlite.jni.capi.sqlite3_stmt get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public org.sqlite.jni.capi.sqlite3_stmt take(){
      final org.sqlite.jni.capi.sqlite3_stmt v = value;
      value = null;
      return v;
    }
  }

  /**
     Output pointer for use with routines, such as sqlite3_prepupdate_new(),
     which return a sqlite3_value handle via an output pointer. These
     pointers can only be set by the JNI layer, not by client-level
     code.
  */
  public static final class sqlite3_value {
    private org.sqlite.jni.capi.sqlite3_value value;
    /** Initializes with a null value. */
    public sqlite3_value(){value = null;}
    /** Sets the current value to null. */
    public void clear(){value = null;}
    /** Returns the current value. */
    public org.sqlite.jni.capi.sqlite3_value get(){return value;}
    /** Equivalent to calling get() then clear(). */
    public org.sqlite.jni.capi.sqlite3_value take(){
      final org.sqlite.jni.capi.sqlite3_value v = value;
      value = null;
      return v;
    }
  }

  /**
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    */
    public boolean value;
    /** Initializes with the value 0. */
    public Bool(){this(false);}
    /** Initializes with the value v. */
    public Bool(boolean v){value = v;}
    /** Returns the current value. */
    public final boolean get(){return value;}
    /** Sets the current value to v. */
    public final void set(boolean v){value = v;}
  }

  /**
     Output pointer for use with native routines which return integers via
     output pointers.
  */
  public static final class Int32 {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public int value;
    /** Initializes with the value 0. */
    public Int32(){this(0);}
    /** Initializes with the value v. */
    public Int32(int v){value = v;}
    /** Returns the current value. */
    public final int get(){return value;}
    /** Sets the current value to v. */
    public final void set(int v){value = v;}
  }

  /**
     Output pointer for use with native routines which return 64-bit integers
     via output pointers.
  */
  public static final class Int64 {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public long value;
    /** Initializes with the value 0. */
    public Int64(){this(0);}
    /** Initializes with the value v. */
    public Int64(long v){value = v;}
    /** Returns the current value. */
    public final long get(){return value;}
    /** Sets the current value. */
    public final void set(long v){value = v;}
  }

  /**
     Output pointer for use with native routines which return strings via
     output pointers.
  */
  public static final class String {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public java.lang.String value;
    /** Initializes with a null value. */
    public String(){this(null);}
    /** Initializes with the value v. */
    public String(java.lang.String v){value = v;}
    /** Returns the current value. */
    public final java.lang.String get(){return value;}
    /** Sets the current value. */
    public final void set(java.lang.String v){value = v;}
  }

  /**
     Output pointer for use with native routines which return byte
     arrays via output pointers.
  */
  public static final class ByteArray {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public byte[] value;
    /** Initializes with the value null. */
    public ByteArray(){this(null);}
    /** Initializes with the value v. */
    public ByteArray(byte[] v){value = v;}
    /** Returns the current value. */
    public final byte[] get(){return value;}
    /** Sets the current value. */
    public final void set(byte[] v){value = v;}
  }

  /**
     Output pointer for use with native routines which return
     blobs via java.nio.ByteBuffer.

     See {@link org.sqlite.jni.capi.CApi#sqlite3_jni_supports_nio}
  */
  public static final class ByteBuffer {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public java.nio.ByteBuffer value;
    /** Initializes with the value null. */
    public ByteBuffer(){this(null);}
    /** Initializes with the value v. */
    public ByteBuffer(java.nio.ByteBuffer v){value = v;}
    /** Returns the current value. */
    public final java.nio.ByteBuffer get(){return value;}
    /** Sets the current value. */
    public final void set(java.nio.ByteBuffer v){value = v;}
  }
}







|

|

















|

|

















|

|

















|

|

















|

|



















|

|


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    */
    public boolean value;
    /** Initializes with the value 0. */
    public Bool(){this(false);}
    /** Initializes with the value v. */
    public Bool(boolean v){value = v;}
    /** Returns the current value. */
    public boolean get(){return value;}
    /** Sets the current value to v. */
    public void set(boolean v){value = v;}
  }

  /**
     Output pointer for use with native routines which return integers via
     output pointers.
  */
  public static final class Int32 {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public int value;
    /** Initializes with the value 0. */
    public Int32(){this(0);}
    /** Initializes with the value v. */
    public Int32(int v){value = v;}
    /** Returns the current value. */
    public int get(){return value;}
    /** Sets the current value to v. */
    public void set(int v){value = v;}
  }

  /**
     Output pointer for use with native routines which return 64-bit integers
     via output pointers.
  */
  public static final class Int64 {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public long value;
    /** Initializes with the value 0. */
    public Int64(){this(0);}
    /** Initializes with the value v. */
    public Int64(long v){value = v;}
    /** Returns the current value. */
    public long get(){return value;}
    /** Sets the current value. */
    public void set(long v){value = v;}
  }

  /**
     Output pointer for use with native routines which return strings via
     output pointers.
  */
  public static final class String {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public java.lang.String value;
    /** Initializes with a null value. */
    public String(){this(null);}
    /** Initializes with the value v. */
    public String(java.lang.String v){value = v;}
    /** Returns the current value. */
    public java.lang.String get(){return value;}
    /** Sets the current value. */
    public void set(java.lang.String v){value = v;}
  }

  /**
     Output pointer for use with native routines which return byte
     arrays via output pointers.
  */
  public static final class ByteArray {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public byte[] value;
    /** Initializes with the value null. */
    public ByteArray(){this(null);}
    /** Initializes with the value v. */
    public ByteArray(byte[] v){value = v;}
    /** Returns the current value. */
    public byte[] get(){return value;}
    /** Sets the current value. */
    public void set(byte[] v){value = v;}
  }

  /**
     Output pointer for use with native routines which return
     blobs via java.nio.ByteBuffer.

     See {@link org.sqlite.jni.capi.CApi#sqlite3_jni_supports_nio}
  */
  public static final class ByteBuffer {
    /**
       This is public for ease of use. Accessors are provided for
       consistency with the higher-level types.
    */
    public java.nio.ByteBuffer value;
    /** Initializes with the value null. */
    public ByteBuffer(){this(null);}
    /** Initializes with the value v. */
    public ByteBuffer(java.nio.ByteBuffer v){value = v;}
    /** Returns the current value. */
    public java.nio.ByteBuffer get(){return value;}
    /** Sets the current value. */
    public void set(java.nio.ByteBuffer v){value = v;}
  }
}
Changes to ext/jni/src/org/sqlite/jni/capi/PrepareMultiCallback.java.
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    }
  }

  /**
     A PrepareMultiCallback impl which steps entirely through a result set,
     ignoring all non-error results.
  */
  public static final class StepAll implements PrepareMultiCallback {
    public StepAll(){}
    /**
       Calls sqlite3_step() on st until it returns something other than
       SQLITE_ROW. If the final result is SQLITE_DONE then 0 is returned,
       else the result of the final step is returned.
    */
    @Override public int call(sqlite3_stmt st){







|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    }
  }

  /**
     A PrepareMultiCallback impl which steps entirely through a result set,
     ignoring all non-error results.
  */
  final class StepAll implements PrepareMultiCallback {
    public StepAll(){}
    /**
       Calls sqlite3_step() on st until it returns something other than
       SQLITE_ROW. If the final result is SQLITE_DONE then 0 is returned,
       else the result of the final step is returned.
    */
    @Override public int call(sqlite3_stmt st){
Changes to ext/jni/src/org/sqlite/jni/capi/SQLTester.java.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the main application entry pointer for the
** SQLTester framework.
*/
package org.sqlite.jni.capi;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.nio.charset.StandardCharsets;
import java.util.regex.*;
import static org.sqlite.jni.capi.CApi.*;

/**
   Modes for how to escape (or not) column values and names from
   SQLTester.execSql() to the result buffer output.
*/
enum ResultBufferMode {
  //! Do not append to result buffer
  NONE,
  //! Append output escaped.
  ESCAPED,
  //! Append output as-is
  ASIS
};


/**
   Modes to specify how to emit multi-row output from
   SQLTester.execSql() to the result buffer.
*/
enum ResultRowMode {
  //! Keep all result rows on one line, space-separated.
  ONELINE,
  //! Add a newline between each result row.
  NEWLINE
};


/**
   Base exception type for test-related failures.
*/
class SQLTesterException extends RuntimeException {
  private boolean bFatal = false;








<

















<
>










<
>







9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the main application entry pointer for the
** SQLTester framework.
*/
package org.sqlite.jni.capi;

import java.util.ArrayList;
import java.util.Arrays;
import java.nio.charset.StandardCharsets;
import java.util.regex.*;
import static org.sqlite.jni.capi.CApi.*;

/**
   Modes for how to escape (or not) column values and names from
   SQLTester.execSql() to the result buffer output.
*/
enum ResultBufferMode {
  //! Do not append to result buffer
  NONE,
  //! Append output escaped.
  ESCAPED,
  //! Append output as-is
  ASIS

}

/**
   Modes to specify how to emit multi-row output from
   SQLTester.execSql() to the result buffer.
*/
enum ResultRowMode {
  //! Keep all result rows on one line, space-separated.
  ONELINE,
  //! Add a newline between each result row.
  NEWLINE

}

/**
   Base exception type for test-related failures.
*/
class SQLTesterException extends RuntimeException {
  private boolean bFatal = false;

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
    }
    final long tEnd = System.currentTimeMillis();
    outln("Total run-time: ",(tEnd-tStart),"ms");
    Util.unlink(initialDbName);
  }

  private StringBuilder clearBuffer(StringBuilder b){
    b.setLength(0);;
    return b;
  }

  StringBuilder clearInputBuffer(){
    return clearBuffer(inputBuffer);
  }








|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
    }
    final long tEnd = System.currentTimeMillis();
    outln("Total run-time: ",(tEnd-tStart),"ms");
    Util.unlink(initialDbName);
  }

  private StringBuilder clearBuffer(StringBuilder b){
    b.setLength(0);
    return b;
  }

  StringBuilder clearInputBuffer(){
    return clearBuffer(inputBuffer);
  }

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
  }
}

//! --close command
class CloseDbCommand extends Command {
  public void process(SQLTester t, TestScript ts, String[] argv) throws Exception{
    argcCheck(ts,argv,0,1);
    Integer id;
    if(argv.length>1){
      String arg = argv[1];
      if("all".equals(arg)){
        t.closeAllDbs();
        return;
      }
      else{







|







775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
  }
}

//! --close command
class CloseDbCommand extends Command {
  public void process(SQLTester t, TestScript ts, String[] argv) throws Exception{
    argcCheck(ts,argv,0,1);
    int id;
    if(argv.length>1){
      String arg = argv[1];
      if("all".equals(arg)){
        t.closeAllDbs();
        return;
      }
      else{
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
    argcCheck(ts,argv,1);
    ts.setVerbosity( Integer.parseInt(argv[1]) );
  }
}

class CommandDispatcher {

  private static java.util.Map<String,Command> commandMap =
    new java.util.HashMap<>();

  /**
     Returns a (cached) instance mapped to name, or null if no match
     is found.
  */
  static Command getCommandByName(String name){







|







1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
    argcCheck(ts,argv,1);
    ts.setVerbosity( Integer.parseInt(argv[1]) );
  }
}

class CommandDispatcher {

  private static final java.util.Map<String,Command> commandMap =
    new java.util.HashMap<>();

  /**
     Returns a (cached) instance mapped to name, or null if no match
     is found.
  */
  static Command getCommandByName(String name){
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
            i += nChar-1;
          }
          break;
      }
    }
    cur.pos = i;
    final String rv = cur.sb.toString();
    if( i==cur.src.length && 0==rv.length() ){
      return null /* EOF */;
    }
    return rv;
  }/*getLine()*/

  /**
     Fetches the next line then resets the cursor to its pre-call







|







1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
            i += nChar-1;
          }
          break;
      }
    }
    cur.pos = i;
    final String rv = cur.sb.toString();
    if( i==cur.src.length && rv.isEmpty() ){
      return null /* EOF */;
    }
    return rv;
  }/*getLine()*/

  /**
     Fetches the next line then resets the cursor to its pre-call
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
        throw new IncompatibleDirective(this, "REQUIRED_PROPERTIES: "+rp);
      }
    }
    m = patternMixedModuleName.matcher(line);
    if( m.find() ){
      throw new IncompatibleDirective(this, m.group(1)+": "+m.group(3));
    }
    if( line.indexOf("\n|")>=0 ){
      throw new IncompatibleDirective(this, "newline-pipe combination.");
    }
    return;
  }

  boolean isCommandLine(String line, boolean checkForImpl){
    final Matcher m = patternCommand.matcher(line);







|







1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
        throw new IncompatibleDirective(this, "REQUIRED_PROPERTIES: "+rp);
      }
    }
    m = patternMixedModuleName.matcher(line);
    if( m.find() ){
      throw new IncompatibleDirective(this, m.group(1)+": "+m.group(3));
    }
    if( line.contains("\n|") ){
      throw new IncompatibleDirective(this, "newline-pipe combination.");
    }
    return;
  }

  boolean isCommandLine(String line, boolean checkForImpl){
    final Matcher m = patternCommand.matcher(line);