sequel 4.46.0 → 4.47.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +20 -0
  3. data/doc/release_notes/4.47.0.txt +56 -0
  4. data/lib/sequel/adapters/jdbc/as400.rb +1 -1
  5. data/lib/sequel/adapters/shared/postgres.rb +3 -1
  6. data/lib/sequel/ast_transformer.rb +1 -1
  7. data/lib/sequel/extensions/schema_dumper.rb +6 -2
  8. data/lib/sequel/extensions/server_block.rb +32 -15
  9. data/lib/sequel/model.rb +1 -1
  10. data/lib/sequel/model/associations.rb +19 -3
  11. data/lib/sequel/model/base.rb +10 -3
  12. data/lib/sequel/plugins/association_autoreloading.rb +2 -0
  13. data/lib/sequel/plugins/association_dependencies.rb +3 -3
  14. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  15. data/lib/sequel/plugins/boolean_subsets.rb +1 -1
  16. data/lib/sequel/plugins/class_table_inheritance.rb +4 -3
  17. data/lib/sequel/plugins/column_select.rb +2 -2
  18. data/lib/sequel/plugins/defaults_setter.rb +3 -1
  19. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +2 -0
  20. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  21. data/lib/sequel/plugins/pg_typecast_on_load.rb +2 -0
  22. data/lib/sequel/plugins/rcte_tree.rb +0 -20
  23. data/lib/sequel/plugins/serialization.rb +5 -5
  24. data/lib/sequel/plugins/validation_helpers.rb +2 -2
  25. data/lib/sequel/version.rb +1 -1
  26. data/spec/adapters/postgres_spec.rb +2 -0
  27. data/spec/extensions/column_select_spec.rb +1 -0
  28. data/spec/extensions/defaults_setter_spec.rb +14 -0
  29. data/spec/extensions/pg_typecast_on_load_spec.rb +11 -9
  30. data/spec/extensions/schema_dumper_spec.rb +16 -0
  31. data/spec/extensions/server_block_spec.rb +7 -0
  32. data/spec/integration/model_test.rb +53 -4
  33. data/spec/integration/plugin_test.rb +0 -1
  34. data/spec/model/association_reflection_spec.rb +42 -0
  35. data/spec/model/model_spec.rb +37 -1
  36. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ecafb93f6c5af1a4ba3d659bbac127a7ee31e6d
4
- data.tar.gz: 9e9a68697228e06a456cfd8ccefcbb9acff1dbef
3
+ metadata.gz: e4d1bdb365601ad2d67120764a7211a4c12ecff3
4
+ data.tar.gz: 1e1a3e0d8fb915792b66a91e96577ba0c522c9b6
5
5
  SHA512:
6
- metadata.gz: 6a82addc13ea6af0d5259a621a12da38e992eb249e2f7f623ff50ec5224e16670c2517c073e2e9af596f8d903603770883974731ef8173ca1183bd3d58c91613
7
- data.tar.gz: 708159da412ed6bc0e45fc2af49a344df092e1bad67b343481e0cf976b9d185d338f8643269997dc9b40a392084391c7ad1cde72284eb92c6bc33683d18dda20
6
+ metadata.gz: 47bd614656335d42c4d5f2dbe1fbf9ead5143975b2d57b06c982a26039e5d7bb359470e1ffead7993be9651bafb706a174cd99e26fff7786833d96d02b311275
7
+ data.tar.gz: 2ab2a499dc1cd2dd45fa7f9bf3a58e902742a4a087f297918b634f535c59953d26bee14aee90e8111142d38d703a5c8bc05966139d93f410f79ea236af5e0f11
data/CHANGELOG CHANGED
@@ -1,3 +1,23 @@
1
+ === 4.47.0 (2017-06-01)
2
+
3
+ * Deprecate pg_typecast_on_load plugin, only useful on deprecated do and swift adapters (jeremyevans)
4
+
5
+ * Deprecate association_autoreloading and many_to_one_pk_lookup plugins, which were made the default model behavior in Sequel 4 (jeremyevans)
6
+
7
+ * Deprecate setting invalid datasets for models unless required_valid_table = false (jeremyevans)
8
+
9
+ * Make Model.require_valid_table = true not raise for datasets where Database#schema raises an error but Dataset#columns works (jeremyevans)
10
+
11
+ * Make Database#with_server in the server_block extension accept a second argument for a different read_only shard (jeremyevans) (#1355)
12
+
13
+ * Make schema_dumper extension handle Oracle 11g XE inclusion of not null in the db_type (StevenCregan, jeremyevans) (#1351)
14
+
15
+ * Add Model.default_association_type_options for changing default association options per association type (jeremyevans)
16
+
17
+ * Add :materialized option to Database#views on PostgreSQL to return materialized views (Blargel) (#1348)
18
+
19
+ * Make defaults_setter plugin inherit custom default values when subclassing (jeremyevans)
20
+
1
21
  === 4.46.0 (2017-05-01)
2
22
 
3
23
  * Recognize additional disconnect error on MySQL (jeremyevans)
@@ -0,0 +1,56 @@
1
+ = Deprecated Features
2
+
3
+ * Setting an invalid dataset for a model is now deprecated.
4
+ Historically, Sequel has swallowed exceptions for this to keep
5
+ backwards compatibility, but it generally just results in code
6
+ breaking later. To allow invalid datasets to be used:
7
+
8
+ Sequel::Model.require_valid_table = false
9
+
10
+ * The association_autoreloading and many_to_one_pk_lookup plugins
11
+ are now deprecated. They were moved from plugins to standard
12
+ model behavior in Sequel 4.0, and have been no-ops since.
13
+
14
+ * The pg_typecast_on_load plugin is now deprecated. It is only useful
15
+ on the already deprecated do and swift adapters.
16
+
17
+ = New Features
18
+
19
+ * Database#with_server in the server_block extension now accepts an
20
+ optional second argument for the read only server to use. This
21
+ allows for overriding the default server while providing a separate
22
+ default for read only queries:
23
+
24
+ DB.with_server(:server1, :server1ro) do
25
+ DB[:a].all # Uses server1ro
26
+ DB[:b].insert(1) # Uses server1
27
+ end
28
+
29
+ * Model.default_association_type_options has been added, allowing the
30
+ ability to set default options per association type. This can be
31
+ used to make some association types read_only by default:
32
+
33
+ opts = Sequel::Model.default_association_type_options
34
+ opts[:one_to_many] = opts[:many_to_many] = {:read_only=>true}
35
+
36
+ * Database#views on PostgreSQL now accepts a :materialized option to
37
+ return materialized views instead of regular views.
38
+
39
+ = Other Improvements
40
+
41
+ * Setting Sequel::Model.require_valid_table = true no longer raises
42
+ an exception when using a valid dataset that selects from a subquery
43
+ or table returning function or uses a join.
44
+
45
+ * The defaults_setter plugin now inherits any custom default
46
+ values when subclassing.
47
+
48
+ * The schema_dumper extension now handles Oracle 11g XE behavior of
49
+ appending not null to the database type.
50
+
51
+ = Backwards Compatibility
52
+
53
+ * External callers of Database#check_non_connection_error (private
54
+ method) should update their code to call it with a true or false
55
+ argument specifying whether to raise an error for exceptions that
56
+ are not connection errors.
@@ -1,6 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- Sequel::Deprecation.deprecate("The jdbc/as400 adapter", "Please consider maintaining it yourself as an external gem if you want to continue using it")
3
+ Sequel::Deprecation.deprecate("The jdbc/as400 adapter", "This gem will replace it: https://github.com/ecraft/sequel-jdbc-as400")
4
4
 
