VIEW models no longer have encapsulated, null-safe data models from joined tables
See original GitHub issueLet’s take the following *.sq
files:
-- Animal.sq
CREATE TABLE animal(
id INTEGER PRIMARY KEY AUTOINCREMENT
);
animal_view:
CREATE VIEW animal_view AS
SELECT A.*, H.*, C.*
FROM animal A
LEFT JOIN human H ON H.animal_id = A.id
LEFT JOIN cat C ON C.animal_id = A.id;
-- Human.sq
CREATE TABLE human(
id INTEGER PRIMARY KEY AUTOINCREMENT,
animal_id INTEGER NOT NULL,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
FOREIGN KEY(animal_id) REFERENCES animal(id)
);
Cat.sq
CREATE TABLE cat(
id INTEGER PRIMARY KEY AUTOINCREMENT,
animal_id INTEGER NOT NULL,
name TEXT,
pattern TEXT,
FOREIGN KEY(animal_id) REFERENCES animal(id)
);
For SqlDelight 0.9.0, or pre-1.0 for that matter, the animal_view
model looks like so:
interface Animal_viewModel<T1 extends AnimalModel, T2 extends HumanModel, T3 extends CatModel> {
@NonNull
T1 A();
@Nullable
T2 H();
@Nullable
T3 C();
}
Where for T1
, T2
, and T3
we have:
public interface AnimalModel {
...
long id();
...
}
public interface HumanModel {
...
long id();
long animal_id();
@NonNull
String first_name();
@NonNull
String last_name();
...
}
public interface CatModel {
...
long id();
long animal_id();
@Nullable
String name();
@Nullable
String pattern();
...
}
Notice how we have encapsulation of the joined table models and some null-safety thanks to the nullable annotations. Even though the generated code is in Java, Kotlin can infer the null type-safety thanks to the annotations.
When compiling these same *.sq
files with SqlDelight 1.1.3, we get the following, more flat-structured model for animal_view
:
interface Animal_view {
val id: Long
val id_: Long?
val animal_id: Long?
val first_name: String?
val last_name: String?
val id__: Long?
val animal_id_: Long?
val name: String?
val pattern: String?
...
Two issues I see with the newer model structure:
- Slight naming conflict with
id
andanimal_id
. It is not straightforward to distinguish betweenid
,id_
, andid__
oranimal_id
andanimal_id_
. This can become even more confusing/error prone with larger projections. - Everything aside from the first
id
is nullable. This potentially leads to code that requires!!
orcheckNotNull
if the code is certain that for a given row entry, a subset of of the columns are non-null
.
In many ways, I find the pre-version 1 view
models to be safer to use. Any reason why we would not want to bring a similar structure back? In Kotlin of course. 🙂
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:6 (3 by maintainers)
Top Results From Across the Web
Is it possible to create view models by out of ... - Stack Overflow
1 Answer 1 · Data Model: It is a simple class related to specified table from the database and can be used in...
Read more >Inner join drops records in result - Azure Databricks
You perform an inner join, but the resulting joined table is missing data. For example, assume you have two tables, orders and models...
Read more >Inner join drops records in result - Databricks Knowledge Base
You perform an inner join, but the resulting joined table is missing data. For example, assume you have two tables, orders and models....
Read more >NULL SAFE Join - No One Will Tell You This❤️Data Engineer
SQL Interview PRO. NULL SAFE Join - Tricky SQL Interview Question SQL Joins - No One Will Tell You This❤️ Data Engineer...
Read more >Join SQL Server tables where columns include NULL values
Dealing with NULL values especially when joining tables can become a challenge. Let's take a look at this issue and how this can...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Well even if you use fine grain projections it could still generate a model for a subset. As it is right now it’s pretty inconvenient because of name clashes and when you have utility methods for the full model.
Any chance this will ever be re-evaluated? There are many instances throughout my code base that would benefit from using a star projection, even though there are other places where star projections are bad.
I’ve been sort of using mappers, but I interface directly with SqlDelight in all of our modules so it’s difficult. I wanted to make a “store” abstraction so we can only expose what we need to, but there are others on my team who don’t want that. My point being that real world scenarios can sometimes outweigh idealistic practices.