sequel 4.9.0 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +79 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/Rakefile +2 -12
  6. data/bin/sequel +1 -0
  7. data/doc/advanced_associations.rdoc +82 -25
  8. data/doc/association_basics.rdoc +21 -22
  9. data/doc/core_extensions.rdoc +1 -1
  10. data/doc/opening_databases.rdoc +7 -0
  11. data/doc/release_notes/4.10.0.txt +226 -0
  12. data/doc/security.rdoc +1 -0
  13. data/doc/testing.rdoc +7 -7
  14. data/doc/transactions.rdoc +8 -0
  15. data/lib/sequel/adapters/jdbc.rb +160 -168
  16. data/lib/sequel/adapters/jdbc/db2.rb +17 -18
  17. data/lib/sequel/adapters/jdbc/derby.rb +5 -28
  18. data/lib/sequel/adapters/jdbc/h2.rb +11 -22
  19. data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
  20. data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
  21. data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
  22. data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
  23. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
  24. data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
  25. data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
  26. data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
  27. data/lib/sequel/adapters/openbase.rb +1 -7
  28. data/lib/sequel/adapters/postgres.rb +1 -1
  29. data/lib/sequel/adapters/shared/access.rb +3 -6
  30. data/lib/sequel/adapters/shared/cubrid.rb +24 -9
  31. data/lib/sequel/adapters/shared/db2.rb +13 -5
  32. data/lib/sequel/adapters/shared/firebird.rb +16 -16
  33. data/lib/sequel/adapters/shared/informix.rb +2 -5
  34. data/lib/sequel/adapters/shared/mssql.rb +72 -63
  35. data/lib/sequel/adapters/shared/mysql.rb +72 -40
  36. data/lib/sequel/adapters/shared/oracle.rb +27 -15
  37. data/lib/sequel/adapters/shared/postgres.rb +24 -44
  38. data/lib/sequel/adapters/shared/progress.rb +1 -5
  39. data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
  40. data/lib/sequel/adapters/shared/sqlite.rb +21 -6
  41. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
  42. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
  43. data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
  44. data/lib/sequel/core.rb +14 -9
  45. data/lib/sequel/database/dataset_defaults.rb +1 -0
  46. data/lib/sequel/database/misc.rb +12 -0
  47. data/lib/sequel/database/query.rb +4 -1
  48. data/lib/sequel/database/schema_methods.rb +3 -2
  49. data/lib/sequel/database/transactions.rb +47 -17
  50. data/lib/sequel/dataset/features.rb +12 -2
  51. data/lib/sequel/dataset/mutation.rb +2 -0
  52. data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
  53. data/lib/sequel/dataset/prepared_statements.rb +6 -0
  54. data/lib/sequel/dataset/query.rb +1 -1
  55. data/lib/sequel/dataset/sql.rb +132 -70
  56. data/lib/sequel/extensions/columns_introspection.rb +1 -1
  57. data/lib/sequel/extensions/null_dataset.rb +8 -4
  58. data/lib/sequel/extensions/pg_array.rb +4 -4
  59. data/lib/sequel/extensions/pg_row.rb +1 -0
  60. data/lib/sequel/model/associations.rb +468 -188
  61. data/lib/sequel/model/base.rb +88 -13
  62. data/lib/sequel/plugins/association_pks.rb +23 -64
  63. data/lib/sequel/plugins/auto_validations.rb +3 -2
  64. data/lib/sequel/plugins/dataset_associations.rb +1 -3
  65. data/lib/sequel/plugins/many_through_many.rb +18 -65
  66. data/lib/sequel/plugins/pg_array_associations.rb +97 -86
  67. data/lib/sequel/plugins/prepared_statements.rb +2 -1
  68. data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
  69. data/lib/sequel/plugins/rcte_tree.rb +12 -16
  70. data/lib/sequel/plugins/sharding.rb +21 -3
  71. data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
  72. data/lib/sequel/plugins/subclasses.rb +1 -9
  73. data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
  74. data/lib/sequel/plugins/tree.rb +2 -2
  75. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  76. data/lib/sequel/version.rb +1 -1
  77. data/spec/adapters/mssql_spec.rb +57 -15
  78. data/spec/adapters/mysql_spec.rb +11 -0
  79. data/spec/bin_spec.rb +2 -2
  80. data/spec/core/database_spec.rb +38 -4
  81. data/spec/core/dataset_spec.rb +45 -7
  82. data/spec/core/placeholder_literalizer_spec.rb +17 -0
  83. data/spec/core/schema_spec.rb +6 -1
  84. data/spec/extensions/active_model_spec.rb +18 -9
  85. data/spec/extensions/association_pks_spec.rb +20 -18
  86. data/spec/extensions/association_proxies_spec.rb +9 -9
  87. data/spec/extensions/auto_validations_spec.rb +6 -0
  88. data/spec/extensions/columns_introspection_spec.rb +1 -0
  89. data/spec/extensions/constraint_validations_spec.rb +3 -1
  90. data/spec/extensions/many_through_many_spec.rb +191 -111
  91. data/spec/extensions/pg_array_associations_spec.rb +133 -103
  92. data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
  93. data/spec/extensions/rcte_tree_spec.rb +35 -27
  94. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
  95. data/spec/extensions/sharding_spec.rb +2 -2
  96. data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
  97. data/spec/extensions/to_dot_spec.rb +1 -0
  98. data/spec/extensions/touch_spec.rb +2 -2
  99. data/spec/integration/associations_test.rb +130 -37
  100. data/spec/integration/dataset_test.rb +17 -0
  101. data/spec/integration/model_test.rb +17 -0
  102. data/spec/integration/schema_test.rb +14 -0
  103. data/spec/integration/transaction_test.rb +25 -1
  104. data/spec/model/association_reflection_spec.rb +63 -24
  105. data/spec/model/associations_spec.rb +104 -57
  106. data/spec/model/base_spec.rb +14 -1
  107. data/spec/model/class_dataset_methods_spec.rb +1 -0
  108. data/spec/model/eager_loading_spec.rb +221 -74
  109. data/spec/model/model_spec.rb +119 -1
  110. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54a1904977f9d5f4de5e523dbd0ba244e8ef6203