5
5
  Sequel::JDBC.load_driver('com.ibm.as400.access.AS400JDBCDriver')
6
6
  Sequel.require 'adapters/jdbc/transactions'
@@ -614,12 +614,14 @@ module Sequel
614
614
  # Array of symbols specifying view names in the current database.
615
615
  #
616
616
  # Options:
617
+ # :materialized :: Return materialized views
617
618
  # :qualify :: Return the views as Sequel::SQL::QualifiedIdentifier instances,
618
619
  # using the schema the view is located in as the qualifier.
619
620
  # :schema :: The schema to search
620
621
  # :server :: The server to use
621
622
  def views(opts=OPTS)
622
- pg_class_relname('v', opts)
623
+ relkind = opts[:materialized] ? 'm' : 'v'
624
+ pg_class_relname(relkind, opts)
623
625
  end
624
626
 
625
627
  private
@@ -93,7 +93,7 @@ module Sequel
93
93
  def initialize(table, unused=nil)
94
94
  if unused
95
95
  # :nocov:
96
- Sequel::Deprecation.deprecate("Passing two arguments to Sequel::Qualifier.new", 'Pass only the second arguument specifying the table used for qualification')
96
+ Sequel::Deprecation.deprecate("Passing two arguments to Sequel::Qualifier.new", 'Pass only the second argument specifying the table used for qualification')
97
97
  @table = unused
98
98
  # :nocov:
99
99
  else
@@ -20,7 +20,11 @@ module Sequel
20
20
  # be :type. The other options added should modify that type (e.g. :size). If a
21
21
  # database type is not recognized, return it as a String type.
22
22
  def column_schema_to_ruby_type(schema)
23
- case schema[:db_type].downcase
23
+ type = schema[:db_type].downcase
24
+ if database_type == :oracle
25
+ type = type.sub(/ not null\z/, '')
26
+ end
27
+ case type
24
28
  when /\A(medium|small)?int(?:eger)?(?:\((\d+)\))?( unsigned)?\z/o
25
29
  if !$1 && $2 && $2.to_i >= 10 && $3
26
30
  # Unsigned integer type with 10 digits can potentially contain values which
@@ -49,7 +53,7 @@ module Sequel
49
53
  {:type=>Time, :only_time=>true}
50
54
  when /\An?char(?:acter)?(?:\((\d+)\))?\z/o
51
55
  {:type=>String, :size=>($1.to_i if $1), :fixed=>true}
52
- when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/o
56
+ when /\A(?:n?varchar2?|character varying|bpchar|string)(?:\((\d+)\))?\z/o
53
57
  {:type=>String, :size=>($1.to_i if $1)}
54
58
  when /\A(?:small)?money\z/o
55
59
  {:type=>BigDecimal, :size=>[19,2]}
@@ -16,7 +16,7 @@
16
16
  # end
17
17
  # DB[:a].all # Uses default
18
18
  #
19
- # You can even nest calls to with_server:
19
+ # You can nest calls to with_server:
20
20
  #
21
21
  # DB.with_server(:shard1) do
22
22
  # DB[:a].all # Uses shard1
@@ -39,6 +39,19 @@
39
39
  # DB[:a].server(:read_only).all # Uses shard1
40
40
  # end
41
41
  #
42
+ # If you pass two separate shards to with_server, the second shard will
43
+ # be used instead of the :read_only shard, and the first shard will be
44
+ # used instead of the :default shard:
45
+ #
46
+ # DB.with_server(:shard1, :shard2) do
47
+ # DB[:a].all # Uses shard2
48
+ # DB[:a].delete # Uses shard1
49
+ # DB[:a].server(:shard3).all # Uses shard3
50
+ # DB[:a].server(:shard3).delete # Uses shard3
51
+ # DB[:a].server(:default).all # Uses shard1
52
+ # DB[:a].server(:read_only).delete # Uses shard2
53
+ # end
54
+ #
42
55
  # Related modules: Sequel::ServerBlock, Sequel::UnthreadedServerBlock,
