Room: how to check whether row exists - android

In my repository class, I want to fetch data only if none exists in a Room table. How to check whether any row exists in a table?

Use EXISTS operator, and return 1 means true and 0 means false.
If you want to check some specific row and some condition, do this trick:
#Query("SELECT EXISTS(SELECT * FROM tableName WHERE id = :id)")
fun isRowIsExist(id : Int) : Boolean
Or simple use this:
#Query("SELECT EXISTS(SELECT * FROM tableName)")
fun isExists(): Boolean

You can use EXISTS operator and return just Boolean:
#Query("SELECT EXISTS(SELECT * FROM table)")
fun hasItem(): Boolean

As ADM suggested, you might get lucky using COUNT() to count the actual rows in a table.
However, I would recommend just fetching the data anyway - if none exists Room will simply return an empty list, and this should not be less efficient than asking for the row count (if it's 0 anyway).
As a plus you will have less code to write to get the functionality you want! :-)

Related

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.

cant find out how to read a row from room database

I am new to Android studio, especially in room database.
I can't find out how to read a row from room database
//in dao
#Query("SELECT * from qarindosh_table LIMIT 1")
Qarindosh getAnyQarindosh();
I couldn't find out how to read a row. Please help.
Room database is working.
This is how you do it
#Query("SELECT * FROM qarindosh_table")
List<ModelClass> getAllItems();
If I understand you correctly, you wish to read 1 specific row from a database. In order to do that, you need to query by primary key, usually named id in the Entity. Something like that:
#Query("SELECT * FROM qarindosh_table WHERE id=(:id)")
Qarindosh loadQarindoshById(int id);

Room DB select List of all items + total sum of these items

