I have this code in SQL:
SELECT SUM(number), DAY(date) FROM conting GROUP BY DAY(date) ORDER BY DAY(date) ASC
then I need to convert in room:
#Query("SELECT SUM(number), DAY(date) FROM Records GROUP BY DAY(date) ORDER BY DAY(date) ASC") fun getResumeData(): List<Graph>
Graph.kt
data class Graph (
#ColumnInfo(name = "DAY(date)") var index: Int,
#ColumnInfo(name = "SUM(number)") var value: Int
)
but it returns the error no such function: DAY how can I fix it?
note:
Android (and Room) uses SQLite, not MySQL, so you will need to structure your queries with functions that SQLite has available. You can do something similar with SQLite's date() and datetime() functions, see https://www.sqlite.org/lang_datefunc.html for more information.
Related
I need to perform column sum operation
But I don't understand what exactly I need to insert into fun getSumItem(): Flow<Cursor>
this is my Dao
#Dao
interface Dao {
#Insert
fun InsertItem(item: Income)
#Query("SELECT SUM(sum) AS value FROM income")
fun getSumItem(): Flow<Cursor>
}
this is my table
#Entity(tableName = "income")
data class Income(
#PrimaryKey(autoGenerate = true)
var id: Int? = null,
#ColumnInfo(name = "date")
var date: String,
#ColumnInfo(name = "type")
var type: String,
#ColumnInfo(name = "sum")
var sum: Float,
)
I did not find a similar example and any detailed information on the Internet.
when I use Cursor i get this error:
Entities and POJOs must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type). - android.database.Cursor
all other options that I found on the Internet also gave errors
When you say SELECT SUM(sum) AS value FROM income the output that Room handles will be a Cursor with a single column named value. Room does not know how to extract this value and build a Cursor object from that single value.
Room expects to extract data from the underlying Cursor that is generated by the SQLite API, which Room is a wrapper to/around, and deliver the data according to the object that the function returns (and thus must be able to ascertain how to build the resultant object).
As Room extracts a single value then you simply need to retrieve the value returned as a Float.
fun getSumItem(): Flow<Float>
I am trying to create a small app using Kotlin Multiplatform where i can save book titles and their authors but i'm struggling with the data classes and how to map them together so that i get the author with all of their books and the publish date.
CREATE TABLE book(
id INTEGER NOT NULL,
name TEXT NOT NULL,
publishDate INTEGER NOT NULL,
authorId INTEGER NOT NULL
)
CREATE TABLE author(
id INTEGER NOT NULL,
name TEXT NOT NULL
)
Here are my data classes:
#Serializable
data class bookEntity(
id: Int,
name: String,
authorId: Int
)
#Serializable
data class authorEntity(
id: Int,
authorName: String
books: List<bookEntity>
)
and my Query:
selectAuthors:
SELECT * FROM author
JOIN book ON book.authorId = author.id
WHERE book.authorId = author.id
i tried the following mapping but it didn't work:
private fun mapAuthor(
id: Int,
authorName: String,
bookId: String,
name: String,
publishDate: Long
): Author(
return Author (
id = id,
authorName = authorName,
book = List<BookEntity>(
id = bookId,
name = name,
publishDate = publishDate
)
)
)
How can i work with lists like this?
Every help is appreciated!
The ON clause of the JOIN is the condition which links both tables. You don't need to repeat the condition in the WHEN clause. Use WHEN to further narrow down the query, for instance if you're searching for a specific author name.
SELECT * FROM author
JOIN book ON book.authorId = author.id
WHERE author.name LIKE 'John%';
If you want to query all authors, just remove the WHEN completely.
Also, you don't need to create data classes and do the mapping yourself. SQLDelight already creates data classes for your queries.
I am new to Room and it's throwing me through a loop. I am trying to take a specific row of a specific data class in my Room database and compile into a list and turn this list into a String so I can do stuff with it. I can sort of do this by printing the contents of the Room database table to the console, but that's it.
I'll show you my code that I have
this is my data class.
code.kt
#Parcelize
#Entity(tableName = "code_table")
data class code(
#PrimaryKey(autoGenerate = true)
val id: Int,
val code: String //this is the item I want to isolate
): Parcelable
a snippet of my ViewModel.kt that I use.
val readAllData: LiveData<List<code>>
private val repository: respository
init {
val Dao = database.getDatabase(application).dao()
repository = respository(Dao)
readAllData = repository.readAllData
}
a snippet of my repository.kt that I use.
val readAllData: LiveData<List<code>> = dao.readAllData()
a snippet of my Dao.kt that I use.
#Query("SELECT * FROM code_table ORDER BY id ASC")
fun readAllData(): LiveData<List<code>>
How I read the Room database table
private fun dbread(){
mUserViewModel = ViewModelProvider(this).get(ViewModel::class.java)
mUserViewModel.readAllData.observe(viewLifecycleOwner, Observer { user ->
var abc = user
println(abc)
})
}
this is what it outputs
I/System.out: [code(id=2, code=textA), code(id=3, code=textB), code(id=4, code=textC)]
I am not hell-bent on only querying the code row but I need to aggregate all the data in the code row into a string or JSON array. so, in this case, that would be the textA, textB and textC (I'm worried I haven't made myself clear)
I have also tried doing the following in the Dao
#Query("SELECT code FROM code_table")
fun readdb(): LiveData<List<code>>//I've tried this with lot different types within the Parentheses
this makes the build fail: it says the following
:app:kaptDebugKotlin 1 error
java.lang.reflect.InvocationTargetException (no error message)
I would guesstimate that this error is because the SQL syntax is off but I don't think it is.
I have also tried messing around with the ViewModel and repository to see if I can get them to only output just the code row but to no avail. I'm surprised I'm the first to post about this.
thank you for your time.
You can obtain you desidered result just by using SQL.
In Android (and with Room) you're using a SQLite database, so the most important thing is writing some SQL that is compliant with SQLite.
Then you can select the concatenation of all the values in your table, just by asking to the database to do it. You can achieve it with this:
#Query("SELECT GROUP_CONCAT(code) FROM code_table")
fun readConcatenatedCode(): LiveData<String>
The returned value will be a LiveData of String, and the String will contain all the values, concatenated.
I've two columns (name and description) in FTS virtual table and I want to prioritize the name column in FTS using matchinfo function, but with room in android I'm getting following error:
Error retrieving data from table.: unable to use function matchinfo in the requested context (code 1 SQLITE_ERROR)
Here is my Query:
#Query("""select workout_cache.id, workout_cache.met, workout_cache.name, workout_cache.workoutDescription, matchinfo(workout_cache_fts, 'pcs') as mi
from workout_cache join workout_cache_fts on workout_cache.id = workout_cache_fts.id
where workout_cache_fts match :text group by workout_cache.id""")
abstract suspend fun query(text: String): List<WorkoutCacheEntityWithMatchInfo>
My WorkoutCacheEntityWithMatchInfo class
class WorkoutCacheEntityWithMatchInfo(
#Embedded
val workout: WorkoutCacheEntity,
#ColumnInfo(name = "mi")
val matchInfo: ByteArray
)
UPDATE: It's working fine when I don't use join clause.
It's silly. I just removed the group by clause and it worked.
Here updated Dao:
#Query("""select workout_cache.id, workout_cache.met, workout_cache.name, workout_cache.workoutDescription, matchinfo(workout_cache_fts, 'pcs') as mi
from workout_cache join workout_cache_fts on workout_cache.id = workout_cache_fts.id
where workout_cache_fts match :text""")
abstract suspend fun query(text: String): List<WorkoutCacheEntityWithMatchInfo>
I have the following query function -
#Query("select chats.groupId, (select count(*) from ${Constants.messagesTable} where groupId = chats.groupId) as 'count' from ${Constants.chatsTable} chats where chats.groupId in (:groupIdListAsString)")
fun getChatMessagesCount(groupIdListAsString : String) : LiveData<List<ChatCountModel>>
and the following object -
#Dao
data class ChatCountModel (val groupId : String, val count : Int)
I have checked the query, it is working fine. But it can't create the needed custom object from the 2 selections I make from this query.
How can I make it work?
Solved - groupIdListAsString was a list joined to string. I just gave it the list and it was able to work with it as a list object.