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