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
Raise AR::IrreversibleOrderError when #reverse_order can not do it's job #18928
Conversation
|
||
order_query.flat_map do |o| | ||
case o | ||
when Arel::Nodes::Ordering | ||
o.reverse | ||
when String | ||
o.to_s.split(',').map! do |s| | ||
if o =~ /\([^()]*,[^()]*\)/ |
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.
Can we pull this out into a method that states what it's looking for, like contains_functions_or_complex_sql_expressions_or_whatever_i_dont_thing_regexes_are_great_at_expressing_intent?(o)
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.
Maybe a comment is better here?
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.
I'd prefer a method, which is less likely to get out of sync with the code.
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.
done
This is definitely my preferred solution to the problem. I think we might need to have a deprecation cycle though, if there was previously a case where this could generate valid SQL, even if that SQL was incorrect. |
@sgrif current regexp basically checks if there is a function call that has at least one comma inside like:
Lets try to find a case when |
aee0039
to
5a9352f
Compare
@@ -1,3 +1,17 @@ | |||
* `AR::Relation#reverse_order` throwns `AR::UnreversableOrderError` when the order can not be reversed | |||
using current trival algorithm. Also raises the same errow when `#reverse_order` is called on |
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.
Typos in trivial and error here 😉
5a9352f
to
1c1b52a
Compare
Thanks everyone for good comments. |
@@ -1,3 +1,17 @@ | |||
* `AR::Relation#reverse_order` throwns `AR::IrreversableOrderError` when the order can not be reversed |
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.
throws
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.
fixed
1c1b52a
to
1c3d9de
Compare
@@ -1,3 +1,17 @@ | |||
* `AR::Relation#reverse_order` throws `AR::IrreversableOrderError` when the order can not be reversed |
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.
sorry but this is still typo should be Irreversible, not Irreversable :-)
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.
fixed. 👍
1c3d9de
to
9011ddd
Compare
|
||
def test_reverse_order_with_multiargument_function | ||
assert_raises(ActiveRecord::IrreversibleOrderError) do | ||
Topic.order("concat(author_name, title)").reverse_order |
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.
Why is a concat too complex to reverse? I understand the example with the nested DESC, but not this one. Unless I misread, this should still work if you swap the single ASC with DESC or vice versa, without changing anything in the function.
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.
The following in stable rails: Topic.order("concat(author_name, title)").reverse_order.to_sql
will give you order by concat(author_name desc, title) desc
.
The goal of this patch is not to improve a way how rails reverse order but clearly mark cases that rails can not handle.
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.
Better to fix reverse_order
imho
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.
@slbug no matter how hard you try, you will not be able to support all use cases. This patch is not about making reverse_order
better, but about confirming it is not perfect and will never be.
9011ddd
to
115422b
Compare
Is as much as this resembles #16779 (comment), I'm clearly 👍. But I suspect the current might-this-be-bad regexp is too narrow. |
We should check for |
115422b
to
1264d9d
Compare
@sgrif added |
1264d9d
to
9011ddd
Compare
@sgrif any time to come back to this issue? |
It looks like you never pushed up the nulls first/last change. Can you do that and squash/rebase than ping me again? |
Raises when #reverse_order can not process SQL order instead of making invalid SQL before this patch
9011ddd
to
14efb42
Compare
@sgrif done. |
Raise AR::IrreversibleOrderError when #reverse_order can not do it's job
Current
#reverse_order
algorithm is very simple and doesn't try tohandle complicated cases of reversing order given as string.
This patch makes AR to raise exception instead of generating invalid SQL
inside
#reverse_order
.Fixes #8225, #11571
This patch is alternative to #16779 and #18754.