Comments (10)
@0xTim I don't think this is in scope for Fluent 4 at all at this point, and I question whether it's worthwhile to consider it for the future - even in Postgres, INHERITS
doesn't make everything "just work"; last time I did polymorphic entities with Fluent, it ended up meaning a lot of extremely ugly CHECK
constraints and nasty cheats like generated columns with no values. @calebkleveter was there, he can tell you! 😅
That being said, if someone in the community wants to delve into it and come up with something workable, I'm not so against it as to reject it out of hand 🙂.
from fluent-kit.
Instead of a polymorphic foreign key, model inheritance backed by classic IsA
hierarchy in the E-R world might be an easier solution.
Hibernate has something similar: https://www.baeldung.com/hibernate-inheritance
For the original Post
Comment
Likable
example, we would want the Delta Table
pattern or @Inheritance(strategy = InheritanceType.JOINED)
from Hibernate.
from fluent-kit.
Motivation:
Imagine a social app with posts, comments, images, etc. The user can "like" a post, a comment or an image. They can also "comment" on a post, another comment, etc.
Polymorphism has always been the best solution for this need. You would have a Like
class and LikeableEntity
base class that Post
, Comment
, etc. would inherit from. This allows you to be able to list all of a user's likes across multiple classes.
Solutions without polymorphism are always lacking in one way or another. For example, you can have the Like table have different fields for postId
, commentId
, etc. This would let you list all likes across different "classes" but that's a waste of storage and you need to add more fields as you add more like-able objects. Alternatively a Like
model can have a generic objectId
and a type
field which would be 'post', 'comment', 'image', etc. but the disadvantage here is that objectId
would not be a foreign key or indexable. Another alternative is to have separate tables for PostLike
, CommentLike
etc. and while you can have foreign keys, you would not be able to list all likes across different classes.
Postgres support polymorphism with the INHERITS
keyword:
https://www.postgresql.org/docs/10/tutorial-inheritance.html
Other ORM's support this: https://laravel.com/docs/5.7/eloquent-relationships#polymorphic-relationships. It would be great for Fluent to support this too!!!
from fluent-kit.
@sherwinzadeh do you know if other SQL DBs (MySQL, SQLite, Oracle, MariaDB, Cockroach, etc) support INHERITS
or something similar?
If the majority of DBs Fluent works with support such a feature, then it makes sense to consider utilizing it as a solution for polymorphism. Otherwise, if this is Postgres only, then we will probably need to go for one of the other approaches. In that situation, we could still add support for INHERITS
to PostgresKit
though.
from fluent-kit.
@tanner0101 Polymorphism is still useful without specific DB support for INHERITS
type clauses; Laravel embraces polymorphism for all its supported database drivers, for example.
from fluent-kit.
I really hope this feature comes to Fluent! I've been asking for a variation of this, Single Table Inheritance
, for some time. I assume that most ORMs, like those based on JPA, don't rely on any feature of the RDBMS itself for inheritance and instead use a discriminator column to differentiate types. That said, the language side looks complicated: Property wrappers don't work with protocols and Swift lacks abstract classes, so how would you create a super type?
from fluent-kit.
No progress on this I'm afraid. @gwynne I'm assuming this isn't really on our radar and something we should tag with help-wanted
to see if we can get a community PR?
from fluent-kit.
Just read this and I haven't read how others are doing it, but here's my first idea:
inheritance is a bit like owning a unique reference to the parent. So you want a 1:1 relationship, but with the additional requirement that the parent references exactly one child table of multiple possible child tables.
I think a lot of this could be achieved completely with checks on the Swift side.
- Have the parent reference each possible child table with
@ChildTable
. - Whenever create is called with a
Parent
, make sure using reflection that exactly one child table is actually referenced. The referenced child must have all its nonnullable fields initialized. - Whenever update is called with a
Parent
, make sure using reflection that exactly one child table is actually loaded. "Loaded" is an important keyword here, the child must actually come from the data base rather than having been attached arbitrarily. That means that the@ChildTable
needs some way to store this information. - Have the above checks done at runtime by a database middleware
ParentCheckMiddleware<Parent>
that is automatically added to the db when you declare in a migration that you do inheritance.
Whether you actually store the @ChildTable
s in the parent table is an implementation detail as long as you do things only on the swift side. If we want to support this feature even when non-swift applications can write into the db, one would have to store this information and enforce the behavior in the db somehow.
from fluent-kit.
2 minute google validates this idea to an extent:
https://stackoverflow.com/questions/1730665/how-to-emulate-tagged-union-in-a-database
from fluent-kit.
Update: I had only cross read the answers in this stackoverflow question because I didn't have much time, but one of the answers actually makes this whole thing quite simple:
- the parent's primary key should be an id plus the type (integer or enum)
- the child references this primary key, uses the parent's id as its own primary key and checks that the referenced parent's type is correct
from fluent-kit.
Related Issues (20)
- Page<T> where T: Encodable does not seem to be allowed to be extendable HOT 1
- Document how to use the FluentBenchmarker tests
- Insert queries error when models have relations defined HOT 9
- Date filters fail when TimeStamp.format has un underlying value that isn't Date
- Fluent Postgres driver crashes getting sum and average aggregates
- 1.42.2 no longer supports multiple properties with the same field name HOT 1
- MySQL delete multiple-field index fails HOT 1
- Filtering with ~~ on enum collection does not work HOT 6
- Async functions within attach closure
- Aliases in select queries can cause fatal errors HOT 7
- Using Querybuilder with .field() or .fields() on models with optional relations crashes in SiblingsEagerLoader() HOT 1
- owner likely unsaved, attach within attach closure HOT 2
- [PostgreSQL] Storing Arrays of Custom Codable Types as JSONB[] instead of JSONB?
- Fluent Models malfunction if given a property named `description`
- @Group does not compile if SwiftUI is imported
- ServiceContext lost when eager loading parent models
- Fatal error "Non-uniform query input" when creating models from a collection. HOT 2
- Improve FieldKey ergonomics HOT 4
- Separate Field property wrappers into separate package HOT 4
- Print binding data in exception description
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fluent-kit.