sequel 4.48.0 → 4.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +56 -0
  3. data/doc/advanced_associations.rdoc +1 -1
  4. data/doc/opening_databases.rdoc +3 -2
  5. data/doc/release_notes/4.49.0.txt +222 -0
  6. data/lib/sequel/adapters/ibmdb.rb +6 -1
  7. data/lib/sequel/adapters/jdbc.rb +3 -1
  8. data/lib/sequel/adapters/jdbc/h2.rb +10 -1
  9. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
  10. data/lib/sequel/adapters/jdbc/sqlserver.rb +9 -2
  11. data/lib/sequel/adapters/mock.rb +3 -0
  12. data/lib/sequel/adapters/mysql2.rb +1 -1
  13. data/lib/sequel/adapters/postgres.rb +2 -1
  14. data/lib/sequel/adapters/shared/mysql.rb +4 -1
  15. data/lib/sequel/adapters/shared/oracle.rb +26 -3
  16. data/lib/sequel/connection_pool.rb +9 -2
  17. data/lib/sequel/connection_pool/sharded_single.rb +1 -1
  18. data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
  19. data/lib/sequel/connection_pool/single.rb +2 -2
  20. data/lib/sequel/connection_pool/threaded.rb +2 -2
  21. data/lib/sequel/database/connecting.rb +3 -3
  22. data/lib/sequel/database/dataset_defaults.rb +14 -1
  23. data/lib/sequel/dataset.rb +1 -1
  24. data/lib/sequel/dataset/actions.rb +54 -0
  25. data/lib/sequel/dataset/dataset_module.rb +58 -0
  26. data/lib/sequel/dataset/query.rb +3 -3
  27. data/lib/sequel/exceptions.rb +8 -0
  28. data/lib/sequel/extensions/_model_pg_row.rb +5 -2
  29. data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
  30. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  31. data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -2
  32. data/lib/sequel/extensions/migration.rb +5 -2
  33. data/lib/sequel/extensions/null_dataset.rb +1 -0
  34. data/lib/sequel/model/associations.rb +3 -0
  35. data/lib/sequel/model/base.rb +10 -55
  36. data/lib/sequel/model/dataset_module.rb +5 -43
  37. data/lib/sequel/model/errors.rb +2 -1
  38. data/lib/sequel/model/inflections.rb +17 -5
  39. data/lib/sequel/plugins/active_model.rb +2 -2
  40. data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
  41. data/lib/sequel/plugins/composition.rb +2 -2
  42. data/lib/sequel/plugins/dataset_associations.rb +25 -13
  43. data/lib/sequel/plugins/json_serializer.rb +2 -2
  44. data/lib/sequel/plugins/pg_row.rb +4 -2
  45. data/lib/sequel/plugins/serialization.rb +1 -0
  46. data/lib/sequel/plugins/single_table_inheritance.rb +6 -1
  47. data/lib/sequel/plugins/touch.rb +2 -1
  48. data/lib/sequel/plugins/validation_helpers.rb +10 -2
  49. data/lib/sequel/sql.rb +16 -7
  50. data/lib/sequel/version.rb +1 -1
  51. data/spec/adapters/mssql_spec.rb +4 -4
  52. data/spec/adapters/mysql_spec.rb +5 -1
  53. data/spec/adapters/oracle_spec.rb +4 -0
  54. data/spec/bin_spec.rb +7 -1
  55. data/spec/core/connection_pool_spec.rb +28 -14
  56. data/spec/core/database_spec.rb +149 -0
  57. data/spec/core/dataset_spec.rb +173 -0
  58. data/spec/extensions/class_table_inheritance_spec.rb +58 -17
  59. data/spec/extensions/composition_spec.rb +13 -0
  60. data/spec/extensions/dataset_associations_spec.rb +12 -0
  61. data/spec/extensions/many_through_many_spec.rb +4 -4
  62. data/spec/extensions/null_dataset_spec.rb +1 -1
  63. data/spec/extensions/serialization_spec.rb +1 -1
  64. data/spec/extensions/single_table_inheritance_spec.rb +16 -0
  65. data/spec/extensions/validation_helpers_spec.rb +1 -2
  66. data/spec/integration/associations_test.rb +8 -0
  67. data/spec/integration/plugin_test.rb +8 -3
  68. data/spec/model/association_reflection_spec.rb +1 -1
  69. data/spec/model/associations_spec.rb +29 -9
  70. data/spec/model/class_dataset_methods_spec.rb +6 -0
  71. data/spec/model/eager_loading_spec.rb +8 -8
  72. data/spec/model/plugins_spec.rb +34 -0
  73. data/spec/model/record_spec.rb +1 -1
  74. data/spec/spec_config.rb +2 -0
  75. metadata +5 -2
