SQLite Android Bindings
Check-in [e8a9b149f7]
Not logged in

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

Overview
Comment:Restore standard behaviours of (a) activating a connection pool in wal mode and (b) switching into wal mode automatically if the flag is set even if SQLITE_HAS_CODEC is defined (they were previously disabled in this case). Strip any URI parameters from the database name before it is included in any log messages. Always build with SQLITE_USE_URI=1 defined.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e8a9b149f74f517b80ad0b2fc723a7cb7ccf8d2b
User & Date: dan 2017-05-03 18:18:33
References
2018-09-24
19:06
Partly revert [e8a9b149f7] so that for SEE-enabled builds, the journal mode of the database is not changed to match the configuration flags as soon as it is opened. check-in: 8a027aa451 user: dan tags: trunk
Context
2017-05-03
19:59
Update see.wiki to advise use of a URI parameter instead of "PRAGMA key = ?". check-in: 7a62c59e53 user: dan tags: trunk
18:18
Restore standard behaviours of (a) activating a connection pool in wal mode and (b) switching into wal mode automatically if the flag is set even if SQLITE_HAS_CODEC is defined (they were previously disabled in this case). Strip any URI parameters from the database name before it is included in any log messages. Always build with SQLITE_USE_URI=1 defined. check-in: e8a9b149f7 user: dan tags: trunk
2017-05-02
19:54
Add a new test that uses AndroidJUnit4. And related gradle changes. check-in: 40f79eca30 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to sqlite3/src/androidTest/java/org/sqlite/database/SeeTest1.java.

     1      1   package org.sqlite.database;
     2      2   
     3         -
     4      3   import android.content.Context;
     5      4   import android.database.Cursor;
     6      5   import android.os.AsyncTask;
     7      6   import android.support.test.InstrumentationRegistry;
     8      7   import android.support.test.runner.AndroidJUnit4;
            8  +import android.util.Log;
     9      9   
    10     10   import junit.framework.Assert;
    11     11   
    12     12   import org.junit.Before;
    13     13   import org.junit.Test;
    14     14   import org.junit.runner.RunWith;
    15     15   
           16  +import org.sqlite.database.sqlite.SQLiteConnection;
    16     17   import org.sqlite.database.sqlite.SQLiteDatabase;
    17     18   import org.sqlite.database.sqlite.SQLiteOpenHelper;
    18     19   
    19     20   import java.io.File;
           21  +import java.io.FileInputStream;
           22  +import java.util.Arrays;
    20     23   
    21     24   import static org.junit.Assert.*;
    22     25   
    23     26   
    24     27   class MyHelper extends SQLiteOpenHelper {
    25     28   
    26     29       public static final String DATABASE_NAME = "mydb.db";
    27     30   
    28     31       public MyHelper(Context ctx){
    29         -        super(ctx, ctx.getDatabasePath(DATABASE_NAME).getAbsolutePath(), null, 1);
           32  +        super(ctx, "file:" + ctx.getDatabasePath(DATABASE_NAME).getAbsolutePath() + "?key=secret", null, 1);
    30     33       }
    31     34       public void onConfigure(SQLiteDatabase db){
    32         -        db.execSQL("PRAGMA key = 'secret'");
    33         -
    34     35           db.enableWriteAheadLogging();
    35         -
    36         -        final Cursor pragmaCursor = db.rawQuery("PRAGMA journal_mode = WAL", null);
    37         -        pragmaCursor.moveToFirst();
    38         -        pragmaCursor.close();
    39     36       }
    40     37       public void onCreate(SQLiteDatabase db){
    41     38           db.execSQL("CREATE TABLE t1(x)");
    42     39       }
    43     40       public void onUpgrade(SQLiteDatabase db, int iOld, int iNew){
    44     41       }
    45     42   }