43
56
  # Sequel::ThreadedServerBlock
44
57
 
@@ -60,17 +73,17 @@ module Sequel
60
73
  end
61
74
 
62
75
  # Delegate to the connection pool
63
- def with_server(server, &block)
64
- pool.with_server(server, &block)
76
+ def with_server(default_server, read_only_server=default_server, &block)
77
+ pool.with_server(default_server, read_only_server, &block)
65
78
  end
66
79
  end
67
80
 
68
81
  # Adds with_server support for the sharded single connection pool.
69
82
  module UnthreadedServerBlock
70
83
  # Set a default server/shard to use inside the block.
71
- def with_server(server)
84
+ def with_server(default_server, read_only_server=default_server)
72
85
  begin
73
- set_default_server(server)
86
+ set_default_server(default_server, read_only_server)
74
87
  yield
75
88
  ensure
76
89
  clear_default_server
@@ -80,8 +93,8 @@ module Sequel
80
93
  private
81
94
 
82
95
  # Make the given server the new default server.
83
- def set_default_server(server)
84
- @default_servers << server
96
+ def set_default_server(default_server, read_only_server=default_server)
97
+ @default_servers << [default_server, read_only_server]
85
98
  end
86
99
 
87
100
  # Remove the current default server, restoring the
@@ -96,8 +109,10 @@ module Sequel
96
109
  super
97
110
  else
98
111
  case server
99
- when :default, nil, :read_only
100
- @default_servers.last
112
+ when :default, nil
113
+ @default_servers[-1][0]
114
+ when :read_only
115
+ @default_servers[-1][1]
101
116
  else
102
117
  super
103
118
  end
@@ -109,9 +124,9 @@ module Sequel
109
124
  module ThreadedServerBlock
110
125
  # Set a default server/shard to use inside the block for the current
111
126
  # thread.
112
- def with_server(server)
127
+ def with_server(default_server, read_only_server=default_server)
113
128
  begin
114
- set_default_server(server)
129
+ set_default_server(default_server, read_only_server)
115
130
  yield
116
131
  ensure
117
132
  clear_default_server
@@ -121,8 +136,8 @@ module Sequel
121
136
  private
122
137
 
123
138
  # Make the given server the new default server for the current thread.
124
- def set_default_server(server)
125
- sync{(@default_servers[Thread.current] ||= [])} << server
139
+ def set_default_server(default_server, read_only_server=default_server)
140
+ sync{(@default_servers[Thread.current] ||= [])} << [default_server, read_only_server]
126
141
  end
127
142
 
128
143
  # Remove the current default server for the current thread, restoring the
@@ -141,8 +156,10 @@ module Sequel
141
156
  super
142
157
  else
143
158
  case server
144
- when :default, nil, :read_only
145
- a.last
159
+ when :default, nil
160
+ a[-1][0]
161
+ when :read_only
162
+ a[-1][1]
146
163
  else
147
164
  super
148
165
  end
@@ -106,7 +106,7 @@ module Sequel
106
106
  @raise_on_save_failure = true
107
107
  @raise_on_typecast_failure = false
108
108
  @require_modification = nil
109
- @require_valid_table = false
109
+ @require_valid_table = nil
110
110
  @restrict_primary_key = true
111
111
  @setter_methods = nil
112
112
  @simple_pk = nil
@@ -15,6 +15,7 @@ module Sequel
15
15
  @autoreloading_associations = {}
16
16
  @cache_associations = true
17
17
  @default_association_options = {}
18
+ @default_association_type_options = {}
18
19
  @dataset_module_class = DatasetModule
19
20
  end
20
21
  end
@@ -1526,9 +1527,15 @@ module Sequel
1526
1527
  # the previous class.
1527
1528
  attr_accessor :cache_associations
1528
1529
 
1529
- # The default options to use for all associations.
1530
+ # The default options to use for all associations. This hash is merged into the association reflection hash for
1531
+ # all association reflections.
1530
1532
  attr_accessor :default_association_options
1531
1533
 
1534
+ # The default options to use for all associations of a given type. This is a hash keyed by association type
1535
+ # symbol. If there is a value for the association type symbol key, the resulting hash will be merged into the
1536
+ # association reflection hash for all association reflections of that type.
1537
+ attr_accessor :default_association_type_options
1538
+
1532
1539
  # The default :eager_limit_strategy option to use for limited or offset associations (default: true, causing Sequel
1533
1540
  # to use what it considers the most appropriate strategy).
1534
1541
  attr_accessor :default_eager_limit_strategy
@@ -1768,7 +1775,14 @@ module Sequel
1768
1775
  orig_opts = cloned_assoc[:orig_opts].merge(orig_opts)
1769
1776
  end
1770
1777
 
