Radically rethink complex prefetch - make most useful cases just work (tm)
authorPeter Rabbitson <ribasushi@cpan.org>
Thu, 28 Feb 2013 08:31:13 +0000 (09:31 +0100)
committerPeter Rabbitson <ribasushi@cpan.org>
Sun, 10 Mar 2013 12:29:18 +0000 (13:29 +0100)
commit1e4f9fb3b8bd1f54518bc2942554099356fa6524
tree2edd8c6431fc7f965bd27c3f17b31b60ddb83407
parent4df1400e9a42e3e19f143151de2c8ba5865cb553
Radically rethink complex prefetch - make most useful cases just work (tm)

TL;DR: mst - I AM SORRY!!! I will rebase the dq branch for you when this
pile of eyebleed goes stable.

The long version - since we now allow arbitrary prefetch, the old
_prefetch_selector_range mechanism doesn't cut it anymore. Instead we
recognize prefetch solely based on _related_results_construction.
Furthermore group_by/limits do not play well with right-side order_by
(which we now also support, by transforming foreign order criteria into
aggregates).

Thus a much more powerful introspection is needed to decide what goes on
the inside and outside of the prefetch subquery. This is mostly done now
by the augmented _resolve_aliastypes_from_select_args to track
identifiers it saw (97e130fa48), and by extra logic considering what
exactly are we grouping by.

Everything is done while observing the "group over selection +
aggregates only" rule, which sould allow us to remain RDBMS agnostic
(even for pathological cases of "MySQL-ish aggregates").

As a bonus more cases of "the user knows what they are doing" are now
correctly recognized and left alone. See a t/prefetch/with_limit.t diff
for a general idea of the scope of improvements.

Yes - there is more regexing crap in the codebase now, and it is
possible we will call _resolve_aliastypes_from_select_args up to 4(!!!)
times per statement preparation. However this allows us to establish a
set of test cases towards which to write optimizations/flog the dq
framework.
Changes
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/ResultSetColumn.pm
lib/DBIx/Class/Storage/DBI.pm
lib/DBIx/Class/Storage/DBIHacks.pm
t/prefetch/grouped.t
t/prefetch/manual.t
t/prefetch/o2m_o2m_order_by_with_limit.t
t/prefetch/with_limit.t
t/sqlmaker/limit_dialects/torture.t