Hey Fred,
"what does the old :include do?" - it ignores your :order so it's
arbitrary as far as I'm concerned.
Ironically and by happy coincidence, using mysql and a has_one :order
where you want the most recent record tends to actually give you the
most recent record even though your :order clause is discarded. Yes,
this means that fallback-eager is (probably) favoring the last record
in the set.
"you're still loading all comments" - yeah, new-eager and
fallback-eager both ask the database for rows that will be discarded.
What I'm bringing up in the ticket is that there are currently 3
different results, none of which are consistent with any others.
1 - Non eager is definitively correct.
2 - fallback-eager ignores :order so can't be trusted [*]
3 - new-eager does the opposite of #1 so is *never* correct
[*] sorta, if you are aware of the issues/limitations it might still
work out for you
Both eager styles discard records so the impact is the same - it's
just that new-eager is guaranteed to always be wrong.
So now that I've gotten that bit out of the way, you mentioned "still
loading all comments".
I've spent a bit of time on the resultset trimming issue for has_one
with :order and found:
If all databases supported a postgres-style "distinct on" operation
the solution would be trivial. Of course, mysql doesn't have anything
like this.
The only query-based approach to trimming the results that I've found
to work reliably in mysql is to craft a rather heinous self-join:
select comments.* from comments
left join comments_prune on comments.post_id = comments_prune.post_id and
comments.created_at < comments_prune.created_at
where comments_prune.id is null and
comments.post_id in (1,2,3,4,5)
order by comments.created_at desc
It would be possible to build such a query by parsing the :order
option and adding appropriate 'and' join conditions but it gets
quickly out of hand - imagine :order => 'foo asc, bar desc, wibble
asc'. BLECH.
The most bulletproof solution when :order is present on a has_one is
to just issue 2 queries: first fetch the id and foreign_key ordered
appropriately, build a list of ids that discards
non-first-for-foreign_key ids and then fetch again using your pruned
id list.
But as I said, trimming the resultset isn't relevant to my ticket and
I have to admit I'm not sure how much value would be generated by
coding up trimming logic anyhow.
Regards,
Trevor