@@ -67,6 +67,7 @@ module Sequel
67
67
  ACCESS_DURATION_UNITS = DURATION_UNITS.zip(%w'yyyy m d h n s'.map(&:freeze)).freeze
68
68
  DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
69
69
  FDBSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.chop).freeze}).freeze
70
+ Sequel::Deprecation.deprecate_constant(self, :FDBSQL_DURATION_UNITS)
70
71
 
71
72
  # Append the SQL fragment for the DateAdd expression to the SQL query.
72
73
  def date_add_sql_append(sql, da)
@@ -43,6 +43,8 @@ module Sequel
43
43
  clone(:on_duplicate_columns=>handler||block)
44
44
  end
45
45
 
46
+ private
47
+
46
48
  # Override the attr_writer to check for duplicate columns, and call
47
49
  # handle_duplicate_columns if necessary.
48
50
  def columns=(cols)
@@ -52,8 +54,6 @@ module Sequel
52
54
  super
53
55
  end
54
56
 
55
- private
56
-
57
57
  # Invoke the appropriate behavior when duplicate columns are present.
58
58
  def handle_duplicate_columns(cols)
59
59
  message = "#{caller(*CALLER_ARGS).first}: One or more duplicate columns present in #{cols.inspect}"
@@ -352,8 +352,11 @@ module Sequel
352
352
  # Part of the +migration+ extension.
353
353
  class Migrator
354
354
  MIGRATION_FILE_PATTERN = /\A(\d+)_.+\.rb\z/i.freeze
355
+
355
356
  MIGRATION_SPLITTER = '_'.freeze
357
+ Sequel::Deprecation.deprecate_constant(self, :MIGRATION_SPLITTER)
356
358
  MINIMUM_TIMESTAMP = 20000101
359
+ Sequel::Deprecation.deprecate_constant(self, :MINIMUM_TIMESTAMP)
357
360
 
358
361
  # Exception class raised when there is an error with the migrator's
359
362
  # file structure, database, or arguments.
@@ -408,7 +411,7 @@ module Sequel
408
411
  if self.equal?(Migrator)
409
412
  Dir.new(directory).each do |file|
410
413
  next unless MIGRATION_FILE_PATTERN.match(file)
411
- return TimestampMigrator if file.split(MIGRATION_SPLITTER, 2).first.to_i > MINIMUM_TIMESTAMP
414
+ return TimestampMigrator if file.split('_', 2).first.to_i > 20000101
412
415
  end
413
416
  IntegerMigrator
414
417
  else
@@ -497,7 +500,7 @@ module Sequel
497
500
 
498
501
  # Return the integer migration version based on the filename.
499
502
  def migration_version_from_file(filename)
500
- filename.split(MIGRATION_SPLITTER, 2).first.to_i
503
+ filename.split('_', 2).first.to_i
501
504
  end
502
505
  end
503
506
 
@@ -46,6 +46,7 @@ module Sequel
46
46
 
47
47
  # Nullify the current dataset
48
48
  def nullify!
49
+ Sequel::Deprecation.deprecate("Dataset#nullify! from the null_dataset extension", "Use Dataset#nullify, which returned a modified copy")
49
50
  extend NullDataset