1771
- opts = default_association_options.merge(orig_opts).merge(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
1778
+ opts = Hash[default_association_options]
1779
+ if type_options = default_association_type_options[type]
1780
+ opts.merge!(type_options)
1781
+ end
1782
+ opts.merge!(orig_opts)
1783
+ opts.merge!(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
1784
+
1785
+ opts
1772
1786
  opts[:block] = block if block
1773
1787
  if !opts.has_key?(:instance_specific) && (block || orig_opts[:block] || orig_opts[:dataset])
1774
1788
  # It's possible the association is instance specific, in that it depends on
@@ -1832,6 +1846,8 @@ module Sequel
1832
1846
  @association_reflections.freeze.each_value(&:freeze)
1833
1847
  @autoreloading_associations.freeze.each_value(&:freeze)
1834
1848
  @default_association_options.freeze
1849
+ @default_association_type_options.freeze
1850
+ @default_association_type_options.each_value(&:freeze)
1835
1851
 
1836
1852
  super
1837
1853
  end
@@ -1869,7 +1885,7 @@ module Sequel
1869
1885
  associate(:one_to_one, name, opts, &block)
1870
1886
  end
1871
1887
 
1872
- Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@default_association_options=>:dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
1888
+ Plugins.inherited_instance_variables(self, :@association_reflections=>:dup, :@autoreloading_associations=>:hash_dup, :@default_association_options=>:dup, :@default_association_type_options=>:hash_dup, :@cache_associations=>nil, :@default_eager_limit_strategy=>nil)
1873
1889
  Plugins.def_dataset_methods(self, [:eager, :eager_graph, :eager_graph_with_options, :association_join, :association_full_join, :association_inner_join, :association_left_join, :association_right_join])
1874
1890
 
1875
1891
  private
@@ -981,13 +981,20 @@ module Sequel
981
981
  private
982
982
 
983
983
  # Yield to the passed block and swallow all errors other than DatabaseConnectionErrors.
984
- def check_non_connection_error
984
+ def check_non_connection_error(do_raise=require_valid_table)
985
985
  begin
986
986
  db.transaction(:savepoint=>:only){yield}
987
987
  rescue Sequel::DatabaseConnectionError
988
988
  raise
989
989
  rescue Sequel::Error
990
- raise if require_valid_table
990
+ case do_raise
991
+ when nil
992
+ Sequel::Deprecation.deprecate("Setting a model class dataset to an invalid dataset", "Either use a valid dataset or set require_valid_table = false for the model class")
993
+ when false
994
+ # nothing
995
+ else
996
+ raise
997
+ end
991
998
  end
992
999
  end
993
1000
 
@@ -1097,7 +1104,7 @@ module Sequel
1097
1104
  schema_hash = {}
1098
1105
  ds_opts = dataset.opts
1099
1106
  get_columns = proc{check_non_connection_error{columns} || []}
1100
- schema_array = check_non_connection_error{db.schema(dataset, :reload=>reload)} if db.supports_schema_parsing?
1107
+ schema_array = check_non_connection_error(false){db.schema(dataset, :reload=>reload)} if db.supports_schema_parsing?
1101
1108
  if schema_array
1102
1109
  schema_array.each{|k,v| schema_hash[k] = v}
1103
1110
 
@@ -1,5 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
+ Sequel::Deprecation.deprecate("The association_autoreloading plugin", "This plugin was integrated into the default model behavior in Sequel 4.0, and no longer has an effect")
4
+
3
5
  module Sequel
4
6
  module Plugins
5
7
  # Empty plugin module for backwards compatibility
@@ -6,9 +6,9 @@ module Sequel
6
6
  # for destroying, deleting, or nullifying associated model objects. The following
7
7
  # association types support the following dependency actions:
8
8
  #
9
- # * :many_to_many - :nullify (removes all related entries in join table)
10
- # * :many_to_one - :delete, :destroy
11
- # * :one_to_many, one_to_one - :delete, :destroy, :nullify (sets foreign key to NULL for all associated objects)
9
+ # :many_to_many :: :nullify (removes all related entries in join table)
10
+ # :many_to_one :: :delete, :destroy
11
+ # :one_to_many, one_to_one :: :delete, :destroy, :nullify (sets foreign key to NULL for all associated objects)
12
12
  #
13
13
  # This plugin works directly with the association datasets and does not use any cached association values.
14
14
  # The :delete action will delete all associated objects from the database in a single SQL call.
@@ -49,7 +49,7 @@ module Sequel
49
49
  # Add attribute? methods for all of the boolean attributes for this model.
50
50
  def create_boolean_readers
51
51
  im = instance_methods.collect(&:to_s)
52
- if cs = check_non_connection_error{columns}
52
+ if cs = check_non_connection_error(false){columns}
53
53
  cs.each{|c| create_boolean_reader(c) if boolean_attribute?(c) && !im.include?("#{c}?")}
54
54
  end
55
55
  end
@@ -48,7 +48,7 @@ module Sequel
48
48
 
49
49
  # Add subset methods for all of the boolean columns in this model.
50
50
  def create_boolean_subsets
51
- if cs = check_non_connection_error{columns}
51
+ if cs = check_non_connection_error(false){columns}
52
52
  cs = cs.select{|c| db_schema[c][:type] == :boolean}.map{|c| boolean_subset_args(c)}
53
53
  dataset_module do
54
54
  cs.each{|c| where(*c)}
@@ -281,7 +281,7 @@ module Sequel
281
281
  columns = db.from(table).columns
282
282
  else
283
283
  table = subclass.implicit_table_name
284
- columns = check_non_connection_error{db.from(table).columns}
284
+ columns = check_non_connection_error(false){db.from(table).columns}
285
285
  table = nil if !columns || columns.empty?
286
286
  end
287
287
  end
@@ -295,8 +295,9 @@ module Sequel
295
295
  ds = ds.select(*self.columns.map{|cc| Sequel.qualify(cti_table_name, Sequel.identifier(cc))})
296
296
  end
297
297
  cols = columns - [pk]
298
- unless (cols & ds.columns).empty?
299
- Sequel::Deprecation.deprecate('Using class_table_inheritance with duplicate column names in subclass tables (other than the primary key column)', 'Make sure all tables used have unique column names, or implement support for handling duplicate column names in the class_table_inheritance plugin')
298
+ dup_cols = cols & ds.columns
299
+ unless dup_cols.empty?
300
+ Sequel::Deprecation.deprecate("Using class_table_inheritance with duplicate column names (#{n} => #{dup_cols}) in subclass tables (other than the primary key column)', 'Make sure all tables used have unique column names, or implement support for handling duplicate column names in the class_table_inheritance plugin")
300
301
  end
301
302
  sel_app = cols.map{|cc| Sequel.qualify(table, Sequel.identifier(cc))}
302
303
  @sti_dataset = ds = ds.join(table, pk=>pk).select_append(*sel_app)
@@ -43,13 +43,13 @@ module Sequel
43
43
  ds = super
44
44
  if !ds.opts[:select] && (from = ds.opts[:from]) && from.length == 1 && !ds.opts[:join]
45
45
  if db.supports_schema_parsing?
46
- cols = check_non_connection_error{db.schema(ds)}
46
+ cols = check_non_connection_error(false){db.schema(ds)}
47
47
  if cols
48
48
  cols = cols.map{|c, _| c}
49
49
  end
50
50
  end
51
51
 
52
- if cols ||= check_non_connection_error{ds.columns}
52
+ if cols ||= check_non_connection_error(false){ds.columns}
53
53
  ds = ds.select(*cols.map{|c| Sequel.qualify(ds.first_source, Sequel.identifier(c))})
54
54
  end
55
55
  end
@@ -36,6 +36,8 @@ module Sequel
36
36
 
37
37
  Plugins.after_set_dataset(self, :set_default_values)
38
38
 
39
+ Plugins.inherited_instance_variables(self, :@default_values=>:dup)
40
+
39
41
  # Freeze default values when freezing model class
40
42
  def freeze
41
43
  @default_values.freeze
@@ -48,7 +50,7 @@ module Sequel
48
50
  def set_default_values
49
51
  h = {}
50
52
  @db_schema.each{|k, v| h[k] = convert_default_value(v[:ruby_default]) unless v[:ruby_default].nil?} if @db_schema
51
- @default_values = h
53
+ @default_values = h.merge!(@default_values || {})
52
54
  end
53
55
 
54
56
  # Handle the CURRENT_DATE and CURRENT_TIMESTAMP values specially by returning an appropriate Date or
@@ -1,5 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
+ Sequel::Deprecation.deprecate("The many_to_one_pk_lookup plugin", "This plugin was integrated into the default model behavior in Sequel 4.0, and no longer has an effect")
4
+
3
5
  module Sequel
4
6
  module Plugins
5
7
  # Empty plugin module for backwards compatibility
@@ -70,7 +70,7 @@ module Sequel
70
70
  #
71
71
  # Then you can do:
72
72
  #
73
- # artist.update(params[:artist])
73
+ # artist.update_fields(params[:artist], [:name, :albums_artists])
74
74
  #
75
75
  # To save changes to the artist, create the first album and associate it to the artist,
76
76
  # and update the other existing associated album.
@@ -1,5 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
+ Sequel::Deprecation.deprecate("The pg_typecast_on_load plugin", "This plugin is only useful on the deprecated do and switch adapters")
4
+
3
5
  module Sequel
4
6
  module Plugins
5
7
  # The PgTypecastOnLoad plugin exists because when you connect to PostgreSQL
@@ -12,26 +12,6 @@ module Sequel
12
12
  # level (where level 1 is children, level 2 is children and grandchildren
13
13
  # etc.) in a single query.
14
14
  #
15
- # = Background
16
- #
17
- # There are two types of common models for storing tree structured data
18
- # in an SQL database, the adjacency list model and the nested set model.
19
- # Before recursive common table expressions (or similar capabilities such
20
- # as CONNECT BY for Oracle), the nested set model was the only easy way
21
- # to retrieve all ancestors and descendants in a single query. However,
22
- # it has significant performance corner cases.
23
- #
24
- # On PostgreSQL 8.4, with a significant number of rows, the nested set
25
- # model is almost 500 times slower than using a recursive common table
26
- # expression with the adjacency list model to get all descendants, and
27
- # almost 24,000 times slower to get all descendants to a given level.
28
- #
29
- # Considering that the nested set model requires more difficult management
30
- # than the adjacency list model, it's almost always better to use the
31
- # adjacency list model if your database supports common table expressions.
32
- # See http://explainextended.com/2009/09/24/adjacency-list-vs-nested-sets-postgresql/
33
- # for detailed analysis.
34
- #
35
15
  # = Usage
36
16
  #
37
17
  # The rcte_tree plugin adds four associations to the model: parent, children, ancestors, and
@@ -7,11 +7,11 @@ module Sequel
7
7
  # when you call an accessor.
8
8
  #
9
9
  # This plugin works by keeping the serialized value in the values, and
10
- # adding a @deserialized_values hash. The reader method for serialized columns
11
- # will check the @deserialized_values for the value, return it if present,
12
- # or deserialized the entry in @values and return it. The writer method will
13
- # set the @deserialized_values entry. This plugin adds a before_save hook
14
- # that serializes all @deserialized_values to @values.
10
+ # adding a deserialized_values hash. The reader method for serialized columns
11
+ # will check the deserialized_values for the value, return it if present,
12
+ # or deserialized the entry in values and return it. The writer method will
13
+ # set the deserialized_values entry. This plugin adds a before_save hook
14
+ # that serializes all deserialized_values to values.
15
15
  #
16
16
  # You can specify the serialization format as a pair of serializer/deserializer
17
17
  # callable objects. You can also specify the serialization format as a single
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Sequel
4
4
  module Plugins
5
- # The validation_helpers plugin contains instance method equivalents for most of the legacy
6
- # class-level validations. The names and APIs are different, though. Example:
5
+ # The validation_helpers plugin contains validate_* methods designed to be called inside Model#validate
6
+ # to perform validations:
7
7
  #
8
8
  # Sequel::Model.plugin :validation_helpers
9
9
  # class Album < Sequel::Model
@@ -5,7 +5,7 @@ module Sequel
5
5
  MAJOR = 4
6
6
  # The minor version of Sequel. Bumped for every non-patch level
7
7
  # release, generally around once a month.
8
- MINOR = 46
8
+ MINOR = 47
9
9
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
10
10
  # releases that fix regressions from previous versions.
11
11
  TINY = 0
@@ -168,6 +168,8 @@ describe "PostgreSQL views" do
168
168
  @db[:items_view].select_order_map(:number).must_equal [10, 20]
169
169
  @db.refresh_view(:items_view)
170
170
  @db[:items_view].select_order_map(:number).must_equal [10, 15, 20]
171
+ @db.views.wont_include :items_view
172
+ @db.views(@opts).must_include :items_view
171
173
  end if DB.server_version >= 90300
172
174
 
173
175
  it "should support refreshing materialized views concurrently" do
@@ -114,6 +114,7 @@ describe "Sequel::Plugins::ColumnSelect" do
114
114
  def @db.supports_schema_parsing?() true end
115
115
  def @db.schema_parse_table(t, *) [] end
116
116
  @db.extend_datasets{def columns; raise Sequel::DatabaseError; end}
117
+ @Album.require_valid_table = false
117
118
  @Album.plugin :column_select
118
119
  @Album.dataset.sql.must_equal 'SELECT * FROM albums'
119
120
  end
@@ -72,6 +72,7 @@ describe "Sequel::Plugins::DefaultsSetter" do
72
72
 
73
73
  it "should contain the default values in default_values" do
74
74
  @pr.call(2).default_values.must_equal(:a=>2)
75
+ @c.default_values.clear
75
76
  @pr.call(nil).default_values.must_equal({})
76
77
  end
77
78
 
@@ -93,6 +94,19 @@ describe "Sequel::Plugins::DefaultsSetter" do
93
94
  @c.new.a.must_be_nil
94
95
  end
95
96
 
97
+ it "should work in subclasses" do
98
+ @pr.call(2)
99
+ @c.default_values[:a] = proc{1}
100
+ c = Class.new(@c)
101
+
102
+ @c.new.a.must_equal 1
103
+ c.new.a.must_equal 1
104
+
105
+ c.default_values[:a] = proc{2}
106
+ @c.new.a.must_equal 1
107
+ c.new.a.must_equal 2
108
+ end
109
+
96
110
  it "should work correctly on a model without a dataset" do
97
111
  @pr.call(2)
98
112
  c = Class.new(Sequel::Model(@db[:bar]))
@@ -7,28 +7,30 @@ describe Sequel::Model, "PgTypecastOnLoad plugin" do
7
7
  [[:id, {}], [:b, {:type=>:boolean, :oid=>16}], [:y, {:type=>:integer, :oid=>20}]]
8
8
  end
9
9
  @c = Class.new(Sequel::Model(@db[:items]))
10
- @c.plugin :pg_typecast_on_load, :b, :y
10
+ deprecated do
11
+ @c.plugin :pg_typecast_on_load, :b, :y
12
+ end
11
13
  end
12
14
 
13
- it "should call the database conversion proc for all given columns" do
15
+ deprecated "should call the database conversion proc for all given columns" do
14
16
  @c.first.values.must_equal(:id=>1, :b=>true, :y=>0)
15
17
  end
16
18
 
17
- it "should call the database conversion proc with value when reloading the object, for all given columns" do
19
+ deprecated "should call the database conversion proc with value when reloading the object, for all given columns" do
18
20
  @c.first.refresh.values.must_equal(:id=>1, :b=>true, :y=>0)
19
21
  end
20
22
 
21
- it "should not fail if schema oid does not have a related conversion proc" do
23
+ deprecated "should not fail if schema oid does not have a related conversion proc" do
22
24
  @c.db_schema[:b][:oid] = 0
23
25
  @c.first.refresh.values.must_equal(:id=>1, :b=>"t", :y=>0)
24
26
  end
25
27
 
26
- it "should call the database conversion proc with value when automatically reloading the object on creation via insert_select" do
28
+ deprecated "should call the database conversion proc with value when automatically reloading the object on creation via insert_select" do
27
29
  @c.dataset = @c.dataset.with_extend{def insert_select(h) insert(h); first end}
28
30
  @c.create.values.must_equal(:id=>1, :b=>true, :y=>0)
29
31
  end
30
32
 
31
- it "should allowing setting columns separately via add_pg_typecast_on_load_columns" do
33
+ deprecated "should allowing setting columns separately via add_pg_typecast_on_load_columns" do
32
34
  @c = Class.new(Sequel::Model(@db[:items]))
33
35
  @c.plugin :pg_typecast_on_load
34
36
  @c.first.values.must_equal(:id=>1, :b=>"t", :y=>"0")
@@ -38,7 +40,7 @@ describe Sequel::Model, "PgTypecastOnLoad plugin" do
38
40
  @c.first.values.must_equal(:id=>1, :b=>true, :y=>0)
39
41
  end
40
42
 
41
- it "should work with subclasses" do
43
+ deprecated "should work with subclasses" do
42
44
  @c = Class.new(Sequel::Model(@db[:items]))
43
45
  @c.plugin :pg_typecast_on_load
44
46
  @c.first.values.must_equal(:id=>1, :b=>"t", :y=>"0")
@@ -57,11 +59,11 @@ describe Sequel::Model, "PgTypecastOnLoad plugin" do
57
59
  c1.first.values.must_equal(:id=>1, :b=>"t", :y=>0)
58
60
  end
59
61
 
60
- it "should not mark the object as modified" do
62
+ deprecated "should not mark the object as modified" do
61
63
  @c.first.modified?.must_equal false
62
64
  end
63
65
 
64
- it "should freeze pg_typecast_on_load_columns" do
66
+ deprecated "should freeze pg_typecast_on_load_columns" do
65
67
  @c.freeze
66
68
  @c.pg_typecast_on_load_columns.frozen?.must_equal true
67
69
  end
@@ -802,6 +802,22 @@ end
802
802
  END_MIG
803
803
  end
804
804
 
805
+ it "should convert oracle special types to ruby types" do
806
+ @d.meta_def(:database_type){:oracle}
807
+ types = ['number not null', 'date not null', 'varchar2(4 byte) not null']
808
+ @d.meta_def(:schema) do |t, *o|
809
+ i = 0
810
+ types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>false}]}
811
+ end
812
+ @d.dump_table_schema(:x).must_equal((<<END_MIG).chomp)
813
+ create_table(:x) do
814
+ BigDecimal :c1, :null=>false
815
+ Date :c2, :null=>false
816
+ String :c3, :null=>false
817
+ end
818
+ END_MIG
819
+ end
820
+
805
821
  it "should force specify :null option for MySQL timestamp columns when using :same_db" do
