The Artima Developer Community
Sponsored Link

Agile Buzz Forum
A subtle potential bug in most Rails applications

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Dave Thomas

Posts: 85
Nickname: pragdave
Registered: Mar, 2003

Dave Thomas is...
A subtle potential bug in most Rails applications Posted: Mar 21, 2012 8:43 PM
Reply to this message Reply

This post originated from an RSS feed registered with Agile Buzz by Dave Thomas.
Original Post: A subtle potential bug in most Rails applications
Feed Title: PragDave
Feed URL: http://pragdave.blogs.pragprog.com/pragdave/atom.xml
Feed Description: The 'Practices' section of Dave Thomas's blog, including stuff on design, architecture, and the Code Kata exercises.
Latest Agile Buzz Posts
Latest Agile Buzz Posts by Dave Thomas
Latest Posts From PragDave

Advertisement

The ActiveRecord component in Rails offers a convenient and powerful interface between the set-oriented world of relational databases and the object-oriented world of Ruby programs. However, there's a potential bug lurking in many (if not most) Rails applications due to a subtle implication of the fact that sets, and hence database result sets, and not ordered.

Take a simple ActiveRecord call such as Post.first. Ask Rails developers what this does, and most will say that it returns the first row from the posts table. And, most of the time for small to medium size tables, on most database engines, it does. But thats purely a coincidence, because SQL does not define the order of rows in an SQL result set—database engines are free to return rows in an order that is convenient for them unless an explicit order by clause is used. But the SQL generated by ActiveRecord for this query is select `posts`.* from `posts` limit 1.

When talking about select statements, the Mysql reference says: You may have noticed in the preceding examples that the result rows are displayed in no particular order. The Oracle documentation says Without an order_by_clause, no guarantee exists that the same query executed more than once will retrieve rows in the same order. And PostgreSQL says  If ORDER BY is not given, the rows are returned in whatever order the system finds fastest to produce.

So that innocent select statement is just returning a row at the whim of the database engine. It could be the first. It could be the 42nd. It could be any row. The same applies to queries using limit and offset, often used to paginate results. Call Post.limit(10).offset(10) and ActiveRecord executes select `posts`.* from `posts` limit 10 offset 10. Again, there's no ordering applied, and no guarantee that the same rows will be returned given the same query.

Does this actually affect us? Not often. In fact, probably you're never seen it happen. I have seen the results of a query change when using Oracle. As a table filled, Oracle decided to reorganize an index. As a result, paginating through a set of orders suddenly stopped displaying orders in date order. Adding an explicit order by fixed it.

The moral? Well, first, this isn't a big deal. But, whenever you use finders that assume an ordering in a result set, make sure you make the order explicit—add an order() call to the ARel chain. If you want first() to be compatible with last(), add order("id") to the call to first() (because, somewhat inconsistently, last() currently does add an order by id clause). If you want your paginated result sets to be consistent, make sure you order them (perhaps by id, or by created_at).

 

Read: A subtle potential bug in most Rails applications

Topic: EMC Acquires Pivotal Tracker Company Previous Topic   Next Topic Topic: Atlassian Releases GreenHopper 5.9.1

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use