4
- data.tar.gz: 404f40b96e9fc774587485c727186aa6ab2c54b7
3
+ metadata.gz: d32a56c879a430a1257dd8e5f13e7346a4fe52bc
4
+ data.tar.gz: 5dd875255c904b9b4a26e8b62c8beb1e31c20a59
5
5
  SHA512:
6
- metadata.gz: 323f3bb4faea4a371565fecf027aa190a8b4b8232b2da1a0205fcdbccaac20decddbed540a992a4a7c19df78904483b4da3e70be408f3c432c4288357c5b37d3
7
- data.tar.gz: cef071ae2cac67201d942e674905dfb266cf9054bf80f3d1aed43ce9e2e032a71325101406ce689592c757335a8f2471ce14f8102f4e178b37e6dd9777c12b40
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 datatset with static SQL (jeremyevans)
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-2013 Jeremy Evans
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
@@ -34,7 +34,7 @@ If you have any comments or suggestions please post to the Google group.
34
34
 
35
35
  == Installation
36
36
 
37
- sudo gem install sequel
37
+ gem install sequel
38
38
 
39
39
  == A Short Example
40
40
 
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
- sh "#{FileUtils::RUBY} -S 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\""
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
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'optparse'
5
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
5
6
  require 'sequel'
6
7
 
7
8
  code = nil
@@ -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 3 separate strategies for dealing with such cases,
259
- depending on database support.
258
+ approach. Sequel has 4 separate strategies for dealing with such cases.
260
259
 
261
- On PostgreSQL, for *_one associations that don't use an offset, it will by
262
- default use the distinct on strategy, which uses a DISTINCT ON clause:
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.one_to_one :first_album, :class=>:Album, :order=>:release_date
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, it will use a subquery
272
- with a window function:
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
- If the database doesn't support window functions, it will fall back to
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. Sequel can use a variant of the same 3 strategies,
290
- but by default it retrieves all records and then does the array slice
291
- in ruby. As eager_graph does not support options, to use an eager_graph
292
- limit strategy you have to use the eager_graph_with_options method with
293
- the :limit_strategy option.
294
-
295
- The distinct on strategy uses DISTINCT ON in a subquery and JOINs that
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 window function approach JOINs to a nested subquery using a window
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 reason that Sequel does not automatically use the distinct on or
326
- window function strategy for eager_graph is that it can perform much worse than the
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, using a similar approach as
338
- when using eager to eagerly load.
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 distinct on strategy:
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 window function strategy:
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
- Note that if the database does not support window functions, filtering by associations
371
- with limited associations will not work correctly, leading it to return results where
372
- associated object used as an argument is not within the limit of the association.
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
 
@@ -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 specific strategy.
1754
-
1755
- You can specify true for this option to have Sequel choose which strategy
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
+
@@ -170,7 +170,7 @@ Alternative: Sequel.like:
170
170
 
171
171
  Sequel.like(:a, 'b%')
172
172
 
173
- ==== like
173
+ ==== ilike
174
174
 
175
175
  Symbol#ilike returns a case insensitive LIKE expression between the identifier and the given argument:
176
176
 
@@ -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.