How to get specific column from android room db? - android

I tried to get columns through column names in DAO, but it didn't work.
#Query("SELECT :columnName FROM info_table")
suspend fun getItem(columnName: String): List<Any>
I have so many columns so It is not proper approach.
#Query("SELECT TIME FROM info_table")
suspend fun getTime(): List<Long>
So How can i deal with it?

Unless you hard code the column names you cannot use a variable for the column name in an #Query annotation.
However, you could utilise a RawQuery e.g. :-
#RawQuery
fun rawQuery(theQuery: SimpleSQLiteQuery): List<String>
fun getAColumnFromATable(columnName: String, tableName: String): List<String> {
return rawQuery(SimpleSQLiteQuery("SELECT $columnName FROM $tableName"))
}
in which case you use the getAColumnFromATable function, which in this case would return a List which would be capable of getting any values store in the database with the exception of ByteArrays (BLOBS in SQLite terms, in which case you could utilise the SQLite built-in hex function).
this is more than you asked for as it has the additional flexibility of being able to work for any table.

Related

How to use sorting by two values including datatime properly in Room?

As in topic, how to use sorting by two values including datatime properly in Room?
My dataString = "02/03/2012", so format dd/MM/YYYY.
#Query("SELECT * FROM notification_list ORDER BY isRead ASC, STR_TO_DATE(data,\"%d-%m-%Y\") DESC")
abstract suspend fun readAllData(): List<NotificationItemsResponse.NotificationItemData>
error: There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such function: STR_TO_DATE)
public abstract java.lang.Object readAllData(#org.jetbrains.annotations.NotNull()
I also have found method with convert, but it doesn't work as well with similar error.
Does room with sqLite have inner methods that I could use?
What is a solution for this?

Android Room combining the result of N queries into a live data list

I have a room database setup and I want to query that database N number of times and combine the results of each query into a live data array to display back to the user.
I'm pretty sure I want to be using MediatorLiveData but every example online has a predefined amount of live data sources it is combining.
I have the following setup:
petDao
#Query("SELECT * FROM pet_table WHERE name LIKE :petName")
fun getPetsByPetName(petName: String): LiveData<Pet>
petRepository
fun getPetsByPetName(petNames: List<String>): LiveData<List<Pet>> {
for (petName: String in petNames) {
val pets = petDao.getPetsByPetName(petName)
// Combine into one live list of pets
}
}
Have you tried this in your DAO?
#Query("SELECT * FROM pet_table WHERE name IN (:petNames)")
fun getPetsByPetName(petNames: List<String>): LiveData<List<Pet>>
It should work with a list of up to 999 arguments. (not sure if the parameter has to be an array, or if the list is fine)
As an extension over SQLite bind arguments, Room supports binding a
list of parameters to the query. At runtime, Room will build the
correct query to have matching number of bind arguments depending on
the number of items in the method parameter.
https://developer.android.com/reference/androidx/room/Query
To me it seems more appropriate for the example you've given.

Apply search filter on list returned by LiveData Android Kotlin

I am loading a set of data from db using room and pagedList since it is a large set. I need to filter that data and show it to the user accordingly using the same pagedlistadapter. Please help.
dao is as follows
#WorkerThread
#Query("SELECT * FROM users WHERE name LIKE :query ORDER BY id DESC")
fun getAll(query: String): DataSource.Factory<Int, users>
Table has 4 fields - id,name,phone,address
You should use Transformations.switchMap() to requery the database any time the search term changes:
https://github.com/gavingt/upcoming-games/blob/cd7af7fbdd60933991ea7f8b966ca171bb594cb3/app/src/main/java/com/gavinsappcreations/upcominggames/ui/list/ListViewModel.kt#L35
Or see Google's Paging Library codelab, which does the same thing:
https://codelabs.developers.google.com/codelabs/android-paging/index.html?index=..%2F..%2Findex#1
#Query("SELECT * FROM users WHERE name LIKE :query ORDER BY id DESC")
fun getAll(query: String): DataSource.Factory<Int, users>
Here's your query string must be like %ABC% where abc is the name of the user.
The LIKE key word is use to check/find the pattern in the records Here you can read the possible pattern searches
To attach the % % to your query string you need to call this function as
YOUR_HELPER.getAll("%".plus(YOUR_QUERY).plus("%"))
plus() uses for Concatenation.

Passing in a string to use as part of a Room query

Why does this not work in Room?:
val dataSourceFactory =
database.gameDao.getGames("Game.platforms LIKE '%XONE%'")
#Query("SELECT * FROM Game WHERE :likeClause")
fun getGames(likeClause: String): DataSource.Factory<Int, Game>
But this does?:
#Query("SELECT * FROM Game WHERE Game.platforms LIKE '%XONE%'")
fun getGames(): DataSource.Factory<Int, Game>
Is there any way to pass in a string that can stand in as part of the query?
EDIT: I know this isn't the correct way to form a single LIKE clause, but I'm actually trying to pass in multiple LIKE clauses. So I want a way to inject text directly into the query, but Room doesn't seem to want me to do that.
You are talking about dynamic SQL and I dont think this is possible with room. what would work is
#Query("SELECT * FROM Game WHERE Game.platforms LIKE :likeClause1 AND Game.publisher LIKE :likeClause2")
fun getGames(likeClause1: String, likeClause2: String): DataSource.Factory<Int, Game>
and you can use either AND or OR as needed and if you want to ignore one of the like clauses just pass an empty string

Room - SELECT query, get or default

In SQL Brite, there's a method mapToOneOrDefault. Is there a similar thing in Room?
Say for Model
#Entity(tableName = "users")
data class User(#PrimaryKey val name: String)
and Dao
#Dao
interface UserDao {
#Query("SELECT FROM users where name = :name")
fun getUserByName(name: String): Flowable<User>
}
Not the stream returns nothing for getUserByName("John") if there's no John in DataBase. Is there a way to get a default value, say User("")?
Not the stream returns nothing for getUserByName("John") if there's no
John in DataBase. Is there a way to get a default value, say User("")
There is no default mechanism.
You could change from Flowable<User> to Flowable<List<User>>. In case of no user you will get an empty list back. You can use a map to check and return a default value or filter+switchIfEmpty.
Or you could change from Flowable to Single. With Single, in case of no rows, matching your query, onError will be triggered. You can then implement onErrorReturn or onErrorResumeNext to return a default value
You can use Maybe instead of the Flowable in this case.
Maybe: Conceptually, it is a union of Single and Completable providing the means to capture an emission pattern where there could be 0 or 1 item or an error signaled by some reactive source.
You can then use the operator defaultIfEmpty to map to a new object if the query didn't return a value.
Reference

Categories

Resources