sequel 4.9.0 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +79 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/Rakefile +2 -12
- data/bin/sequel +1 -0
- data/doc/advanced_associations.rdoc +82 -25
- data/doc/association_basics.rdoc +21 -22
- data/doc/core_extensions.rdoc +1 -1
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.10.0.txt +226 -0
- data/doc/security.rdoc +1 -0
- data/doc/testing.rdoc +7 -7
- data/doc/transactions.rdoc +8 -0
- data/lib/sequel/adapters/jdbc.rb +160 -168
- data/lib/sequel/adapters/jdbc/db2.rb +17 -18
- data/lib/sequel/adapters/jdbc/derby.rb +5 -28
- data/lib/sequel/adapters/jdbc/h2.rb +11 -22
- data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
- data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
- data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
- data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
- data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
- data/lib/sequel/adapters/openbase.rb +1 -7
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +3 -6
- data/lib/sequel/adapters/shared/cubrid.rb +24 -9
- data/lib/sequel/adapters/shared/db2.rb +13 -5
- data/lib/sequel/adapters/shared/firebird.rb +16 -16
- data/lib/sequel/adapters/shared/informix.rb +2 -5
- data/lib/sequel/adapters/shared/mssql.rb +72 -63
- data/lib/sequel/adapters/shared/mysql.rb +72 -40
- data/lib/sequel/adapters/shared/oracle.rb +27 -15
- data/lib/sequel/adapters/shared/postgres.rb +24 -44
- data/lib/sequel/adapters/shared/progress.rb +1 -5
- data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
- data/lib/sequel/adapters/shared/sqlite.rb +21 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
- data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
- data/lib/sequel/core.rb +14 -9
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +12 -0
- data/lib/sequel/database/query.rb +4 -1
- data/lib/sequel/database/schema_methods.rb +3 -2
- data/lib/sequel/database/transactions.rb +47 -17
- data/lib/sequel/dataset/features.rb +12 -2
- data/lib/sequel/dataset/mutation.rb +2 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/dataset/sql.rb +132 -70
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/null_dataset.rb +8 -4
- data/lib/sequel/extensions/pg_array.rb +4 -4
- data/lib/sequel/extensions/pg_row.rb +1 -0
- data/lib/sequel/model/associations.rb +468 -188
- data/lib/sequel/model/base.rb +88 -13
- data/lib/sequel/plugins/association_pks.rb +23 -64
- data/lib/sequel/plugins/auto_validations.rb +3 -2
- data/lib/sequel/plugins/dataset_associations.rb +1 -3
- data/lib/sequel/plugins/many_through_many.rb +18 -65
- data/lib/sequel/plugins/pg_array_associations.rb +97 -86
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
- data/lib/sequel/plugins/rcte_tree.rb +12 -16
- data/lib/sequel/plugins/sharding.rb +21 -3
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
- data/lib/sequel/plugins/subclasses.rb +1 -9
- data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
- data/lib/sequel/plugins/tree.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +57 -15
- data/spec/adapters/mysql_spec.rb +11 -0
- data/spec/bin_spec.rb +2 -2
- data/spec/core/database_spec.rb +38 -4
- data/spec/core/dataset_spec.rb +45 -7
- data/spec/core/placeholder_literalizer_spec.rb +17 -0
- data/spec/core/schema_spec.rb +6 -1
- data/spec/extensions/active_model_spec.rb +18 -9
- data/spec/extensions/association_pks_spec.rb +20 -18
- data/spec/extensions/association_proxies_spec.rb +9 -9
- data/spec/extensions/auto_validations_spec.rb +6 -0
- data/spec/extensions/columns_introspection_spec.rb +1 -0
- data/spec/extensions/constraint_validations_spec.rb +3 -1
- data/spec/extensions/many_through_many_spec.rb +191 -111
- data/spec/extensions/pg_array_associations_spec.rb +133 -103
- data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
- data/spec/extensions/rcte_tree_spec.rb +35 -27
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
- data/spec/extensions/sharding_spec.rb +2 -2
- data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
- data/spec/extensions/to_dot_spec.rb +1 -0
- data/spec/extensions/touch_spec.rb +2 -2
- data/spec/integration/associations_test.rb +130 -37
- data/spec/integration/dataset_test.rb +17 -0
- data/spec/integration/model_test.rb +17 -0
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/transaction_test.rb +25 -1
- data/spec/model/association_reflection_spec.rb +63 -24
- data/spec/model/associations_spec.rb +104 -57
- data/spec/model/base_spec.rb +14 -1
- data/spec/model/class_dataset_methods_spec.rb +1 -0
- data/spec/model/eager_loading_spec.rb +221 -74
- data/spec/model/model_spec.rb +119 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d32a56c879a430a1257dd8e5f13e7346a4fe52bc
|
4
|
+
data.tar.gz: 5dd875255c904b9b4a26e8b62c8beb1e31c20a59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1377c4ecd45ba6af86ac084cddcaa444d02055606c4296633edf333f3f67c630d4dbf3283b18eed57a054ef6c017b6aa86424cbe9c0da0de60fe56809a874ca2
|
7
|
+
data.tar.gz: 18257e8bbfae77001b6e94eca09f63615cfcf78169eb98d75fef94bcb8027b90948a44af43389de2e6dd2c0e17ddc70b1b0314df78f487b442bde0fc8b58ede0
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,81 @@
|
|
1
|
+
=== 4.10.0 (2014-05-01)
|
2
|
+
|
3
|
+
* Make Model.include API same as Module.include (ged) (#803)
|
4
|
+
|
5
|
+
* Dataset::PlaceholderLiteralizer now handles DelayedEvaluations correctly (jeremyevans)
|
6
|
+
|
7
|
+
* Refactor type conversion in the jdbc adapter, for up to a 20% speedup (jeremyevans)
|
8
|
+
|
9
|
+
* Add Dataset#with_fetch_size to jdbc adapter, for setting fetch size for JDBC ResultSets (jeremyevans)
|
10
|
+
|
11
|
+
* Default to a fetch_size of 100 in the jdbc/oracle adapter, similar to the oci8-based oracle adapter (jeremyevans)
|
12
|
+
|
13
|
+
* Add Database#fetch_size accessor and :fetch_size option to jdbc adapter, for setting JDBC Statement fetch size (jeremyevans)
|
14
|
+
|
15
|
+
* Automatically determine array type in pg_array_associations plugin, explicitly cast arrays in more places (jeremyevans, maccman) (#800)
|
16
|
+
|
17
|
+
* Speed up Dataset#literal for symbols 60% by caching results, speeding up dataset literalization up to 40% or more (jeremyevans)
|
18
|
+
|
19
|
+
* Speed up Sequel.split_symbol 10-20x by caching results, speeding up dataset literalization up to 80% or more (jeremyevans)
|
20
|
+
|
21
|
+
* Speed up dataset literalization for simple datasets by up to 100% (jeremyevans)
|
22
|
+
|
23
|
+
* Support :fractional_seconds Database option on MySQL 5.6.5+ to support fractional seconds by default (jeremyevans) (#797)
|
24
|
+
|
25
|
+
* Work around MySQL 5.6+ bug when combining DROP FOREIGN KEY and DROP INDEX in same ALTER TABLE statement (jeremyevans)
|
26
|
+
|
27
|
+
* Make auto_validations plugin handle models that select from subqueries (jeremyevans)
|
28
|
+
|
29
|
+
* Recognize additional disconnect errors in the postgres adapter (jeremyevans)
|
30
|
+
|
31
|
+
* Make import/multi_insert insert multiple rows in a single query using a UNION on Oracle, DB2, and Firebird (jeremyevans)
|
32
|
+
|
33
|
+
* Speed up association_pks many_to_many setter method by using Dataset#import (jeremyevans)
|
34
|
+
|
35
|
+
* Add Model.prepared_finder, similar to .finder but using a prepared statement (jeremyevans)
|
36
|
+
|
37
|
+
* Model.def_{add_method,association_dataset_methods,remove_methods} are now deprecated (jeremyevans)
|
38
|
+
|
39
|
+
* Model.eager_loading_dataset and Model.apply_association_dataset_opts are now deprecated (jeremyevans)
|
40
|
+
|
41
|
+
* Make prepared_statement_associations plugin handle one_through_one and one_through_many associations (jeremyevans)
|
42
|
+
|
43
|
+
* Use placeholder literalizer for regular association loading for up to 85% speedup (jeremyevans)
|
44
|
+
|
45
|
+
* Use placeholder literalizer for eager association loading for up to 20% speedup (jeremyevans)
|
46
|
+
|
47
|
+
* Make Model#marshallable! work correctly when using the tactical_eager_loading plugin (jeremyevans)
|
48
|
+
|
49
|
+
* Respect :foreign_key_constraint_name option when adding columns to existing table on MySQL (noah256) (#795)
|
50
|
+
|
51
|
+
* AssociationReflection#association_dataset now handles joining tables if necessary (jeremyevans)
|
52
|
+
|
53
|
+
* Support drop_view :if_exists option on SQLite, MySQL, H2, and HSQLDB (jeremyevans) (#793)
|
54
|
+
|
55
|
+
* Support drop_table :if_exists option on HSQLDB (jeremyevans)
|
56
|
+
|
57
|
+
* Add Database#transaction :auto_savepoint option, for automatically using a savepoint in nested transactions (jeremyevans)
|
58
|
+
|
59
|
+
* Add :server_version Database option on Microsoft SQL Server, instead of querying the database for it (jeremyevans)
|
60
|
+
|
61
|
+
* Support :correlated_subquery as an eager_graph and filter by associations limit strategy for one_to_* associations (jeremyevans)
|
62
|
+
|
63
|
+
* Support named paramters in call_mssql_sproc on Microsoft SQL Server (y.zemlyanukhin, jeremyevans) (#792)
|
64
|
+
|
65
|
+
* Handle placeholder literalizer arguments when emulating offsets (jeremyevans)
|
66
|
+
|
67
|
+
* Don't attempt to emulate offsets if the dataset uses literal SQL (jeremyevans)
|
68
|
+
|
69
|
+
* Use a UNION-based strategy by default to eagerly load limited associations (jeremyevans)
|
70
|
+
|
71
|
+
* Support offsets without limits on MySQL, SQLite, H2, SQLAnywhere and CUBRID (jeremyevans)
|
72
|
+
|
73
|
+
* Remove the install/uninstall rake tasks (jeremyevans)
|
74
|
+
|
75
|
+
* Use INSERT VALUES with multiple rows for Dataset#import and #multi_insert on more databases (jeremyevans)
|
76
|
+
|
77
|
+
* Support common table expressions (WITH clause) on SQLite >=3.8.3 (jeremyevans)
|
78
|
+
|
1
79
|
=== 4.9.0 (2014-04-01)
|
2
80
|
|
3
81
|
* Recognize CHECK constraint violations on newer versions of SQLite (jeremyevans)
|
@@ -3298,7 +3376,7 @@
|
|
3298
3376
|
|
3299
3377
|
* Optimize Model.[] by using static sql when possible, for a 30-40% speed increase (jeremyevans)
|
3300
3378
|
|
3301
|
-
* Add Dataset#with_sql, which returns a clone of the
|
3379
|
+
* Add Dataset#with_sql, which returns a clone of the dataset with static SQL (jeremyevans)
|
3302
3380
|
|
3303
3381
|
* Refactor Dataset#literal so it doesn't need to be overridden in subadapters, for a 20-25% performance increase (jeremyevans)
|
3304
3382
|
|
data/MIT-LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Copyright (c) 2007-2008 Sharon Rosner
|
2
|
-
Copyright (c) 2008-
|
2
|
+
Copyright (c) 2008-2014 Jeremy Evans
|
3
3
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
of this software and associated documentation files (the "Software"), to
|
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -7,7 +7,6 @@ VERS = lambda do
|
|
7
7
|
Sequel.version
|
8
8
|
end
|
9
9
|
CLEAN.include ["**/.*.sw?", "sequel-*.gem", ".config", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc*", '**/*.rbc']
|
10
|
-
SUDO = ENV['SUDO'] || 'sudo'
|
11
10
|
|
12
11
|
# Gem Packaging and Release
|
13
12
|
|
@@ -16,16 +15,6 @@ task :package=>[:clean] do |p|
|
|
16
15
|
sh %{#{FileUtils::RUBY} -S gem build sequel.gemspec}
|
17
16
|
end
|
18
17
|
|
19
|
-
desc "Install sequel gem"
|
20
|
-
task :install=>[:package] do
|
21
|
-
sh %{#{SUDO} #{FileUtils::RUBY} -S gem install ./#{NAME}-#{VERS.call} --local}
|
22
|
-
end
|
23
|
-
|
24
|
-
desc "Uninstall sequel gem"
|
25
|
-
task :uninstall=>[:clean] do
|
26
|
-
sh %{#{SUDO} #{FileUtils::RUBY} -S gem uninstall #{NAME}}
|
27
|
-
end
|
28
|
-
|
29
18
|
desc "Publish sequel gem to rubygems.org"
|
30
19
|
task :release=>[:package] do
|
31
20
|
sh %{#{FileUtils::RUBY} -S gem push ./#{NAME}-#{VERS.call}.gem}
|
@@ -119,7 +108,8 @@ begin
|
|
119
108
|
desc "#{d} with -w, some warnings filtered"
|
120
109
|
task "#{name}_w" do
|
121
110
|
ENV['RUBYOPT'] ? (ENV['RUBYOPT'] += " -w") : (ENV['RUBYOPT'] = '-w')
|
122
|
-
|
111
|
+
rake = ENV['RAKE'] || "#{FileUtils::RUBY} -S rake"
|
112
|
+
sh "#{rake} #{name} 2>&1 | egrep -v \"(spec/.*: warning: (possibly )?useless use of == in void context|: warning: instance variable @.* not initialized|: warning: method redefined; discarding old|: warning: previous definition of)|rspec\""
|
123
113
|
end
|
124
114
|
|
125
115
|
desc d
|
data/bin/sequel
CHANGED
@@ -255,22 +255,36 @@ a LIMIT:
|
|
255
255
|
=== Eager Loading via eager
|
256
256
|
|
257
257
|
However, if you want to eagerly load an association, you must use a different
|
258
|
-
approach. Sequel has
|
259
|
-
depending on database support.
|
258
|
+
approach. Sequel has 4 separate strategies for dealing with such cases.
|
260
259
|
|
261
|
-
|
262
|
-
|
260
|
+
The default strategy used on all databases is a UNION-based approach, which
|
261
|
+
will submit multiple subqueries in a UNION query:
|
263
262
|
|
264
|
-
Artist.
|
263
|
+
Artist.where(:id=>[1,2]).eager(:first_10_albums).all
|
264
|
+
# SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 1) LIMIT 10) UNION ALL
|
265
|
+
# SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 2) LIMIT 10)
|
266
|
+
|
267
|
+
This is the fastest way to load the associated objects on most databases, as long as
|
268
|
+
there is an index on albums.artist_id. Without an index it is probably the slowest
|
269
|
+
approach, so make sure you have an index on the key columns. If you cannot add an
|
270
|
+
index, you'll want to manually specify the :eager_limit_strategy option as shown below.
|
271
|
+
|
272
|
+
On PostgreSQL, for *_one associations that don't use an offset, you can
|
273
|
+
choose to use a the distinct on strategy:
|
274
|
+
|
275
|
+
Artist.one_to_one :first_album, :class=>:Album, :order=>:release_date,
|
276
|
+
:eager_limit_strategy=>:distinct_on
|
265
277
|
Artist.where(:id=>[1,2]).eager(:first_album).all
|
266
278
|
# SELECT DISTINCT ON (albums.artist_id) *
|
267
279
|
# FROM albums
|
268
280
|
# WHERE (albums.artist_id IN (1, 2))
|
269
281
|
# ORDER BY albums.artist_id, release_date
|
270
282
|
|
271
|
-
Otherwise, if the database supports window functions,
|
272
|
-
|
283
|
+
Otherwise, if the database supports window functions, you can choose to use
|
284
|
+
the window function strategy:
|
273
285
|
|
286
|
+
Artist.one_to_many :first_10_albums, :class=>:Album, :order=>:release_date, :limit=>10,
|
287
|
+
:eager_limit_strategy=>:window_function
|
274
288
|
Artist.where(:id=>[1,2]).eager(:first_10_albums).all
|
275
289
|
# SELECT * FROM (
|
276
290
|
# SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY release_date) AS x_sequel_row_number_x
|
@@ -279,20 +293,21 @@ with a window function:
|
|
279
293
|
# ) AS t1
|
280
294
|
# WHERE (x_sequel_row_number_x <= 10)
|
281
295
|
|
282
|
-
|
296
|
+
Alternatively, you can use the :ruby strategy, which will fall back to
|
283
297
|
retrieving all records, and then will slice the resulting array to get
|
284
298
|
the first 10 after retrieval.
|
285
299
|
|
286
300
|
=== Eager Loading via eager_graph_with_options
|
287
301
|
|
288
302
|
When eager loading an association via eager_graph (which uses JOINs), the
|
289
|
-
situation is similar.
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
303
|
+
situation is similar. While the UNION-based strategy cannot be used as
|
304
|
+
you don't know the records being eagerly loaded in advance, Sequel can use
|
305
|
+
a variant of the other 3 strategies. By default it retrieves all records
|
306
|
+
and then does the array slice in ruby. As eager_graph does not support
|
307
|
+
options, to use an eager_graph limit strategy you have to use the
|
308
|
+
eager_graph_with_options method with the :limit_strategy option.
|
309
|
+
|
310
|
+
The :distinct_on strategy uses DISTINCT ON in a subquery and JOINs that
|
296
311
|
subquery:
|
297
312
|
|
298
313
|
Artist.eager_graph_with_options(:first_album, :limit_strategy=>true).all
|
@@ -306,7 +321,7 @@ subquery:
|
|
306
321
|
# ORDER BY albums.artist_id, release_date
|
307
322
|
# ) AS first_album ON (first_album.artist_id = artists.id)
|
308
323
|
|
309
|
-
The
|
324
|
+
The :window_function approach JOINs to a nested subquery using a window
|
310
325
|
function:
|
311
326
|
|
312
327
|
Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>true).all
|
@@ -322,8 +337,30 @@ function:
|
|
322
337
|
# ) AS t1 WHERE (x_sequel_row_number_x <= 10)
|
323
338
|
# ) AS first_10_albums ON (first_10_albums.artist_id = artists.id)
|
324
339
|
|
325
|
-
The
|
326
|
-
|
340
|
+
The :correlated_subquery approach JOINs to a nested subquery using a correlated
|
341
|
+
subquery:
|
342
|
+
|
343
|
+
Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>true).all
|
344
|
+
# SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
|
345
|
+
# first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
|
346
|
+
# first_10_albums.release_date
|
347
|
+
# FROM artists
|
348
|
+
# LEFT OUTER JOIN (
|
349
|
+
# SELECT *
|
350
|
+
# FROM albums
|
351
|
+
# WHERE albums.id IN (
|
352
|
+
# SELECT t1.id
|
353
|
+
# FROM tracks AS t1
|
354
|
+
# WHERE (t1.album_id = tracks.album_id)
|
355
|
+
# ORDER BY release_date
|
356
|
+
# LIMIT 10
|
357
|
+
# )
|
358
|
+
# ) AS first_10_albums ON (first_10_albums.artist_id = artists.id)
|
359
|
+
|
360
|
+
(SELECT * FROM tracks WHERE (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) LIMIT 1)))
|
361
|
+
|
362
|
+
The reason that Sequel does not automatically use the :distinct_on, :window function
|
363
|
+
or :correlated_subquery strategy for eager_graph is that it can perform much worse than the
|
327
364
|
default of just doing the array slicing in ruby. If you are only using eager_graph to
|
328
365
|
return a few records, it may be cheaper to get all of their associated records and filter
|
329
366
|
them in ruby as opposed to computing the set of limited associated records for all rows.
|
@@ -334,10 +371,14 @@ it against the default behavior and found it is faster for your use case.
|
|
334
371
|
=== Filtering By Associations
|
335
372
|
|
336
373
|
In order to return correct results, Sequel automatically uses a limit strategy when
|
337
|
-
using filtering by associations with limited associations,
|
338
|
-
|
374
|
+
using filtering by associations with limited associations, if the database supports
|
375
|
+
it. As in the eager_graph case, the UNION-based strategy doesn't work. Unlike
|
376
|
+
in the eager and eager_graph cases, the array slicing in ruby approach does not work,
|
377
|
+
you must use an SQL-based strategy. Sequel will select an appropriate default
|
378
|
+
strategy based on the database you are using, and you can override it using the
|
379
|
+
:filter_limit_strategy option.
|
339
380
|
|
340
|
-
The
|
381
|
+
The :distinct_on strategy:
|
341
382
|
|
342
383
|
Artist.where(:first_album=>Album[1]).all
|
343
384
|
# SELECT *
|
@@ -351,7 +392,7 @@ The distinct on strategy:
|
|
351
392
|
# ORDER BY albums.artist_id, release_date
|
352
393
|
# )) AND (albums.id = 1))))
|
353
394
|
|
354
|
-
The
|
395
|
+
The :window_function strategy:
|
355
396
|
|
356
397
|
Artist.where(:first_10_albums=>Album[1]).all
|
357
398
|
# SELECT *
|
@@ -367,9 +408,25 @@ The window function strategy:
|
|
367
408
|
# WHERE (x_sequel_row_number_x <= 10)
|
368
409
|
# )) AND (albums.id = 1))))
|
369
410
|
|
370
|
-
|
371
|
-
|
372
|
-
|
411
|
+
The :correlated_subquery strategy:
|
412
|
+
|
413
|
+
Artist.where(:first_10_albums=>Album[1]).all
|
414
|
+
# SELECT *
|
415
|
+
# FROM artists
|
416
|
+
# WHERE (artists.id IN (
|
417
|
+
# SELECT albums.artist_id
|
418
|
+
# FROM albums
|
419
|
+
# WHERE ((albums.artist_id IS NOT NULL) AND (albums.id IN (
|
420
|
+
# SELECT t1.id
|
421
|
+
# FROM albums AS t1
|
422
|
+
# WHERE (t1.artist_id = albums.artist_id)
|
423
|
+
# ORDER BY release_date
|
424
|
+
# LIMIT 1
|
425
|
+
# )) AND (albums.id = 1))))
|
426
|
+
|
427
|
+
Note that filtering by limited associations does not work on MySQL, as does not support
|
428
|
+
any of the strategies. It's also not supported when using composite keys on databases
|
429
|
+
that don't support window functions and don't support multiple columns in IN.
|
373
430
|
|
374
431
|
== Additional Association Types
|
375
432
|
|
data/doc/association_basics.rdoc
CHANGED
@@ -1732,33 +1732,32 @@ can't use LIMIT directly, since you want a limit for each group of
|
|
1732
1732
|
associated records, not a LIMIT on the total number of records returned
|
1733
1733
|
by the dataset.
|
1734
1734
|
|
1735
|
-
By default, if a *_to_many association uses a limit or offset, or a
|
1736
|
-
one_*_one association uses an offset or an order, Sequel will choose to use an
|
1737
|
-
eager limit strategy. The default strategy depends on the database
|
1738
|
-
being used. For databases which support window functions, a window
|
1739
|
-
function will be used. Other databases will just have an ruby array
|
1740
|
-
slice done on the entire record set.
|
1741
|
-
|
1742
|
-
For one_*_one associations without an offset or order, no strategy is used by default
|
1743
|
-
because none is needed for a true one-to-one association (since there
|
1744
|
-
is only one associated record per current record). However, if you are
|
1745
|
-
using a one_to_one association where the relationship is really one_to_many,
|
1746
|
-
and using an order to pick the first matching row, then if you don't
|
1747
|
-
use an limit strategy, you'll be loading all related
|
1748
|
-
rows just to have Sequel ignore all rows after the first. By using a
|
1749
|
-
strategy to change the query to only return one associated record per
|
1750
|
-
current record, you can get much better database performance.
|
1751
|
-
|
1752
1735
|
In general, Sequel picks an appropriate strategy, so it is not usually
|
1753
|
-
necessary to specify a
|
1754
|
-
|
1755
|
-
|
1756
|
-
to use (this is the default). You can specify a symbol to manually choose
|
1757
|
-
a strategy. The available strategies are:
|
1736
|
+
necessary to specify a strategy. You can specify true for this option to
|
1737
|
+
have Sequel choose which strategy to use (this is the default). You can
|
1738
|
+
specify a symbol to manually choose a strategy. The available strategies are:
|
1758
1739
|
|
1740
|
+
:union :: Uses one or more UNION queries with a subquery for each record
|
1741
|
+
you are eagerly loading for (this is the default strategy).
|
1759
1742
|
:distinct_on :: Uses DISTINCT ON to ensure only the first matching record
|
1760
1743
|
is loaded (only used for one_*_one associations without
|
1761
1744
|
offsets on PostgreSQL).
|
1762
1745
|
:window_function :: Uses a ROW_NUMBER window functions to ensure the
|
1763
1746
|
correctly limited/offset records are returned.
|
1764
1747
|
:ruby :: Uses ruby array slicing to emulate database limiting/offsetting.
|
1748
|
+
|
1749
|
+
==== :subqueries_per_union
|
1750
|
+
|
1751
|
+
The number of subqueries per union query to use when eager loading for a
|
1752
|
+
limited association using a union strategy. This defaults to 40, but the
|
1753
|
+
optimum number depends on the database in use and the latency between the
|
1754
|
+
database and the application.
|
1755
|
+
|
1756
|
+
==== :filter_limit_strategy
|
1757
|
+
|
1758
|
+
The strategy to use when filtering by limited associations. In general
|
1759
|
+
Sequel will choose either a :distinct_on, :window_function, or
|
1760
|
+
:correlated_subquery strategy based on the association type and what
|
1761
|
+
the database supports, but you can override that if necessary using
|
1762
|
+
this option.
|
1763
|
+
|
data/doc/core_extensions.rdoc
CHANGED
data/doc/opening_databases.rdoc
CHANGED
@@ -304,6 +304,10 @@ The following additional options are supported:
|
|
304
304
|
:config_default_group :: The default group to read from the in the MySQL config file.
|
305
305
|
:config_local_infile :: If provided, sets the Mysql::OPT_LOCAL_INFILE option on the connection with the given value.
|
306
306
|
:encoding :: Specify the encoding/character set to use for the connection.
|
307
|
+
:fractional_seconds :: On MySQL 5.6.5+, this option is recognized and will include fractional seconds in
|
308
|
+
time/timestamp values, as well as have the schema method create columns that can contain
|
309
|
+
fractional seconds by deafult. This option is also supported on other adapters that connect
|
310
|
+
to MySQL.
|
307
311
|
:socket :: Can be used to specify a Unix socket file to connect to instead of a TCP host and port.
|
308
312
|
:sql_mode :: Set the sql_mode(s) for a given connection. Can be single symbol or string,
|
309
313
|
or an array of symbols or strings (e.g. <tt>:sql_mode=>[:no_zero_date, :pipes_as_concat]</tt>).
|
@@ -444,6 +448,9 @@ options that you may want to set are :login_timeout, :timeout, :tds_version, :az
|
|
444
448
|
|
445
449
|
Other Sequel specific options:
|
446
450
|
|
451
|
+
:server_version :: Override the server version to use (9000000 = SQL Server 2005).
|
452
|
+
This also works on any other adapter that connects to Microsoft
|
453
|
+
SQL Server.
|
447
454
|
:textsize :: Override the default TEXTSIZE setting for this connection. The FreeTDS
|
448
455
|
default is small (around 64000 bytes), but can be set up to around 2GB.
|
449
456
|
This should be specified as an integer. If you plan on setting large
|
@@ -0,0 +1,226 @@
|
|
1
|
+
= Performance Enhancements
|
2
|
+
|
3
|
+
* Dataset literalization for simple datasets is now faster by
|
4
|
+
creating a per-adapter SQL literalization method instead of
|
5
|
+
having all adapters share a generic method with higher overhead.
|
6
|
+
Sequel.split_symbol now caches results globally. Symbol
|
7
|
+
literalization is now cached per Database.
|
8
|
+
|
9
|
+
Combining these three optimizations, here are the performance
|
10
|
+
increases compared to 4.9.0 for a couple example datasets:
|
11
|
+
|
12
|
+
ds1 = DB[:a]
|
13
|
+
ds2 = DB[:a].select(:a, :b).where(:c=>1).order(:d, :e)
|
14
|
+
|
15
|
+
.sql .all (1 row)
|
16
|
+
ds1 140% 11%
|
17
|
+
ds2 187% 32%
|
18
|
+
|
19
|
+
* Regular association loading now uses a placeholder literalizer
|
20
|
+
in most cases, for up to an 85% improvement when loading
|
21
|
+
simple associations.
|
22
|
+
|
23
|
+
* Eager loading associations using Dataset#eager now uses a
|
24
|
+
placeholder literalizer in most cases, for up to a
|
25
|
+
20% improvement when eager loading simple associations.
|
26
|
+
|
27
|
+
* Eager loading associations with limits using Dataset#eager now
|
28
|
+
uses a UNION-based strategy by default. After extensive
|
29
|
+
testing, this was found to be the fastest strategy if the
|
30
|
+
key columns are indexed. Unfortunately, it is a much slower
|
31
|
+
strategy if the key columns are not indexed. You can override
|
32
|
+
the default UNION strategy by using the :eager_limit_strategy
|
33
|
+
association option.
|
34
|
+
|
35
|
+
On some databases, execution time of UNION queries with n subqueries
|
36
|
+
increases faster than O(n). Also, there are limits on the number of
|
37
|
+
subqueries supported in a single UNION query. Sequel chooses a
|
38
|
+
default limit of 40 subqueries per UNION query. You can increase
|
39
|
+
this via the :subqueries_per_union association option.
|
40
|
+
|
41
|
+
* Dataset#import and #multi_insert can now insert multiple rows
|
42
|
+
in a single query on H2, HSQLDB, Derby, SQLAnywhere, CUBRID,
|
43
|
+
SQLite, Oracle, DB2, and Firebird, which should be significantly
|
44
|
+
faster than previous versions that issued a separate INSERT query
|
45
|
+
per row.
|
46
|
+
|
47
|
+
* The many_to_many setter method in the association_pks plugin now
|
48
|
+
uses Dataset#import to insert many rows at once, instead of using
|
49
|
+
a seperate query per insert.
|
50
|
+
|
51
|
+
* The jdbc adapter's type conversion has been rewritten to be
|
52
|
+
more similar to the other adapters, setting up the type
|
53
|
+
conversion procs before iterating over results. This increases
|
54
|
+
performance up to 20%.
|
55
|
+
|
56
|
+
* The jdbc/oracle adapter now defaults to a fetch_size of 100,
|
57
|
+
similar to the oci8-based oracle adapter, significantly improving
|
58
|
+
performance for large datasets.
|
59
|
+
|
60
|
+
= New Features
|
61
|
+
|
62
|
+
* Database#transaction now supports an :auto_savepoint option. This
|
63
|
+
option makes it so that transactions inside the transaction block
|
64
|
+
automatically use savepoints unless they use the :savepoint=>false
|
65
|
+
option. This should make testing transactional behavior easier.
|
66
|
+
|
67
|
+
* Model.prepared_finder has been added. This has an API similar to
|
68
|
+
Model.finder, but it uses a prepared statement instead of a
|
69
|
+
placeholder literalizer. It is less flexible than Model.finder
|
70
|
+
as prepared statements have fixed SQL, but it may perform better.
|
71
|
+
|
72
|
+
* Common table expressions (WITH clauses) are now supported on SQLite
|
73
|
+
3.8.3+.
|
74
|
+
|
75
|
+
* :correlated_subquery has been added as an eager_graph and filter by
|
76
|
+
association limit strategy for one_to_one and one_to_many
|
77
|
+
associations. In certain cases it was found that this is faster
|
78
|
+
than the :window_function limit strategy. It is the default
|
79
|
+
filter by associations limit strategy on databases that do not
|
80
|
+
support window functions.
|
81
|
+
|
82
|
+
Filtering by limited associations using a correlated subquery
|
83
|
+
strategy does not work in all cases, but it should handle most
|
84
|
+
cases correctly.
|
85
|
+
|
86
|
+
* The prepared_statement_associations plugin now handles
|
87
|
+
one_through_one and one_through_many associations.
|
88
|
+
|
89
|
+
* Sequel now emulates support for offsets without limits on MySQL,
|
90
|
+
SQLite, H2, SQLAnywhere, and CUBRID.
|
91
|
+
|
92
|
+
* In the jdbc adapter, the Database#fetch_size accessor and
|
93
|
+
:fetch_size option can be used to automatically set the JDBC
|
94
|
+
fetch size for JDBC Statement objects created by the database.
|
95
|
+
|
96
|
+
* Dataset#with_fetch_size has been added to jdbc adapter datasets,
|
97
|
+
setting the fetch size to use on ResultSets generated by the
|
98
|
+
dataset. This generally has the effect of overriding the
|
99
|
+
Database fetch_size setting.
|
100
|
+
|
101
|
+
* On MySQL 5.6.5+, Sequel supports a :fractional_seconds Database
|
102
|
+
option, which will use fractional seconds for timestamp values,
|
103
|
+
and have the schema modification code create timestamp columns
|
104
|
+
that accept fractional timestamps by default.
|
105
|
+
|
106
|
+
* Database#call_mssql_sproc on Microsoft SQL Server now handles named
|
107
|
+
parameters:
|
108
|
+
|
109
|
+
DB.call_mssql_sproc(:sproc_name, :args => {
|
110
|
+
'input_arg1_name' => 'input arg1 value',
|
111
|
+
'input_arg2_name' => 'input arg2 value',
|
112
|
+
'output_arg_name' => [:output, 'int', 'result key name']
|
113
|
+
})
|
114
|
+
|
115
|
+
* Database#drop_view now supports an :if_exists option on SQLite,
|
116
|
+
MySQL, H2, and HSQLDB.
|
117
|
+
|
118
|
+
* Database#drop_table now supports an :if_exists option on HSQLDB.
|
119
|
+
|
120
|
+
* A :filter_limit_strategy association option has been added, for
|
121
|
+
choosing the strategy that will be used when filtering/excluding by
|
122
|
+
associations with limits. For backwards compatibility, Sequel will
|
123
|
+
fallback to looking at the :eager_limit_strategy option.
|
124
|
+
|
125
|
+
* A :server_version Database option is now supported on Microsoft SQL
|
126
|
+
Server, which will use the value given instead of querying for it.
|
127
|
+
|
128
|
+
= Other Improvements
|
129
|
+
|
130
|
+
* Dataset::PlaceholderLiteralizer arguments are how handled
|
131
|
+
correctly when emulating offsets via the row_number window function
|
132
|
+
on DB2, MSSQL <=2012, and Oracle.
|
133
|
+
|
134
|
+
* Dataset::PlaceholderLiteralizer now handles DelayedEvaluation
|
135
|
+
objects correctly.
|
136
|
+
|
137
|
+
* Offset emulation is skipped if static SQL is used on Access,
|
138
|
+
DB2, and MSSQL <=2008.
|
139
|
+
|
140
|
+
* Additional disconnect errors are now recognized in the postgres
|
141
|
+
adapter.
|
142
|
+
|
143
|
+
* The :foreign_key_constraint_name option is now respected when
|
144
|
+
adding a foreign key column to an existing table on MySQL.
|
145
|
+
|
146
|
+
* Sequel now attempts to work around a bug on MySQL 5.6+ when
|
147
|
+
combining DROP FOREIGN KEY and DROP INDEX in the same ALTER TABLE
|
148
|
+
statement.
|
149
|
+
|
150
|
+
* Dataset#for_update is now respected on H2.
|
151
|
+
|
152
|
+
* Timestamp with local time zone types are now returned as
|
153
|
+
Time/DateTime objects on jdbc/oracle.
|
154
|
+
|
155
|
+
* Model.include now has the same API as Module.include.
|
156
|
+
|
157
|
+
* Model#marshallable! now works correctly when using the
|
158
|
+
tactical_eager_loading plugin.
|
159
|
+
|
160
|
+
* The pg_array_associations plugin now attempts to automatically
|
161
|
+
determine the correct array type to use, and explicitly casts
|
162
|
+
to that array type in more places.
|
163
|
+
|
164
|
+
* The auto_validations plugin now handles models that select from
|
165
|
+
subqueries.
|
166
|
+
|
167
|
+
* The association_pks plugin does no longer creates getter and setter
|
168
|
+
methods for one_through_one associations.
|
169
|
+
|
170
|
+
* bin/sequel now uses the Sequel code in the related lib directory.
|
171
|
+
This makes it easier to use from a repository checkout.
|
172
|
+
|
173
|
+
= Backwards Compatibility
|
174
|
+
|
175
|
+
* AssociationReflection#associated_dataset now returns a joined
|
176
|
+
dataset for associations that require joins (e.g. many_to_many).
|
177
|
+
Anyone using this directly for associations that require joins
|
178
|
+
probably needs to update their code.
|
179
|
+
|
180
|
+
* Model.associate now adds the association instance methods instead
|
181
|
+
of relying on the def_#{association_type} method doing so. Anyone
|
182
|
+
using custom association types probably needs to update their code.
|
183
|
+
|
184
|
+
* Model.eager_loading_dataset, .apply_association_dataset_opts, and
|
185
|
+
.def_{add_method,association_dataset_methods,remove_methods}
|
186
|
+
are now deprecated.
|
187
|
+
|
188
|
+
* Key conditions for associations requiring joins have been moved
|
189
|
+
from the JOIN ON clause to the WHERE clause. This should be
|
190
|
+
optimized the same by the database, but it can break tests that
|
191
|
+
expect specific SQL.
|
192
|
+
|
193
|
+
* Dataset#_insert_sql and #_update_sql are now private instead of
|
194
|
+
protected.
|
195
|
+
|
196
|
+
* The install/uninstall rake tasks have been removed.
|
197
|
+
|
198
|
+
* Model association and association reflection internals have
|
199
|
+
changed significantly, if you were relying on them, you'll
|
200
|
+
probably need to update your code.
|
201
|
+
|
202
|
+
* Database transaction internals have changed significantly, if you
|
203
|
+
were relying on them, you'll probably need to update your code.
|
204
|
+
|
205
|
+
* Dataset literalization internals have changed significantly, with
|
206
|
+
the Dataset#*_clause_methods private methods being removed.
|
207
|
+
Custom adapters that used these methods should switch to using the
|
208
|
+
new Dataset.def_sql_method method.
|
209
|
+
|
210
|
+
* Common table expressions are no longer enabled by default in
|
211
|
+
Sequel. External adapters for databases that support common
|
212
|
+
table expressions should define Dataset#supports_cte?(type) to
|
213
|
+
return true.
|
214
|
+
|
215
|
+
* Support for RETURNING is no longer determined via introspection.
|
216
|
+
External adapters for databases that support RETURNING should
|
217
|
+
define Dataset#supports_returning?(type) to return true.
|
218
|
+
|
219
|
+
* The new jdbc adapter type conversion code may not be completely
|
220
|
+
compatible with the previous code. The currently known case
|
221
|
+
where it is different is on jdbc/postgresql, when using an
|
222
|
+
array type where no conversion proc exists, the returned object
|
223
|
+
will be a ruby array containing java objects, instead of a ruby
|
224
|
+
array containing ruby objects. It is recommended that
|
225
|
+
jdbc/postgresql users using array types use the pg_array extension
|
226
|
+
to avoid this issue.
|