Use placeholder literalizer when eager loading for up to 20% speedup

This only adds a significant speedup if you are not eager loading
many rows.  If you are eager loading many rows, the time spent
building the query is small compared to loading the associated
rows.

Currently, this caching works because eager_limit_strategy cannot
vary per-call.  If we move to allowing eager_limit_strategy to
change per-call, then we'll need to change the caching.
Generalize the deoptimization flag used in prepared_statements_associations

This deoptimization flag is used to make sure we don't use a
cached prepared statement for an association that depends on
instance specific properiteis in addition to the key values.

This is useful for handling deoptimization in general, so
move the check into the default associations code.
Use consistent style for array modification code

This returns early instead of using a conditional, similar to
the def_many_to_one and def_many_to_many.
Add Model#_load_associated_object_via_primary_key private method

This extracts the code as a separate method, for easier overridding.
in plugins.  It also changes the prepared_statements_associations
plugin to override the more specific methods instead of the
generic method.  This makes the code a little more verbose, but
should be faster and is conceptually better.
Use placeholder literalizer for regular association loading for up to 85% speedup

This uses a placeholder literalizer for regular association loading
if the association does not depend on values other than the keys
and a dynamic callback is not used.

The pg_array_associations plugin does not like this because it
doesn't use simple key values, so add a use_placheolder_loader
method as a deoptimization flag to turn this off.

The sharding plugin doesn't like this because the placeholder
loader doesn't respect the shard, so also offer the ability for
the model objects to deoptimize by having the
_associated_object_loader method return nil.

An explicit SQL::BooleanExpression.new is used here as the key
values should always be equal and it's significantly faster.
Fix AssociationReflection#eager_loading_dataset not cascading eager loading correctly

This enables many_to_one to use the optimized placeholder eager
loader.  This exposed the bug, since the tests for cascading
associations for multiple levels all started with many_to_one
as the first level.
Make prepared_statement_associations plugin handle one_through_one and one_through_many associations
Make the sharding plugin work with new eager loading code

Add Model.eager_load_results as a middleman between the
:eager_loader and AssociationReflection#eager_load_results
code.  Have the sharding plugin override it so the dataset
can be set directly for the shard.
Switch pg_array_associations to new eager loading code

This adds AssociationReflection#eager_loading_predicate_condition,
which many_to_pg_array can override to use an overlaps condition
instead of a typical IN.

This also adds the :loader=>false option that the eager loader
can use to specify that an placeholder literalizer loader should
not be used.