samc
2008-04-22 14:09:33 UTC
I'm pretty sure I've found a bug with Sequel 1.4 when used with MySql
(5.0.51a in my case).
I'm using pagination to get a page of my Location entities:
@locations = Location.order(:name).paginate(page_num, NUM_PER_PAGE)
Having turned on logging of the SQL that Sequel outputs, I see that if
page_num = 1 it runs:
SELECT COUNT(*) FROM location;
SELECT COUNT(*) FROM location LIMIT 10 OFFSET 0;
SELECT * FROM location ORDER BY 'name' LIMIT 10 OFFSET 0
This returns correct results, though I wonder why it needs to perform
the first two queries. The last one alone would suffice to return the
data. That would mean 1 DB round trip rather than 3, which would be a
worthwhile optimisation.
If page_num = 2 it runs:
SELECT COUNT(*) FROM location;
SELECT COUNT(*) FROM location LIMIT 10 OFFSET 10;
And then it returns an empty result set. I don't know why it's
checking the count at all, to be honest, but I can see the problem
with the SQL in any case. In MySQL the LIMIT applies *after* the
count. So it gets the count for the whole location table (12 rows in
my case) to give a 1 row set, then it applies the LIMIT to that set.
So if OFFSET is anything other than 0 we get an empty set. The SQL is
of course wrong even in the page_num = 1 case, it just happens not to
interfere with returning the page of data.
This is a big problem for me right now, so I'm keen to hear your
thoughts.
Thanks
Sam
(5.0.51a in my case).
I'm using pagination to get a page of my Location entities:
@locations = Location.order(:name).paginate(page_num, NUM_PER_PAGE)
Having turned on logging of the SQL that Sequel outputs, I see that if
page_num = 1 it runs:
SELECT COUNT(*) FROM location;
SELECT COUNT(*) FROM location LIMIT 10 OFFSET 0;
SELECT * FROM location ORDER BY 'name' LIMIT 10 OFFSET 0
This returns correct results, though I wonder why it needs to perform
the first two queries. The last one alone would suffice to return the
data. That would mean 1 DB round trip rather than 3, which would be a
worthwhile optimisation.
If page_num = 2 it runs:
SELECT COUNT(*) FROM location;
SELECT COUNT(*) FROM location LIMIT 10 OFFSET 10;
And then it returns an empty result set. I don't know why it's
checking the count at all, to be honest, but I can see the problem
with the SQL in any case. In MySQL the LIMIT applies *after* the
count. So it gets the count for the whole location table (12 rows in
my case) to give a 1 row set, then it applies the LIMIT to that set.
So if OFFSET is anything other than 0 we get an empty set. The SQL is
of course wrong even in the page_num = 1 case, it just happens not to
interfere with returning the page of data.
This is a big problem for me right now, so I'm keen to hear your
thoughts.
Thanks
Sam