................................................................................
    46     43   
    47     44   
    48     45   /**
    49     46    * Created by dan on 5/3/17.
    50     47    */
    51     48   @RunWith(AndroidJUnit4.class)
    52     49   public class SeeTest1 {
    53         -        private Context mContext;
           50  +    private Context mContext;
           51  +
           52  +    /*
           53  +    ** Test if the database at path is encrypted or not. The db
           54  +    ** is assumed to be encrypted if the first 6 bytes are anything
           55  +    ** other than "SQLite".
           56  +    **
           57  +    ** If the test reveals that the db is encrypted, return the string
           58  +    ** "encrypted". Otherwise, "unencrypted".
           59  +    */
           60  +    public String db_is_encrypted(String path) throws Exception {
           61  +      FileInputStream in = new FileInputStream(mContext.getDatabasePath(path));
           62  +
           63  +      byte[] buffer = new byte[6];
           64  +      in.read(buffer, 0, 6);
           65  +
           66  +      String res = "encrypted";
           67  +      if( Arrays.equals(buffer, (new String("SQLite")).getBytes()) ){
           68  +        res = "unencrypted";
           69  +      }
           70  +      return res;
           71  +    }
    54     72   
    55     73       @Before
    56     74       public void setup() throws Exception {
    57     75   
    58     76           System.loadLibrary("sqliteX");
    59     77   
    60     78           mContext = InstrumentationRegistry.getTargetContext();
................................................................................
    64     82           databaseFile.mkdirs();
    65     83           if (databaseFile.exists()) {
    66     84               databaseFile.delete();
    67     85           }
    68     86       }
    69     87   
    70     88       @Test
    71         -    public void testAndroidDefaultWalMode() throws Exception {
           89  +    public void testEncryptedWalMode() throws Exception {
    72     90           // create database
    73     91           final MyHelper helper = new MyHelper(mContext);
    74     92           helper.getWritableDatabase();
    75     93   
    76     94           // verify that WAL journal mode is set
    77     95           final Cursor pragmaCursor = helper.getWritableDatabase().rawQuery("PRAGMA journal_mode", null);
    78     96           pragmaCursor.moveToFirst();
    79         -        Assert.assertEquals(pragmaCursor.getString(pragmaCursor.getColumnIndex("journal_mode")), "wal");
           97  +        Assert.assertEquals("wal", pragmaCursor.getString(pragmaCursor.getColumnIndex("journal_mode")));
    80     98           pragmaCursor.close();
    81     99   
    82    100           // start long running transaction
    83    101           AsyncTask.execute(new Runnable() {
    84    102               @Override
    85    103               public void run() {
    86    104                   helper.getWritableDatabase().beginTransactionNonExclusive();
................................................................................
   105    123           //try to read something from the database while the slow transaction is running
   106    124           helper.getWritableDatabase().execSQL("SELECT * FROM t1");
   107    125   
   108    126           //verify that the operation didn't wait until the 3000ms long operation finished
   109    127           if (System.currentTimeMillis() - startTime > 3000) {
   110    128               throw new Exception("WAL mode isn't working corectly - read operation was blocked");
   111    129           }
          130  +
          131  +        if( SQLiteConnection.hasCodec() ){
          132  +          Assert.assertEquals("encrypted", db_is_encrypted(MyHelper.DATABASE_NAME));
          133  +        } else {
          134  +          Assert.assertEquals("unencrypted", db_is_encrypted(MyHelper.DATABASE_NAME));
          135  +        }
   112    136       }
   113    137   }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java.

   218    218                   mConfiguration.label,
   219    219                   SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);
   220    220   
   221    221           setPageSize();
   222    222           setForeignKeyModeFromConfiguration();
   223    223           setJournalSizeLimit();
   224    224   	setAutoCheckpointInterval();
   225         -	if( !nativeHasCodec() ){
   226         -	  setWalModeFromConfiguration();
   227         -          setLocaleFromConfiguration();
   228         -	}
          225  +        setWalModeFromConfiguration();
          226  +        setLocaleFromConfiguration();
   229    227   
   230    228           // Register custom functions.
   231    229           final int functionCount = mConfiguration.customFunctions.size();
   232    230           for (int i = 0; i < functionCount; i++) {
   233    231               SQLiteCustomFunction function = mConfiguration.customFunctions.get(i);
   234    232               nativeRegisterCustomFunction(mConnectionPtr, function);
   235    233           }

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java.

   946    946       }
   947    947   
   948    948       private static int getPriority(int connectionFlags) {
   949    949           return (connectionFlags & CONNECTION_FLAG_INTERACTIVE) != 0 ? 1 : 0;
   950    950       }
   951    951   
   952    952       private void setMaxConnectionPoolSizeLocked() {
   953         -        if( !SQLiteDatabase.hasCodec()
   954         -	 && (mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0
   955         -	) {
          953  +        if ((mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
   956    954               mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
   957    955           } else {
   958    956               // TODO: We don't actually need to restrict the connection pool size to 1
   959    957               // for non-WAL databases.  There might be reasons to use connection pooling
   960    958               // with other journal modes.  For now, enabling connection pooling and
   961    959               // using WAL are the same thing in the API.
   962    960               mMaxConnectionPoolSize = 1;

Changes to sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabaseConfiguration.java.

   157    157        * @return True if the database is in-memory.
   158    158        */
   159    159       public boolean isInMemoryDb() {
   160    160           return path.equalsIgnoreCase(MEMORY_DB_PATH);
   161    161       }
   162    162   
   163    163       private static String stripPathForLogs(String path) {
          164  +        /* Strip off all URI parameters. */
          165  +        int iIdx = path.indexOf('?');
          166  +        if( iIdx>=0 ){
          167  +            path = (String) path.subSequence(0, iIdx);
          168  +        }
          169  +
   164    170           if (path.indexOf('@') == -1) {
   165    171               return path;
   166    172           }
   167    173           return EMAIL_IN_DB_PATTERN.matcher(path).replaceAll("XX@YY");
   168    174       }
   169    175   }

Changes to sqlite3/src/main/jni/sqlite/Android.mk.

    20     20   #
    21     21   LOCAL_CFLAGS += -DSQLITE_TEMP_STORE=3
    22     22   
    23     23   LOCAL_CFLAGS += -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA
    24     24   LOCAL_CFLAGS += -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL
    25     25   LOCAL_CFLAGS += -U__APPLE__
    26     26   LOCAL_CFLAGS += -DHAVE_STRCHRNUL=0
           27  +LOCAL_CFLAGS += -DSQLITE_USE_URI=1
    27     28   LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast
    28         -LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
           29  +LOCAL_CFLAGS += -Wno-uninitialized -Wno-parentheses
    29     30   LOCAL_CPPFLAGS += -Wno-conversion-null
    30     31   
    31     32   
    32     33   ifeq ($(TARGET_ARCH), arm)
    33     34   	LOCAL_CFLAGS += -DPACKED="__attribute__ ((packed))"
    34     35   else
    35     36   	LOCAL_CFLAGS += -DPACKED=""