Skip to content

Commit

Permalink
[android][sqlite] Migrate to Expo Modules API (expo#23115)
Browse files Browse the repository at this point in the history
  • Loading branch information
alanjhughes authored Jun 27, 2023
1 parent b29c181 commit 09ee958
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import expo.modules.sms.SMSModule
import expo.modules.speech.SpeechPackage
import expo.modules.splashscreen.SplashScreenModule
import expo.modules.splashscreen.SplashScreenPackage
import expo.modules.sqlite.SQLitePackage
import expo.modules.sqlite.SQLiteModule
import expo.modules.storereview.StoreReviewModule
import expo.modules.systemui.SystemUIModule
import expo.modules.systemui.SystemUIPackage
Expand Down Expand Up @@ -87,7 +87,6 @@ object ExperiencePackagePicker : ModulesProvider {
NavigationBarPackage(),
NotificationsPackage(),
PermissionsPackage(),
SQLitePackage(),
SecureStorePackage(),
SensorsPackage(),
SpeechPackage(),
Expand Down Expand Up @@ -142,6 +141,7 @@ object ExperiencePackagePicker : ModulesProvider {
SharingModule::class.java,
SplashScreenModule::class.java,
StoreReviewModule::class.java,
SQLiteModule::class.java,
SystemUIModule::class.java,
VideoThumbnailsModule::class.java,
VideoViewModule::class.java,
Expand Down
2 changes: 2 additions & 0 deletions packages/expo-sqlite/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### 🎉 New features

- Migrated Android codebase to Expo Modules API. ([#23115](https://github.com/expo/expo/pull/23115) by [@alanjhughes](https://github.com/alanjhughes))

### 🐛 Bug fixes

### 💡 Others
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package expo.modules.sqlite

import expo.modules.kotlin.exception.CodedException

class OpenDatabaseException(name: String) :
CodedException("Unable to delete database '$name' that is currently open. Close it prior to deletion.")

class DatabaseNotFoundException(name: String) :
CodedException("Database '$name' not found")

class DeleteDatabaseException(name: String) :
CodedException("Unable to delete the database file for '$name' database")

class SQLiteException(message: String?, cause: Throwable?) :
CodedException(SQLiteModule::class.java.simpleName, message, cause)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package expo.modules.sqlite

import expo.modules.kotlin.records.Field
import expo.modules.kotlin.records.Record

data class Query(
@Field
val sql: String,
@Field
val args: List<Any?>
) : Record
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package expo.modules.sqlite

import java.io.File
import java.io.IOException
import java.util.ArrayList

@Throws(IOException::class)
internal fun ensureDirExists(dir: File): File {
Expand Down Expand Up @@ -77,7 +76,7 @@ private fun startsWithCaseInsensitive(str: String, substr: String): Boolean {
return str.trimStart().startsWith(substr, true)
}

internal fun convertParamsToStringArray(paramArrayArg: ArrayList<Any?>): Array<String?> {
internal fun convertParamsToStringArray(paramArrayArg: List<Any?>): Array<String?> {
return paramArrayArg.map { param ->
when (param) {
is String -> unescapeBlob(param)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,30 @@ package expo.modules.sqlite
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import expo.modules.core.ExportedModule
import expo.modules.core.Promise
import expo.modules.core.interfaces.ExpoMethod
import expo.modules.kotlin.exception.Exceptions
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
import java.io.File
import java.io.IOException
import java.util.*

private val TAG = SQLiteModule::class.java.simpleName
private val EMPTY_ROWS = arrayOf<Array<Any?>>()
private val EMPTY_COLUMNS = arrayOf<String?>()
private val EMPTY_ROWS = emptyArray<Array<Any?>>()
private val EMPTY_COLUMNS = emptyArray<String?>()
private val EMPTY_RESULT = SQLiteModule.SQLitePluginResult(EMPTY_ROWS, EMPTY_COLUMNS, 0, 0, null)
private val DATABASES: MutableMap<String, SQLiteDatabase?> = HashMap()

class SQLiteModule(private val mContext: Context) : ExportedModule(mContext) {
override fun getName(): String {
return "ExpoSQLite"
}
class SQLiteModule : Module() {
private val context: Context
get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()

override fun definition() = ModuleDefinition {
Name("ExpoSQLite")

@ExpoMethod
fun exec(dbName: String, queries: ArrayList<ArrayList<Any>>, readOnly: Boolean, promise: Promise) {
try {
AsyncFunction("exec") { dbName: String, queries: List<Query>, readOnly: Boolean ->
val db = getDatabase(dbName)
val results = queries.map { sqlQuery ->
val sql = sqlQuery[0] as String
val bindArgs = convertParamsToStringArray(sqlQuery[1] as ArrayList<Any?>)
val sql = sqlQuery.sql
val bindArgs = convertParamsToStringArray(sqlQuery.args)
try {
if (isSelect(sql)) {
doSelectInBackgroundAndPossiblyThrow(sql, bindArgs, db)
Expand All @@ -43,37 +42,27 @@ class SQLiteModule(private val mContext: Context) : ExportedModule(mContext) {
SQLitePluginResult(EMPTY_ROWS, EMPTY_COLUMNS, 0, 0, e)
}
}
val data = pluginResultsToPrimitiveData(results)
promise.resolve(data)
} catch (e: Exception) {
promise.reject("SQLiteError", e)
return@AsyncFunction pluginResultsToPrimitiveData(results)
}
}

@ExpoMethod
fun close(dbName: String, promise: Promise) {
DATABASES
.remove(dbName)
?.close()
promise.resolve(null)
}

@ExpoMethod
fun deleteAsync(dbName: String, promise: Promise) {
val errorCode = "SQLiteError"
if (DATABASES.containsKey(dbName)) {
promise.reject(errorCode, "Unable to delete database '$dbName' that is currently open. Close it prior to deletion.")
}
val dbFile = File(pathForDatabaseName(dbName))
if (!dbFile.exists()) {
promise.reject(errorCode, "Database '$dbName' not found")
return
AsyncFunction("close") { dbName: String ->
DATABASES
.remove(dbName)
?.close()
}
if (!dbFile.delete()) {
promise.reject(errorCode, "Unable to delete the database file for '$dbName' database")
return

AsyncFunction("deleteAsync") { dbName: String ->
if (DATABASES.containsKey(dbName)) {
throw OpenDatabaseException(dbName)
}
val dbFile = File(pathForDatabaseName(dbName))
if (!dbFile.exists()) {
throw DatabaseNotFoundException(dbName)
}
if (!dbFile.delete()) {
throw DeleteDatabaseException(dbName)
}
}
promise.resolve(null)
}

// do a update/delete/insert operation
Expand Down Expand Up @@ -143,14 +132,15 @@ class SQLiteModule(private val mContext: Context) : ExportedModule(mContext) {
// convert byte[] to binary string; it's good enough, because
// WebSQL doesn't support blobs anyway
String(cursor.getBlob(index))

Cursor.FIELD_TYPE_STRING -> cursor.getString(index)
else -> null
}
}

@Throws(IOException::class)
private fun pathForDatabaseName(name: String): String {
val directory = File("${mContext.filesDir}${File.separator}SQLite")
val directory = File("${context.filesDir}${File.separator}SQLite")
ensureDirExists(directory)
return "$directory${File.separator}$name"
}
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion packages/expo-sqlite/build/SQLite.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion packages/expo-sqlite/build/SQLite.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 09ee958

Please sign in to comment.