50
51
  end
51
52
  end
@@ -327,6 +327,7 @@ module Sequel
327
327
 
328
328
  # Alias of predicate_key, only for backwards compatibility.
329
329
  def eager_loading_predicate_key
330
+ Sequel::Deprecation.deprecate("AssociationReflection#eager_loading_predicate_key", "Use #predicate_key instead")
330
331
  predicate_key
331
332
  end
332
333
 
@@ -1803,6 +1804,7 @@ module Sequel
1803
1804
 
1804
1805
  opts[:eager_block] = opts[:block] unless opts.include?(:eager_block)
1805
1806
  if !opts.has_key?(:predicate_key) && opts.has_key?(:eager_loading_predicate_key)
1807
+ Sequel::Deprecation.deprecate("The :eager_loading_predicate_key association option", "Use the :predicate_key option instead")
1806
1808
  opts[:predicate_key] = opts[:eager_loading_predicate_key]
1807
1809
  end
1808
1810
  opts[:graph_join_type] ||= :left_outer
@@ -2555,6 +2557,7 @@ module Sequel
2555
2557
  end
2556
2558
 
2557
2559
  if res == false and stop_on_false
2560
+ Sequel::Deprecation.deprecate("Having #{callback_type} association callback return false to cancel modification", "Instead, call Model#cancel_action inside the association callback")
2558
2561
  raise(HookFailed, "Unable to modify association for #{inspect}: one of the #{callback_type} hooks returned false")
2559
2562
  end
2560
2563
  end
@@ -26,9 +26,8 @@ module Sequel
26
26
  # (default: not set, so all columns not otherwise restricted are allowed).
27
27
  attr_reader :allowed_columns # SEQUEL5: Deprecate after release
28
28
 
29
- # Whether to cache the anonymous models created by Sequel::Model(). This is
30
- # required for reloading them correctly (avoiding the superclass mismatch). True
31
- # by default for backwards compatibility.
29
+ # Whether to cache the anonymous models created by Sequel::Model(), true by default. This is
30
+ # required for reloading them correctly (avoiding the superclass mismatch).
32
31
  attr_accessor :cache_anonymous_models
33
32
 
34
33
  # Array of modules that extend this model's dataset. Stored
@@ -716,7 +715,7 @@ module Sequel
716
715
  pluralize(underscore(demodulize(name))).to_sym
717
716
  end
718
717
 
719
- # Calls #call with the values hash. Only for backwards compatibility.
718
+ # Calls #call with the values hash.
720
719
  def load(values)
721
720
  call(values)
722
721
  end
@@ -992,7 +991,7 @@ module Sequel
992
991
  end
993
992
 
994
993
  # Add model methods that call dataset methods
995
- Plugins.def_dataset_methods(self, (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server, :where_all, :where_each, :where_single_value]) - [:<<, :and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases])
994
+ Plugins.def_dataset_methods(self, (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server]) - [:<<, :and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases])
996
995
  # SEQUEL5: add :set_graph_aliases to remove list and remove :and
997
996
 
998
997
  private
@@ -1249,6 +1248,7 @@ module Sequel
1249
1248
  rescue LoadError => e
1250
1249
  begin
1251
1250
  require "sequel_#{plugin}"
1251
+ Sequel::Deprecation.deprecate("requiring 'sequel_#{plugin}' to load a plugin", "Update the #{plugin} plugin to be required via 'sequel/plugins/#{plugin}'")
1252
1252
  rescue LoadError => e2
1253
1253
  e.message << "; #{e2.message}"
1254
1254
  raise e
@@ -2684,52 +2684,6 @@ module Sequel
2684
2684
  as_hash(*a)
2685
2685
  end
2686
2686
 
