On Thu, 23 Feb 2012 14:49:16 -0600, Andy Doan andy.doan@linaro.org wrote:
I just hit something interesting in Djano and thought I'd share. I was playing with some data from a queryset. I was somewhat aware its not your ordinary python list. However, I was surprised to see this issue:
I had a query that was returning TestResult objects.
From what happens next I guess the query didn't have an ORDER BY?
When I iterated over the list like:
for r in results: print r.measurement
I got the objects I expected. However, at the time I was coding I needed to know the loop index, so I did something like:
for i in xrange(results.count()) print results[i].measurement
This example acts like it works, but upon looking at the data I realized I got incorrect results. It seems like results[0] and results[1] are always the same, but I haven't dug enough to prove that's always the case.
Anyway, I had a feeling using the xrange approach was wrong to begin with, but it turns out to be actually wrong without telling you.
If there's a bug here, it's that Django lets you write this. "results[i]" appears to translate to this sort of query:
select * from ... where ... limit 1 offset $i
So the for loop you wrote is executing this results.count() times.
The thing is, if you execute the query multiple times, there is no guarantee that the ordering as considered by the limit & offset will be the same, so you won't necessarily get the all the objects once in the for loop.
Even if you did ORDER BY the query, it's still horribly inefficient. You probably wanted to write:
for i, ob in enumerate(results): ...
instead :-)
I think it's arguably a bug that Django lets you issue offset/limit queries on unordered result sets. I can't imagine when it would be the right thing to do.
Cheers, mwh