Skip to content

Commit 907200f

Browse files
committed
initial implementation of support database APIs
1 parent 79bfeed commit 907200f

File tree

8 files changed

+367
-5
lines changed

8 files changed

+367
-5
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@ android-database-sqlcipher/src/main/external/android-libs/
77
android-database-sqlcipher/.externalNativeBuild/
88
android-database-sqlcipher/src/main/libs*
99
android-database-sqlcipher/src/main/obj
10-
android-database-sqlcipher/src/main/external/openssl-*/
10+
android-database-sqlcipher/src/main/external/openssl-*/
11+
.idea/
12+
*.iml
13+
local.properties

android-database-sqlcipher/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ android {
3636
}
3737
}
3838

39+
dependencies {
40+
implementation "androidx.sqlite:sqlite:2.0.1"
41+
}
42+
3943
clean.dependsOn cleanNative
4044
check.dependsOn editorconfigCheck
4145
buildNative.mustRunAfter buildAmalgamation
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (C) 2019 Mark L. Murphy
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 net.sqlcipher.database;
18+
19+
import android.util.SparseArray;
20+
import androidx.sqlite.db.SupportSQLiteProgram;
21+
22+
class BindingsRecorder implements SupportSQLiteProgram {
23+
private SparseArray<Object> bindings=new SparseArray<>();
24+
25+
@Override
26+
public void bindNull(int index) {
27+
bindings.put(index, null);
28+
}
29+
30+
@Override
31+
public void bindLong(int index, long value) {
32+
bindings.put(index, value);
33+
}
34+
35+
@Override
36+
public void bindDouble(int index, double value) {
37+
bindings.put(index, value);
38+
}
39+
40+
@Override
41+
public void bindString(int index, String value) {
42+
bindings.put(index, value);
43+
}
44+
45+
@Override
46+
public void bindBlob(int index, byte[] value) {
47+
bindings.put(index, value);
48+
}
49+
50+
@Override
51+
public void clearBindings() {
52+
bindings.clear();
53+
}
54+
55+
@Override
56+
public void close() {
57+
clearBindings();
58+
}
59+
60+
String[] getBindings() {
61+
final String[] result=new String[bindings.size()];
62+
63+
for (int i=0;i<bindings.size();i++) {
64+
Object binding=bindings.get(i);
65+
66+
if (binding!=null) {
67+
result[i]=bindings.get(i).toString();
68+
}
69+
else {
70+
result[i]=""; // SQLCipher does not like null binding values
71+
}
72+
}
73+
74+
return(result);
75+
}
76+
}

android-database-sqlcipher/src/main/java/net/sqlcipher/database/SQLiteDatabase.java

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454

5555
import android.content.Context;
5656

57+
import android.os.CancellationSignal;
5758
import android.os.Debug;
5859
import android.os.SystemClock;
5960
import android.text.TextUtils;
@@ -62,6 +63,8 @@
6263
import android.util.Pair;
6364

6465
import java.io.UnsupportedEncodingException;
66+
import androidx.sqlite.db.SupportSQLiteDatabase;
67+
import androidx.sqlite.db.SupportSQLiteQuery;
6568

