sequel 4.45.0 → 4.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|