views:

249

answers:

1

rails 2.3.4, sqlite3

I'm trying this

Production.find(:all, :conditions => ["time > ?", start_time.utc], :order => "time DESC", :limit => 100)

The condition works perfectly, but I'm having problems with the :order => time DESC.

By chance, I discovered that it worked at Heroku (testing with heroku console), which runs PostgreSQL. However, locally, using sqlite3, new entries will be sorted after old ones, no matter what I set time to. Like this (output has been manually stripped): second entry is new:

Production id: 2053939460, time: "2010-04-24 23:00:04", created_at: "2010-04-24 23:00:05"

Production id: 2053939532, time: "2010-04-25 10:00:00", created_at: "2010-04-27 05:58:30"

Production id: 2053939461, time: "2010-04-25 00:00:04", created_at: "2010-04-25 00:00:04"

Production id: 2053939463, time: "2010-04-25 01:00:04", created_at: "2010-04-25 01:00:04"

Seems like it sorts on the primary key, id, not time. Note that the query works fine on heroku, returning a correctly ordered list! I like sqlite, it's so KISS, I hope you can help me...

Any suggestions?


UPDATE/SOLVED: time is a reserved sqlite3 keyword (date, amongst others, is too). This is why :order => 'time DESC' works in PostgreSQL (non-reserved keyword http://bit.ly/9akitb), but not in sqlite3. The solution is to avoid having sqlite3 keywords as column names if you ever intend to sort on them. Renaming solves the problem.

I've tested with the standard rails pattern *updated_at* and *created_at*, which works perfectly.

I still prefer sqlite3 in development, it's so simple and smooth to work with, copy the database and send to your partner. Thanks to @newtover !

+3  A: 

It is usually a bad idea to use reserved words without surrounding quotes. time is a built-in function in SQLite, try using the following instead and better get rid of the ambiguity in the first place:

Production.find(:all,
                :conditions => ["`time` > ?", start_time.utc],
                :order => "`time` DESC",
                :limit => 100)

UPD: The problem seems to have appeared on SO:

http://stackoverflow.com/questions/742700/rails-active-record-findall-order-issue

newtover
Ah, I'm using a reserved word! Stupid me.. It doesn't seem to work with the neither ` or ' but I've tested you're right, using updated_at instead of time. I guess I'll have to rename the column then?
Ole Morten Amundsen
It's too sad I can't give you a vote, the answer was quick and spot on! You should get extra points, votes, repu or whatever, for answering people who you know cannot upvote you :) So, thank you!
Ole Morten Amundsen
@Ole Morten Amundsen: it seems like your problem is known. Try to order by `strftime('%s', updated) DESC`
newtover
What I read of that SO the answers are summarized like this:**1.** Switching to another database solves the problem (To me, that's not solving) **2.** *date* is poorly handled in sqlite3. (date is also reserved, right? So they probably have the same problem as I, with *time*)It doesn't seem to help with anything, as long as my **column name = reserved keyword** . Could not make it work with *strftime* either. ** But to me, avoiding reserved words is a real solution ** :)
Ole Morten Amundsen
@Ole Morten Amundsen: unfortunatelly the problem is not with sqlite3, but with the connector to the sqlite in ruby. Since I have never coded ruby, I can not play with the example myself. Have you tried ordering by INT or TEXT fields? Can you try to sort by an expression? Try sorting by julianday(updated) which returns a number. Try issuing the statement with sqlite console directly or with syntax described here: http://sqlite-ruby.rubyforge.org/sqlite3/faq.html. The problem might be in the ORM solution yoo use.
newtover
I'm running PostgreSQL at the server and sqlite3 in dev. I wouldn't recommend using the DB-specific commands as in the examples of the link you provided. Note that I can order by anything, ints, texts **and time/dates**, it's only a problem when I've named the *column time*. I see you write *updated*, you mean the column name, which should be *time*, right? I have a column *updated_at* too, which works perfectly fine with the ordering. And yes, the problem may that of the ORM, ActiveRecord or the sqlite3-ruby connector. I'll rename the column, as I know that works. Thanks @newtover !
Ole Morten Amundsen
Should work with double quotes around the keywords; that's the SQL standard way of making a reserved word safe (and SQLite adheres to the standard here). Don't know how you pass that through from Ruby…
Donal Fellows