diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsContentProvider.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsContentProvider.kt index c532ed3cc7..2483afb70e 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsContentProvider.kt +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsContentProvider.kt @@ -2,12 +2,13 @@ package fr.free.nrw.commons.bookmarks.items import android.content.ContentValues import android.database.Cursor -import android.database.sqlite.SQLiteQueryBuilder +import android.database.sqlite.SQLiteDatabase import android.net.Uri import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.bookmarks.items.BookmarkItemsTable.TABLE_NAME import fr.free.nrw.commons.di.CommonsDaggerContentProvider import androidx.core.net.toUri +import androidx.sqlite.db.SupportSQLiteQueryBuilder import fr.free.nrw.commons.bookmarks.items.BookmarkItemsTable.COLUMN_ID /** @@ -28,14 +29,12 @@ class BookmarkItemsContentProvider : CommonsDaggerContentProvider() { uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String? ): Cursor { - val queryBuilder = SQLiteQueryBuilder().apply { - tables = TABLE_NAME - } - - return queryBuilder.query( - requireDb(), projection, selection, - selectionArgs, null, null, sortOrder - ).apply { + val query = SupportSQLiteQueryBuilder + .builder(TABLE_NAME) + .columns(projection) + .selection(selection, selectionArgs) + .orderBy(sortOrder).create() + return requireDb().query(query).apply { setNotificationUri(context?.contentResolver, uri) } } @@ -51,21 +50,23 @@ class BookmarkItemsContentProvider : CommonsDaggerContentProvider() { uri: Uri, contentValues: ContentValues?, selection: String?, selectionArgs: Array? ): Int { - val rowsUpdated: Int + val rowsUpdated: Int = if (selection.isNullOrEmpty()) { val id = uri.lastPathSegment!!.toInt() - rowsUpdated = requireDb().update( - TABLE_NAME, - contentValues, - "$COLUMN_ID = ?", - arrayOf(id.toString()) - ) + contentValues?.let { + requireDb().update( + TABLE_NAME, + SQLiteDatabase.CONFLICT_NONE, + it, + "$COLUMN_ID = ?", + arrayOf(id.toString()) + ) + } ?: 0 } else { throw IllegalArgumentException( "Parameter `selection` should be empty when updating an ID" ) } - context?.contentResolver?.notifyChange(uri, null) return rowsUpdated } @@ -74,7 +75,8 @@ class BookmarkItemsContentProvider : CommonsDaggerContentProvider() { * Handles the insertion of new bookmark items record to local SQLite Database */ override fun insert(uri: Uri, contentValues: ContentValues?): Uri? { - val id = requireDb().insert(TABLE_NAME, null, contentValues) + val id = + contentValues?.let { requireDb().insert(TABLE_NAME, SQLiteDatabase.CONFLICT_NONE, it) } context?.contentResolver?.notifyChange(uri, null) return "$BASE_URI/$id".toUri() } diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsTable.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsTable.kt index b1b03c71b5..e4ca535a60 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsTable.kt +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsTable.kt @@ -1,6 +1,6 @@ package fr.free.nrw.commons.bookmarks.items -import android.database.sqlite.SQLiteDatabase +import androidx.sqlite.db.SupportSQLiteDatabase /** * Table of bookmarksItems data @@ -47,18 +47,18 @@ object BookmarkItemsTable { /** * Creates table * - * @param db SQLiteDatabase + * @param db SupportSQLiteDatabase */ - fun onCreate(db: SQLiteDatabase) { + fun onCreate(db: SupportSQLiteDatabase) { db.execSQL(CREATE_TABLE_STATEMENT) } /** * Deletes database * - * @param db SQLiteDatabase + * @param db SupportSQLiteDatabase */ - fun onDelete(db: SQLiteDatabase) { + fun onDelete(db: SupportSQLiteDatabase) { db.execSQL(DROP_TABLE_STATEMENT) onCreate(db) } @@ -66,11 +66,11 @@ object BookmarkItemsTable { /** * Updates database * - * @param db SQLiteDatabase + * @param db SupportSQLiteDatabase * @param from starting * @param to end */ - fun onUpdate(db: SQLiteDatabase, from: Int, to: Int) { + fun onUpdate(db: SupportSQLiteDatabase, from: Int, to: Int) { if (from == to) { return } diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesContentProvider.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesContentProvider.kt index a47eed8ca9..f0397f7163 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesContentProvider.kt +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesContentProvider.kt @@ -2,11 +2,12 @@ package fr.free.nrw.commons.bookmarks.pictures import android.content.ContentValues import android.database.Cursor -import android.database.sqlite.SQLiteQueryBuilder +import android.database.sqlite.SQLiteDatabase import android.net.Uri import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.di.CommonsDaggerContentProvider import androidx.core.net.toUri +import androidx.sqlite.db.SupportSQLiteQueryBuilder import fr.free.nrw.commons.bookmarks.pictures.BookmarksTable.COLUMN_MEDIA_NAME import fr.free.nrw.commons.bookmarks.pictures.BookmarksTable.TABLE_NAME @@ -28,17 +29,14 @@ class BookmarkPicturesContentProvider : CommonsDaggerContentProvider() { uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String? ): Cursor { - val queryBuilder = SQLiteQueryBuilder().apply { - tables = TABLE_NAME + val query = SupportSQLiteQueryBuilder + .builder(TABLE_NAME) + .columns(projection) + .selection(selection, selectionArgs) + .orderBy(sortOrder).create() + return requireDb().query(query).apply { + setNotificationUri(context?.contentResolver, uri) } - - val cursor = queryBuilder.query( - requireDb(), projection, selection, - selectionArgs, null, null, sortOrder - ) - cursor.setNotificationUri(context?.contentResolver, uri) - - return cursor } /** @@ -52,15 +50,18 @@ class BookmarkPicturesContentProvider : CommonsDaggerContentProvider() { uri: Uri, contentValues: ContentValues?, selection: String?, selectionArgs: Array? ): Int { - val rowsUpdated: Int + val rowsUpdated: Int = if (selection.isNullOrEmpty()) { val id = uri.lastPathSegment!!.toInt() - rowsUpdated = requireDb().update( - TABLE_NAME, - contentValues, - "$COLUMN_MEDIA_NAME = ?", - arrayOf(id.toString()) - ) + contentValues?.let { + requireDb().update( + TABLE_NAME, + SQLiteDatabase.CONFLICT_NONE, + it, + "$COLUMN_MEDIA_NAME = ?", + arrayOf(id.toString()) + ) + } ?: 0 } else { throw IllegalArgumentException( "Parameter `selection` should be empty when updating an ID" @@ -74,7 +75,8 @@ class BookmarkPicturesContentProvider : CommonsDaggerContentProvider() { * Handles the insertion of new bookmark pictures record to local SQLite Database */ override fun insert(uri: Uri, contentValues: ContentValues?): Uri { - val id = requireDb().insert(TABLE_NAME, null, contentValues) + val id = + contentValues?.let { requireDb().insert(TABLE_NAME, SQLiteDatabase.CONFLICT_NONE, it) } context?.contentResolver?.notifyChange(uri, null) return "$BASE_URI/$id".toUri() } diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarksTable.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarksTable.kt index 6a8f4d541a..7b47548ef5 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarksTable.kt +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarksTable.kt @@ -1,6 +1,6 @@ package fr.free.nrw.commons.bookmarks.pictures -import android.database.sqlite.SQLiteDatabase +import androidx.sqlite.db.SupportSQLiteDatabase object BookmarksTable { const val TABLE_NAME: String = "bookmarks" @@ -20,15 +20,15 @@ object BookmarksTable { "$COLUMN_CREATOR STRING" + ");") - fun onCreate(db: SQLiteDatabase) = + fun onCreate(db: SupportSQLiteDatabase) = db.execSQL(CREATE_TABLE_STATEMENT) - fun onDelete(db: SQLiteDatabase) { + fun onDelete(db: SupportSQLiteDatabase) { db.execSQL(DROP_TABLE_STATEMENT) onCreate(db) } - fun onUpdate(db: SQLiteDatabase, from: Int, to: Int) { + fun onUpdate(db: SupportSQLiteDatabase, from: Int, to: Int) { if (from == to) { return } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.kt index 8a5d031032..05706217be 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.kt @@ -5,10 +5,11 @@ import android.content.ContentValues import android.content.UriMatcher import android.content.UriMatcher.NO_MATCH import android.database.Cursor -import android.database.sqlite.SQLiteQueryBuilder +import android.database.sqlite.SQLiteDatabase import android.net.Uri import android.text.TextUtils import androidx.core.net.toUri +import androidx.sqlite.db.SupportSQLiteQueryBuilder import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.category.CategoryTable.ALL_FIELDS import fr.free.nrw.commons.category.CategoryTable.COLUMN_ID @@ -25,31 +26,27 @@ class CategoryContentProvider : CommonsDaggerContentProvider() { @SuppressWarnings("ConstantConditions") override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? { - val queryBuilder = SQLiteQueryBuilder().apply { - tables = TABLE_NAME - } val uriType = uriMatcher.match(uri) val db = requireDb() val cursor: Cursor? = when (uriType) { - CATEGORIES -> queryBuilder.query( - db, - projection, - selection, - selectionArgs, - null, - null, - sortOrder + CATEGORIES -> db.query( + SupportSQLiteQueryBuilder.builder( + TABLE_NAME + ).selection(selection, selectionArgs) + .columns(projection) + .orderBy(sortOrder) + .create() ) - CATEGORIES_ID -> queryBuilder.query( - db, - ALL_FIELDS, - "_id = ?", - arrayOf(uri.lastPathSegment), - null, - null, - sortOrder + + CATEGORIES_ID -> db.query( + SupportSQLiteQueryBuilder.builder( + TABLE_NAME + ).selection("_id = ?", arrayOf(uri.lastPathSegment)) + .columns(ALL_FIELDS) + .orderBy(sortOrder) + .create() ) else -> throw IllegalArgumentException("Unknown URI $uri") } @@ -63,10 +60,12 @@ class CategoryContentProvider : CommonsDaggerContentProvider() { @SuppressWarnings("ConstantConditions") override fun insert(uri: Uri, contentValues: ContentValues?): Uri { val uriType = uriMatcher.match(uri) - val id: Long + var id: Long = 0L when (uriType) { CATEGORIES -> { - id = requireDb().insert(TABLE_NAME, null, contentValues) + contentValues?.let { + id = requireDb().insert(TABLE_NAME, SQLiteDatabase.CONFLICT_NONE, it) + } } else -> throw IllegalArgumentException("Unknown URI: $uri") } @@ -85,7 +84,7 @@ class CategoryContentProvider : CommonsDaggerContentProvider() { when (uriType) { CATEGORIES -> { for (value in values) { - sqlDB.insert(TABLE_NAME, null, value) + sqlDB.insert(TABLE_NAME, SQLiteDatabase.CONFLICT_NONE, value) } sqlDB.setTransactionSuccessful() } @@ -100,18 +99,21 @@ class CategoryContentProvider : CommonsDaggerContentProvider() { override fun update(uri: Uri, contentValues: ContentValues?, selection: String?, selectionArgs: Array?): Int { val uriType = uriMatcher.match(uri) - val rowsUpdated: Int + var rowsUpdated: Int = 0 when (uriType) { CATEGORIES_ID -> { if (TextUtils.isEmpty(selection)) { val id = uri.lastPathSegment?.toInt() ?: throw IllegalArgumentException("Invalid ID") - rowsUpdated = requireDb().update( - TABLE_NAME, - contentValues, - "$COLUMN_ID = ?", - arrayOf(id.toString()) - ) + contentValues?.let { + rowsUpdated = requireDb().update( + TABLE_NAME, + SQLiteDatabase.CONFLICT_NONE, + it, + "$COLUMN_ID = ?", + arrayOf(id.toString()) + ) + } } else { throw IllegalArgumentException( "Parameter `selection` should be empty when updating an ID") diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryTable.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryTable.kt index 454a0bc009..8c47fdb3d3 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryTable.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryTable.kt @@ -1,6 +1,6 @@ package fr.free.nrw.commons.category -import android.database.sqlite.SQLiteDatabase +import androidx.sqlite.db.SupportSQLiteDatabase object CategoryTable { const val TABLE_NAME = "categories" @@ -33,14 +33,14 @@ object CategoryTable { "$COLUMN_TIMES_USED INTEGER" + ");" - fun onCreate(db: SQLiteDatabase) = db.execSQL(CREATE_TABLE_STATEMENT) + fun onCreate(db: SupportSQLiteDatabase) = db.execSQL(CREATE_TABLE_STATEMENT) - fun onDelete(db: SQLiteDatabase) { + fun onDelete(db: SupportSQLiteDatabase) { db.execSQL(DROP_TABLE_STATEMENT) onCreate(db) } - fun onUpdate(db: SQLiteDatabase, from: Int, to: Int) { + fun onUpdate(db: SupportSQLiteDatabase, from: Int, to: Int) { if (from == to) return if (from < 4) { // doesn't exist yet diff --git a/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.kt b/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.kt index db3178567f..1b074d3ad6 100644 --- a/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.kt +++ b/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.kt @@ -1,9 +1,10 @@ package fr.free.nrw.commons.data import android.content.Context -import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteException -import android.database.sqlite.SQLiteOpenHelper +import androidx.sqlite.db.SupportSQLiteDatabase +import androidx.sqlite.db.SupportSQLiteOpenHelper +import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory import fr.free.nrw.commons.bookmarks.items.BookmarkItemsTable import fr.free.nrw.commons.bookmarks.pictures.BookmarksTable import fr.free.nrw.commons.category.CategoryTable @@ -13,7 +14,7 @@ import fr.free.nrw.commons.recentlanguages.RecentLanguagesTable class DBOpenHelper( context: Context -): SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { +) { companion object { private const val DATABASE_NAME = "commons.db" @@ -27,7 +28,7 @@ class DBOpenHelper( * Do not use directly - @Inject an instance where it's needed and let * dependency injection take care of managing this as a singleton. */ - override fun onCreate(db: SQLiteDatabase) { + private fun createAllTables(db: SupportSQLiteDatabase) { CategoryTable.onCreate(db) BookmarksTable.onCreate(db) BookmarkItemsTable.onCreate(db) @@ -35,25 +36,53 @@ class DBOpenHelper( RecentLanguagesTable.onCreate(db) } - override fun onUpgrade(db: SQLiteDatabase, from: Int, to: Int) { - CategoryTable.onUpdate(db, from, to) - BookmarksTable.onUpdate(db, from, to) - BookmarkItemsTable.onUpdate(db, from, to) - RecentSearchesTable.onUpdate(db, from, to) - RecentLanguagesTable.onUpdate(db, from, to) - deleteTable(db, CONTRIBUTIONS_TABLE) - deleteTable(db, BOOKMARKS_LOCATIONS) - } + /** + * Delegate to handle database lifecycle + * Used to expose writableDatabase , readableDatabase properties + */ + private val delegate: SupportSQLiteOpenHelper = FrameworkSQLiteOpenHelperFactory().create( + SupportSQLiteOpenHelper.Configuration.builder(context) + .name(DATABASE_NAME) + .callback(object : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) { + + override fun onCreate(db: SupportSQLiteDatabase) { + createAllTables(db) + } + + override fun onUpgrade( + db: SupportSQLiteDatabase, + oldVersion: Int, + newVersion: Int + ) { + CategoryTable.onUpdate(db, oldVersion, newVersion) + BookmarksTable.onUpdate(db, oldVersion, newVersion) + BookmarkItemsTable.onUpdate(db, oldVersion, newVersion) + RecentSearchesTable.onUpdate(db, oldVersion, newVersion) + RecentLanguagesTable.onUpdate(db, oldVersion, newVersion) + deleteTable(db, CONTRIBUTIONS_TABLE) + deleteTable(db, BOOKMARKS_LOCATIONS) + } + + }) + .build() + ) + + val writableDatabase: SupportSQLiteDatabase + get() = delegate.writableDatabase + + val readableDatabase: SupportSQLiteDatabase + get() = delegate.readableDatabase + /** * Delete table in the given db * @param db * @param tableName */ - fun deleteTable(db: SQLiteDatabase, tableName: String) { + fun deleteTable(db: SupportSQLiteDatabase, tableName: String) { try { db.execSQL(String.format(DROP_TABLE_STATEMENT, tableName)) - onCreate(db) + createAllTables(db) } catch (e: SQLiteException) { e.printStackTrace() } diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsDaggerContentProvider.kt b/app/src/main/java/fr/free/nrw/commons/di/CommonsDaggerContentProvider.kt index 4c77d1aad5..8cbc5514d1 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsDaggerContentProvider.kt +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsDaggerContentProvider.kt @@ -1,7 +1,7 @@ package fr.free.nrw.commons.di import android.content.ContentProvider -import android.database.sqlite.SQLiteDatabase +import androidx.sqlite.db.SupportSQLiteDatabase import fr.free.nrw.commons.data.DBOpenHelper import fr.free.nrw.commons.di.ApplicationlessInjection.Companion.getInstance import javax.inject.Inject @@ -18,7 +18,7 @@ abstract class CommonsDaggerContentProvider : ContentProvider() { fun requireDbOpenHelper(): DBOpenHelper = dbOpenHelper!! - fun requireDb(): SQLiteDatabase = requireDbOpenHelper().writableDatabase!! + fun requireDb(): SupportSQLiteDatabase = requireDbOpenHelper().writableDatabase!! private fun inject() { val injection = getInstance(context!!) diff --git a/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesContentProvider.kt b/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesContentProvider.kt index c18f101ae5..eb1cfdea69 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesContentProvider.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesContentProvider.kt @@ -3,9 +3,10 @@ package fr.free.nrw.commons.explore.recentsearches import android.content.ContentValues import android.content.UriMatcher import android.database.Cursor -import android.database.sqlite.SQLiteQueryBuilder +import android.database.sqlite.SQLiteDatabase import android.net.Uri import androidx.core.net.toUri +import androidx.sqlite.db.SupportSQLiteQueryBuilder import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.di.CommonsDaggerContentProvider import fr.free.nrw.commons.explore.recentsearches.RecentSearchesTable.ALL_FIELDS @@ -25,26 +26,25 @@ class RecentSearchesContentProvider : CommonsDaggerContentProvider() { uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String? ): Cursor { - val queryBuilder = SQLiteQueryBuilder().apply { - tables = TABLE_NAME - } + val queryBuilder = SupportSQLiteQueryBuilder.builder(TABLE_NAME) val uriType = uriMatcher.match(uri) val cursor = when (uriType) { - RECENT_SEARCHES -> queryBuilder.query( - requireDb(), projection, selection, selectionArgs, - null, null, sortOrder + RECENT_SEARCHES -> requireDb().query( + queryBuilder.columns(projection) + .selection(selection, selectionArgs) + .orderBy(sortOrder) + .create() ) - RECENT_SEARCHES_ID -> queryBuilder.query( - requireDb(), - ALL_FIELDS, - "$COLUMN_ID = ?", - arrayOf(uri.lastPathSegment), - null, - null, - sortOrder + RECENT_SEARCHES_ID -> requireDb().query( + queryBuilder.columns(ALL_FIELDS) + .selection( + "$COLUMN_ID = ?", arrayOf(uri.lastPathSegment) + ) + .orderBy(sortOrder) + .create() ) else -> throw IllegalArgumentException("Unknown URI$uri") @@ -62,8 +62,10 @@ class RecentSearchesContentProvider : CommonsDaggerContentProvider() { */ override fun insert(uri: Uri, contentValues: ContentValues?): Uri? { val uriType = uriMatcher.match(uri) - val id: Long = when (uriType) { - RECENT_SEARCHES -> requireDb().insert(TABLE_NAME, null, contentValues) + val id: Long? = when (uriType) { + RECENT_SEARCHES -> contentValues?.let { + requireDb().insert(TABLE_NAME, SQLiteDatabase.CONFLICT_NONE, it) + } else -> throw IllegalArgumentException("Unknown URI: $uri") } @@ -101,7 +103,7 @@ class RecentSearchesContentProvider : CommonsDaggerContentProvider() { sqlDB.beginTransaction() when (uriType) { RECENT_SEARCHES -> for (value in values) { - sqlDB.insert(TABLE_NAME, null, value) + sqlDB.insert(TABLE_NAME, SQLiteDatabase.CONFLICT_NONE, value) } else -> throw IllegalArgumentException("Unknown URI: $uri") @@ -129,16 +131,19 @@ class RecentSearchesContentProvider : CommonsDaggerContentProvider() { and will error out otherwise. */ val uriType = uriMatcher.match(uri) - val rowsUpdated: Int + var rowsUpdated: Int = 0 when (uriType) { RECENT_SEARCHES_ID -> if (selection.isNullOrEmpty()) { val id = uri.lastPathSegment!!.toInt() - rowsUpdated = requireDb().update( - TABLE_NAME, - contentValues, - "$COLUMN_ID = ?", - arrayOf(id.toString()) - ) + contentValues?.let { + rowsUpdated = requireDb().update( + TABLE_NAME, + SQLiteDatabase.CONFLICT_NONE, + it, + "$COLUMN_ID = ?", + arrayOf(id.toString()) + ) + } } else { throw IllegalArgumentException( "Parameter `selection` should be empty when updating an ID" diff --git a/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesTable.kt b/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesTable.kt index e32fc9fa49..0c1e973365 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesTable.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/recentsearches/RecentSearchesTable.kt @@ -1,6 +1,6 @@ package fr.free.nrw.commons.explore.recentsearches -import android.database.sqlite.SQLiteDatabase +import androidx.sqlite.db.SupportSQLiteDatabase /** * This class contains the database table architechture for recent searches, It also contains @@ -25,18 +25,18 @@ object RecentSearchesTable { const val CREATE_TABLE_STATEMENT: String = ("CREATE TABLE $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY,$COLUMN_NAME STRING,$COLUMN_LAST_USED INTEGER);") /** - * This method creates a RecentSearchesTable in SQLiteDatabase + * This method creates a RecentSearchesTable in SupportSQLiteDatabase * - * @param db SQLiteDatabase + * @param db SupportSQLiteDatabase */ - fun onCreate(db: SQLiteDatabase) = db.execSQL(CREATE_TABLE_STATEMENT) + fun onCreate(db: SupportSQLiteDatabase) = db.execSQL(CREATE_TABLE_STATEMENT) /** - * This method deletes RecentSearchesTable from SQLiteDatabase + * This method deletes RecentSearchesTable from SupportSQLiteDatabase * - * @param db SQLiteDatabase + * @param db SupportSQLiteDatabase */ - fun onDelete(db: SQLiteDatabase) { + fun onDelete(db: SupportSQLiteDatabase) { db.execSQL(DROP_TABLE_STATEMENT) onCreate(db) } @@ -44,11 +44,11 @@ object RecentSearchesTable { /** * This method is called on migrating from a older version to a newer version * - * @param db SQLiteDatabase + * @param db SupportSQLiteDatabase * @param from Version from which we are migrating * @param to Version to which we are migrating */ - fun onUpdate(db: SQLiteDatabase, from: Int, to: Int) { + fun onUpdate(db: SupportSQLiteDatabase, from: Int, to: Int) { if (from == to) { return } diff --git a/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesContentProvider.kt b/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesContentProvider.kt index c9f7551dc0..e4c12579da 100644 --- a/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesContentProvider.kt +++ b/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesContentProvider.kt @@ -3,13 +3,14 @@ package fr.free.nrw.commons.recentlanguages import android.content.ContentValues import android.database.Cursor -import android.database.sqlite.SQLiteQueryBuilder +import android.database.sqlite.SQLiteDatabase import android.net.Uri import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.di.CommonsDaggerContentProvider import fr.free.nrw.commons.recentlanguages.RecentLanguagesTable.COLUMN_NAME import fr.free.nrw.commons.recentlanguages.RecentLanguagesTable.TABLE_NAME import androidx.core.net.toUri +import androidx.sqlite.db.SupportSQLiteQueryBuilder /** @@ -46,18 +47,13 @@ class RecentLanguagesContentProvider : CommonsDaggerContentProvider() { selectionArgs: Array?, sortOrder: String? ): Cursor? { - val queryBuilder = SQLiteQueryBuilder().apply { - tables = TABLE_NAME - } + val queryBuilder = SupportSQLiteQueryBuilder.builder(TABLE_NAME) - val cursor = queryBuilder.query( - requireDb(), - projection, - selection, - selectionArgs, - null, - null, - sortOrder + val cursor = requireDb().query( + queryBuilder.columns(projection) + .selection(selection, selectionArgs) + .orderBy(sortOrder) + .create() ) cursor.setNotificationUri(context?.contentResolver, uri) return cursor @@ -76,16 +72,19 @@ class RecentLanguagesContentProvider : CommonsDaggerContentProvider() { selection: String?, selectionArgs: Array? ): Int { - val rowsUpdated: Int + var rowsUpdated: Int = 0 if (selection.isNullOrEmpty()) { val id = uri.lastPathSegment?.toInt() ?: throw IllegalArgumentException("Invalid URI: $uri") - rowsUpdated = requireDb().update( - TABLE_NAME, - contentValues, - "$COLUMN_NAME = ?", - arrayOf(id.toString()) - ) + contentValues?.let { + rowsUpdated = requireDb().update( + TABLE_NAME, + SQLiteDatabase.CONFLICT_NONE, + it, + "$COLUMN_NAME = ?", + arrayOf(id.toString()) + ) + } } else { throw IllegalArgumentException("Parameter `selection` should be empty when updating an ID") } @@ -100,11 +99,13 @@ class RecentLanguagesContentProvider : CommonsDaggerContentProvider() { * @param contentValues : new values to be entered to the database */ override fun insert(uri: Uri, contentValues: ContentValues?): Uri? { - val id = requireDb().insert( - TABLE_NAME, - null, - contentValues - ) + val id = contentValues?.let { + requireDb().insert( + TABLE_NAME, + SQLiteDatabase.CONFLICT_NONE, + it + ) + } context?.contentResolver?.notifyChange(uri, null) return "$BASE_URI/$id".toUri() } diff --git a/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesTable.kt b/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesTable.kt index ccd98edaee..77acf40ca1 100644 --- a/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesTable.kt +++ b/app/src/main/java/fr/free/nrw/commons/recentlanguages/RecentLanguagesTable.kt @@ -1,7 +1,7 @@ package fr.free.nrw.commons.recentlanguages import android.annotation.SuppressLint -import android.database.sqlite.SQLiteDatabase +import androidx.sqlite.db.SupportSQLiteDatabase object RecentLanguagesTable { const val TABLE_NAME = "recent_languages" @@ -23,33 +23,33 @@ object RecentLanguagesTable { ");" /** - * This method creates a LanguagesTable in SQLiteDatabase - * @param db SQLiteDatabase + * This method creates a LanguagesTable in SupportSQLiteDatabase + * @param db SupportSQLiteDatabase */ @SuppressLint("SQLiteString") @JvmStatic - fun onCreate(db: SQLiteDatabase) { + fun onCreate(db: SupportSQLiteDatabase) { db.execSQL(CREATE_TABLE_STATEMENT) } /** - * This method deletes LanguagesTable from SQLiteDatabase - * @param db SQLiteDatabase + * This method deletes LanguagesTable from SupportSQLiteDatabase + * @param db SupportSQLiteDatabase */ @JvmStatic - fun onDelete(db: SQLiteDatabase) { + fun onDelete(db: SupportSQLiteDatabase) { db.execSQL(DROP_TABLE_STATEMENT) onCreate(db) } /** * This method is called on migrating from a older version to a newer version - * @param db SQLiteDatabase + * @param db SupportSQLiteDatabase * @param from Version from which we are migrating * @param to Version to which we are migrating */ @JvmStatic - fun onUpdate(db: SQLiteDatabase, from: Int, to: Int) { + fun onUpdate(db: SupportSQLiteDatabase, from: Int, to: Int) { if (from == to) { return } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/items/BookmarkItemsDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/items/BookmarkItemsDaoTest.kt index e7ecbe0747..4754e82aff 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/items/BookmarkItemsDaoTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/items/BookmarkItemsDaoTest.kt @@ -4,9 +4,9 @@ import android.content.ContentProviderClient import android.content.ContentValues import android.database.Cursor import android.database.MatrixCursor -import android.database.sqlite.SQLiteDatabase import android.net.Uri import android.os.RemoteException +import androidx.sqlite.db.SupportSQLiteDatabase import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.argumentCaptor @@ -58,7 +58,7 @@ class BookmarkItemsDaoTest { COLUMN_ID, ) private val client: ContentProviderClient = mock() - private val database: SQLiteDatabase = mock() + private val database: SupportSQLiteDatabase = mock() private val captor = argumentCaptor() private lateinit var testObject: BookmarkItemsDao diff --git a/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/locations/BookMarkLocationDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/locations/BookMarkLocationDaoTest.kt index 4808d85188..71e7bdd682 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/locations/BookMarkLocationDaoTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/locations/BookMarkLocationDaoTest.kt @@ -4,7 +4,6 @@ import android.content.ContentProviderClient import android.content.ContentValues import android.database.Cursor import android.database.MatrixCursor -import android.database.sqlite.SQLiteDatabase import android.net.Uri import android.os.RemoteException import androidx.room.Room diff --git a/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/pictures/BookmarkPictureDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/pictures/BookmarkPictureDaoTest.kt index 5932f24bc1..74d95908e2 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/pictures/BookmarkPictureDaoTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/bookmarks/pictures/BookmarkPictureDaoTest.kt @@ -4,9 +4,9 @@ import android.content.ContentProviderClient import android.content.ContentValues import android.database.Cursor import android.database.MatrixCursor -import android.database.sqlite.SQLiteDatabase import android.net.Uri import android.os.RemoteException +import androidx.sqlite.db.SupportSQLiteDatabase import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.argumentCaptor @@ -42,7 +42,7 @@ import org.robolectric.annotation.Config class BookmarkPictureDaoTest { private val columns = arrayOf(COLUMN_MEDIA_NAME, COLUMN_CREATOR) private val client: ContentProviderClient = mock() - private val database: SQLiteDatabase = mock() + private val database: SupportSQLiteDatabase = mock() private val captor = argumentCaptor() private lateinit var testObject: BookmarkPicturesDao diff --git a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryDaoTest.kt index 6037a8e45f..53d82dabf7 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryDaoTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryDaoTest.kt @@ -4,8 +4,8 @@ import android.content.ContentProviderClient import android.content.ContentValues import android.database.Cursor import android.database.MatrixCursor -import android.database.sqlite.SQLiteDatabase import android.os.RemoteException +import androidx.sqlite.db.SupportSQLiteDatabase import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.argumentCaptor @@ -55,7 +55,7 @@ class CategoryDaoTest { COLUMN_TIMES_USED, ) private val client: ContentProviderClient = mock() - private val database: SQLiteDatabase = mock() + private val database: SupportSQLiteDatabase = mock() private val captor = argumentCaptor() private val queryCaptor = argumentCaptor>() diff --git a/app/src/test/kotlin/fr/free/nrw/commons/explore/recentsearches/RecentSearchesDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/explore/recentsearches/RecentSearchesDaoTest.kt index 5e128d4ee2..f5e338e857 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/explore/recentsearches/RecentSearchesDaoTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/explore/recentsearches/RecentSearchesDaoTest.kt @@ -4,8 +4,8 @@ import android.content.ContentProviderClient import android.content.ContentValues import android.database.Cursor import android.database.MatrixCursor -import android.database.sqlite.SQLiteDatabase import android.os.RemoteException +import androidx.sqlite.db.SupportSQLiteDatabase import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.argumentCaptor @@ -45,7 +45,7 @@ import java.util.Date class RecentSearchesDaoTest { private val columns = arrayOf(COLUMN_ID, COLUMN_NAME, COLUMN_LAST_USED) private val client: ContentProviderClient = mock() - private val database: SQLiteDatabase = mock() + private val database: SupportSQLiteDatabase = mock() private val captor = argumentCaptor() private val queryCaptor = argumentCaptor>() diff --git a/app/src/test/kotlin/fr/free/nrw/commons/recentlanguages/RecentLanguagesDaoUnitTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/recentlanguages/RecentLanguagesDaoUnitTest.kt index 5c0776da9f..4c9c9b96bc 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/recentlanguages/RecentLanguagesDaoUnitTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/recentlanguages/RecentLanguagesDaoUnitTest.kt @@ -4,8 +4,8 @@ import android.content.ContentProviderClient import android.content.ContentValues import android.database.Cursor import android.database.MatrixCursor -import android.database.sqlite.SQLiteDatabase import android.os.RemoteException +import androidx.sqlite.db.SupportSQLiteDatabase import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.argumentCaptor import com.nhaarman.mockitokotlin2.inOrder @@ -40,7 +40,7 @@ class RecentLanguagesDaoUnitTest { ) private val client: ContentProviderClient = mock() - private val database: SQLiteDatabase = mock() + private val database: SupportSQLiteDatabase = mock() private val captor = argumentCaptor() private lateinit var testObject: RecentLanguagesDao