Home | History | Annotate | Download | only in sqlite
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.database.sqlite;
     18 
     19 import java.util.ArrayList;
     20 import java.util.Locale;
     21 import java.util.regex.Pattern;
     22 
     23 /**
     24  * Describes how to configure a database.
     25  * <p>
     26  * The purpose of this object is to keep track of all of the little
     27  * configuration settings that are applied to a database after it
     28  * is opened so that they can be applied to all connections in the
     29  * connection pool uniformly.
     30  * </p><p>
     31  * Each connection maintains its own copy of this object so it can
     32  * keep track of which settings have already been applied.
     33  * </p>
     34  *
     35  * @hide
     36  */
     37 public final class SQLiteDatabaseConfiguration {
     38     // The pattern we use to strip email addresses from database paths
     39     // when constructing a label to use in log messages.
     40     private static final Pattern EMAIL_IN_DB_PATTERN =
     41             Pattern.compile("[\\w\\.\\-]+@[\\w\\.\\-]+");
     42 
     43     /**
     44      * Special path used by in-memory databases.
     45      */
     46     public static final String MEMORY_DB_PATH = ":memory:";
     47 
     48     /**
     49      * The database path.
     50      */
     51     public final String path;
     52 
     53     /**
     54      * The label to use to describe the database when it appears in logs.
     55      * This is derived from the path but is stripped to remove PII.
     56      */
     57     public final String label;
     58 
     59     /**
     60      * The flags used to open the database.
     61      */
     62     public int openFlags;
     63 
     64     /**
     65      * The maximum size of the prepared statement cache for each database connection.
     66      * Must be non-negative.
     67      *
     68      * Default is 25.
     69      */
     70     public int maxSqlCacheSize;
     71 
     72     /**
     73      * The database locale.
     74      *
     75      * Default is the value returned by {@link Locale#getDefault()}.
     76      */
     77     public Locale locale;
     78 
     79     /**
     80      * True if foreign key constraints are enabled.
     81      *
     82      * Default is false.
     83      */
     84     public boolean foreignKeyConstraintsEnabled;
     85 
     86     /**
     87      * The custom functions to register.
     88      */
     89     public final ArrayList<SQLiteCustomFunction> customFunctions =
     90             new ArrayList<SQLiteCustomFunction>();
     91 
     92     /**
     93      * The size in bytes of each lookaside slot
     94      *
     95      * <p>If negative, the default lookaside configuration will be used
     96      */
     97     public int lookasideSlotSize = -1;
     98 
     99     /**
    100      * The total number of lookaside memory slots per database connection
    101      *
    102      * <p>If negative, the default lookaside configuration will be used
    103      */
    104     public int lookasideSlotCount = -1;
    105 
    106     /**
    107      * The number of milliseconds that SQLite connection is allowed to be idle before it
    108      * is closed and removed from the pool.
    109      * <p>By default, idle connections are not closed
    110      */
    111     public long idleConnectionTimeoutMs = Long.MAX_VALUE;
    112 
    113     /**
    114      * Journal mode to use when {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} is not set.
    115      * <p>Default is returned by {@link SQLiteGlobal#getDefaultJournalMode()}
    116      */
    117     public String journalMode;
    118 
    119     /**
    120      * Synchronous mode to use.
    121      * <p>Default is returned by {@link SQLiteGlobal#getDefaultSyncMode()}
    122      * or {@link SQLiteGlobal#getWALSyncMode()} depending on journal mode
    123      */
    124     public String syncMode;
    125 
    126     /**
    127      * Creates a database configuration with the required parameters for opening a
    128      * database and default values for all other parameters.
    129      *
    130      * @param path The database path.
    131      * @param openFlags Open flags for the database, such as {@link SQLiteDatabase#OPEN_READWRITE}.
    132      */
    133     public SQLiteDatabaseConfiguration(String path, int openFlags) {
    134         if (path == null) {
    135             throw new IllegalArgumentException("path must not be null.");
    136         }
    137 
    138         this.path = path;
    139         label = stripPathForLogs(path);
    140         this.openFlags = openFlags;
    141 
    142         // Set default values for optional parameters.
    143         maxSqlCacheSize = 25;
    144         locale = Locale.getDefault();
    145     }
    146 
    147     /**
    148      * Creates a database configuration as a copy of another configuration.
    149      *
    150      * @param other The other configuration.
    151      */
    152     public SQLiteDatabaseConfiguration(SQLiteDatabaseConfiguration other) {
    153         if (other == null) {
    154             throw new IllegalArgumentException("other must not be null.");
    155         }
    156 
    157         this.path = other.path;
    158         this.label = other.label;
    159         updateParametersFrom(other);
    160     }
    161 
    162     /**
    163      * Updates the non-immutable parameters of this configuration object
    164      * from the other configuration object.
    165      *
    166      * @param other The object from which to copy the parameters.
    167      */
    168     public void updateParametersFrom(SQLiteDatabaseConfiguration other) {
    169         if (other == null) {
    170             throw new IllegalArgumentException("other must not be null.");
    171         }
    172         if (!path.equals(other.path)) {
    173             throw new IllegalArgumentException("other configuration must refer to "
    174                     + "the same database.");
    175         }
    176 
    177         openFlags = other.openFlags;
    178         maxSqlCacheSize = other.maxSqlCacheSize;
    179         locale = other.locale;
    180         foreignKeyConstraintsEnabled = other.foreignKeyConstraintsEnabled;
    181         customFunctions.clear();
    182         customFunctions.addAll(other.customFunctions);
    183         lookasideSlotSize = other.lookasideSlotSize;
    184         lookasideSlotCount = other.lookasideSlotCount;
    185         idleConnectionTimeoutMs = other.idleConnectionTimeoutMs;
    186         journalMode = other.journalMode;
    187         syncMode = other.syncMode;
    188     }
    189 
    190     /**
    191      * Returns true if the database is in-memory.
    192      * @return True if the database is in-memory.
    193      */
    194     public boolean isInMemoryDb() {
    195         return path.equalsIgnoreCase(MEMORY_DB_PATH);
    196     }
    197 
    198     boolean useCompatibilityWal() {
    199         return journalMode == null && syncMode == null
    200                 && (openFlags & SQLiteDatabase.DISABLE_COMPATIBILITY_WAL) == 0;
    201     }
    202 
    203     private static String stripPathForLogs(String path) {
    204         if (path.indexOf('@') == -1) {
    205             return path;
    206         }
    207         return EMAIL_IN_DB_PATTERN.matcher(path).replaceAll("XX@YY");
    208     }
    209 
    210     boolean isLookasideConfigSet() {
    211         return lookasideSlotCount >= 0 && lookasideSlotSize >= 0;
    212     }
    213 }
    214