2687
- # Return an array of all rows matching the given filter condition, also
2688
- # yielding each row to the given block. Basically the same as where(cond).all(&block),
2689
- # except it can be optimized to not create an intermediate dataset.
2690
- #
2691
- # Artist.where_all(:id=>[1,2,3])
2692
- # # SELECT * FROM artists WHERE (id IN (1, 2, 3))
2693
- def where_all(cond, &block)
2694
- if loader = _model_where_loader
2695
- loader.all(filter_expr(cond), &block)
2696
- else
2697
- where(cond).all(&block)
2698
- end
2699
- end
2700
-
2701
- # Iterate over all rows matching the given filter condition,
2702
- # yielding each row to the given block. Basically the same as where(cond).each(&block),
2703
- # except it can be optimized to not create an intermediate dataset.
2704
- #
2705
- # Artist.where_each(:id=>[1,2,3]){|row| p row}
2706
- # # SELECT * FROM artists WHERE (id IN (1, 2, 3))
2707
- def where_each(cond, &block)
2708
- if loader = _model_where_loader
2709
- loader.each(filter_expr(cond), &block)
2710
- else
2711
- where(cond).each(&block)
2712
- end
2713
- end
2714
-
2715
- # Filter the datasets using the given filter condition, then return a single value.
2716
- # This assumes that the dataset has already been setup to limit the selection to
2717
- # a single column. Basically the same as where(cond).single_value,
2718
- # except it can be optimized to not create an intermediate dataset.
2719
- #
2720
- # Artist.select(:name).where_single_value(:id=>1)
2721
- # # SELECT name FROM artists WHERE (id = 1) LIMIT 1
2722
- def where_single_value(cond)
2723
- if loader = cached_placeholder_literalizer(:_model_where_single_value_loader) do |pl|
2724
- single_value_ds.where(pl.arg)
2725
- end
2726
-
2727
- loader.get(filter_expr(cond))
2728
- else
2729
- where(cond).single_value
2730
- end
2731
- end
2732
-
2733
2687
  # Given a primary key value, return the first record in the dataset with that primary key
2734
2688
  # value. If no records matches, returns nil.
2735
2689
  #
@@ -2756,11 +2710,12 @@ module Sequel
2756
2710
 
2757
2711
  private
2758
2712
 
2759
- # Loader used for where_all and where_each.
2713
+ # SEQUEL5: Remove
2760
2714
  def _model_where_loader
2761
- cached_placeholder_literalizer(:_model_where_loader) do |pl|
2762
- where(pl.arg)
2763
- end
2715
+ # :nocov:
2716
+ Sequel::Deprecation.deprecate("Dataset#_model_where_loader", "Use _where_loader instead")
2717
+ _where_loader
2718
+ # :nocov:
2764
2719
  end
2765
2720
 
2766
2721
  # If the dataset is not already ordered, and the model has a primary key,
@@ -3,12 +3,11 @@
3
3
  module Sequel
4
4
  class Model
5
5
  # This Module subclass is used by Model.dataset_module
6
- # to add dataset methods to classes. It adds a couple
7
- # of features standard Modules, allowing you to use
8
- # the same subset method you can call on Model, as well
9
- # as making sure that public methods added to the module
10
- # automatically have class methods created for them.
11
- class DatasetModule < ::Module
6
+ # to add dataset methods to classes. In addition to the
7
+ # methods offered by Dataset::DatasetModule, it also
8
+ # automatically creates class methods for public dataset
9
+ # methods.
10
+ class DatasetModule < Dataset::DatasetModule
12
11
  # Store the model related to this dataset module.
13
12
  def initialize(model)
14
13
  @model = model
@@ -19,43 +18,6 @@ module Sequel
19
18
  where(name, *args, &block)
20
19
  end
21
20
 
