sequel 4.48.0 → 4.49.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +56 -0
- data/doc/advanced_associations.rdoc +1 -1
- data/doc/opening_databases.rdoc +3 -2
- data/doc/release_notes/4.49.0.txt +222 -0
- data/lib/sequel/adapters/ibmdb.rb +6 -1
- data/lib/sequel/adapters/jdbc.rb +3 -1
- data/lib/sequel/adapters/jdbc/h2.rb +10 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
- data/lib/sequel/adapters/jdbc/sqlserver.rb +9 -2
- data/lib/sequel/adapters/mock.rb +3 -0
- data/lib/sequel/adapters/mysql2.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +2 -1
- data/lib/sequel/adapters/shared/mysql.rb +4 -1
- data/lib/sequel/adapters/shared/oracle.rb +26 -3
- data/lib/sequel/connection_pool.rb +9 -2
- data/lib/sequel/connection_pool/sharded_single.rb +1 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/connection_pool/threaded.rb +2 -2
- data/lib/sequel/database/connecting.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +14 -1
- data/lib/sequel/dataset.rb +1 -1
- data/lib/sequel/dataset/actions.rb +54 -0
- data/lib/sequel/dataset/dataset_module.rb +58 -0
- data/lib/sequel/dataset/query.rb +3 -3
- data/lib/sequel/exceptions.rb +8 -0
- data/lib/sequel/extensions/_model_pg_row.rb +5 -2
- data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -2
- data/lib/sequel/extensions/migration.rb +5 -2
- data/lib/sequel/extensions/null_dataset.rb +1 -0
- data/lib/sequel/model/associations.rb +3 -0
- data/lib/sequel/model/base.rb +10 -55
- data/lib/sequel/model/dataset_module.rb +5 -43
- data/lib/sequel/model/errors.rb +2 -1
- data/lib/sequel/model/inflections.rb +17 -5
- data/lib/sequel/plugins/active_model.rb +2 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +25 -13
- data/lib/sequel/plugins/json_serializer.rb +2 -2
- data/lib/sequel/plugins/pg_row.rb +4 -2
- data/lib/sequel/plugins/serialization.rb +1 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +6 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +10 -2
- data/lib/sequel/sql.rb +16 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +4 -4
- data/spec/adapters/mysql_spec.rb +5 -1
- data/spec/adapters/oracle_spec.rb +4 -0
- data/spec/bin_spec.rb +7 -1
- data/spec/core/connection_pool_spec.rb +28 -14
- data/spec/core/database_spec.rb +149 -0
- data/spec/core/dataset_spec.rb +173 -0
- data/spec/extensions/class_table_inheritance_spec.rb +58 -17
- data/spec/extensions/composition_spec.rb +13 -0
- data/spec/extensions/dataset_associations_spec.rb +12 -0
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +16 -0
- data/spec/extensions/validation_helpers_spec.rb +1 -2
- data/spec/integration/associations_test.rb +8 -0
- data/spec/integration/plugin_test.rb +8 -3
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +29 -9
- data/spec/model/class_dataset_methods_spec.rb +6 -0
- data/spec/model/eager_loading_spec.rb +8 -8
- data/spec/model/plugins_spec.rb +34 -0
- data/spec/model/record_spec.rb +1 -1
- data/spec/spec_config.rb +2 -0
- 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(
|
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(
|
503
|
+
filename.split('_', 2).first.to_i
|
501
504
|
end
|
502
505
|
end
|
503
506
|
|
@@ -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
|
data/lib/sequel/model/base.rb
CHANGED
@@ -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).
|
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.
|
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
|
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
|
-
#
|
2713
|
+
# SEQUEL5: Remove
|
2760
2714
|
def _model_where_loader
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
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.
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
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
|
data/lib/sequel/model/errors.rb
CHANGED
@@ -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(
|
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(
|
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 =
|
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(
|
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(
|
161
|
-
gsub(
|
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
|
-
|
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|
|
126
|
+
setter_meths.each{|sm| set_column_value(sm, nil)}
|
127
127
|
else
|
128
|
-
setters.each{|sm, 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
|
-
|
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(*
|
110
|
-
where(
|
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.
|
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.
|
349
|
+
key_name = c.alias.to_s
|
350
350
|
c = c.expression
|
351
351
|
else
|
352
352
|
key_name = c.to_s
|