SQLite Android Bindings

Check-in [530b9f3aef]
Login

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

Overview
Comment:Merge fix for supplementary unicode characters with this branch.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | api-level-15
Files: files | file ages | folders
SHA1: 530b9f3aef3d0ad612b945803cd3fa5fd7c17fef
User & Date: dan 2015-03-03 15:42:12.930
Context
2015-04-04
08:23
Apply the 64-bit pointer fix to this branch. (check-in: 2aa724ae34 user: dan tags: api-level-15)
2015-03-03
15:42
Merge fix for supplementary unicode characters with this branch. (check-in: 530b9f3aef user: dan tags: api-level-15)
15:38
Fix a problem in the handling of supplementary unicode characters. (check-in: 20f8872529 user: dan tags: trunk)
2014-11-05
19:19
Merge latest fixes with this branch. (check-in: 60e268f5be user: dan tags: api-level-15)
Changes
Unified Diff Ignore Whitespace Patch
Changes to jni/sqlite/android_database_SQLiteConnection.cpp.
670
671
672
673
674
675
676
677

678
679
680
681
682
683
684
685
      case SQLITE_FLOAT: {
        jdouble val = sqlite3_column_double(pStmt, i);
        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTDOUBLE].id, val, iRow, i);
        break;
      }

      case SQLITE_TEXT: {
        const char *zVal = (const char*)sqlite3_column_text(pStmt, i);

        jstring val = pEnv->NewStringUTF(zVal);
        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTSTRING].id, val, iRow, i);
        pEnv->DeleteLocalRef(val);
        break;
      }

      default: {
        assert( sqlite3_column_type(pStmt, i)==SQLITE_BLOB );







|
>
|







670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
      case SQLITE_FLOAT: {
        jdouble val = sqlite3_column_double(pStmt, i);
        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTDOUBLE].id, val, iRow, i);
        break;
      }

      case SQLITE_TEXT: {
        jchar *pStr = (jchar*)sqlite3_column_text16(pStmt, i);
        int nStr = sqlite3_column_bytes16(pStmt, i) / sizeof(jchar);
        jstring val = pEnv->NewString(pStr, nStr);
        bOk = pEnv->CallBooleanMethod(win, aMethod[CW_PUTSTRING].id, val, iRow, i);
        pEnv->DeleteLocalRef(val);
        break;
      }

      default: {
        assert( sqlite3_column_type(pStmt, i)==SQLITE_BLOB );
Changes to src/org/sqlite/app/customsqlite/CustomSqlite.java.
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
254
255
256
257
258
259
260



261

262


263
264
265
266
267
268

269
270

271
272
273
274
275
276
277
    }else{
      test_warning("csr_test_1", "c==NULL");
    }
    test_result("csr_test_2.2", "" + nRow, "15000");

    db.close();
  }














  public void csr_test_1() throws Exception {
    SQLiteDatabase.deleteDatabase(DB_PATH);
    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
    String res = "";

    db.execSQL("CREATE TABLE t1(x)");
    db.execSQL("INSERT INTO t1 VALUES ('one'), ('two'), ('three')");
    
    Cursor c = db.rawQuery("SELECT x FROM t1", null);
    if( c!=null ){
      boolean bRes;
      for(bRes=c.moveToFirst(); bRes; bRes=c.moveToNext()){
        String x = c.getString(0);
        res = res + "." + x;
      }
    }else{
      test_warning("csr_test_1", "c==NULL");
    }
    test_result("csr_test_1.1", res, ".one.two.three");

    db.close();
    test_result("csr_test_1.2", db_is_encrypted(), "unencrypted");
  }


  public void stmt_jrnl_test_1() throws Exception {
    SQLiteDatabase.deleteDatabase(DB_PATH);
    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
    String res = "";

    db.execSQL("CREATE TABLE t1(x, y UNIQUE)");
    db.execSQL("BEGIN");
      db.execSQL("INSERT INTO t1 VALUES(1, 1), (2, 2), (3, 3)");
      db.execSQL("UPDATE t1 SET y=y+3");
    db.execSQL("COMMIT");
    db.close();
    test_result("stmt_jrnl_test_1.1", "did not crash", "did not crash");
  }

  public String string_from_t1_x(SQLiteDatabase db){



    String res = "";




    Cursor c = db.rawQuery("SELECT x FROM t1", null);
    boolean bRes;
    for(bRes=c.moveToFirst(); bRes; bRes=c.moveToNext()){
      String x = c.getString(0);
      res = res + "." + x;
    }


    return res;

  }

  /*
  ** If this is a SEE build, check that encrypted databases work.
  */
  public void see_test_1() throws Exception {
    if( !SQLiteDatabase.hasCodec() ) return;







>
>
>
>
>
>
>
>
>
>
>
>
>









<
<
<
<
<
|
<
<
<
<





<















|
>
>
>

>

>
>
|
<
<
<
|
|
>

<
>







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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272



273
274
275
276

277
278
279
280
281
282
283
284
    }else{
      test_warning("csr_test_1", "c==NULL");
    }
    test_result("csr_test_2.2", "" + nRow, "15000");

    db.close();
  }

  public String string_from_t1_x(SQLiteDatabase db){
    String res = "";

    Cursor c = db.rawQuery("SELECT x FROM t1", null);
    boolean bRes;
    for(bRes=c.moveToFirst(); bRes; bRes=c.moveToNext()){
      String x = c.getString(0);
      res = res + "." + x;
    }

    return res;
  }

  public void csr_test_1() throws Exception {
    SQLiteDatabase.deleteDatabase(DB_PATH);
    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
    String res = "";

    db.execSQL("CREATE TABLE t1(x)");
    db.execSQL("INSERT INTO t1 VALUES ('one'), ('two'), ('three')");
    





    res = string_from_t1_x(db);




    test_result("csr_test_1.1", res, ".one.two.three");

    db.close();
    test_result("csr_test_1.2", db_is_encrypted(), "unencrypted");
  }


  public void stmt_jrnl_test_1() throws Exception {
    SQLiteDatabase.deleteDatabase(DB_PATH);
    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
    String res = "";

    db.execSQL("CREATE TABLE t1(x, y UNIQUE)");
    db.execSQL("BEGIN");
      db.execSQL("INSERT INTO t1 VALUES(1, 1), (2, 2), (3, 3)");
      db.execSQL("UPDATE t1 SET y=y+3");
    db.execSQL("COMMIT");
    db.close();
    test_result("stmt_jrnl_test_1.1", "did not crash", "did not crash");
  }


  public void supp_char_test_1() throws Exception {
    SQLiteDatabase.deleteDatabase(DB_PATH);
    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null);
    String res = "";
    String smiley = new String( Character.toChars(0x10000) );

    db.execSQL("CREATE TABLE t1(x)");
    db.execSQL("INSERT INTO t1 VALUES ('a" + smiley + "b')");




    res = string_from_t1_x(db);
    
    test_result("supp_char_test1." + smiley, res, ".a" + smiley + "b");


    db.close();
  }

  /*
  ** If this is a SEE build, check that encrypted databases work.
  */
  public void see_test_1() throws Exception {
    if( !SQLiteDatabase.hasCodec() ) return;
368
369
370
371
372
373
374

375
376
377
378
379
380
381

    myTV.setText("");
    myNErr = 0;
    myNTest = 0;

    try {
      report_version();

      csr_test_1();
      csr_test_2();
      thread_test_1();
      thread_test_2(); 
      see_test_1();
      see_test_2();
      stmt_jrnl_test_1();







>







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

    myTV.setText("");
    myNErr = 0;
    myNTest = 0;

    try {
      report_version();
      supp_char_test_1();
      csr_test_1();
      csr_test_2();
      thread_test_1();
      thread_test_2(); 
      see_test_1();
      see_test_2();
      stmt_jrnl_test_1();
Changes to www/index.wiki.
65
66
67
68
69
70
71














72
73
74
75
76
77
78
  the jni/ directory (including the custom SQLite version) to shared libraries
  that will be deployed to the device along with the application. Assuming
  it is successful, unless you modify the sources or makefiles within the
  jni/ directory structure, you should not need to run "ndk-build" again.

<h3>Application Programming</h3>















<p>
  The classes that make up the built-in Android SQLite interface reside in
  the "android.database.sqlite" namespace. This interface provides all of
  the same classes, except within the "org.sqlite.database.sqlite" namespace.
  This means that to modify an application to use the custom version of 
  SQLite, all that is usually required is to replace all occurrences
  "android.database.sqlite" within the source code with







>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  the jni/ directory (including the custom SQLite version) to shared libraries
  that will be deployed to the device along with the application. Assuming
  it is successful, unless you modify the sources or makefiles within the
  jni/ directory structure, you should not need to run "ndk-build" again.

<h3>Application Programming</h3>

<p>
  Before using any SQLite related methods or objects, the shared library
  compiled using the ndk must be loaded into the application using the
  following code:

<verbatim>
  System.loadLibrary("sqliteX");
</verbatim>

<p>
  One way to ensure that the shared library is loaded early enough is
  to add it to a "static" block within the declaration of the application's
  main Activity class.

<p>
  The classes that make up the built-in Android SQLite interface reside in
  the "android.database.sqlite" namespace. This interface provides all of
  the same classes, except within the "org.sqlite.database.sqlite" namespace.
  This means that to modify an application to use the custom version of 
  SQLite, all that is usually required is to replace all occurrences
  "android.database.sqlite" within the source code with