sequel 4.45.0 → 4.46.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +108 -0
- data/doc/release_notes/4.46.0.txt +404 -0
- data/doc/security.rdoc +9 -0
- data/doc/sql.rdoc +2 -2
- data/doc/testing.rdoc +1 -1
- data/doc/validations.rdoc +1 -2
- data/lib/sequel/adapters/ado.rb +8 -3
- data/lib/sequel/adapters/ado/access.rb +8 -4
- data/lib/sequel/adapters/ado/mssql.rb +3 -1
- data/lib/sequel/adapters/amalgalite.rb +5 -0
- data/lib/sequel/adapters/cubrid.rb +16 -7
- data/lib/sequel/adapters/do.rb +7 -1
- data/lib/sequel/adapters/do/mysql.rb +8 -4
- data/lib/sequel/adapters/ibmdb.rb +10 -5
- data/lib/sequel/adapters/jdbc.rb +8 -2
- data/lib/sequel/adapters/jdbc/as400.rb +10 -3
- data/lib/sequel/adapters/jdbc/db2.rb +27 -16
- data/lib/sequel/adapters/jdbc/derby.rb +47 -20
- data/lib/sequel/adapters/jdbc/h2.rb +13 -7
- data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
- data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
- data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
- data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
- data/lib/sequel/adapters/mock.rb +5 -0
- data/lib/sequel/adapters/mysql.rb +8 -1
- data/lib/sequel/adapters/mysql2.rb +6 -1
- data/lib/sequel/adapters/odbc.rb +20 -8
- data/lib/sequel/adapters/odbc/mssql.rb +6 -3
- data/lib/sequel/adapters/oracle.rb +12 -6
- data/lib/sequel/adapters/postgres.rb +20 -8
- data/lib/sequel/adapters/shared/access.rb +76 -47
- data/lib/sequel/adapters/shared/cubrid.rb +16 -11
- data/lib/sequel/adapters/shared/db2.rb +46 -19
- data/lib/sequel/adapters/shared/firebird.rb +20 -8
- data/lib/sequel/adapters/shared/informix.rb +6 -3
- data/lib/sequel/adapters/shared/mssql.rb +132 -72
- data/lib/sequel/adapters/shared/mysql.rb +112 -65
- data/lib/sequel/adapters/shared/oracle.rb +36 -21
- data/lib/sequel/adapters/shared/postgres.rb +91 -56
- data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
- data/lib/sequel/adapters/shared/sqlite.rb +67 -32
- data/lib/sequel/adapters/sqlanywhere.rb +9 -1
- data/lib/sequel/adapters/sqlite.rb +8 -1
- data/lib/sequel/adapters/swift.rb +5 -0
- data/lib/sequel/adapters/swift/mysql.rb +4 -2
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +10 -3
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
- data/lib/sequel/adapters/utils/pg_types.rb +14 -6
- data/lib/sequel/adapters/utils/replace.rb +4 -2
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/core.rb +24 -11
- data/lib/sequel/database/connecting.rb +9 -3
- data/lib/sequel/database/dataset_defaults.rb +7 -1
- data/lib/sequel/database/logging.rb +1 -0
- data/lib/sequel/database/misc.rb +5 -2
- data/lib/sequel/database/query.rb +7 -5
- data/lib/sequel/database/schema_generator.rb +1 -0
- data/lib/sequel/database/schema_methods.rb +50 -27
- data/lib/sequel/database/transactions.rb +19 -9
- data/lib/sequel/dataset/actions.rb +15 -6
- data/lib/sequel/dataset/graph.rb +15 -5
- data/lib/sequel/dataset/misc.rb +12 -4
- data/lib/sequel/dataset/mutation.rb +17 -8
- data/lib/sequel/dataset/prepared_statements.rb +3 -2
- data/lib/sequel/dataset/query.rb +84 -38
- data/lib/sequel/dataset/sql.rb +302 -191
- data/lib/sequel/deprecated.rb +26 -17
- data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/from_block.rb +1 -0
- data/lib/sequel/extensions/graph_each.rb +1 -1
- data/lib/sequel/extensions/identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/migration.rb +28 -4
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +4 -4
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
- data/lib/sequel/extensions/set_overrides.rb +2 -0
- data/lib/sequel/extensions/split_array_nil.rb +2 -2
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model.rb +11 -7
- data/lib/sequel/model/associations.rb +5 -7
- data/lib/sequel/model/base.rb +47 -45
- data/lib/sequel/model/dataset_module.rb +9 -14
- data/lib/sequel/model/plugins.rb +3 -0
- data/lib/sequel/no_core_ext.rb +1 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -1
- data/lib/sequel/plugins/boolean_subsets.rb +7 -5
- data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
- data/lib/sequel/plugins/dataset_associations.rb +1 -1
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/finder.rb +240 -0
- data/lib/sequel/plugins/inverted_subsets.rb +19 -12
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/schema.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
- data/lib/sequel/plugins/subset_conditions.rb +11 -3
- data/lib/sequel/plugins/whitelist_security.rb +118 -0
- data/lib/sequel/sql.rb +80 -36
- data/lib/sequel/timezones.rb +2 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +20 -0
- data/spec/adapters/mysql_spec.rb +1 -1
- data/spec/adapters/oracle_spec.rb +12 -8
- data/spec/adapters/postgres_spec.rb +1 -1
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +36 -34
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +87 -9
- data/spec/core/dataset_spec.rb +501 -129
- data/spec/core/deprecated_spec.rb +1 -1
- data/spec/core/expression_filters_spec.rb +146 -60
- data/spec/core/mock_adapter_spec.rb +1 -1
- data/spec/core/object_graph_spec.rb +61 -9
- data/spec/core/placeholder_literalizer_spec.rb +20 -2
- data/spec/core/schema_generator_spec.rb +6 -6
- data/spec/core/schema_spec.rb +54 -5
- data/spec/core_extensions_spec.rb +122 -18
- data/spec/deprecation_helper.rb +27 -2
- data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
- data/spec/extensions/association_proxies_spec.rb +2 -2
- data/spec/extensions/auto_literal_strings_spec.rb +212 -0
- data/spec/extensions/blacklist_security_spec.rb +1 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
- data/spec/extensions/column_select_spec.rb +20 -8
- data/spec/extensions/columns_introspection_spec.rb +3 -3
- data/spec/extensions/core_refinements_spec.rb +29 -12
- data/spec/extensions/dataset_associations_spec.rb +12 -12
- data/spec/extensions/def_dataset_method_spec.rb +100 -0
- data/spec/extensions/error_sql_spec.rb +1 -1
- data/spec/extensions/finder_spec.rb +260 -0
- data/spec/extensions/graph_each_spec.rb +2 -2
- data/spec/extensions/identifier_mangling_spec.rb +14 -8
- data/spec/extensions/inverted_subsets_spec.rb +4 -4
- data/spec/extensions/lazy_attributes_spec.rb +7 -0
- data/spec/extensions/many_through_many_spec.rb +38 -14
- data/spec/extensions/nested_attributes_spec.rb +18 -6
- data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
- data/spec/extensions/pg_enum_spec.rb +16 -1
- data/spec/extensions/pg_interval_spec.rb +11 -2
- data/spec/extensions/pg_loose_count_spec.rb +5 -0
- data/spec/extensions/pg_row_spec.rb +25 -0
- data/spec/extensions/prepared_statements_spec.rb +10 -1
- data/spec/extensions/query_spec.rb +2 -2
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/set_overrides_spec.rb +7 -3
- data/spec/extensions/sql_expr_spec.rb +0 -1
- data/spec/extensions/subset_conditions_spec.rb +6 -6
- data/spec/extensions/table_select_spec.rb +24 -12
- data/spec/extensions/to_dot_spec.rb +4 -4
- data/spec/extensions/whitelist_security_spec.rb +131 -0
- data/spec/integration/dataset_test.rb +9 -5
- data/spec/integration/model_test.rb +2 -0
- data/spec/integration/plugin_test.rb +2 -2
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/model/associations_spec.rb +39 -11
- data/spec/model/base_spec.rb +44 -24
- data/spec/model/class_dataset_methods_spec.rb +18 -16
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +84 -24
- data/spec/model/model_spec.rb +97 -63
- data/spec/model/record_spec.rb +21 -13
- metadata +13 -2
@@ -141,7 +141,7 @@ module Sequel
|
|
141
141
|
def apply_window_function_eager_limit_strategy(ds, limit_and_offset=limit_and_offset())
|
142
142
|
rn = ds.row_number_column
|
143
143
|
limit, offset = limit_and_offset
|
144
|
-
ds = ds.unordered.select_append{|o| o.row_number
|
144
|
+
ds = ds.unordered.select_append{|o| o.row_number.function.over(:partition=>predicate_key, :order=>ds.opts[:order]).as(rn)}.from_self
|
145
145
|
ds = if !returns_array?
|
146
146
|
ds.where(rn => offset ? offset+1 : 1)
|
147
147
|
elsif offset
|
@@ -694,14 +694,12 @@ module Sequel
|
|
694
694
|
v = fetch(:filter_limit_strategy, self[:eager_limit_strategy])
|
695
695
|
if v || self[:limit] || !returns_array?
|
696
696
|
case v ||= self[:model].default_eager_limit_strategy
|
697
|
-
when :union, :ruby
|
697
|
+
when true, :union, :ruby
|
698
698
|
# Can't use a union or ruby-based strategy for filtering by associations, switch to default eager graph limit
|
699
699
|
# strategy.
|
700
700
|
true_eager_graph_limit_strategy
|
701
701
|
when Symbol
|
702
702
|
v
|
703
|
-
when true
|
704
|
-
true_eager_graph_limit_strategy
|
705
703
|
end
|
706
704
|
end
|
707
705
|
end
|
@@ -2661,10 +2659,10 @@ END
|
|
2661
2659
|
# types, this is a simple transformation, but for +many_to_many+ associations this
|
2662
2660
|
# creates a subquery to the join table.
|
2663
2661
|
def complex_expression_sql_append(sql, op, args)
|
2664
|
-
r = args
|
2662
|
+
r = args[1]
|
2665
2663
|
if (((op == :'=' || op == :'!=') and r.is_a?(Sequel::Model)) ||
|
2666
2664
|
(multiple = ((op == :IN || op == :'NOT IN') and ((is_ds = r.is_a?(Sequel::Dataset)) or r.all?{|x| x.is_a?(Sequel::Model)}))))
|
2667
|
-
l = args
|
2665
|
+
l = args[0]
|
2668
2666
|
if ar = model.association_reflections[l]
|
2669
2667
|
if multiple
|
2670
2668
|
klass = ar.associated_class
|
@@ -3235,7 +3233,7 @@ END
|
|
3235
3233
|
@records_map = records_map
|
3236
3234
|
|
3237
3235
|
datasets = opts[:graph][:table_aliases].to_a.reject{|ta,ds| ds.nil?}
|
3238
|
-
column_aliases = opts[:graph_aliases] || opts[:graph][:column_aliases]
|
3236
|
+
column_aliases = opts[:graph_aliases] || opts[:graph][:column_aliases] # SEQUEL5: Remove :graph_aliases support
|
3239
3237
|
primary_keys = {}
|
3240
3238
|
column_maps = {}
|
3241
3239
|
models = {}
|
data/lib/sequel/model/base.rb
CHANGED
@@ -12,7 +12,7 @@ module Sequel
|
|
12
12
|
module ClassMethods
|
13
13
|
# Which columns should be the only columns allowed in a call to a mass assignment method (e.g. set)
|
14
14
|
# (default: not set, so all columns not otherwise restricted are allowed).
|
15
|
-
attr_reader :allowed_columns
|
15
|
+
attr_reader :allowed_columns # SEQUEL5: Deprecate after release
|
16
16
|
|
17
17
|
# Whether to cache the anonymous models created by Sequel::Model(). This is
|
18
18
|
# required for reloading them correctly (avoiding the superclass mismatch). True
|
@@ -238,7 +238,7 @@ module Sequel
|
|
238
238
|
# # => #<Artist {:name=>'Bob', ...}>
|
239
239
|
def [](*args)
|
240
240
|
args = args.first if args.size <= 1
|
241
|
-
args.is_a?(Hash) ?
|
241
|
+
args.is_a?(Hash) ? first(args) : (primary_key_lookup(args) unless args.nil?)
|
242
242
|
end
|
243
243
|
|
244
244
|
# Initializes a model instance as an existing record. This constructor is
|
@@ -393,7 +393,10 @@ module Sequel
|
|
393
393
|
# sharding support.
|
394
394
|
def db=(db)
|
395
395
|
@db = db
|
396
|
-
|
396
|
+
if @dataset
|
397
|
+
Sequel::Deprecation.deprecate("Sequel::Model.db= when the model has an existing dataset", "Use Sequel::Model.dataset= instead")
|
398
|
+
set_dataset(db.dataset.clone(@dataset.opts))
|
399
|
+
end
|
397
400
|
end
|
398
401
|
|
399
402
|
# Returns the cached schema information if available or gets it
|
@@ -446,8 +449,10 @@ module Sequel
|
|
446
449
|
|
447
450
|
if block
|
448
451
|
raise(Error, "Defining a dataset method using a block requires only one argument") if args.length > 1
|
452
|
+
Sequel::Deprecation.deprecate("Sequel::Model.def_dataset_method", "Define the method inside a dataset_module block, or use the def_dataset_method_plugin")
|
449
453
|
dataset_module{define_method(args.first, &block)}
|
450
454
|
else
|
455
|
+
Sequel::Deprecation.deprecate("Sequel::Model.def_dataset_method", "Define a class method that calls the dataset method, or use the def_dataset_method_plugin")
|
451
456
|
args.each{|arg| def_model_dataset_method(arg)}
|
452
457
|
end
|
453
458
|
end
|
@@ -461,12 +466,7 @@ module Sequel
|
|
461
466
|
# Artist.find{name > 'M'}
|
462
467
|
# # SELECT * FROM artists WHERE (name > 'M') LIMIT 1
|
463
468
|
def find(*args, &block)
|
464
|
-
|
465
|
-
# Use optimized finder
|
466
|
-
first_where(args.first)
|
467
|
-
else
|
468
|
-
where(*args, &block).first
|
469
|
-
end
|
469
|
+
first(*args, &block)
|
470
470
|
end
|
471
471
|
|
472
472
|
# Like +find+ but invokes create with given conditions when record does not
|
@@ -484,7 +484,6 @@ module Sequel
|
|
484
484
|
def find_or_create(cond, &block)
|
485
485
|
find(cond) || create(cond, &block)
|
486
486
|
end
|
487
|
-
|
488
487
|
|
489
488
|
FINDER_TYPES = [:first, :all, :each, :get].freeze
|
490
489
|
|
@@ -544,6 +543,7 @@ module Sequel
|
|
544
543
|
#
|
545
544
|
# See Dataset::PlaceholderLiteralizer for additional caveats.
|
546
545
|
def finder(meth=OPTS, opts=OPTS, &block)
|
546
|
+
Sequel::Deprecation.deprecate("Sequel::Model.finder and Sequel::Model.prepared_finder", "They have been moved to the finder plugin")
|
547
547
|
if block
|
548
548
|
raise Error, "cannot pass both a method name argument and a block of Model.finder" unless meth.is_a?(Hash)
|
549
549
|
raise Error, "cannot pass two option hashes to Model.finder" unless opts.equal?(OPTS)
|
@@ -607,29 +607,21 @@ module Sequel
|
|
607
607
|
end
|
608
608
|
end
|
609
609
|
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
# Use optimized finder
|
615
|
-
first_where(args.first)
|
610
|
+
def first_where(cond)
|
611
|
+
Sequel::Deprecation.deprecate("Sequel::Model.first_where", "Instead, use Sequel::Model.first")
|
612
|
+
if cond.is_a?(Integer)
|
613
|
+
dataset.where(cond).first(cond)
|
616
614
|
else
|
617
|
-
dataset.first(
|
615
|
+
dataset.first(cond)
|
618
616
|
end
|
619
617
|
end
|
620
618
|
|
621
|
-
# An alias for calling first! on the model's dataset, but with
|
622
|
-
# optimized handling of the single argument case.
|
623
|
-
def first!(*args, &block)
|
624
|
-
first(*args, &block) || raise(Sequel::NoMatchingRow.new(dataset))
|
625
|
-
end
|
626
|
-
|
627
619
|
# Freeze a model class, disallowing any further changes to it.
|
628
620
|
def freeze
|
629
621
|
dataset_module.freeze
|
630
622
|
overridable_methods_module.freeze
|
631
623
|
|
632
|
-
@finder_loaders.freeze
|
624
|
+
@finder_loaders.freeze # SEQUEL5: Remove
|
633
625
|
|
634
626
|
if @dataset
|
635
627
|
@dataset.freeze
|
@@ -637,16 +629,16 @@ module Sequel
|
|
637
629
|
db_schema.freeze.each_value(&:freeze)
|
638
630
|
columns.freeze
|
639
631
|
setter_methods.freeze
|
640
|
-
@finder_loaders.each_key{|k| finder_for(k)}
|
632
|
+
@finder_loaders.each_key{|k| finder_for(k)} # SEQUEL5: Remove
|
641
633
|
else
|
642
634
|
@setter_methods = [].freeze
|
643
635
|
end
|
644
636
|
|
645
637
|
@dataset_method_modules.freeze
|
646
638
|
@default_set_fields_options.freeze
|
647
|
-
@finders.freeze
|
639
|
+
@finders.freeze # SEQUEL5: Remove
|
648
640
|
@plugins.freeze
|
649
|
-
@allowed_columns.freeze if @allowed_columns
|
641
|
+
@allowed_columns.freeze if @allowed_columns # SEQUEL5: Remove
|
650
642
|
|
651
643
|
super
|
652
644
|
end
|
@@ -802,6 +794,7 @@ module Sequel
|
|
802
794
|
# exception:
|
803
795
|
# :type :: Specifies the type of prepared statement to create
|
804
796
|
def prepared_finder(meth=OPTS, opts=OPTS, &block)
|
797
|
+
# SEQUEL5: Remove
|
805
798
|
if block
|
806
799
|
raise Error, "cannot pass both a method name argument and a block of Model.finder" unless meth.is_a?(Hash)
|
807
800
|
meth = meth.merge(:prepare=>true)
|
@@ -837,6 +830,7 @@ module Sequel
|
|
837
830
|
# Artist.set(:name=>'Bob', :hometown=>'Sactown') # No Error
|
838
831
|
# Artist.set(:name=>'Bob', :records_sold=>30000) # Error
|
839
832
|
def set_allowed_columns(*cols)
|
833
|
+
Sequel::Deprecation.deprecate("Sequel::Model.set_allowed_columns", "Load the whitelist_security plugin into the model class")
|
840
834
|
clear_setter_methods_cache
|
841
835
|
@allowed_columns = cols
|
842
836
|
end
|
@@ -945,15 +939,9 @@ module Sequel
|
|
945
939
|
# This method creates dataset methods that do not accept arguments. To create
|
946
940
|
# dataset methods that accept arguments, you should use define a
|
947
941
|
# method directly inside a #dataset_module block.
|
948
|
-
def subset(
|
949
|
-
|
950
|
-
|
951
|
-
else
|
952
|
-
key = :"_subset_#{name}_ds"
|
953
|
-
def_dataset_method(name) do
|
954
|
-
cached_dataset(key){filter(*args)}
|
955
|
-
end
|
956
|
-
end
|
942
|
+
def subset(*args, &block)
|
943
|
+
Sequel::Deprecation.deprecate("Sequel::Model.subset", "Use the subset method inside a dataset_module block, or use the def_dataset_method plugin")
|
944
|
+
dataset_module{where(*args, &block)}
|
957
945
|
end
|
958
946
|
|
959
947
|
# Returns name of primary table for the dataset. If the table for the dataset
|
@@ -1011,6 +999,10 @@ module Sequel
|
|
1011
999
|
self.simple_table = db.literal(ds).freeze
|
1012
1000
|
ds = db.from(ds)
|
1013
1001
|
when Dataset
|
1002
|
+
if ds.joined_dataset?
|
1003
|
+
Sequel::Deprecation.deprecate("Using a joined dataset as a Sequel::Model dataset", respond_to?(:cti_base_model) ? "Use the class_table_inheritance plugin :alias option in #{cti_base_model.inspect}" : "Call from_self on the dataset to wrap it in a subquery")
|
1004
|
+
end
|
1005
|
+
|
1014
1006
|
self.simple_table = if ds.send(:simple_select_all?)
|
1015
1007
|
ds.literal(ds.first_source_table).freeze
|
1016
1008
|
end
|
@@ -1072,12 +1064,14 @@ module Sequel
|
|
1072
1064
|
# Define a finder method in the given module with the given method name that
|
1073
1065
|
# load rows using the finder with the given name.
|
1074
1066
|
def def_finder_method(mod, meth, type)
|
1067
|
+
# SEQUEL5: Remove
|
1075
1068
|
mod.send(:define_method, meth){|*args, &block| finder_for(meth).send(type, *args, &block)}
|
1076
1069
|
end
|
1077
1070
|
|
1078
1071
|
# Define a prepared_finder method in the given module that will call the associated prepared
|
1079
1072
|
# statement.
|
1080
1073
|
def def_prepare_method(mod, meth)
|
1074
|
+
# SEQUEL5: Remove
|
1081
1075
|
mod.send(:define_method, meth){|*args, &block| finder_for(meth).call(prepare_method_arg_hash(args), &block)}
|
1082
1076
|
end
|
1083
1077
|
|
@@ -1085,6 +1079,7 @@ module Sequel
|
|
1085
1079
|
# for the method, load the finder and set correctly in the finders hash, then
|
1086
1080
|
# return the finder.
|
1087
1081
|
def finder_for(meth)
|
1082
|
+
# SEQUEL5: Remove
|
1088
1083
|
unless finder = (frozen? ? @finders[meth] : Sequel.synchronize{@finders[meth]})
|
1089
1084
|
finder_loader = @finder_loaders.fetch(meth)
|
1090
1085
|
finder = finder_loader.call(self)
|
@@ -1143,6 +1138,7 @@ module Sequel
|
|
1143
1138
|
# that want to modify the methods used.
|
1144
1139
|
def get_setter_methods
|
1145
1140
|
if allowed_columns
|
1141
|
+
# SEQUEL5: Remove allowed_columns handling
|
1146
1142
|
allowed_columns.map{|x| "#{x}="}
|
1147
1143
|
else
|
1148
1144
|
meths = instance_methods.collect(&:to_s).grep(SETTER_METHOD_REGEXP) - RESTRICTED_SETTER_METHODS
|
@@ -1223,6 +1219,7 @@ module Sequel
|
|
1223
1219
|
# An hash of prepared argument values for the given arguments, with keys
|
1224
1220
|
# starting at a. Used by the methods created by prepared_finder.
|
1225
1221
|
def prepare_method_arg_hash(args)
|
1222
|
+
# SEQUEL5: Remove
|
1226
1223
|
h = {}
|
1227
1224
|
prepare_method_args('a', args.length).zip(args).each{|k, v| h[k] = v}
|
1228
1225
|
h
|
@@ -1230,6 +1227,7 @@ module Sequel
|
|
1230
1227
|
|
1231
1228
|
# An array of prepared statement argument names, of length n and starting with base.
|
1232
1229
|
def prepare_method_args(base, n)
|
1230
|
+
# SEQUEL5: Remove
|
1233
1231
|
(0...n).map do
|
1234
1232
|
s = base.to_sym
|
1235
1233
|
base = base.next
|
@@ -1251,9 +1249,9 @@ module Sequel
|
|
1251
1249
|
ds.fetch_rows(sql){|r| return ds.row_proc.call(r)}
|
1252
1250
|
nil
|
1253
1251
|
elsif dataset.joined_dataset?
|
1254
|
-
|
1252
|
+
dataset.first(qualified_primary_key_hash(pk))
|
1255
1253
|
else
|
1256
|
-
|
1254
|
+
dataset.first(primary_key_hash(pk))
|
1257
1255
|
end
|
1258
1256
|
end
|
1259
1257
|
|
@@ -1276,7 +1274,7 @@ module Sequel
|
|
1276
1274
|
# Reset the instance dataset to a modified copy of the current dataset,
|
1277
1275
|
# should be used whenever the model's dataset is modified.
|
1278
1276
|
def reset_instance_dataset
|
1279
|
-
Sequel.synchronize{@finders.clear if @finders
|
1277
|
+
Sequel.synchronize{@finders.clear} if @finders && !@finders.frozen?
|
1280
1278
|
@instance_dataset = @dataset.limit(1).naked.skip_limit_check if @dataset
|
1281
1279
|
end
|
1282
1280
|
|
@@ -1800,6 +1798,7 @@ module Sequel
|
|
1800
1798
|
# artist.set_all(:name=>'Jim')
|
1801
1799
|
# artist.name # => 'Jim'
|
1802
1800
|
def set_all(hash)
|
1801
|
+
Sequel::Deprecation.deprecate("Sequel::Model#set_all", "Switch to set or load the whitelist_security plugin into the model class")
|
1803
1802
|
set_restricted(hash, :all)
|
1804
1803
|
end
|
1805
1804
|
|
@@ -1870,6 +1869,7 @@ module Sequel
|
|
1870
1869
|
#
|
1871
1870
|
# artist.set_only({:hometown=>'LA'}, :name) # Raise Error
|
1872
1871
|
def set_only(hash, *only)
|
1872
|
+
Sequel::Deprecation.deprecate("Sequel::Model#set_only", "Switch to set_fields with the :missing=>:skip option or load the whitelist_security plugin into the model class")
|
1873
1873
|
set_restricted(hash, only.flatten)
|
1874
1874
|
end
|
1875
1875
|
|
@@ -1916,6 +1916,7 @@ module Sequel
|
|
1916
1916
|
# Artist.set_allowed_columns(:num_albums)
|
1917
1917
|
# artist.update_all(:name=>'Jim') # UPDATE artists SET name = 'Jim' WHERE (id = 1)
|
1918
1918
|
def update_all(hash)
|
1919
|
+
Sequel::Deprecation.deprecate("Sequel::Model#update_all", "Switch to update or load the whitelist_security plugin into the model class")
|
1919
1920
|
update_restricted(hash, :all)
|
1920
1921
|
end
|
1921
1922
|
|
@@ -1941,6 +1942,7 @@ module Sequel
|
|
1941
1942
|
#
|
1942
1943
|
# artist.update_only({:hometown=>'LA'}, :name) # Raise Error
|
1943
1944
|
def update_only(hash, *only)
|
1945
|
+
Sequel::Deprecation.deprecate("Sequel::Model#update_only", "Switch to update_fields with the :missing=>:skip option or load the whitelist_security plugin into the model class")
|
1944
1946
|
update_restricted(hash, only.flatten)
|
1945
1947
|
end
|
1946
1948
|
|
@@ -2002,8 +2004,6 @@ module Sequel
|
|
2002
2004
|
# even if validation is skipped. This is a private hook. It exists so that
|
2003
2005
|
# plugins can set values automatically before validation (as the values
|
2004
2006
|
# need to be validated), but should be set even if validation is skipped.
|
2005
|
-
# Unlike the regular before_validation hook, we do not skip the save/validation
|
2006
|
-
# if this returns false.
|
2007
2007
|
def _before_validation
|
2008
2008
|
end
|
2009
2009
|
|
@@ -2428,7 +2428,7 @@ module Sequel
|
|
2428
2428
|
# Array :: Only allow setting of columns in the given array.
|
2429
2429
|
def setter_methods(type)
|
2430
2430
|
if type == :default
|
2431
|
-
if !@singleton_setter_added || model.allowed_columns
|
2431
|
+
if !@singleton_setter_added || model.allowed_columns # SEQUEL5: Remove model.allowed_columns
|
2432
2432
|
return model.setter_methods
|
2433
2433
|
end
|
2434
2434
|
end
|
@@ -2503,7 +2503,7 @@ module Sequel
|
|
2503
2503
|
#
|
2504
2504
|
# Artist.dataset[1] # SELECT * FROM artists WHERE (id = 1) LIMIT 1
|
2505
2505
|
def [](*args)
|
2506
|
-
if args.length == 1 && (i = args
|
2506
|
+
if args.length == 1 && (i = args[0]) && i.is_a?(Integer)
|
2507
2507
|
with_pk(i)
|
2508
2508
|
else
|
2509
2509
|
super
|
@@ -2531,6 +2531,7 @@ module Sequel
|
|
2531
2531
|
# # FROM artists LEFT OUTER JOIN albums ON (albums.artist_id = artists.id)
|
2532
2532
|
def graph(table, *args, &block)
|
2533
2533
|
if table.is_a?(Class) && table < Sequel::Model
|
2534
|
+
Sequel::Deprecation.deprecate("Passing Sequel::Model class as first argument to Sequel::Dataset#graph", "Pass the model's dataset as the first argument instead")
|
2534
2535
|
super(table.dataset, *args, &block)
|
2535
2536
|
else
|
2536
2537
|
super
|
@@ -2544,7 +2545,8 @@ module Sequel
|
|
2544
2545
|
# Album.insert(Album.load(:name=>'A'))
|
2545
2546
|
# # INSERT INTO albums (name) VALUES ('A')
|
2546
2547
|
def insert_sql(*values)
|
2547
|
-
if values.size == 1 && (v = values
|
2548
|
+
if values.size == 1 && (v = values[0]).is_a?(Sequel::Model) && !v.respond_to?(:sql_literal_append)
|
2549
|
+
Sequel::Deprecation.deprecate("Passing Sequel::Model instance argument to Sequel::Dataset#insert", "Pass model_instance.values or model_instance.to_hash as the argument instead")
|
2548
2550
|
super(v.to_hash)
|
2549
2551
|
else
|
2550
2552
|
super
|
@@ -2558,6 +2560,7 @@ module Sequel
|
|
2558
2560
|
# # SELECT * FROM artists INNER JOIN albums ON (albums.artist_id = artists.id)
|
2559
2561
|
def join_table(type, table, *args, &block)
|
2560
2562
|
if table.is_a?(Class) && table < Sequel::Model
|
2563
|
+
Sequel::Deprecation.deprecate("Passing Sequel::Model class to a dataset join method", "Pass the model's table name or dataset as the first argument instead")
|
2561
2564
|
if table.dataset.simple_select_all?
|
2562
2565
|
super(type, table.table_name, *args, &block)
|
2563
2566
|
else
|
@@ -2721,6 +2724,5 @@ module Sequel
|
|
2721
2724
|
|
2722
2725
|
extend ClassMethods
|
2723
2726
|
plugin self
|
2724
|
-
finder(:where, :arity=>1, :mod=>ClassMethods)
|
2725
2727
|
end
|
2726
2728
|
end
|
@@ -14,24 +14,18 @@ module Sequel
|
|
14
14
|
@model = model
|
15
15
|
end
|
16
16
|
|
17
|
-
#
|
18
|
-
# Model.subset for details.
|
17
|
+
# Alias for where.
|
19
18
|
def subset(name, *args, &block)
|
20
|
-
|
19
|
+
where(name, *args, &block)
|
21
20
|
end
|
22
21
|
|
23
|
-
|
24
|
-
def where(name, *args, &block)
|
25
|
-
subset(name, *args, &block)
|
26
|
-
end
|
27
|
-
|
28
|
-
%w'exclude exclude_having having'.map(&:to_sym).each do |meth|
|
22
|
+
%w'where exclude exclude_having having'.map(&:to_sym).each do |meth|
|
29
23
|
define_method(meth) do |name, *args, &block|
|
30
24
|
if block || args.flatten.any?{|arg| arg.is_a?(Proc)}
|
31
|
-
|
25
|
+
define_method(name){send(meth, *args, &block)}
|
32
26
|
else
|
33
27
|
key = :"_#{meth}_#{name}_ds"
|
34
|
-
|
28
|
+
define_method(name) do
|
35
29
|
cached_dataset(key){send(meth, *args)}
|
36
30
|
end
|
37
31
|
end
|
@@ -48,10 +42,10 @@ module Sequel
|
|
48
42
|
def self.def_dataset_caching_method(mod, meth)
|
49
43
|
mod.send(:define_method, meth) do |name, *args, &block|
|
50
44
|
if block
|
51
|
-
|
45
|
+
define_method(name){send(meth, *args, &block)}
|
52
46
|
else
|
53
47
|
key = :"_#{meth}_#{name}_ds"
|
54
|
-
|
48
|
+
define_method(name) do
|
55
49
|
cached_dataset(key){send(meth, *args)}
|
56
50
|
end
|
57
51
|
end
|
@@ -67,7 +61,8 @@ module Sequel
|
|
67
61
|
# Add a class method to the related model that
|
68
62
|
# calls the dataset method of the same name.
|
69
63
|
def method_added(meth)
|
70
|
-
@model.send(:def_model_dataset_method, meth)
|
64
|
+
@model.send(:def_model_dataset_method, meth) if public_method_defined?(meth)
|
65
|
+
super
|
71
66
|
end
|
72
67
|
end
|
73
68
|
|
data/lib/sequel/model/plugins.rb
CHANGED
@@ -25,6 +25,9 @@ module Sequel
|
|
25
25
|
# In the given module +mod+, define methods that are call the same method
|
26
26
|
# on the dataset. This is designed for plugins to define dataset methods
|
27
27
|
# inside ClassMethods that call the implementations in DatasetMethods.
|
28
|
+
#
|
29
|
+
# This should not be called with untrusted input or method names that
|
30
|
+
# can't be used literally, since it uses class_eval.
|
28
31
|
def self.def_dataset_methods(mod, meths)
|
29
32
|
Array(meths).each do |meth|
|
30
33
|
mod.class_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__)
|
data/lib/sequel/no_core_ext.rb
CHANGED
@@ -58,7 +58,7 @@ module Sequel
|
|
58
58
|
# restricted_columns.
|
59
59
|
def get_setter_methods
|
60
60
|
meths = super
|
61
|
-
if !allowed_columns && restricted_columns
|
61
|
+
if !(respond_to?(:allowed_columns) && allowed_columns) && restricted_columns
|
62
62
|
meths -= restricted_columns.map{|x| "#{x}="}
|
63
63
|
end
|
64
64
|
meths
|
@@ -9,7 +9,7 @@ module Sequel
|
|
9
9
|
# <tt>column IS TRUE</tt> (assuming the database supports that syntax).
|
10
10
|
#
|
11
11
|
# You can provide a block to the plugin, which will be called with column name
|
12
|
-
# symbol, and should return an array of arguments to pass to +
|
12
|
+
# symbol, and should return an array of arguments to pass to +dataset_module.where+.
|
13
13
|
# Using this, you can change the method name and arguments for each column.
|
14
14
|
# This block is executed in the context of the model class.
|
15
15
|
#
|
@@ -28,12 +28,11 @@ module Sequel
|
|
28
28
|
# [column.to_s.sub(/\Ais_/, ''), {column=>'Y'}]
|
29
29
|
# end
|
30
30
|
module BooleanSubsets
|
31
|
-
#
|
32
|
-
# attribute? boolean reader methods for the class's columns if the class has a dataset.
|
31
|
+
# Create boolean subset methods for each boolean column.
|
33
32
|
def self.configure(model, &block)
|
34
33
|
model.instance_eval do
|
35
34
|
(class << self; self; end).send(:define_method, :boolean_subset_args, &block) if block
|
36
|
-
|
35
|
+
create_boolean_subsets if @dataset
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
@@ -50,7 +49,10 @@ module Sequel
|
|
50
49
|
# Add subset methods for all of the boolean columns in this model.
|
51
50
|
def create_boolean_subsets
|
52
51
|
if cs = check_non_connection_error{columns}
|
53
|
-
cs.
|
52
|
+
cs = cs.select{|c| db_schema[c][:type] == :boolean}.map{|c| boolean_subset_args(c)}
|
53
|
+
dataset_module do
|
54
|
+
cs.each{|c| where(*c)}
|
55
|
+
end
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|