-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: interleaved tables support #618
Comments
Hi all! Is there a plan on how we plan to support this? |
Hey @michi88, thanks for taking a look. I updated the description with more info, the next step is to decide how we want to expose interleaved tables in this package's API and write some test cases. I suggested adding an |
From a conversation with @michi88: Another approach is to add a
We could use this with or without a new We need to decide whether to (a) have one parent ID field (as in the example above) or (b) separate fields for each ancestor. (a) makes for smaller models but requires some introspection for operations like inserts that require ancestors' IDs, (b) is more explicit but may mean doing some extra integrity checks. |
Spanner Limitations added via PR lists some workaround for folks who are blocked on this. Keeping this issue open for tracking reasons. |
Bumping the priority down to p2 since workaround exists. @asthamohta : Please take it forward and feel free to revert in case that's not the right direction. |
(@c24t edit)
Spanner recommends using interleaved tables for parent-child relationships. Interleaving is a special case foreign key relationship that guarantees child and parent rows are co-located in Spanner. Django has no concept of interleaved tables.
Some investigation using the example from the cloud spanner docs:
inspectdb
gives us reasonable models, but not immediately usable:Some cleanup: keep the
unique_together
constraints, loseSongs.singerid
, add FKs fromAlbums
toSingers
andSongs
toAlbums
:Using these models, writing a row to the interleaved child table fails:
The error we get back from Spanner is
INVALID_ARGUMENT
, which gets surfaced as aProgrammingError
in the spanner python client. The offending gRPC call togoogle.spanner.v1.Spanner/ExecuteSql
has args:This makes sense: it shouldn't be possible to change
SingerId
after creating the album since this would break the parent-child relationship. But why are we doing an update in the first place?When we save the model, django tries doing an update first, and then an insert if there was no existing row to update.
If we skip the call to
_do_update
in django, the following insert actually works as expected. The request is the same as above, but with a differentsql
arg:This suggests we might be able to make interleaved tables behave by adding some special handling in
SQLUpdateCompiler
andSQLInsertCompiler
, and adding something like anInterleavedForeignKey
field so we can treat parent-child relationships differently than regular FKs in the compiler.There may be a simpler approach, and there are almost definitely other complications that I haven't considered here, but I think it's good news that we can treat interleaved parents essentially as FKs and still use the basic django model machinery.
@michi88 let me know what you think, if you've got another use case in mind I'd be interested to hear it.
The text was updated successfully, but these errors were encountered: