= New Features

* An eager_graph_eager plugin has been added, which allows you to
  chain eager loads using separate queries to an existing dataset that
  uses eager_graph.  Given the following model associations:

    Band.one_to_many :albums
    Album.one_to_many :tracks

  Let's say you wanted to return bands ordered by album name, and
  eagerly load those albums, you can do that using:

    Band.eager_graph(:albums).order{albums[:name]}

  Let's say you also wanted to eagerly load the tracks for each album.
  You could just add them to the eager_graph call:

    Band.eager_graph(albums: :tracks).order{albums[:name]}

  However, the bloats the result set, and you aren't ordering by the
  track information, so a join is not required.  The eager_graph_eager
  plugin allows you to specify that the tracks be eagerly loaded in a
  separate query after the eager_graph load of albums:

    Band.eager_graph(:albums).
      eager_graph_eager([:albums], :tracks).
      order{albums[:name]}

  eager_graph_eager's first argument is a dependency chain, specified
  as an array of symbols.  This specifies the point at which to
  perform the eager load. The remaining arguments are arguments that
  could be passed to Dataset#eager to specify what dependent
  associations should be loaded at that point.

* A caller_logging Database extension has been added, which logs
  caller information before queries, filtering out the internal
  Sequel callers.  Example:

    DB.extension :caller_logging
    DB[:table].first
    # Logger:
    # (0.000041s) (source: /path/to/app/foo/t.rb:12 in `get_first`)
    # SELECT * FROM table LIMIT 1

  You can further filter the caller lines by setting
  Database#caller_logging_ignore to a regexp of additional caller
  lines to ignore.  This is useful if you have specific methods or
  internal extensions/plugins that you would also like to ignore as
  they obscure the code actually making the request.
 
    DB.caller_logging_ignore = %r{/path/to/app/lib/plugins}
 
  You can also format the caller before it is placed in the logger,
  using caller_logging_formatter:
 
    DB.caller_logging_formatter = lambda do |caller|
      "(#{caller.sub(/\A\/path\/to\/app\//, '')})"
    end
    DB[:table].first
    # Logger:
    # (0.000041s) (foo/t.rb:12 in `get_first`) SELECT * FROM table LIMIT 1
 
* Database#call_procedure has been added to the postgres adapter, and
  is usable on PostgreSQL 11+ for calling procedures created with
  CREATE PROCEDURE.

    DB.call_procedure(:foo, 1, "bar")
    # CALL foo(1, 'bar')

  This method will return a hash of results if the procedure returns
  a result, or nil if it does not return a result.

= Other Improvements

* It is now possible to use Dataset#eager_graph in an eager load
  callback for associations that use join tables.  This allows you
  to eager load some associations using separate queries and other
  associations using joins.  For example:

    Band.eager(:albums=>proc{|ds| ds.eager_graph(:tracks)})

  Will load the bands in one query, and load the albums and tracks
  in a separate query using a join.  Previously, this construction
  worked only for associations that did not use join tables.  It now
  works for associations that use join tables, as long as existing
  selected columns are not removed inside the callback.

* The tactical_eager_loading plugin now handles automatic eager
  loading for associated objects that were created during the
  load of dataset that uses eager_graph.  When using the plugin,
  the following code will now only execute 2 queries, instead of
  issuing a separate query for each album to get the tracks for
  the album.

    artists = Artist.eager_graph(:albums).all
    artists.each do |artist|
      artist.albums.each do |album|
        album.tracks
      end
    end

* Calling Dataset#graph with a dataset with existing selections where
  the column aliases cannot be determined automatically now works
  correctly by using a subselect.  Previously, attempting to do this
  would raise an exception.  This allows the following code to work:

    DB[:table].select_all(:table).select_append(expr).graph(...)

* Datasets now cache the EagerGraphLoader object that is generated to
  convert arrays of hashes into an object graph, so that subsequent
  eager loads on the same dataset do not need to recompute the same
  information.  Most EagerGraphLoader internal state is now frozen to
  prevent unintentional modification.

* Sequel.extension now loads files from gems.  Previously, it used
  Kernel.require, which does not load files from gems.

* Adapters that emulate prepared statements using literalization now
  use a placeholder literalizer and should execute significantly
  faster.  More prepared statement internal metadata is now frozen
  to prevent unintentional modification.

* Dataset#intersect, #except, and #nowait are now supported on MariaDB
  10.3+.

* The constraint_validations extension now respects the
  constraint_validations_table setting when adding metadata for the
  constraint validations.

* In the oracle adapter, the clob prepared statement argument type is
  now mapped to the OCI8::CLOB class, allowing the use of Oracle
  procedures with clob output parameters.

* The Model.load_cache method in the static_cache plugin is now public.

= Backwards Compatibility

* The private Dataset#prepared_arg? method has been removed.  It is no
  longer necessary after the refactoring to the prepared statement
  code.  External adapters that currently call the method should be
  updated to no longer call the method.