22
- %w'where exclude exclude_having having'.map(&:to_sym).each do |meth|
23
- define_method(meth) do |name, *args, &block|
24
- if block || args.flatten.any?{|arg| arg.is_a?(Proc)}
25
- define_method(name){send(meth, *args, &block)}
26
- else
27
- key = :"_#{meth}_#{name}_ds"
28
- define_method(name) do
29
- cached_dataset(key){send(meth, *args)}
30
- end
31
- end
32
- end
33
- end
34
-
35
- meths = (<<-METHS).split.map(&:to_sym)
36
- distinct grep group group_and_count group_append
37
- limit offset order order_append order_prepend
38
- select select_all select_append select_group server
39
- METHS
40
-
41
- # Define a method in the module
42
- def self.def_dataset_caching_method(mod, meth)
43
- mod.send(:define_method, meth) do |name, *args, &block|
44
- if block
45
- define_method(name){send(meth, *args, &block)}
46
- else
47
- key = :"_#{meth}_#{name}_ds"
48
- define_method(name) do
49
- cached_dataset(key){send(meth, *args)}
50
- end
51
- end
52
- end
53
- end
54
-
55
- meths.each do |meth|
56
- def_dataset_caching_method(self, meth)
57
- end
58
-
59
21
  private
60
22
 
61
23
  # Add a class method to the related model that
@@ -6,6 +6,7 @@ module Sequel
6
6
  # with a few convenience methods.
7
7
  class Errors < ::Hash
8
8
  ATTRIBUTE_JOINER = ' and '.freeze
9
+ Sequel::Deprecation.deprecate_constant(self, :ATTRIBUTE_JOINER)
9
10
 
10
11
  # Adds an error for the given attribute.
11
12
  #
@@ -40,7 +41,7 @@ module Sequel
40
41
  def full_messages
41
42
  inject([]) do |m, kv|
42
43
  att, errors = *kv
43
- errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(ATTRIBUTE_JOINER)} #{e}")}
44
+ errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(' and ')} #{e}")}
44
45
  m
45
46
  end
46
47
  end
@@ -26,17 +26,29 @@ module Sequel
26
26
  # already have been loaded.
27
27
  module Inflections
28
28
  CAMELIZE_CONVERT_REGEXP = /(^|_)(.)/.freeze
29
+ Sequel::Deprecation.deprecate_constant(self, :CAMELIZE_CONVERT_REGEXP)
29
30
  CAMELIZE_MODULE_REGEXP = /\/(.?)/.freeze
31
+ Sequel::Deprecation.deprecate_constant(self, :CAMELIZE_MODULE_REGEXP)
30
32
  DASH = '-'.freeze
33
+ Sequel::Deprecation.deprecate_constant(self, :DASH)
31
34
  DEMODULIZE_CONVERT_REGEXP = /^.*::/.freeze
35
+ Sequel::Deprecation.deprecate_constant(self, :DEMODULIZE_CONVERT_REGEXP)
32
36
  EMPTY_STRING= ''.freeze
37
+ Sequel::Deprecation.deprecate_constant(self, :EMPTY_STRING)
33
38
  SLASH = '/'.freeze
39
+ Sequel::Deprecation.deprecate_constant(self, :SLASH)
34
40
  VALID_CONSTANT_NAME_REGEXP = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.freeze
41
+ Sequel::Deprecation.deprecate_constant(self, :VALID_CONSTANT_NAME_REGEXP)
35
42
  UNDERSCORE = '_'.freeze
43
+ Sequel::Deprecation.deprecate_constant(self, :UNDERSCORE)
36
44
  UNDERSCORE_CONVERT_REGEXP1 = /([A-Z]+)([A-Z][a-z])/.freeze
45
+ Sequel::Deprecation.deprecate_constant(self, :UNDERSCORE_CONVERT_REGEXP1)
37
46
  UNDERSCORE_CONVERT_REGEXP2 = /([a-z\d])([A-Z])/.freeze
47
+ Sequel::Deprecation.deprecate_constant(self, :UNDERSCORE_CONVERT_REGEXP2)
38
48
  UNDERSCORE_CONVERT_REPLACE = '\1_\2'.freeze