806
822
  @d.meta_def(:database_type){:mysql}
807
823
  @d.meta_def(:schema){|*s| [[:c1, {:db_type=>'timestamp', :primary_key=>true, :allow_null=>true}]]}
@@ -8,6 +8,13 @@ with_server_specs = shared_description do
8
8
  @db.sqls.must_equal ["SELECT * FROM t -- b"]
9
9
  end
10
10
 
11
+ it "should set the default server to use in the block" do
12
+ @db.with_server(:a, :b){@db[:t].all}
13
+ @db.sqls.must_equal ["SELECT * FROM t -- b"]
14
+ @db.with_server(:a, :b){@db[:t].insert}
15
+ @db.sqls.must_equal ["INSERT INTO t DEFAULT VALUES -- a"]
16
+ end
17
+
11
18
  it "should have no affect after the block" do
12
19
  @db.with_server(:a){@db[:t].all}
13
20
  @db.sqls.must_equal ["SELECT * FROM t -- a"]
@@ -49,7 +49,7 @@ describe "Sequel::Model basic support" do
49
49
  Item.all.must_equal [Item.load(:id=>1, :name=>'J')]
50
50
  end
51
51
 
52
- it "should not raise an error if the implied database table doesn't exist " do
52
+ deprecated "should not raise an error if the implied database table doesn't exist" do
53
53
  class ::Item::Thing < Sequel::Model(@db)
