I want to model relationships with SQLDelight, especially a one to many relationship.
I have 2 tables: recipe
and ingredient
. For simplicity they look like this:
CREATE TABLE recipe (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL
)
CREATE TABLE ingredient (
recipe_id INTEGER NOT NULL,
name TEXT NOT NULL,
FOREIGN KEY (recipe_id) REFERENCES recipe(id) ON DELETE CASCADE
);
So I have a list of recipes and each recipe can contain 0-n ingredients.
I have 2 goals:
I'm pretty sure the first one can only be done manually, e.g. insert the recipe then manually insert the associating ingredients.
For the latter I try to join the tables with this statement:
selectWithIngredients:
SELECT *
FROM recipe
INNER JOIN ingredient ON recipe.id = ingredient.recipe_id
WHERE recipe.id=?;
For which SQLDelight generates me a 1:1 relationship file:
public data class SelectWithIngredients(
public val id: Long,
public val name: String,
public val recipe_id: Long,
public val name_: String,
)
Is there any nice way to retrieve the data (recipe + list of ingredients) with one generated function? Something similar to Rooms @Embedded
and @Relation
annotations.
Unfortunately, SQLDelight is not so exquisite. All it does is give you a data class for each row of a query, if you want to do more complicated logic like mapping one table to a list of some other table than you will need to do that yourself in kotlin.
E.g. having Recipe like this
data class Recipe(val name: String, val ingredients: List<String>)
You can do this with your select
val rows: List<SelectWithIngredients>
rows.groupBy { it.name }
.map { (recipe, selectRows) ->
Recipe(name, selectRows.map { it.name_ }
}