49
+ Sequel::Deprecation.deprecate_constant(self, :UNDERSCORE_CONVERT_REPLACE)
39
50
  UNDERSCORE_MODULE_REGEXP = /::/.freeze
51
+ Sequel::Deprecation.deprecate_constant(self, :UNDERSCORE_MODULE_REGEXP)
40
52
 
41
53
  @plurals, @singulars, @uncountables = [], [], []
42
54
 
@@ -113,7 +125,7 @@ module Sequel
113
125
  def camelize(s)
114
126
  s = s.to_s
115
127
  return s.camelize if s.respond_to?(:camelize)
116
- s = s.gsub(CAMELIZE_MODULE_REGEXP){|x| "::#{x[-1..-1].upcase unless x == SLASH}"}.gsub(CAMELIZE_CONVERT_REGEXP){|x| x[-1..-1].upcase}
128
+ s = s.gsub(/\/(.?)/){|x| "::#{x[-1..-1].upcase unless x == '/'}"}.gsub(/(^|_)(.)/){|x| x[-1..-1].upcase}
117
129
  s
118
130
  end
119
131
 
@@ -123,7 +135,7 @@ module Sequel
123
135
  def constantize(s)
124
136
  s = s.to_s
125
137
  return s.constantize if s.respond_to?(:constantize)
126
- raise(NameError, "#{s.inspect} is not a valid constant name!") unless m = VALID_CONSTANT_NAME_REGEXP.match(s)
138
+ raise(NameError, "#{s.inspect} is not a valid constant name!") unless m = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.match(s)
127
139
  Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
128
140
  end
129
141
 
@@ -131,7 +143,7 @@ module Sequel
131
143
  def demodulize(s)
132
144
  s = s.to_s
133
145
  return s.demodulize if s.respond_to?(:demodulize)
134
- s.gsub(DEMODULIZE_CONVERT_REGEXP, EMPTY_STRING)
146
+ s.gsub(/^.*::/, '')
135
147
  end
136
148
 
137
149
  # Returns the plural form of the word in the string.
@@ -157,8 +169,8 @@ module Sequel
157
169
  def underscore(s)
158
170
  s = s.to_s
159
171
  return s.underscore if s.respond_to?(:underscore)
160
- s.gsub(UNDERSCORE_MODULE_REGEXP, SLASH).gsub(UNDERSCORE_CONVERT_REGEXP1, UNDERSCORE_CONVERT_REPLACE).
161
- gsub(UNDERSCORE_CONVERT_REGEXP2, UNDERSCORE_CONVERT_REPLACE).tr(DASH, UNDERSCORE).downcase
172
+ s.gsub('::', '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
173
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
162
174
  end
163
175
  end
164
176
  end
@@ -18,8 +18,8 @@ module Sequel
18
18
  # # Make the Album class active_model compliant
19
19
  # Album.plugin :active_model
20
20
  module ActiveModel
21
- # The default string to join composite primary keys with in to_param.
22
21
  DEFAULT_TO_PARAM_JOINER = '-'.freeze
22
+ Sequel::Deprecation.deprecate_constant(self, :DEFAULT_TO_PARAM_JOINER)
23
23
 
24
24
  # ActiveModel compliant error class
25
25
  class Errors < Sequel::Model::Errors
@@ -119,7 +119,7 @@ module Sequel
119
119
 
120
120
  # The string to use to join composite primary key param strings.
121
121
  def to_param_joiner
122
- DEFAULT_TO_PARAM_JOINER
122
+ '-'
123
123
  end
124
124
  end
125
125
  end
@@ -242,6 +242,7 @@ module Sequel
242
242
  # giving the columns to update in each backing database table.
243
243
  # For backwards compatibility.
244
244
  def cti_columns
245
+ Sequel::Deprecation.deprecate("#{self}.cti_columns", "Use #{self}.cti_models to get the models, cti_table_name to get the name for the model, and cti_table_columns to get the columns for the model")
245
246
  h = {}
246
247
  cti_models.each { |m| h[m.cti_table_name] = m.cti_table_columns }
247
248
  h
@@ -123,9 +123,9 @@ module Sequel
123
123
  setters = setter_meths.zip(cov_methods)
124
124
  opts[:decomposer] = proc do
125
125
  if (o = compositions[name]).nil?
126
- setter_meths.each{|sm| get_column_value(sm, nil)}
126
+ setter_meths.each{|sm| set_column_value(sm, nil)}
127
127
  else
128
- setters.each{|sm, cm| get_column_value(sm, o.send(cm))}
128
+ setters.each{|sm, cm| set_column_value(sm, o.send(cm))}
129
129
  end
130
130
  end
131
131
  end
@@ -93,22 +93,34 @@ module Sequel
93
93
  where(r.qualify(r.join_table_alias, r[:left_keys])=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns])))