54
54
  set_dataset :items
55
55
  end
@@ -57,6 +57,26 @@ describe "Sequel::Model basic support" do
57
57
  Item::Thing.first.must_equal Item::Thing.load(:id=>1, :name=>'J')
58
58
  end
59
59
 
60
+ it "should raise an error if the implied database table doesn't exist if require_valid_table is true" do
61
+ proc do
62
+ c = Sequel::Model(@db)
63
+ c.require_valid_table = true
64
+ class ::Item::Thing < c
65
+ set_dataset :items
66
+ end
67
+ end.must_raise Sequel::Error
68
+ end
69
+
70
+ it "should not raise an error if the implied database table doesn't exist if require_valid_table is false" do
71
+ c = Sequel::Model(@db)
72
+ c.require_valid_table = false
73
+ class ::Item::Thing < c
74
+ set_dataset :items
75
+ end
76
+ Item.create(:name=>'J')
77
+ Item::Thing.first.must_equal Item::Thing.load(:id=>1, :name=>'J')
78
+ end
79
+
60
80
  it "should create accessors for all table columns even if all dataset columns aren't selected" do
61
81
  c = Class.new(Sequel::Model(@db[:items].select(:id)))
62
82
  o = c.new
@@ -219,14 +239,43 @@ describe "Sequel::Model basic support" do
219
239
  end