6669
/**
6770
* Exposes methods to manage a SQLCipher database.
@@ -73,7 +76,8 @@
7376
* applications.
7477
*
7578
*/
76-
public class SQLiteDatabase extends SQLiteClosable {
79+
public class SQLiteDatabase extends SQLiteClosable implements
80+
SupportSQLiteDatabase {
7781
private static final String TAG = "Database";
7882
private static final int EVENT_DB_OPERATION = 52000;
7983
private static final int EVENT_DB_CORRUPT = 75004;
@@ -741,7 +745,7 @@ public void setForeignKeyConstraintsEnabled(boolean enable) {
741745
* @throws IllegalStateException if the database is not open
742746
*/
743747
public void beginTransaction() {
744-
beginTransactionWithListener(null /* transactionStatusCallback */);
748+
beginTransactionWithListener((SQLiteTransactionListener)null /* transactionStatusCallback */);
745749
}
746750

747751
/**
@@ -2260,6 +2264,28 @@ public long insertWithOnConflict(String table, String nullColumnHack,
22602264
* @throws IllegalStateException if the database is not open
22612265
*/
22622266
public int delete(String table, String whereClause, String[] whereArgs) {
2267+
Object[] args = new Object[whereArgs.length];
2268+
2269+
System.arraycopy(whereArgs, 0, args, 0, whereArgs.length);
2270+
2271+
return delete(table, whereClause, args);
2272+
}
2273+
2274+
/**
2275+
* Convenience method for deleting rows in the database.
2276+
*
2277+
* @param table the table to delete from
2278+
* @param whereClause the optional WHERE clause to apply when deleting.
2279+
* Passing null will delete all rows.
2280+
*
2281+
* @return the number of rows affected if a whereClause is passed in, 0
2282+
* otherwise. To remove all rows and get a count pass "1" as the
2283+
* whereClause.
2284+
*
2285+
* @throws SQLException If the SQL string is invalid for some reason
2286+
* @throws IllegalStateException if the database is not open
2287+
*/
2288+
public int delete(String table, String whereClause, Object[] whereArgs) {
22632289
SQLiteStatement statement = null;
22642290
lock();
22652291
try {
@@ -2909,6 +2935,97 @@ public static char[] getChars(byte[] data){
29092935
return result;
29102936
}
29112937

2938+
/* begin SQLiteSupportDatabase methods */
2939+
2940+
@Override
2941+
public android.database.Cursor query(String query) {
2942+
return rawQuery(query, null);
2943+
}
2944+
2945+
@Override
2946+
public android.database.Cursor query(String query, Object[] bindArgs) {
2947+
return rawQuery(query, bindArgs);
2948+
}
2949+
2950+
@Override
2951+
public android.database.Cursor query(SupportSQLiteQuery query) {
2952+
return query(query, null);
2953+
}
2954+
2955+
@Override
2956+
public android.database.Cursor query(final SupportSQLiteQuery supportQuery,
2957+
CancellationSignal cancellationSignal) {
2958+
BindingsRecorder hack=new BindingsRecorder();
2959+
2960+
supportQuery.bindTo(hack);
2961+
2962+
return rawQuery(supportQuery.getSql(), hack.getBindings());
2963+
}
2964+
2965+
@Override
2966+
public long insert(String table, int conflictAlgorithm,
2967+
ContentValues values)
2968+
throws android.database.SQLException {
2969+
return insertWithOnConflict(table, null, values, conflictAlgorithm);
2970+
}
2971+
2972+
@Override
2973+
public int update(String table, int conflictAlgorithm, ContentValues values,
2974+
String whereClause, Object[] whereArgs) {
2975+
String[] args = new String[whereArgs.length];
2976+
2977+
for (int i = 0; i < whereArgs.length; i++) {
2978+
args[i] = whereArgs[i].toString();
2979+
}
2980+
2981+
return updateWithOnConflict(table, values, whereClause, args, conflictAlgorithm);
2982+
}
2983+
2984+
@Override
2985+
public void beginTransactionWithListener(
2986+
final android.database.sqlite.SQLiteTransactionListener transactionListener) {
2987+
beginTransactionWithListener(new SQLiteTransactionListener() {
2988+
@Override
2989+
public void onBegin() {
2990+
transactionListener.onBegin();
2991+
}
2992+
2993+
@Override
2994+
public void onCommit() {
2995+
transactionListener.onCommit();
2996+
}
2997+
2998+
@Override
2999+
public void onRollback() {
3000+
transactionListener.onRollback();
3001+
}
3002+
});
3003+
}
3004+
3005+
@Override
3006+
public void beginTransactionWithListenerNonExclusive(
3007+
final android.database.sqlite.SQLiteTransactionListener transactionListener) {
3008+
beginTransactionWithListenerNonExclusive(
3009+
new SQLiteTransactionListener() {
3010+
@Override
3011+
public void onBegin() {
3012+
transactionListener.onBegin();
3013+
}
3014+
3015+
@Override
3016+
public void onCommit() {
3017+
transactionListener.onCommit();
3018+
}
3019+
3020+
@Override
3021+
public void onRollback() {
3022+
transactionListener.onRollback();
3023+
}
3024+
});
3025+
}
3026+
3027+
/* end SQLiteSupportDatabase methods */
3028+
29123029
private void beginTransactionWithListenerInternal(SQLiteTransactionListener transactionListener,
29133030
SQLiteDatabaseTransactionType transactionType) {
29143031
lockForced();

android-database-sqlcipher/src/main/java/net/sqlcipher/database/SQLiteProgram.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@
1717
package net.sqlcipher.database;
1818

1919
import android.util.Log;
20+
import androidx.sqlite.db.SupportSQLiteProgram;
2021

2122
/**
2223
* A base class for compiled SQLite programs.
2324
*
2425
* SQLiteProgram is not internally synchronized so code using a SQLiteProgram from multiple
2526
* threads should perform its own synchronization when using the SQLiteProgram.
2627
*/
27-
public abstract class SQLiteProgram extends SQLiteClosable {
28+
public abstract class SQLiteProgram extends SQLiteClosable implements
29+
SupportSQLiteProgram {
2830

2931
private static final String TAG = "SQLiteProgram";
3032

@@ -181,6 +183,7 @@ protected void compile(String sql, boolean forceCompilation) {
181183
*
182184
* @param index The 1-based index to the parameter to bind null to
183185
*/
186+
@Override
184187
public void bindNull(int index) {
185188
if (mClosed) {
186189
throw new IllegalStateException("program already closed");
@@ -203,6 +206,7 @@ public void bindNull(int index) {
203206
* @param index The 1-based index to the parameter to bind
204207
* @param value The value to bind
205208
*/
209+
@Override
206210
public void bindLong(int index, long value) {
207211
if (mClosed) {
208212
throw new IllegalStateException("program already closed");
@@ -225,6 +229,7 @@ public void bindLong(int index, long value) {
225229
* @param index The 1-based index to the parameter to bind
226230
* @param value The value to bind
227231
*/
232+
@Override
228233
public void bindDouble(int index, double value) {
229234
if (mClosed) {
230235
throw new IllegalStateException("program already closed");
@@ -247,6 +252,7 @@ public void bindDouble(int index, double value) {
247252
* @param index The 1-based index to the parameter to bind
248253
* @param value The value to bind
249254
*/
255+
@Override
250256
public void bindString(int index, String value) {
251257
if (value == null) {
252258
throw new IllegalArgumentException("the bind value at index " + index + " is null");
@@ -272,6 +278,7 @@ public void bindString(int index, String value) {
272278
* @param index The 1-based index to the parameter to bind
273279
* @param value The value to bind
274280
*/
281+
@Override
275282
public void bindBlob(int index, byte[] value) {
276283
if (value == null) {
277284
throw new IllegalArgumentException("the bind value at index " + index + " is null");
@@ -293,6 +300,7 @@ public void bindBlob(int index, byte[] value) {
293300
/**
294301
* Clears all existing bindings. Unset bindings are treated as NULL.
295302
*/
303+
@Override
296304
public void clearBindings() {
297305
if (mClosed) {
298306
throw new IllegalStateException("program already closed");

android-database-sqlcipher/src/main/java/net/sqlcipher/database/SQLiteStatement.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package net.sqlcipher.database;
1818

1919
import android.os.SystemClock;
20+
import androidx.sqlite.db.SupportSQLiteStatement;
2021

2122
/**
2223
* A pre-compiled statement against a {@link SQLiteDatabase} that can be reused.
@@ -27,7 +28,8 @@
2728
* SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple
2829
* threads should perform its own synchronization when using the SQLiteStatement.
2930
*/
30-
public class SQLiteStatement extends SQLiteProgram
31+
public class SQLiteStatement extends SQLiteProgram implements
32+
SupportSQLiteStatement
3133
{
3234
/**
3335
* Don't use SQLiteStatement constructor directly, please use
@@ -46,6 +48,7 @@ public class SQLiteStatement extends SQLiteProgram
4648
* @throws android.database.SQLException If the SQL string is invalid for
4749
* some reason
4850
*/
51+
@Override
4952
public void execute() {
5053
if (!mDatabase.isOpen()) {
5154
throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
@@ -71,6 +74,7 @@ public void execute() {
7174
* @throws android.database.SQLException If the SQL string is invalid for
7275
* some reason
7376
*/
77+
@Override
7478
public long executeInsert() {
7579
if (!mDatabase.isOpen()) {
7680
throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
@@ -88,6 +92,7 @@ public long executeInsert() {
8892
}
8993
}
9094

95+
@Override
9196
public int executeUpdateDelete() {
9297
if (!mDatabase.isOpen()) {
9398
throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
@@ -113,6 +118,7 @@ public int executeUpdateDelete() {
113118
*
114119
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
115120
*/
121+
@Override
116122
public long simpleQueryForLong() {
117123
if (!mDatabase.isOpen()) {
118124
throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
@@ -138,6 +144,7 @@ public long simpleQueryForLong() {
138144
*
139145
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
140146
*/
147+
@Override
141148
public String simpleQueryForString() {
142149
if (!mDatabase.isOpen()) {
143150
throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");

0 commit comments

Comments
 (0)