Skip to content

Commit

Permalink
support for other db folders on android based on Nozbe#933
Browse files Browse the repository at this point in the history
  • Loading branch information
dcoj committed Feb 6, 2024
1 parent 0580727 commit 5974507
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 12 deletions.
62 changes: 52 additions & 10 deletions native/android/src/main/java/com/nozbe/watermelondb/WMDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ private WMDatabase(SQLiteDatabase db) {
public static Map<String, WMDatabase> INSTANCES = new HashMap<>();

public static WMDatabase getInstance(String name, Context context) {
return getInstance(name, context, SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING);
return getInstance(name, context,
SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING);
}

public static WMDatabase getInstance(String name, Context context, int openFlags) {
Expand All @@ -42,11 +43,48 @@ public static WMDatabase buildDatabase(String name, Context context, int openFla
return new WMDatabase(sqLiteDatabase);
}

private static String substringAfterLast(String text, char separator) {
if (isEmpty(text)) {
return text;
}
int cPos = text.lastIndexOf(separator);
if (cPos < 0) {
return "";
}
return text.substring(cPos + 1);
}

private static String substringBeforeLast(String text, char separator) {
if (isEmpty(text)) {
return text;
}
int cPos = text.lastIndexOf(separator);
if (cPos < 0) {
return text;
}
return text.substring(0, cPos);
}

private static SQLiteDatabase createSQLiteDatabase(String name, Context context, int openFlags) {
String path;
if (name.equals(":memory:") || name.contains("mode=memory")) {
context.getCacheDir().delete();
path = new File(context.getCacheDir(), name).getPath();
} else if (name.startsWith("/") || name.startsWith("file")) {
// Extracts the database name from the path
var dbName = substringAfterLast(name, "/");
if (dbName.contains(".db")) {
// Extracts the real path where the *.db file will be created
var directory = substringBeforeLast(substringAfterLast(name, "file://"),
"/");

// Creates the directory
var fileObj = new File(directory, "databases");
fileObj.mkdir();
path = new File("${directory}/databases", dbName).getPath();
} else {
throw new IllegalArgumentException("Database name should contain '.db' as extension");
}
} else {
// On some systems there is some kind of lock on `/databases` folder ¯\_(ツ)_/¯
path = context.getDatabasePath("" + name + ".db").getPath().replace("/databases", "");
Expand All @@ -64,8 +102,10 @@ public int getUserVersion() {

public void unsafeExecuteStatements(String statements) {
this.transaction(() -> {
// NOTE: This must NEVER be allowed to take user input - split by `;` is not grammar-aware
// and so is unsafe. Only works with Watermelon-generated strings known to be safe
// NOTE: This must NEVER be allowed to take user input - split by `;` is not
// grammar-aware
// and so is unsafe. Only works with Watermelon-generated strings known to be
// safe
for (String statement : statements.split(";")) {
if (!statement.trim().isEmpty()) {
this.execute(statement);
Expand All @@ -87,8 +127,10 @@ public void delete(String query, Object[] args) {
}

public Cursor rawQuery(String sql, Object[] args) {
// HACK: db.rawQuery only supports String args, and there's no clean way AFAIK to construct
// a query with arbitrary args (like with execSQL). However, we can misuse cursor factory
// HACK: db.rawQuery only supports String args, and there's no clean way AFAIK
// to construct
// a query with arbitrary args (like with execSQL). However, we can misuse
// cursor factory
// to get the reference of a SQLiteQuery before it's executed
// https://github.com/aosp-mirror/platform_frameworks_base/blob/0799624dc7eb4b4641b4659af5b5ec4b9f80dd81/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java#L30
// https://github.com/aosp-mirror/platform_frameworks_base/blob/0799624dc7eb4b4641b4659af5b5ec4b9f80dd81/core/java/android/database/sqlite/SQLiteProgram.java#L32
Expand All @@ -107,12 +149,12 @@ public Cursor rawQuery(String sql, Object[] args) {
} else if (arg == null) {
query.bindNull(i + 1);
} else {
throw new IllegalArgumentException("Bad query arg type: " + arg.getClass().getCanonicalName());
throw new IllegalArgumentException(
"Bad query arg type: " + arg.getClass().getCanonicalName());
}
}
return new SQLiteCursor(driver, editTable, query);
}, sql, rawArgs, null, null
);
}, sql, rawArgs, null, null);
}

public Cursor rawQuery(String sql) {
Expand All @@ -132,11 +174,11 @@ public int count(String query, Object[] args) {
}

public int count(String query) {
return this.count(query, new Object[]{});
return this.count(query, new Object[] {});
}

public String getFromLocalStorage(String key) {
try (Cursor cursor = rawQuery(Queries.select_local_storage, new Object[]{key})) {
try (Cursor cursor = rawQuery(Queries.select_local_storage, new Object[] { key })) {
cursor.moveToFirst();
if (cursor.getCount() > 0) {
return cursor.getString(0);
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@nozbe/watermelondb",
"description": "Build powerful React Native and React web apps that scale from hundreds to tens of thousands of records and remain fast",
"version": "0.27.1",
"version": "0.27.2",
"scripts": {
"up": "yarn",
"build": "NODE_ENV=production node ./scripts/make.mjs",
Expand Down Expand Up @@ -168,4 +168,4 @@
"tslint-config-prettier": "^1.15.0",
"typescript": "^4.5.0"
}
}
}

0 comments on commit 5974507

Please sign in to comment.