How to use replace in android room database sql? - android

#Query("update bookmarks set bookmarks_path= replace(bookmarks_path,:oldPath,:newPath) where bookmarks_path like :oldPath || '%'")
fun updateBookmarksPath(oldPath: String, newPath: String): Completable
I am using the room database and this is my code
I found that the format of this code is not correct when running, android studio prompts me: expression expected, got'replace'
like this
I want to achieve the effect like this
----path------------------path
/root/1/1--------------/stack/1/1
/root/name/1------/stack/name/1
/root/cls/1-----------/stack/cls/1
/root/go/1-----------/stack/go/1
/root/js/1------------/stack/js/1
please

REPLACE is both an SQLite keyword and, in the case of your intended use, the name of a string function: replace() .
The Room annotation processor appears to be rejecting your query string because it is treating replace as keyword instead of function name. Maybe a bug?
Some quick experiments indicate that a possible solution is to surround replace in backticks to mark is as a name (see keyword link above). Please give it a try:
#Query("update bookmarks set bookmarks_path= `replace`(bookmarks_path,:oldPath,:newPath) where bookmarks_path like :oldPath || '%'")
fun updateBookmarksPath(oldPath: String, newPath: String): Completable

Related

Android Room getting substring not working

I am trying to search a substring using room for example in string "I am eating mutton", I am trying to search "eating" as a substring, I am trying this query, it works fine if I search for exact substring "eating" but doesn't work if I search with "I am eating rice" etc.
#Query("select msg_temp from auto_reply where keyword LIKE '%'||:keyword||'%'")
fun selectKeyword(keyword: String): String
I have seen many answers, all are suggesting same method, even this query works in sqlite browser. Any help should be appreciated
Try using :-
#Query("select msg_temp from auto_reply where keyword LIKE :keyword")
fun selectKeyword(keyword: String): String
and then use
selectKeyword("%eating%")
an alternative (but case sensitive) :-
#Query("select msg_temp from auto_reply where instr(keyword,:keyword)")
wild characters are not considered so just selectKeyword("eating")
another that should work but!!!!
#Query("SELECT * FROM user WHERE name LIKE :wildchar || :name || :wildchar")
fun selectKeyword("eating","%")

Android RoomDB dynamic select parameter

in order to cut down on repeated code in my Dao I'm trying to consolidate 4 similar calls into one. I have 4 different queries that are exactly the same except they SELECT a different value from the row. To determine what value I select, I want to pass in a variable which is a string, which corresponds to the entity attribute value:
#Query("""
SELECT :infoType
FROM entry_log
WHERE date >= date(:startDate)
AND date < date(:endDate)
ORDER BY datetime(date) DESC
""")
fun getEntryInfoInDateRange(startDate: String, endDate: String, infoType: String): Observable<List<Int?>>
When I call this, I get back a list with the correct number of elements, but all of them are 0 (which is incorrect)
However, if I have:
SELECT infotypeone
FROM entry_log
WHERE date >= date(:startDate)
AND date < date(:endDate)
ORDER BY datetime(date) DESC
""")
fun getEntryInfoInDateRange(startDate: String, endDate: String, infoType: String): Observable<List<Int?>>
I will be given a list with the correct data (they aren't all 0)
Anyone know if there's some limitation to using parameters in the SELECT field? The parameters in the WHERE/AND fields work just fine
In theory there is one way to do something like you want with #RawQuery. This method has some limitations (for example, you shouldn't expect for type converters to work, and I'm not sure it works seamless with RxJava/LiveData, may be there are others?), but still you can try.
From documentation:
If you know the query at compile time, you should always prefer Query since it validates the query at compile time and also generates more efficient code since Room can compute the query result at compile time
On the other hand, RawQuery serves as an escape hatch where you can build your own SQL query at runtime but still use Room to convert it into objects.
In your Dao there would be two methods (you can play with Observable, but I'm not sure it can digest that):
#RawQuery
fun getEntryInfoInDateRangeTemplate(query: SupportSQLiteQuery): Observable<List<Int>>
fun getEntryInfoInDateRange(startDate: String, endDate: String, infoType: String):Observable<List<Int?>> {
val query =
"""
SELECT infoType
FROM entry_log
WHERE date >= date(?startDate)
AND date < date(?endDate)
ORDER BY datetime(date) DESC
""".replace("infoType", infoType)
return getEntryInfoInDateRangeTemplate(SimpleSQLiteQuery(query, arrayOf(startDate, endDate)))
}
And as a result you can call the second method from Repository/ViewModel.

Android Room Query: Text Matches Exactly the Search String or Start With Search String

What would be the android room query to match a column data exactly match or start with the search string
VVV this seems to giving me only the exact match
select * from table where dna_sequence like :searchTerm
Thanks
this seems to giving me only the exact match
select * from table where dna_sequence like :searchTerm
There is nothing wrong with your query. The problem is with your Java or Kotlin code. You are getting an exact match because you are passing an exact to searchTerm and not using any wildcards. The LIKE operator in SQL allows us to use wildcards in the string to match more than just strict equality. _ will match a single character while % will match zero or more characters. If you don't use these wildcards, then LIKE will be the exact same as =. So you need to pass a value for searchTerm that uses one of these wild card characters. For example, if you a DAO interface declared as
#Dao
public interface MyDao {
#Query("SELECT * FROM foo WHERE search like :searchTerm")
public Foo[] getFooSearch(String searchTerm);
}
You can call the method with something like:
MyDao dao;
dao.getFooSearch("abcdef%");
which will match the start of the string.
Note: This example is a bit contrived because you only provided your SQL query and didn't provide any of the Java or Kotlin code for your DAO or Data Entity.
Try this in search method:
public String getResultForSearchString(String searchTerm){
String searchExptression=searchTerm+"%";
//.. perform search operation on SQLite with searchExpression
return result;
}
For more information visit: https://www.sqlitetutorial.net/sqlite-like/
Hope it helps.

How to put integer literals into Room query?

Is it possible to put integer literals into Room query? Following query leads to build error:
#Query("UPDATE topics SET unreadCount=0 WHERE id=:chatId")
fun resetUnreadCount(chatId: Long)
I have tried several options (including RawQuery) and came to an option of passing Int argument with default value:
#Query("UPDATE chats SET unreadCount=:ZERO WHERE id=:chatId")
fun resetUnreadCount(chatId: Long, ZERO: Int = 0) // hacky way to pass int literal into the query
Is there a normal way to do that?
Please check this documentation.
https://www.sqlite.org/datatype3.html. Look in section 3.4, it talks about coumn affinity behviour
unreadCount='0'
This should also work
#Query("UPDATE topics SET unreadCount='0' WHERE id=:chatId")
First query has a different Entity class 'topics'
#Query("UPDATE topics SET unreadCount=0 WHERE id=:chatId")
Should it be chats too? as the below query is working. integer in the query is fine.
#Query("UPDATE chats SET unreadCount=:ZERO WHERE id=:chatId")

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)).

Categories

Resources