I have 2 queryes from ROOM DB:
#Query("SELECT * FROM basket_items")
Flowable<List<BasketItem>> getAll();
#Query("SELECT SUM(count*amount) FROM basket_items")
Flowable<Long> totalSum();
How can I merge this queryes to one query? And what type of model it will be return?
Room Queries can return POJO (not an #Entity), and therefore you can make temporary model for your DAO.
As I already asked in comments, I don't know what you're trying to achieve (as in what value you want to get from those queries).
But hopefully this example might help:
YourDao.java
#Query("SELECT name AS nameItem, (count * amount) AS countItem FROM basket_items")
Flowable<List<CountedBasketItem>> getAllCounted();
static class CountedBasketItem {
String nameItem;
Long countItem;
}
Additional Answer
What you want to return List and total sum is not possible by the query. SUM is aggregation method, you aggregate the list.
So there're 2 options that you might want to do:
Use GROUP BY in your query
Or execute those 2 Flowable and get the result.
you can create field totalSum in your pojo and use this query
#Query("SELECT *,SUM(count*amount) AS totalSum FROM basket_items")
Flowable<List<BasketItem>> getAll();
you will get all table and the field totalSum is SUM(count*amount)

Room - Select query with IN condition?

Is it possible to use SQLite's IN condition with Room?
I'm trying to select a list of items from my database where the value of a certain column (in this case a TEXT column) matches any one of a set of filter values. That's pretty easily done in SQL and SQLite, by my knowledge, just by adding an IN condition to your SELECT statement (see here). However, I can't seem to make it work with Room.
I keep getting this error:
Error:(70, 25) error: no viable alternative at input 'SELECT * FROM Table WHERE column IN :filterValues'
(where the input to the DAO #Query-annotated method is called filterValues)
I have tried three different methods now:
Passing the argument as a List<String>
Passing the argument as a String[]
And lastly passing the argument as simply a String, but formatted as (value_1, value_2, ..., value_n)
The last one in particular should work easily, as it will (or at least, it should) directly translate to SELECT * FROM Table WHERE column IN (value_1, value_2, ..., value_n), which is the exact way you would manually write out the SELECT if you were just accessing the database directly.
So as I was preparing to submit this, I double-checked a bunch of the stuff I had looked up previously and found the thing I had somehow missed and would have saved this question from being necessary.
As it turns out, both of these options:
Passing the argument as a List<String>
Passing the argument as a String[]
are viable (and you can replace String with any type the database can represent, such as char or int), you simply need to change the syntax in the #Query annotation from this:
#Query("SELECT * FROM Table WHERE column IN :filterValues")
to this:
#Query("SELECT * FROM Table WHERE column IN (:filterValues)")
Easy as pie, right?
Note that the third method above (passing the argument as simply a String, but formatted as (value_1, value_2, ..., value_n)) does not appear to be supported by Room, but that's probably not a bad thing, since that's the hard way.
Since I already had the whole thing typed out, I figured I would leave the question up in case other people are have as much difficulty finding this solution as I did and stumble upon this question.
Hi you can use this query:
#Query("SELECT * FROM user WHERE uid IN(:userIds)")
public abstract List findByIds(int[] userIds);
or
#Query("SELECT * FROM user WHERE uid IN(:userIds)")
public abstract List findByIds(List<Integer> userIds);
Similarly to above answers in Kotlin you can use vararg instead of array or list:
#Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun getUsers(vararg userIds: Int): List<User>?
and use it like repository.getUsers(1, 2, 3).
If needed, to convert vararg to list see https://proandroiddev.com/kotlins-vararg-and-spread-operator-4200c07d65e1 (use *: format(output, *params)).

Hardcode Boolean Query In Room Database

I'm building an Android application that displays a list of potential matches for a user. The user can click on one to like the user, and I save all of those likes locally.
I can write a query to get the list of matches like this:
#Query("SELECT * FROM match WHERE liked = :liked ORDER BY match DESC LIMIT :limit")
fun getMatches(limit: Int = 6, liked: Boolean = true): Flowable<List<Match>>
I've learned that this works fine. However, I don't foresee any scenario where I'll ever set liked to false, and so I'm curious if there is a way to hardcode my Boolean condition? If I try:
#Query("SELECT * FROM match WHERE liked = true ORDER BY match DESC LIMIT :limit")
I get the following error at compile time:
Error:(8, 0) Gradle: error: There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such column: true)
How can I hard code this Boolean in my query string?
I have also tried:
Wrapping the condition in single quotes
#Query("SELECT * FROM match WHERE liked = 'true' ORDER BY match DESC LIMIT :limit")
SQLite does not have a boolean data type. Room maps it to an INTEGER column, mapping true to 1 and false to 0.
So, I would expect this to work:
#Query("SELECT * FROM match WHERE liked = 1 ORDER BY match DESC LIMIT :limit")
Bear in mind that this behavior is undocumented. However, it shouldn't change — at least not without alarm klaxons sounding — as we'd need to use migrations to deal with any changes.
CommonWare's approach does work and also answers the OPs question directly; however, I'm not a fan of making such an assumption about the database. The assumption should be safe, but it may create unexpected work down the road if Room ever decides to change it's boolean implementation.
I'd suggest that the better approach is to not hardcode the boolean 1 or 0 into the query. If the database is behind a repository, it is still possible for the repository to expose a graceful API. Personally, I think shielding the larger codebase from the database implementation is a good thing anyways.
Dao Method (copied from OP's question)
#Query("SELECT * FROM match WHERE liked = :liked ORDER BY match DESC LIMIT :limit")
fun getMatches(limit: Int = 6, liked: Boolean = true): Flowable<List<Match>>
Repository
class Repository {
public Flowable<List<Match>> getLikedMatches() {
return dao.getMatches(6, true);
}
}
Of course, this is an opinionated option in that it assumes a certain architectural style. However, it does not make assumptions about the internal database. Even without the repository shielding the database, the call can be made into the database by passing true everywhere - also without making assumptions as to the underlying data.
You don't have to compare boolean column to a value. Just use the column value itself as a boolean expression. You can easily change your query to SELECT * FROM match WHERE liked ORDER BY match DESC LIMIT :limit.
If you want to compare to false value you can use following expression: where not liked.
#Query("SELECT * FROM searched_data_table WHERE favourit_history==1 ORDER BY lang_id DESC")
Use this query to search data from the table this will give you data in descending order with respect to your key value

Categories

Resources