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

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

Overview
Comment:Update further java classfiles to match the latest Android code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e782e01fbe7dd7b3c78a359cf8b9875632b7a4a8
User & Date: dan 2017-11-28 15:46:24
Context
2017-11-28
17:05
Update some other files to better match stock Android. check-in: 253313a7ee user: dan tags: trunk
15:46
Update further java classfiles to match the latest Android code. check-in: e782e01fbe user: dan tags: trunk
08:22
Update a couple of java source files to more closely match their Android counterparts. check-in: 20bdb663b0 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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

  1679   1679               } finally {
  1680   1680                   statement.close();
  1681   1681               }
  1682   1682           } finally {
  1683   1683               releaseReference();
  1684   1684           }
  1685   1685       }
         1686  +
         1687  +    /**
         1688  +     * Verifies that a SQL SELECT statement is valid by compiling it.
         1689  +     * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
         1690  +     *
         1691  +     * @param sql SQL to be validated
         1692  +     * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
         1693  +     * If the operation is canceled, then {@link OperationCanceledException} will be thrown
         1694  +     * when the query is executed.
         1695  +     * @throws SQLiteException if {@code sql} is invalid
         1696  +     */
         1697  +    public void validateSql(String sql, CancellationSignal cancellationSignal) {
         1698  +        getThreadSession().prepare(sql,
         1699  +                getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null);
         1700  +    }
  1686   1701   
  1687   1702       /**
  1688   1703        * Returns true if the database is opened as read only.
  1689   1704        *
  1690   1705        * @return True if database is opened as read only.
  1691   1706        */
  1692   1707       public boolean isReadOnly() {

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

    13     13    * See the License for the specific language governing permissions and
    14     14    * limitations under the License.
    15     15    */
    16     16   /*
    17     17   ** Modified to support SQLite extensions by the SQLite developers: 
    18     18   ** sqlite-dev@sqlite.org.
    19     19   */
           20  +
    20     21   
    21     22   package org.sqlite.database.sqlite;
    22     23   
    23     24   import android.content.Context;
    24     25   import org.sqlite.database.DatabaseErrorHandler;
    25         -import org.sqlite.database.DefaultDatabaseErrorHandler;
    26     26   import org.sqlite.database.sqlite.SQLiteDatabase.CursorFactory;
    27     27   import android.util.Log;
           28  +import java.io.File;
    28     29   
    29     30   /**
    30     31    * A helper class to manage database creation and version management.
    31     32    *
    32     33    * <p>You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and
    33     34    * optionally {@link #onOpen}, and this class takes care of opening the database
    34     35    * if it exists, creating it if it does not, and upgrading it as necessary.
................................................................................
    55     56       // wanted getWritableDatabase.
    56     57       private static final boolean DEBUG_STRICT_READONLY = false;
    57     58   
    58     59       private final Context mContext;
    59     60       private final String mName;
    60     61       private final CursorFactory mFactory;
    61     62       private final int mNewVersion;
           63  +    private final int mMinimumSupportedVersion;
    62     64   
    63     65       private SQLiteDatabase mDatabase;
    64     66       private boolean mIsInitializing;
    65     67       private boolean mEnableWriteAheadLogging;
    66     68       private final DatabaseErrorHandler mErrorHandler;
    67     69   
    68     70       /**
................................................................................
    97     99        *     {@link #onUpgrade} will be used to upgrade the database; if the database is
    98    100        *     newer, {@link #onDowngrade} will be used to downgrade the database
    99    101        * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
   100    102        * corruption, or null to use the default error handler.
   101    103        */
   102    104       public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
   103    105               DatabaseErrorHandler errorHandler) {
          106  +        this(context, name, factory, version, 0, errorHandler);
          107  +    }
          108  +
          109  +    /**
          110  +     * Same as {@link #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)}
          111  +     * but also accepts an integer minimumSupportedVersion as a convenience for upgrading very old
          112  +     * versions of this database that are no longer supported. If a database with older version that
          113  +     * minimumSupportedVersion is found, it is simply deleted and a new database is created with the
          114  +     * given name and version
          115  +     *
          116  +     * @param context to use to open or create the database
          117  +     * @param name the name of the database file, null for a temporary in-memory database
          118  +     * @param factory to use for creating cursor objects, null for default
          119  +     * @param version the required version of the database
          120  +     * @param minimumSupportedVersion the minimum version that is supported to be upgraded to
          121  +     *            {@code version} via {@link #onUpgrade}. If the current database version is lower
          122  +     *            than this, database is simply deleted and recreated with the version passed in
          123  +     *            {@code version}. {@link #onBeforeDelete} is called before deleting the database
          124  +     *            when this happens. This is 0 by default.
          125  +     * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
          126  +     *            corruption, or null to use the default error handler.
          127  +     * @see #onBeforeDelete(SQLiteDatabase)
          128  +     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)
          129  +     * @see #onUpgrade(SQLiteDatabase, int, int)
          130  +     * @hide
          131  +     */
          132  +    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
          133  +            int minimumSupportedVersion, DatabaseErrorHandler errorHandler) {
   104    134           if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);
   105    135   
   106    136           mContext = context;
   107    137           mName = name;
   108    138           mFactory = factory;
   109    139           mNewVersion = version;
   110    140           mErrorHandler = errorHandler;
          141  +        mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
   111    142       }
   112    143   
   113    144       /**
   114    145        * Return the name of the SQLite database being opened, as given to
   115    146        * the constructor.
   116    147        */
   117    148       public String getDatabaseName() {
................................................................................
   222    253                   try {
   223    254                       if (DEBUG_STRICT_READONLY && !writable) {
   224    255                           final String path = mContext.getDatabasePath(mName).getPath();
   225    256                           db = SQLiteDatabase.openDatabase(path, mFactory,
   226    257                                   SQLiteDatabase.OPEN_READONLY, mErrorHandler);
   227    258                       } else {
   228    259                           db = SQLiteDatabase.openOrCreateDatabase(
   229         -                                mName, mFactory, mErrorHandler
          260  +                            mName, mFactory, mErrorHandler
   230    261                           );
   231    262                       }
   232    263                   } catch (SQLiteException ex) {
   233    264                       if (writable) {
   234    265                           throw ex;
   235    266                       }
   236    267                       Log.e(TAG, "Couldn't open " + mName
................................................................................
   246    277               final int version = db.getVersion();
   247    278               if (version != mNewVersion) {
   248    279                   if (db.isReadOnly()) {
   249    280                       throw new SQLiteException("Can't upgrade read-only database from version " +
   250    281                               db.getVersion() + " to " + mNewVersion + ": " + mName);
   251    282                   }
   252    283   
   253         -                db.beginTransaction();
   254         -                try {
   255         -                    if (version == 0) {
   256         -                        onCreate(db);
          284  +                if (version > 0 && version < mMinimumSupportedVersion) {
          285  +                    File databaseFile = new File(db.getPath());
          286  +                    onBeforeDelete(db);
          287  +                    db.close();
          288  +                    if (SQLiteDatabase.deleteDatabase(databaseFile)) {
          289  +                        mIsInitializing = false;
          290  +                        return getDatabaseLocked(writable);
   257    291                       } else {
   258         -                        if (version > mNewVersion) {
   259         -                            onDowngrade(db, version, mNewVersion);
   260         -                        } else {
   261         -                            onUpgrade(db, version, mNewVersion);
   262         -                        }
          292  +                        throw new IllegalStateException("Unable to delete obsolete database "
          293  +                                + mName + " with version " + version);
   263    294                       }
   264         -                    db.setVersion(mNewVersion);
   265         -                    db.setTransactionSuccessful();
   266         -                } finally {
   267         -                    db.endTransaction();
          295  +                } else {
          296  +                    db.beginTransaction();
          297  +                    try {
          298  +                        if (version == 0) {
          299  +                            onCreate(db);
          300  +                        } else {
          301  +                            if (version > mNewVersion) {
          302  +                                onDowngrade(db, version, mNewVersion);
          303  +                            } else {
          304  +                                onUpgrade(db, version, mNewVersion);
          305  +                            }
          306  +                        }
          307  +                        db.setVersion(mNewVersion);
          308  +                        db.setTransactionSuccessful();
          309  +                    } finally {
          310  +                        db.endTransaction();
          311  +                    }
   268    312                   }
   269    313               }
   270    314   
   271    315               onOpen(db);
   272    316   
   273    317               if (db.isReadOnly()) {
   274    318                   Log.w(TAG, "Opened " + mName + " in read-only mode");
................................................................................
   293    337           if (mDatabase != null && mDatabase.isOpen()) {
   294    338               mDatabase.close();
   295    339               mDatabase = null;
   296    340           }
   297    341       }
   298    342   
   299    343       /**
   300         -     * Called when the database connection is being configured, to enable features
   301         -     * such as write-ahead logging or foreign key support.
          344  +     * Called when the database connection is being configured, to enable features such as
          345  +     * write-ahead logging or foreign key support.
          346  +     * <p>
          347  +     * This method is called before {@link #onCreate}, {@link #onUpgrade}, {@link #onDowngrade}, or
          348  +     * {@link #onOpen} are called. It should not modify the database except to configure the
          349  +     * database connection as required.
          350  +     * </p>
   302    351        * <p>
   303         -     * This method is called before {@link #onCreate}, {@link #onUpgrade},
   304         -     * {@link #onDowngrade}, or {@link #onOpen} are called.  It should not modify
   305         -     * the database except to configure the database connection as required.
   306         -     * </p><p>
   307         -     * This method should only call methods that configure the parameters of the
   308         -     * database connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
   309         -     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled},
   310         -     * {@link SQLiteDatabase#setLocale}, {@link SQLiteDatabase#setMaximumSize},
   311         -     * or executing PRAGMA statements.
          352  +     * This method should only call methods that configure the parameters of the database
          353  +     * connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
          354  +     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled}, {@link SQLiteDatabase#setLocale},
          355  +     * {@link SQLiteDatabase#setMaximumSize}, or executing PRAGMA statements.
   312    356        * </p>
   313    357        *
   314    358        * @param db The database.
   315    359        */
   316    360       public void onConfigure(SQLiteDatabase db) {}
          361  +
          362  +    /**
          363  +     * Called before the database is deleted when the version returned by
          364  +     * {@link SQLiteDatabase#getVersion()} is lower than the minimum supported version passed (if at
          365  +     * all) while creating this helper. After the database is deleted, a fresh database with the
          366  +     * given version is created. This will be followed by {@link #onConfigure(SQLiteDatabase)} and
          367  +     * {@link #onCreate(SQLiteDatabase)} being called with a new SQLiteDatabase object
          368  +     *
          369  +     * @param db the database opened with this helper
          370  +     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, int, DatabaseErrorHandler)
          371  +     * @hide
          372  +     */
          373  +    public void onBeforeDelete(SQLiteDatabase db) {
          374  +    }
   317    375   
   318    376       /**
   319    377        * Called when the database is created for the first time. This is where the
   320    378        * creation of tables and the initial population of the tables should happen.
   321    379        *
   322    380        * @param db The database.
   323    381        */

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

   386    386               // The idea is to ensure that the selection clause is a valid SQL expression
   387    387               // by compiling it twice: once wrapped in parentheses and once as
   388    388               // originally specified. An attacker cannot create an expression that
   389    389               // would escape the SQL expression while maintaining balanced parentheses
   390    390               // in both the wrapped and original forms.
   391    391               String sqlForValidation = buildQuery(projectionIn, "(" + selection + ")", groupBy,
   392    392                       having, sortOrder, limit);
   393         -            validateQuerySql(db, sqlForValidation,
   394         -                    cancellationSignal); // will throw if query is invalid
          393  +            db.validateSql(sqlForValidation, cancellationSignal); // will throw if query is invalid
   395    394           }
   396    395   
   397    396           String sql = buildQuery(
   398    397                   projectionIn, selection, groupBy, having,
   399    398                   sortOrder, limit);
   400    399   
   401    400           if (Log.isLoggable(TAG, Log.DEBUG)) {
................................................................................
   403    402           }
   404    403           return db.rawQueryWithFactory(
   405    404                   mFactory, sql, selectionArgs,
   406    405                   SQLiteDatabase.findEditTable(mTables),
   407    406                   cancellationSignal); // will throw if query is invalid
   408    407       }
   409    408   
   410         -    /**
   411         -     * Verifies that a SQL SELECT statement is valid by compiling it.
   412         -     * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
   413         -     */
   414         -    private void validateQuerySql(SQLiteDatabase db, String sql,
   415         -            CancellationSignal cancellationSignal) {
   416         -        db.getThreadSession().prepare(sql,
   417         -                db.getThreadDefaultConnectionFlags(true /*readOnly*/), cancellationSignal, null);
   418         -    }
   419         -
   420    409       /**
   421    410        * Construct a SELECT statement suitable for use in a group of
   422    411        * SELECT statements that will be joined through UNION operators
   423    412        * in buildUnionQuery.
   424    413        *
   425    414        * @param projectionIn A list of which columns to return. Passing
   426    415        *    null will return all columns, which is discouraged to

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

    35     35           super(db, sql, bindArgs, null);
    36     36       }
    37     37   
    38     38       /**
    39     39        * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
    40     40        * CREATE / DROP table, view, trigger, index etc.
    41     41        *
    42         -     * @throws org.sqlite.database.SQLException If the SQL string is invalid for
           42  +     * @throws android.database.SQLException If the SQL string is invalid for
    43     43        *         some reason
    44     44        */
    45     45       public void execute() {
    46     46           acquireReference();
    47     47           try {
    48     48               getSession().execute(getSql(), getBindArgs(), getConnectionFlags(), null);
    49     49           } catch (SQLiteDatabaseCorruptException ex) {
................................................................................
    55     55       }
    56     56   
    57     57       /**
    58     58        * Execute this SQL statement, if the the number of rows affected by execution of this SQL
    59     59        * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
    60     60        *
    61     61        * @return the number of rows affected by this SQL statement execution.
    62         -     * @throws org.sqlite.database.SQLException If the SQL string is invalid for
           62  +     * @throws android.database.SQLException If the SQL string is invalid for
    63     63        *         some reason
    64     64        */
    65     65       public int executeUpdateDelete() {
    66     66           acquireReference();
    67     67           try {
    68     68               return getSession().executeForChangedRowCount(
    69     69                       getSql(), getBindArgs(), getConnectionFlags(), null);
................................................................................
    77     77   
    78     78       /**
    79     79        * Execute this SQL statement and return the ID of the row inserted due to this call.
    80     80        * The SQL statement should be an INSERT for this to be a useful call.
    81     81        *
    82     82        * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise.
    83     83        *
    84         -     * @throws org.sqlite.database.SQLException If the SQL string is invalid for
           84  +     * @throws android.database.SQLException If the SQL string is invalid for
    85     85        *         some reason
    86     86        */
    87     87       public long executeInsert() {
    88     88           acquireReference();
    89     89           try {
    90     90               return getSession().executeForLastInsertedRowId(
    91     91                       getSql(), getBindArgs(), getConnectionFlags(), null);
................................................................................
    99     99   
   100    100       /**
   101    101        * Execute a statement that returns a 1 by 1 table with a numeric value.
   102    102        * For example, SELECT COUNT(*) FROM table;
   103    103        *
   104    104        * @return The result of the query.
   105    105        *
   106         -     * @throws org.sqlite.database.sqlite.SQLiteDoneException if the query returns zero rows
          106  +     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
   107    107        */
   108    108       public long simpleQueryForLong() {
   109    109           acquireReference();
   110    110           try {
   111    111               return getSession().executeForLong(
   112    112                       getSql(), getBindArgs(), getConnectionFlags(), null);
   113    113           } catch (SQLiteDatabaseCorruptException ex) {
................................................................................
   120    120   
   121    121       /**
   122    122        * Execute a statement that returns a 1 by 1 table with a text value.
   123    123        * For example, SELECT COUNT(*) FROM table;
   124    124        *
   125    125        * @return The result of the query.
   126    126        *
   127         -     * @throws org.sqlite.database.sqlite.SQLiteDoneException if the query returns zero rows
          127  +     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
   128    128        */
   129    129       public String simpleQueryForString() {
   130    130           acquireReference();
   131    131           try {
   132    132               return getSession().executeForString(
   133    133                       getSql(), getBindArgs(), getConnectionFlags(), null);
   134    134           } catch (SQLiteDatabaseCorruptException ex) {
................................................................................
   141    141   
   142    142       /**
   143    143        * Executes a statement that returns a 1 by 1 table with a blob value.
   144    144        *
   145    145        * @return A read-only file descriptor for a copy of the blob value, or {@code null}
   146    146        *         if the value is null or could not be read for some reason.
   147    147        *
   148         -     * @throws org.sqlite.database.sqlite.SQLiteDoneException if the query returns zero rows
          148  +     * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
   149    149        */
   150    150       public ParcelFileDescriptor simpleQueryForBlobFileDescriptor() {
   151    151           acquireReference();
   152    152           try {
   153    153               return getSession().executeForBlobFileDescriptor(
   154    154                       getSql(), getBindArgs(), getConnectionFlags(), null);
   155    155           } catch (SQLiteDatabaseCorruptException ex) {

Deleted sqlite3/src/main/java/org/sqlite/database/sqlite/SqliteWrapper.java.

     1         -/*
     2         - * Copyright (C) 2008 Esmertec AG.
     3         - * Copyright (C) 2008 The Android Open Source Project
     4         - *
     5         - * Licensed under the Apache License, Version 2.0 (the "License");
     6         - * you may not use this file except in compliance with the License.
     7         - * You may obtain a copy of the License at
     8         - *
     9         - *      http://www.apache.org/licenses/LICENSE-2.0
    10         - *
    11         - * Unless required by applicable law or agreed to in writing, software
    12         - * distributed under the License is distributed on an "AS IS" BASIS,
    13         - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14         - * See the License for the specific language governing permissions and
    15         - * limitations under the License.
    16         - */
    17         -/*
    18         -** Modified to support SQLite extensions by the SQLite developers: 
    19         -** sqlite-dev@sqlite.org.
    20         -*/
    21         -
    22         -package org.sqlite.database.sqlite;
    23         -
    24         -import android.content.ContentResolver;
    25         -import android.content.ContentValues;
    26         -import android.content.Context;
    27         -import android.database.Cursor;
    28         -import org.sqlite.database.sqlite.SQLiteException;
    29         -import android.net.Uri;
    30         -import android.util.Log;
    31         -import android.widget.Toast;
    32         -
    33         -/**
    34         - * @hide
    35         - */
    36         -
    37         -public final class SqliteWrapper {
    38         -    private static final String TAG = "SqliteWrapper";
    39         -    private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE
    40         -                = "unable to open database file";
    41         -
    42         -    private SqliteWrapper() {
    43         -        // Forbidden being instantiated.
    44         -    }
    45         -
    46         -    // FIXME: need to optimize this method.
    47         -    private static boolean isLowMemory(SQLiteException e) {
    48         -        return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE);
    49         -    }
    50         -
    51         -    public static void checkSQLiteException(Context context, SQLiteException e) {
    52         -        if (isLowMemory(e)) {
    53         -            Toast.makeText(context, "low memory", Toast.LENGTH_SHORT).show();
    54         -        } else {
    55         -            throw e;
    56         -        }
    57         -    }
    58         -
    59         -    public static Cursor query(Context context, ContentResolver resolver, Uri uri,
    60         -            String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    61         -        try {
    62         -            return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
    63         -        } catch (SQLiteException e) {
    64         -            Log.e(TAG, "Catch a SQLiteException when query: ", e);
    65         -            checkSQLiteException(context, e);
    66         -            return null;
    67         -        }
    68         -    }
    69         -
    70         -    public static boolean requery(Context context, Cursor cursor) {
    71         -        try {
    72         -            return cursor.requery();
    73         -        } catch (SQLiteException e) {
    74         -            Log.e(TAG, "Catch a SQLiteException when requery: ", e);
    75         -            checkSQLiteException(context, e);
    76         -            return false;
    77         -        }
    78         -    }
    79         -    public static int update(Context context, ContentResolver resolver, Uri uri,
    80         -            ContentValues values, String where, String[] selectionArgs) {
    81         -        try {
    82         -            return resolver.update(uri, values, where, selectionArgs);
    83         -        } catch (SQLiteException e) {
    84         -            Log.e(TAG, "Catch a SQLiteException when update: ", e);
    85         -            checkSQLiteException(context, e);
    86         -            return -1;
    87         -        }
    88         -    }
    89         -
    90         -    public static int delete(Context context, ContentResolver resolver, Uri uri,
    91         -            String where, String[] selectionArgs) {
    92         -        try {
    93         -            return resolver.delete(uri, where, selectionArgs);
    94         -        } catch (SQLiteException e) {
    95         -            Log.e(TAG, "Catch a SQLiteException when delete: ", e);
    96         -            checkSQLiteException(context, e);
    97         -            return -1;
    98         -        }
    99         -    }
   100         -
   101         -    public static Uri insert(Context context, ContentResolver resolver,
   102         -            Uri uri, ContentValues values) {
   103         -        try {
   104         -            return resolver.insert(uri, values);
   105         -        } catch (SQLiteException e) {
   106         -            Log.e(TAG, "Catch a SQLiteException when insert: ", e);
   107         -            checkSQLiteException(context, e);
   108         -            return null;
   109         -        }
   110         -    }
   111         -}