94
94
  ds.where(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds))
95
95
  when :many_through_many, :one_through_many
96
- fe, *edges = r.edges
97
- edges << r.final_edge
98
- if fre = r.reverse_edges.first
99
- table = fre[:table]
100
- left = fre[:left]
101
- mds = model.join(fe[:table], Array(fe[:right]).zip(Array(fe[:left])), :implicit_qualifier=>model.table_name)
102
- else
103
- table = fe[:table]
104
- left = edges.first[:left]
105
- edges = []
96
+ if r.reverse_edges.empty?
106
97
  mds = r.associated_dataset
98
+ fe = r.edges.first
99
+ selection = Array(r.qualify(fe[:table], r.final_edge[:left]))
100
+ predicate_key = r.qualify(fe[:table], fe[:right])
101
+ else
102
+ mds = model.dataset
103
+ iq = model.table_name
104
+ edges = r.edges.map(&:dup)
105
+ edges << r.final_edge.dup
106
+ edges.each do |e|
107
+ alias_expr = e[:table]
108
+ aliaz = mds.unused_table_alias(e[:table])
109
+ unless aliaz == alias_expr
110
+ alias_expr = Sequel.as(e[:table], aliaz)
111
+ end
112
+ e[:alias] = aliaz
113
+ mds = mds.join(alias_expr, Array(e[:right]).zip(Array(e[:left])), :implicit_qualifier=>iq)
114
+ iq = nil
115
+ end
116
+ fe, f1e, f2e = edges.values_at(0, -1, -2)
117
+ selection = Array(r.qualify(f2e[:alias], f1e[:left]))
118
+ predicate_key = r.qualify(fe[:alias], fe[:right])
107
119
  end
120
+
108
121
  mds = mds.
109
- select(*Array(r.qualify(table, left))).
110
- where(r.qualify(fe[:table], fe[:right])=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns])))
111
- edges.each{|e| mds = mds.join(e[:table], Array(e[:right]).zip(Array(e[:left])))}
122
+ select(*selection).
123
+ where(predicate_key=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns])))
112
124
  ds.where(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds))
113
125
  when :pg_array_to_many
114
126
  ds.where(Sequel[r.primary_key=>sds.select{Sequel.pg_array_op(r.qualify(r[:model].table_name, r[:key])).unnest}])
@@ -321,7 +321,7 @@ module Sequel
321
321
  if inc.is_a?(Hash)
322
322
  inc.each do |k, v|
323
323
  if k.is_a?(Sequel::SQL::AliasedExpression)
324
- key_name = k.aliaz.to_s
324
+ key_name = k.alias.to_s
325
325
  k = k.expression
326
326
  else
327
327
  key_name = k.to_s
@@ -346,7 +346,7 @@ module Sequel
346
346
  else
347
347
  Array(inc).each do |c|
348
348
  if c.is_a?(Sequel::SQL::AliasedExpression)
349
- key_name = c.aliaz.to_s
349
+ key_name = c.alias.to_s
350
350
  c = c.expression
351
351
  else
352
352
  key_name = c.to_s