-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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
[8.x] Change the order of the bindings for a Sql Server query with a offset and a subquery order by #37728
[8.x] Change the order of the bindings for a Sql Server query with a offset and a subquery order by #37728
Conversation
As SQL Server moves the OrderBy part to be part of the "select" part of the query, we need to move the Order bindings to be in the right place.
Previous attempts at this over the past week have been either causing breaking changes or have been refused. So please make 100% sure that this actually fixes things without breakages on other apps. |
100% is ambitious but I'll do my best. @spawnia, @Javdu10, @madbarron, @arjenvanoostrum @Danil42Russia I noticed you already submitted SQL Server related PR's. |
The currently failing test looks unrelated to this change:
|
Without any more proof, this is my current rationale: The possibilities of breaking anything is more limited then the other PR's this week:
The behavior with this fix is better then the current behavior:
|
Think you hit a false negative. Restarted them and they look fine now. |
@@ -181,6 +181,14 @@ protected function compileAnsiOffset(Builder $query, $components) | |||
|
|||
unset($components['orders']); | |||
|
|||
// As this moves the order statement to be part of the "select" statement, we need to | |||
// move the bindings to the right position: right after "select". | |||
$preferredBindingOrder = ['select', 'order', 'from', 'join', 'where', 'groupBy', 'having', 'union', 'unionOrder']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be defined in a class constant to avoid instantiating this array every time this method is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking a look @spawnia ! Until we have a green light on the PR I prefer to keep it inline to make it easier to reason about.
Your PR mentions "when a limit is used" but this change is in the "offset" method? Also, does this not change the logic for all order by's when an offset is used? Were all order by clauses that also had an offset broken prior to this PR? This seems geared to a particular cause of sub-query order by's that use a limit. In other words, I'm pretty apprehensive this is going to break other more common queries that aren't currently broken. |
My bad. This is indeed related to the "offset" part. I first noticed it when using pagination and attributed it to the limit which is clearly wrong.
It does change the logic for all order by's of the "offsetted" query as all the order query logic is moved to the select.
No, only the order by clauses that had bindings (subqueries).
In understand your hesitance. |
I do think limiting the logic to order bys that are subqueries is safer. |
👍 I've updated this PR to check for subqueries in the |
Hi, One thing I noticed is that the new binding order is not applied when
No issue when fired at a database by the framework, however it is confusing when debugging the bindings. |
Thanks for taking a look @arjenvanoostrum
I've fixed the example to use :namebinding: consistently.
Good point. This could lead to confusion. A reason not to go down that road is that the most common ways of debugging queries (debugbar, telescope, ray) would not be suffering from this confusion. They listen to the QueryExecuted event and My suggestion is:
|
As SQL Server moves the OrderBy part to be part of the "select" part of
the query when using an offset, we need to move the Order bindings to be in the right place.
Example
When using a subquery in the OrderBy
this in the following query
Notice the that
[logins].[name] = ?
(part of the original order part) comes before the[email = ?]
(part of the where clause) part.The normal order of the bindings is:
When getting the bindings, this results in the
order
bindings coming after thewhere
bindings.This results in the following query:
This pull requests changes the order of the bindings by moving
order
to come right afterselect
when a offset is used-- edit: Changed as "limit" to "offset" as that is what determines the current issue.
-- edit 2021-07-21: Fix example to use :namebinding: consistently