[8.x] Inverse morphable type and id filter statements to prevent SQL errors #40523
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There is an SQL bug when using a morph relation when a morphable id column has rows with mixed integer and UUID values.
Setup
Here is my
notifications
table (note that we usevarchar
column because there are tables with primary key as UUID and others with primary key as integer):Now let's say that we have 2 rows in the notifications table, one with a
notifiable_id
asinteger
and the other with anotifiable_id
asstring
.Here is my
User
model:Now, let's reproduce the bug
notifications
relation from aUser
model:Explanation
The statement
notifiable_id = 1
where1
is an integer, will force MySQL to cast the entire columnnotifiable_id
as integer, and then try to find the record1
in dataset. But UUID values can't be casted...One solution is to force quoting the value like
notifiable_id = '1'
but it will create performance issues.The other solution (and the retained here) is to inverse the
notifiable_type
andnotifiable_id
statements.It is probably safe to assume that a table's primary key is either an integer or a string, but not both.
By filtering by
notifiable_type
beforenotifiable_id
, MySQL constrains his dataset to records with only valid integer ids and will not try to cast uuid as integer.Here is the final query executed by MySQL:
Finally