sequel 4.9.0 → 4.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|