220
240
 
221
241
  describe "Sequel::Model with no existing table" do
222
- it "should not raise an error when setting the dataset" do
242
+ deprecated "should not raise an error when setting the dataset" do
223
243
  db = DB
224
244
  db.drop_table?(:items)
225
- class ::Item < Sequel::Model(db); end; Object.send(:remove_const, :Item)
226
- c = Class.new(Sequel::Model); c.set_dataset(db[:items])
245
+ c = Class.new(Sequel::Model)
246
+ c.set_dataset(db[:items])
227
247
  db.transaction do
228
248
  c = Class.new(Sequel::Model(db[:items]))
229
249
  db.get(Sequel.cast(1, Integer)).must_equal 1
230
250
  end
231
251
  end
252
+
253
+ it "should not raise an error when setting the dataset when require_valid_table is true" do
254
+ db = DB
255
+ db.drop_table?(:items)
256
+ c1 = Sequel::Model(db);
257
+ c = Class.new(Sequel::Model)
258
+ c.require_valid_table = true
259
+ proc{c.set_dataset(db[:items])}.must_raise Sequel::Error
260
+ db.transaction do
261
+ c = Class.new(Sequel::Model)
262
+ c.require_valid_table = true
263
+ proc{c.dataset = db[:items]}.must_raise Sequel::Error
264
+ db.get(Sequel.cast(1, Integer)).must_equal 1
265
+ end
266
+ end
267
+
268
+ it "should not raise an error when setting the dataset when require_valid_table is false" do
269
+ db = DB
270
+ db.drop_table?(:items)
271
+ c = Class.new(Sequel::Model)
272
+ c.require_valid_table = false
273
+ c.set_dataset(db[:items])
274
+ db.transaction do
275
+ c = Class.new(Sequel::Model)
276
+ c.require_valid_table = false
277
+ c.dataset = db[:items]
278
+ db.get(Sequel.cast(1, Integer)).must_equal 1
279
+ end
280
+ end
232
281
  end
@@ -1937,7 +1937,6 @@ describe "Caching plugins" do
1937
1937
  end
1938
1938
  before do
1939
1939
  @Album = Class.new(Sequel::Model(@db[:albums]))
