Skip to content
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

Merged
merged 1 commit into from Jan 28, 2016

Conversation

bogdan
Copy link
Contributor

@bogdan bogdan commented Feb 13, 2015

Current #reverse_order algorithm is very simple and doesn't try to
handle 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.


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 =~ /\([^()]*,[^()]*\)/
Copy link
Contributor

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)

Copy link
Contributor Author

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?

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@sgrif
Copy link
Contributor

sgrif commented Feb 13, 2015

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.

@bogdan
Copy link
Contributor Author

bogdan commented Feb 13, 2015

@sgrif current regexp basically checks if there is a function call that has at least one comma inside like:

# match and raises
concat(field1, field2)
length('hello, world')
# not match and generates reverse
length(field1), length(field2)

Lets try to find a case when , inside ( ) can still result in valid SQL.

@@ -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
Copy link
Contributor

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 😉

@bogdan
Copy link
Contributor Author

bogdan commented Feb 13, 2015

  • Renamed exception to IrreversibleOrderError
  • Fixed typos in docs
  • Renamed method

Thanks everyone for good comments.

@@ -1,3 +1,17 @@
* `AR::Relation#reverse_order` throwns `AR::IrreversableOrderError` when the order can not be reversed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throws

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -1,3 +1,17 @@
* `AR::Relation#reverse_order` throws `AR::IrreversableOrderError` when the order can not be reversed
Copy link
Contributor

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 :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed. 👍

@bogdan bogdan changed the title Raise AR::UnreversableOrderError when #reverse_order can not do it's job Raise AR::IrreversibleOrderError when #reverse_order can not do it's job Feb 13, 2015

def test_reverse_order_with_multiargument_function
assert_raises(ActiveRecord::IrreversibleOrderError) do
Topic.order("concat(author_name, title)").reverse_order
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to fix reverse_orderimho

Copy link
Contributor Author

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.

@matthewd
Copy link
Member

Is as much as this resembles #16779 (comment), I'm clearly 👍.

But I suspect the current might-this-be-bad regexp is too narrow.

@sgrif
Copy link
Contributor

sgrif commented Feb 20, 2015

We should check for NULLS FIRST and friends as well.

@bogdan
Copy link
Contributor Author

bogdan commented Feb 23, 2015

@sgrif added /nulls (first|last)\Z/i. Something else?

@bogdan
Copy link
Contributor Author

bogdan commented Jan 26, 2016

@sgrif any time to come back to this issue?

@sgrif
Copy link
Contributor

sgrif commented Jan 26, 2016

It looks like you never pushed up the nulls first/last change. Can you do that and squash/rebase than ping me again?

@sgrif sgrif added this to the 5.0.0 milestone Jan 26, 2016
Raises when #reverse_order can not process SQL order instead of making
invalid SQL before this patch
@bogdan
Copy link
Contributor Author

bogdan commented Jan 27, 2016

@sgrif done.

sgrif added a commit that referenced this pull request Jan 28, 2016
Raise AR::IrreversibleOrderError when #reverse_order can not do it's job
@sgrif sgrif merged commit 74bee83 into rails:master Jan 28, 2016
@bogdan bogdan deleted the unreversable-order branch January 29, 2016 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants