Bug: Queued/chunked export can return values from joined table when using joinRelationship() #281
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
missing information
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pxlrbt/filament-excel#281
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bug: Queued/chunked export can return values from joined table when using
joinRelationship()Description
When exporting a Filament table using
pxlrbt/filament-excelwith a joined relationship, columns with the same name in the parent and joined table can contain values from the wrong table after a chunk boundary.For example, both
employee_recordsandemployeeshave a column namednotes.The table display itself is always correct. The problem only occurs during the export.
The issue occurs when the export is processed in multiple chunks. With our test data, a chunk size of
2or10reliably reproduces the problem.A chunk size of
1000does not reproduce the issue with our current dataset because we have fewer than 1000 records, so there is no second chunk. We therefore expect the issue to occur with a chunk size of1000as soon as the dataset contains more than 1000 records.Versions
pxlrbt/filament-excel:2.5.0maatwebsite/excel:3.1.70anourvalar/eloquent-serialize:1.3.11kirschbaum-development/eloquent-power-joins:4.3.3Example
The Eloquent query uses
joinRelationship():The generated SQL contains the expected parent-table selection:
The important part is that only the parent table is selected:
Observed behavior
Suppose:
The exported value is initially correct:
After a chunk boundary, however, the exported value can become:
This happens in CSV/PDF exports as well, so this does not appear to be specific to PhpSpreadsheet/XLSX formatting.
The actual Eloquent model already contains the wrong value at the mapping stage:
contains the value from
employees.notesinstead ofemployee_records.notes.Important finding
The relevant code in
eloquent-power-joinsis located in:Inside
joinRelationship(), the package registers abeforeQuerycallback:In this example this results in:
The export query itself is created in:
Specifically,
ExcelExport::query()returns the query used by the export.The following behavior is reproducible.
Without manually applying the callbacks
In
ExcelExport.php:and then running the export with:
results in the wrong
notesvalue after a chunk boundary.Manually applying the callbacks
Changing
ExcelExport::query()to:makes the export consistently correct.
This is reproducible with the same data and the same chunk size.
Additional observations
Calling:
also fixes the problem.
This is consistent with Laravel's
Query\Builder::toSql()implementation, which calls:before compiling the SQL.
Calling
compileSelect()directly does not reproduce the fix.Reading bindings alone does not reproduce the fix.
Adding a delay (
usleep) does not reproduce the fix.We also tested the
JoinsHelper::clearCacheBeforeQuery()callback separately. Removing that callback did not make the problem disappear. The relevant behavior appears to be the execution of thebeforeQuerycallbacks, in particular the callback which establishes the explicit parent-table selection.Temporary workaround
Currently, this fixes the problem:
However, modifying the package's
ExcelExport::query()method like this is obviously not ideal, and I would prefer a proper fix.Expected behavior
A queued/chunked export should return the same Eloquent model attributes as a normal query, including when:
joinRelationship()is usedIn particular,
employee_records.notesshould never be replaced byemployees.notes.Actual behavior
After processing a chunk boundary, the model can contain the value of the identically named column from the joined table.
Possible cause
My current suspicion is that the query is cloned and/or serialized for the queued/chunked export before the
beforeQuerycallbacks registered byeloquent-power-joinshave been applied.As a result, the intended:
selection is not necessarily established before the query is executed for a subsequent chunk.
Manually calling:
before returning the query makes the issue disappear.
Thanks!