1940
- @Album.plugin :many_to_one_pk_lookup
1941
1940
  end
1942
1941
  after(:all) do
1943
1942
  @db.drop_table?(:albums, :artists)
@@ -586,6 +586,48 @@ describe Sequel::Model::Associations::AssociationReflection, "with default assoc
586
586
  r[:foo].must_equal 3
587
587
  r[:bar].must_equal 2
588
588
  end
589
+
590
+ it "should have default_association_type_options take precedence over default_association_options" do
591
+ @c.default_association_options = {:foo=>2, :bar=>3}
592
+ @c.default_association_type_options[:many_to_one] = {:foo=>1, :bar=>2}
593
+ @c.many_to_one :c, :class=>@c, :foo=>3
594
+ r = @c.association_reflection(:c)
595
+ r[:foo].must_equal 3
596
+ r[:bar].must_equal 2
597
+ end
598
+
599
+ it "should use default_association_type_options as defaults" do
600
+ @c.default_association_type_options[:many_to_one] = {:foo=>1, :bar=>2}
601
+ @c.many_to_one :c, :class=>@c, :foo=>3
602
+ r = @c.association_reflection(:c)
603
+ r[:foo].must_equal 3
604
+ r[:bar].must_equal 2
605
+
606
+ @c.one_to_many :cs, :class=>@c, :foo=>3
607
+ r = @c.association_reflection(:cs)
608
+ r[:foo].must_equal 3
609
+ r[:bar].must_be_nil
610
+ end
611
+
612
+ it "should inherit default_association_type_options" do
613
+ @c.default_association_type_options[:many_to_one] = {:foo=>1, :bar=>2}
614
+ c = Class.new(@c)
615
+ c.many_to_one :c, :class=>c, :foo=>3
616
+ r = c.association_reflection(:c)
617
+ r[:foo].must_equal 3
618
+ r[:bar].must_equal 2
619
+
620
+ @c.default_association_type_options[:many_to_one][:bar] = 4
621
+ c.many_to_one :d, :class=>c, :foo=>3
622
+ r = c.association_reflection(:d)
623
+ r[:foo].must_equal 3
624
+ r[:bar].must_equal 2
625
+
626
+ c.one_to_many :ds, :class=>c, :foo=>3
627
+ r = c.association_reflection(:ds)
628
+ r[:foo].must_equal 3
629
+ r[:bar].must_be_nil
630
+ end
589
631
  end
590
632
 
591
633
  describe "Sequel::Model.freeze" do
@@ -1114,7 +1114,43 @@ describe "Model.db_schema" do
1114
1114
  @c.db_schema.must_equal(:x=>{:type=>:integer}, :z=>{}, :y=>{:type=>:string})
1115
1115
  end
1116
1116
 
1117
- it "should fallback to fetching records if schema raises an error" do
1117
+ deprecated "should not raise error if setting dataset where getting schema and columns raises an error" do
1118
+ def @db.schema(table, opts={})
1119
+ raise Sequel::Error
1120
+ end
1121
+ @c.dataset = @dataset.join(:x, :id).from_self.columns(:id, :x)
1122
+ @c.db_schema.must_equal(:x=>{}, :id=>{})
1123
+ end
1124
+
1125
+ it "should not raise error if setting dataset where getting schema and columns raises an error and require_valid_table is false" do
1126
+ @c.require_valid_table = false
1127
+ def @db.schema(table, opts={})
1128
+ raise Sequel::Error
1129
+ end
1130
+ @c.dataset = @dataset.join(:x, :id).from_self.columns(:id, :x)
1131
+ @c.db_schema.must_equal(:x=>{}, :id=>{})
1132
+ end
1133
+
1134
+ it "should raise error if setting dataset where getting schema and columns raises an error and require_valid_table is true" do
1135
+ @c.require_valid_table = true
1136
+ def @db.schema(table, opts={})
1137
+ raise Sequel::Error
1138
+ end
1139
+ @c.dataset = @dataset.join(:x, :id).from_self.columns(:id, :x)
1140
+ @c.db_schema.must_equal(:x=>{}, :id=>{})
1141
+ end
1142
+
1143
+ it "should use dataset columns if getting schema raises an error and require_valid_table is false" do
1144
+ @c.require_valid_table = false
1145
+ def @db.schema(table, opts={})
1146
+ raise Sequel::Error
1147
+ end
1148
+ @c.dataset = @dataset.join(:x, :id).from_self.columns(:id, :x)
1149
+ @c.db_schema.must_equal(:x=>{}, :id=>{})
1150
+ end
1151
+
1152
+ it "should use dataset columns if getting schema raises an error and require_valid_table is true" do
1153
+ @c.require_valid_table = true
1118
1154
  def @db.schema(table, opts={})
1119
1155
  raise Sequel::Error
1120
1156
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.46.0
4
+ version: 4.47.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-01 00:00:00.000000000 Z
11
+ date: 2017-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -248,6 +248,7 @@ extra_rdoc_files:
248
248
  - doc/release_notes/4.44.0.txt
249
249
  - doc/release_notes/4.45.0.txt
250
250
  - doc/release_notes/4.46.0.txt
251
+ - doc/release_notes/4.47.0.txt
251
252
  files:
252
253
  - CHANGELOG
253
254
  - MIT-LICENSE
@@ -385,6 +386,7 @@ files:
385
386
  - doc/release_notes/4.44.0.txt
386
387
  - doc/release_notes/4.45.0.txt
387
388
  - doc/release_notes/4.46.0.txt
389
+ - doc/release_notes/4.47.0.txt
388
390
  - doc/release_notes/4.5.0.txt
389
391
  - doc/release_notes/4.6.0.txt
390
392
  - doc/release_notes/4.7.0.txt