1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
= 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.
|