sequel 4.44.0 → 4.45.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +110 -0
  3. data/README.rdoc +8 -9
  4. data/doc/active_record.rdoc +2 -3
  5. data/doc/model_plugins.rdoc +1 -1
  6. data/doc/opening_databases.rdoc +0 -46
  7. data/doc/release_notes/4.45.0.txt +370 -0
  8. data/lib/sequel/adapters/cubrid.rb +2 -0
  9. data/lib/sequel/adapters/do.rb +2 -0
  10. data/lib/sequel/adapters/jdbc/as400.rb +2 -0
  11. data/lib/sequel/adapters/jdbc/cubrid.rb +2 -0
  12. data/lib/sequel/adapters/jdbc/firebirdsql.rb +2 -0
  13. data/lib/sequel/adapters/jdbc/informix-sqli.rb +2 -0
  14. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +2 -0
  15. data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
  16. data/lib/sequel/adapters/jdbc/postgresql.rb +5 -0
  17. data/lib/sequel/adapters/mysql.rb +1 -0
  18. data/lib/sequel/adapters/mysql2.rb +1 -0
  19. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  20. data/lib/sequel/adapters/odbc/progress.rb +2 -0
  21. data/lib/sequel/adapters/postgres.rb +0 -2
  22. data/lib/sequel/adapters/shared/cubrid.rb +2 -0
  23. data/lib/sequel/adapters/shared/firebird.rb +2 -0
  24. data/lib/sequel/adapters/shared/informix.rb +2 -0
  25. data/lib/sequel/adapters/shared/mssql.rb +47 -7
  26. data/lib/sequel/adapters/shared/mysql.rb +16 -1
  27. data/lib/sequel/adapters/shared/postgres.rb +9 -1
  28. data/lib/sequel/adapters/shared/progress.rb +2 -0
  29. data/lib/sequel/adapters/shared/sqlanywhere.rb +1 -1
  30. data/lib/sequel/adapters/swift.rb +2 -0
  31. data/lib/sequel/ast_transformer.rb +13 -6
  32. data/lib/sequel/core.rb +13 -16
  33. data/lib/sequel/database/connecting.rb +25 -10
  34. data/lib/sequel/database/dataset.rb +6 -1
  35. data/lib/sequel/database/dataset_defaults.rb +9 -2
  36. data/lib/sequel/database/misc.rb +10 -3
  37. data/lib/sequel/database/schema_methods.rb +4 -0
  38. data/lib/sequel/dataset/mutation.rb +8 -20
  39. data/lib/sequel/dataset/prepared_statements.rb +2 -0
  40. data/lib/sequel/dataset/query.rb +32 -7
  41. data/lib/sequel/dataset/sql.rb +13 -3
  42. data/lib/sequel/deprecated.rb +9 -1
  43. data/lib/sequel/exceptions.rb +37 -8
  44. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +117 -0
  45. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  46. data/lib/sequel/extensions/identifier_mangling.rb +3 -2
  47. data/lib/sequel/extensions/pg_hstore.rb +1 -5
  48. data/lib/sequel/extensions/schema_dumper.rb +3 -1
  49. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +2 -2
  50. data/lib/sequel/extensions/string_agg.rb +1 -0
  51. data/lib/sequel/model.rb +23 -10
  52. data/lib/sequel/model/associations.rb +17 -5
  53. data/lib/sequel/model/base.rb +115 -62
  54. data/lib/sequel/model/dataset_module.rb +10 -3
  55. data/lib/sequel/model/exceptions.rb +7 -5
  56. data/lib/sequel/plugins/association_pks.rb +13 -1
  57. data/lib/sequel/plugins/association_proxies.rb +8 -1
  58. data/lib/sequel/plugins/before_after_save.rb +1 -0
  59. data/lib/sequel/plugins/class_table_inheritance.rb +7 -3
  60. data/lib/sequel/plugins/columns_updated.rb +42 -0
  61. data/lib/sequel/plugins/composition.rb +10 -5
  62. data/lib/sequel/plugins/error_splitter.rb +1 -1
  63. data/lib/sequel/plugins/hook_class_methods.rb +39 -5
  64. data/lib/sequel/plugins/instance_hooks.rb +58 -5
  65. data/lib/sequel/plugins/lazy_attributes.rb +10 -5
  66. data/lib/sequel/plugins/nested_attributes.rb +10 -5
  67. data/lib/sequel/plugins/prepared_statements.rb +7 -0
  68. data/lib/sequel/plugins/prepared_statements_associations.rb +2 -0
  69. data/lib/sequel/plugins/prepared_statements_with_pk.rb +2 -0
  70. data/lib/sequel/plugins/schema.rb +2 -0
  71. data/lib/sequel/plugins/scissors.rb +2 -0
  72. data/lib/sequel/plugins/serialization.rb +10 -5
  73. data/lib/sequel/plugins/split_values.rb +5 -1
  74. data/lib/sequel/plugins/static_cache.rb +2 -2
  75. data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
  76. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  77. data/lib/sequel/plugins/validation_helpers.rb +1 -0
  78. data/lib/sequel/sql.rb +1 -1
  79. data/lib/sequel/version.rb +1 -1
  80. data/spec/adapters/mssql_spec.rb +31 -0
  81. data/spec/adapters/mysql_spec.rb +20 -2
  82. data/spec/adapters/postgres_spec.rb +43 -12
  83. data/spec/adapters/spec_helper.rb +5 -8
  84. data/spec/core/database_spec.rb +47 -12
  85. data/spec/core/dataset_mutation_spec.rb +22 -22
  86. data/spec/core/dataset_spec.rb +88 -20
  87. data/spec/core/deprecated_spec.rb +1 -1
  88. data/spec/core/expression_filters_spec.rb +1 -1
  89. data/spec/core/mock_adapter_spec.rb +0 -3
  90. data/spec/core/placeholder_literalizer_spec.rb +1 -1
  91. data/spec/core/schema_spec.rb +8 -1
  92. data/spec/core/spec_helper.rb +6 -1
  93. data/spec/core_extensions_spec.rb +4 -0
  94. data/spec/deprecation_helper.rb +17 -0
  95. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +314 -0
  96. data/spec/extensions/association_pks_spec.rb +61 -13
  97. data/spec/extensions/association_proxies_spec.rb +3 -3
  98. data/spec/extensions/class_table_inheritance_spec.rb +39 -0
  99. data/spec/extensions/columns_updated_spec.rb +35 -0
  100. data/spec/extensions/composition_spec.rb +6 -1
  101. data/spec/extensions/hook_class_methods_spec.rb +114 -26
  102. data/spec/extensions/identifier_mangling_spec.rb +107 -73
  103. data/spec/extensions/instance_hooks_spec.rb +78 -14
  104. data/spec/extensions/lazy_attributes_spec.rb +8 -2
  105. data/spec/extensions/many_through_many_spec.rb +2 -2
  106. data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
  107. data/spec/extensions/nested_attributes_spec.rb +8 -2
  108. data/spec/extensions/pg_array_spec.rb +18 -4
  109. data/spec/extensions/prepared_statements_associations_spec.rb +48 -39
  110. data/spec/extensions/prepared_statements_with_pk_spec.rb +13 -11
  111. data/spec/extensions/query_spec.rb +1 -1
  112. data/spec/extensions/schema_dumper_spec.rb +34 -6
  113. data/spec/extensions/schema_spec.rb +13 -7
  114. data/spec/extensions/scissors_spec.rb +3 -1
  115. data/spec/extensions/sequel_3_dataset_methods_spec.rb +4 -4
  116. data/spec/extensions/serialization_spec.rb +7 -1
  117. data/spec/extensions/set_overrides_spec.rb +2 -2
  118. data/spec/extensions/shared_caching_spec.rb +19 -15
  119. data/spec/extensions/spec_helper.rb +7 -3
  120. data/spec/extensions/split_values_spec.rb +45 -10
  121. data/spec/extensions/string_agg_spec.rb +2 -2
  122. data/spec/extensions/subset_conditions_spec.rb +3 -3
  123. data/spec/extensions/tactical_eager_loading_spec.rb +1 -1
  124. data/spec/extensions/validation_contexts_spec.rb +31 -0
  125. data/spec/guards_helper.rb +2 -0
  126. data/spec/integration/associations_test.rb +22 -20
  127. data/spec/integration/dataset_test.rb +25 -2
  128. data/spec/integration/model_test.rb +1 -1
  129. data/spec/integration/plugin_test.rb +11 -16
  130. data/spec/integration/prepared_statement_test.rb +40 -32
  131. data/spec/integration/spec_helper.rb +5 -8
  132. data/spec/model/association_reflection_spec.rb +4 -0
  133. data/spec/model/associations_spec.rb +37 -10
  134. data/spec/model/base_spec.rb +6 -0
  135. data/spec/model/hooks_spec.rb +56 -35
  136. data/spec/model/model_spec.rb +21 -5
  137. data/spec/model/record_spec.rb +14 -11
  138. data/spec/model/spec_helper.rb +7 -1
  139. data/spec/sequel_warning.rb +11 -0
  140. metadata +13 -3
@@ -9,12 +9,16 @@ module Sequel
9
9
 
10
10
  # Array of supported database adapters
11
11
  ADAPTERS = %w'ado amalgalite cubrid do ibmdb jdbc mock mysql mysql2 odbc oracle postgres sqlanywhere sqlite swift tinytds'.collect(&:to_sym)
12
+ # SEQUEL5: Remove cubrid do swift
12
13
 
13
- @single_threaded = false
14
+ def self.single_threaded
15
+ Sequel::Deprecation.deprecate("Sequel::Database.single_threaded", "Use Sequel.single_threaded instead")
16
+ Sequel.single_threaded
17
+ end
14
18
 
15
- class << self
16
- # Whether to use the single threaded connection pool by default
17
- attr_accessor :single_threaded
19
+ def self.single_threaded=(v)
20
+ Sequel::Deprecation.deprecate("Sequel::Database.single_threaded=", "Use Sequel.single_threaded= instead")
21
+ Sequel.single_threaded = v
18
22
  end
19
23
 
20
24
  # The Database subclass for the given adapter scheme.
@@ -37,6 +41,7 @@ module Sequel
37
41
  def self.connect(conn_string, opts = OPTS)
38
42
  case conn_string
39
43
  when String
44
+ # SEQUEL5: Remove do
40
45
  if match = /\A(jdbc|do):/o.match(conn_string)
41
46
  c = adapter_class(match[1].to_sym)
42
47
  opts = opts.merge(:orig_opts=>opts.dup)
@@ -65,6 +70,7 @@ module Sequel
65
70
  end
66
71
  begin
67
72
  db = c.new(opts)
73
+ # SEQUEL5: Default opts[:test] to true
68
74
  db.test_connection if opts[:test] && db.send(:typecast_value_boolean, opts[:test])
69
75
  if block_given?
70
76
  return yield(db)
@@ -183,10 +189,14 @@ module Sequel
183
189
  #
184
190
  # DB.add_servers(:f=>{:host=>"hash_host_f"})
185
191
  def add_servers(servers)
186
- if h = @opts[:servers]
187
- Sequel.synchronize{h.merge!(servers)}
188
- @pool.add_servers(servers.keys)
192
+ unless h = @opts[:servers]
193
+ Sequel::Deprecation.deprecate("Calling Database#add_servers on a database that does not use sharding", "This method should only be called if the database supports sharding.")
194
+ # raise Error, "cannot call Database#add_servers on a Database instance that does not use a sharded connection pool" # SEQUEL5
195
+ return
189
196
  end
197
+
198
+ Sequel.synchronize{h.merge!(servers)}
199
+ @pool.add_servers(servers.keys)
190
200
  end
191
201
 
192
202
  # The database type for this database object, the same as the adapter scheme
@@ -229,6 +239,7 @@ module Sequel
229
239
  #
230
240
  # DB.each_server{|db| db.create_table(:users){primary_key :id; String :name}}
231
241
  def each_server(&block)
242
+ Sequel::Deprecation.deprecate("Database#each_server", "Switching to using Dataset#servers and Database#with_server from the server_block extension: \"DB.servers.each{|s| DB.with_server(s){}}\"")
232
243
  raise(Error, "Database#each_server must be passed a block") unless block
233
244
  servers.each{|s| self.class.connect(server_opts(s), &block)}
234
245
  end
@@ -244,10 +255,14 @@ module Sequel
244
255
  #
245
256
  # DB.remove_servers(:f1, :f2)
246
257
  def remove_servers(*servers)
247
- if h = @opts[:servers]
248
- servers.flatten.each{|s| Sequel.synchronize{h.delete(s)}}
249
- @pool.remove_servers(servers)
258
+ unless h = @opts[:servers]
259
+ Sequel::Deprecation.deprecate("Calling Database#add_servers on a database that does not use sharding", "This method should only be called if the database supports sharding.")
260
+ # raise Error, "cannot call Database#remove_servers on a Database instance that does not use a sharded connection pool" # SEQUEL5
261
+ return
250
262
  end
263
+
264
+ servers.flatten.each{|s| Sequel.synchronize{h.delete(s)}}
265
+ @pool.remove_servers(servers)
251
266
  end
252
267
 
253
268
  # An array of servers/shards for this Database object.
@@ -59,7 +59,12 @@ module Sequel
59
59
  # DB.from(:items){id > 2} # SELECT * FROM items WHERE (id > 2)
60
60
  def from(*args, &block)
61
61
  ds = @default_dataset.from(*args)
62
- block ? ds.where(&block) : ds
62
+ if block
63
+ Sequel::Deprecation.deprecate("Sequel::Database#from with a block", "Use .from(*args).where(&block) instead")
64
+ ds.where(&block)
65
+ else
66
+ ds
67
+ end
63
68
  end
64
69
 
65
70
  # Returns a new dataset with the select method invoked.
@@ -10,10 +10,10 @@ module Sequel
10
10
  # The default class to use for datasets
11
11
  DatasetClass = Sequel::Dataset
12
12
 
13
+ # SEQUEL5: Remove
13
14
  @identifier_input_method = nil
14
15
  @identifier_output_method = nil
15
16
  @quote_identifiers = nil
16
-
17
17
  class << self
18
18
  # The identifier input method to use by default for all databases (default: adapter default)
19
19
  attr_reader :identifier_input_method
@@ -22,19 +22,26 @@ module Sequel
22
22
  attr_reader :identifier_output_method
23
23
 
24
24
  # Whether to quote identifiers (columns and tables) by default for all databases (default: adapter default)
25
- attr_accessor :quote_identifiers
25
+ attr_reader :quote_identifiers
26
26
  end
27
27
 
28
28
  # Change the default identifier input method to use for all databases,
29
29
  def self.identifier_input_method=(v)
30
+ Sequel::Deprecation.deprecate("Sequel.identifier_input_method= and Sequel::Database.identifier_input_method=", "Call Sequel::Database#identifier_input_method= instead")
30
31
  @identifier_input_method = v.nil? ? false : v
31
32
  end
32
33
 
33
34
  # Change the default identifier output method to use for all databases,
34
35
  def self.identifier_output_method=(v)
36
+ Sequel::Deprecation.deprecate("Sequel.identifier_output_method= and Sequel::Database.identifier_output_method=", "Call Sequel::Database#identifier_output_method= instead")
35
37
  @identifier_output_method = v.nil? ? false : v
36
38
  end
37
39
 
40
+ def self.quote_identifiers=(v)
41
+ Sequel::Deprecation.deprecate("Sequel.quote_identifiers= and Sequel::Database.quote_identifiers=", "Call Sequel::Database#quote_identifiers= instead")
42
+ @quote_identifiers = v
43
+ end
44
+
38
45
  # The class to use for creating datasets. Should respond to
39
46
  # new with the Database argument as the first argument, and
40
47
  # an optional options hash.
@@ -29,13 +29,14 @@ module Sequel
29
29
  # Module to be included in shared adapters so that when the DatabaseMethods are
30
30
  # included in the database, the identifier mangling defaults are reset correctly.
31
31
  module ResetIdentifierMangling
32
- def extended(obj)
32
+ def self.extended(obj)
33
33
  # :nocov:
34
34
  Sequel::Deprecation.deprecate("Sequel::Database::ResetIdentifierMangling is no longer needed and will be removed in Sequel 5. Please update your adapter.")
35
35
  obj.send(:reset_identifier_mangling) if obj.respond_to?(:reset_identifier_mangling)
36
36
  # :nocov:
37
37
  end
38
38
  end
39
+ Sequel::Deprecation.deprecate_constant(self, :ResetIdentifierMangling)
39
40
 
40
41
  # Nested hook Proc; each new hook Proc just wraps the previous one.
41
42
  @initialize_hook = Proc.new {|db| }
@@ -125,7 +126,7 @@ module Sequel
125
126
  @opts[:servers] = {} if @opts[:servers].is_a?(String)
126
127
  @sharded = !!@opts[:servers]
127
128
  @opts[:adapter_class] = self.class
128
- @opts[:single_threaded] = @single_threaded = typecast_value_boolean(@opts.fetch(:single_threaded, Database.single_threaded))
129
+ @opts[:single_threaded] = @single_threaded = typecast_value_boolean(@opts.fetch(:single_threaded, Sequel.single_threaded))
129
130
  @default_string_column_size = @opts[:default_string_column_size] || DEFAULT_STRING_COLUMN_SIZE
130
131
 
131
132
  @schemas = {}
@@ -150,7 +151,7 @@ module Sequel
150
151
  reset_default_dataset
151
152
  adapter_initialize
152
153
  if typecast_value_boolean(@opts.fetch(:identifier_mangling, true))
153
- extension(:identifier_mangling)
154
+ extension(:_deprecated_identifier_mangling)
154
155
  end
155
156
 
156
157
  unless typecast_value_boolean(@opts[:keep_reference]) == false
@@ -180,6 +181,12 @@ module Sequel
180
181
  super
181
182
  end
182
183
 
184
+ def initialize_copy(_)
185
+ Sequel::Deprecation.deprecate("Database#dup and #clone", "Use Sequel.connect to create a new Database instance")
186
+ # raise(Error, "cannot dup/clone a Sequel::Database instance") # SEQUEL5
187
+ super
188
+ end
189
+
183
190
  # Cast the given type to a literal type
184
191
  #
185
192
  # DB.cast_type_literal(Float) # double precision
@@ -808,6 +808,10 @@ module Sequel
808
808
 
809
809
  # Proxy the filter_expr call to the dataset, used for creating constraints.
810
810
  def filter_expr(*args, &block)
811
+ if args.length == 1 && args.first.is_a?(Proc) && !block
812
+ block = args.first
813
+ args = nil
814
+ end
811
815
  schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, *args, &block))
812
816
  end
813
817
 
@@ -30,67 +30,55 @@ module Sequel
30
30
 
31
31
  # Like #extension, but modifies and returns the receiver instead of returning a modified clone.
32
32
  def extension!(*exts)
33
- raise_if_frozen!
33
+ raise_if_frozen!("extension!")
34
34
  _extension!(exts)
35
35
  end
36
36
 
37
37
  # Avoid self-referential dataset by cloning.
38
38
  def from_self!(*args, &block)
39
- raise_if_frozen!
39
+ raise_if_frozen!("from_self!")
40
40
  @opts = clone.from_self(*args, &block).opts
41
41
  self
42
42
  end
43
43
 
44
44
  # Remove the row_proc from the current dataset.
45
45
  def naked!
46
- raise_if_frozen!
46
+ raise_if_frozen!("naked=")
47
47
  @opts[:row_proc] = nil
48
48
  self
49
49
  end
50
50
 
51
51
  # Set whether to quote identifiers for this dataset
52
52
  def quote_identifiers=(v)
53
- raise_if_frozen!
53
+ raise_if_frozen!("quote_identifiers=")
54
54
  skip_symbol_cache!
55
55
  @opts[:quote_identifiers] = v
56
56
  end
57
57
 
58
58
  # Override the row_proc for this dataset
59
59
  def row_proc=(v)
60
- raise_if_frozen!
60
+ raise_if_frozen!("row_proc=")
61
61
  @opts[:row_proc] = v
62
62
  end
63
63
 
64
64
  private
65
65
 
66
- # Load the extensions into the receiver, without checking if the receiver is frozen.
67
- def _extension!(exts)
68
- Sequel.extension(*exts)
69
- exts.each do |ext|
70
- if pr = Sequel.synchronize{EXTENSIONS[ext]}
71
- pr.call(self)
72
- else
73
- raise(Error, "Extension #{ext} does not have specific support handling individual datasets (try: Sequel.extension #{ext.inspect})")
74
- end
75
- end
76
- self
77
- end
78
-
79
66
  # Modify the receiver with the results of sending the meth, args, and block
80
67
  # to the receiver and merging the options of the resulting dataset into
81
68
  # the receiver's options.
82
69
  def mutation_method(meth, *args, &block)
83
- raise_if_frozen!
70
+ raise_if_frozen!("#{meth}!")
84
71
  @opts = send(meth, *args, &block).opts
85
72
  @cache = {}
86
73
  self
87
74
  end
88
75
 
89
76
  # Raise a RuntimeError if the receiver is frozen
90
- def raise_if_frozen!
77
+ def raise_if_frozen!(meth = nil)
91
78
  if frozen?
92
79
  raise RuntimeError, "can't modify frozen #{visible_class_name}"
93
80
  end
81
+ Sequel::Deprecation.deprecate("Dataset mutation is deprecated and will be removed in Sequel 5#{" (method called: #{meth})" if meth}")
94
82
  end
95
83
 
96
84
  # Set the dataset to skip the symbol cache
@@ -217,6 +217,7 @@ module Sequel
217
217
  send(*prepared_type, &block)
218
218
  end
219
219
  else
220
+ Sequel::Deprecation.deprecate("Using an unsupported prepared statement type (#{prepared_type.inspect})", 'Switch to using :select as the prepared statement type')
220
221
  all(&block)
221
222
  end
222
223
  end
@@ -338,6 +339,7 @@ module Sequel
338
339
  db.set_prepared_statement(name, ps)
339
340
  else
340
341
  # :nocov:
342
+ # SEQUEL5: Add coverage
341
343
  Sequel::Deprecation.deprecate("Dataset#prepare will change to requiring a name argument in Sequel 5, please update your code.") unless name
342
344
  # :nocov:
343
345
  end
@@ -581,8 +581,8 @@ module Sequel
581
581
  when false
582
582
  nil # Do no qualification
583
583
  when :deep
584
- k = Sequel::Qualifier.new(self, table_name).transform(k)
585
- v = Sequel::Qualifier.new(self, last_alias).transform(v)
584
+ k = Sequel::Qualifier.new(table_name).transform(k)
585
+ v = Sequel::Qualifier.new(last_alias).transform(v)
586
586
  else
587
587
  k = qualified_column_name(k, table_name) if k.is_a?(Symbol)
588
588
  v = qualified_column_name(v, last_alias) if v.is_a?(Symbol)
@@ -897,6 +897,13 @@ module Sequel
897
897
  end
898
898
  end
899
899
 
900
+ # Specify that the check for limits/offsets when updating/deleting be skipped for the dataset.
901
+ def skip_limit_check
902
+ cached_dataset(:_skip_limit_check_ds) do
903
+ clone(:skip_limit_check=>true)
904
+ end
905
+ end
906
+
900
907
  # Skip locked rows when returning results from this dataset.
901
908
  def skip_locked
902
909
  cached_dataset(:_skip_locked_ds) do
@@ -916,6 +923,7 @@ module Sequel
916
923
  # bv # {:a => 1}
917
924
  # ds.call(:select, bv)
918
925
  def unbind
926
+ Sequel::Deprecation.deprecate("Dataset#unbind", "Switch to using placeholders manually instead of unbinding them")
919
927
  u = Unbinder.new
920
928
  ds = clone(:where=>u.transform(opts[:where]), :join=>u.transform(opts[:join]))
921
929
  [ds, u.binds]
@@ -1186,6 +1194,19 @@ module Sequel
1186
1194
 
1187
1195
  private
1188
1196
 
1197
+ # Load the extensions into the receiver, without checking if the receiver is frozen.
1198
+ def _extension!(exts)
1199
+ Sequel.extension(*exts)
1200
+ exts.each do |ext|
1201
+ if pr = Sequel.synchronize{EXTENSIONS[ext]}
1202
+ pr.call(self)
1203
+ else
1204
+ raise(Error, "Extension #{ext} does not have specific support handling individual datasets (try: Sequel.extension #{ext.inspect})")
1205
+ end
1206
+ end
1207
+ self
1208
+ end
1209
+
1189
1210
  # Internal filtering method so it works on either the WHERE or HAVING clauses, with or
1190
1211
  # without inversion.
1191
1212
  def _filter_or_exclude(invert, clause, *cond, &block)
@@ -1214,10 +1235,12 @@ module Sequel
1214
1235
  def filter_expr(expr = nil, &block)
1215
1236
  expr = nil if expr == []
1216
1237
 
1217
- if expr && block
1218
- return SQL::BooleanExpression.new(:AND, filter_expr(expr), filter_expr(block))
1219
- elsif block
1220
- expr = block
1238
+ if block
1239
+ if expr
1240
+ return SQL::BooleanExpression.new(:AND, filter_expr(expr), filter_expr(Sequel.virtual_row(&block)))
1241
+ else
1242
+ return filter_expr(Sequel.virtual_row(&block))
1243
+ end
1221
1244
  end
1222
1245
 
1223
1246
  case expr
@@ -1229,11 +1252,13 @@ module Sequel
1229
1252
  elsif Sequel.condition_specifier?(expr)
1230
1253
  SQL::BooleanExpression.from_value_pairs(expr)
1231
1254
  else
1255
+ Sequel::Deprecation.deprecate("Passing multiple arguments as filter arguments when not using a conditions specifier (#{expr.inspect})", "Pass the arguments to separate filter methods or use Sequel.& to combine them")
1232
1256
  SQL::BooleanExpression.new(:AND, *expr.map{|x| filter_expr(x)})
1233
1257
  end
1234
1258
  when Proc
1259
+ Sequel::Deprecation.deprecate("Passing Proc objects as filter arguments", "Pass them as blocks to the filtering methods or to Sequel.expr")
1235
1260
  filter_expr(Sequel.virtual_row(&expr))
1236
- when Numeric, SQL::NumericExpression, SQL::StringExpression
1261
+ when Numeric, SQL::NumericExpression, SQL::StringExpression #, Proc # SEQUEL5
1237
1262
  raise(Error, "Invalid filter expression: #{expr.inspect}")
1238
1263
  when TrueClass, FalseClass
1239
1264
  if supports_where_true?
@@ -155,6 +155,7 @@ module Sequel
155
155
  static_sql(opts[:sql])
156
156
  else
157
157
  check_truncation_allowed!
158
+ check_not_limited!(:truncate)
158
159
  raise(InvalidOperation, "Can't truncate filtered datasets") if opts[:where] || opts[:having]
159
160
  t = String.new
160
161
  source_list_append(t, opts[:from])
@@ -172,6 +173,7 @@ module Sequel
172
173
  def update_sql(values = OPTS)
173
174
  return static_sql(opts[:sql]) if opts[:sql]
174
175
  check_modification_allowed!
176
+ check_not_limited!(:update)
175
177
  clone(:values=>values).send(:_update_sql)
176
178
  end
177
179
 
@@ -205,7 +207,7 @@ module Sequel
205
207
  lines << "def #{'_' if priv}#{type}_sql"
206
208
  lines << 'if sql = opts[:sql]; return static_sql(sql) end' unless priv
207
209
  lines << "if sql = cache_get(:_#{type}_sql); return sql end" if cacheable
208
- lines << 'check_modification_allowed!' if type == :delete
210
+ lines << 'check_modification_allowed!' << 'check_not_limited!(:delete)' if type == :delete
209
211
  lines << 'sql = @opts[:append_sql] || sql_string_origin'
210
212
 
211
213
  if clauses.all?{|c| c.is_a?(Array)}
@@ -843,7 +845,7 @@ module Sequel
843
845
  # Return a from_self dataset if an order or limit is specified, so it works as expected
844
846
  # with UNION, EXCEPT, and INTERSECT clauses.
845
847
  def compound_from_self
846
- (@opts[:sql] || @opts[:limit] || @opts[:order]) ? from_self : self
848
+ (@opts[:sql] || @opts[:limit] || @opts[:order] || @opts[:offset]) ? from_self : self
847
849
  end
848
850
 
849
851
  private
@@ -922,6 +924,14 @@ module Sequel
922
924
  raise(InvalidOperation, "Joined datasets cannot be modified") if !supports_modifying_joins? && joined_dataset?
923
925
  end
924
926
 
927
+ # Emit deprecation warning if the dataset uses limits or offsets.
928
+ def check_not_limited!(type)
929
+ return if @opts[:skip_limit_check] && type != :truncate
930
+ # SEQUEL5
931
+ #raise InvalidOperation, "Dataset##{type} not supported on datasets with limits or offsets" if opts[:limit] || opts[:offset]
932
+ Sequel::Deprecation.deprecate("Dataset##{type} on datasets with limits or offsets", "Call unlimited to remove the limit #{'or skip_limit_check to ignore the limit ' unless type == :truncate}before calling #{type}") if @opts[:limit] || @opts[:offset]
933
+ end
934
+
925
935
  # Alias of check_modification_allowed!
926
936
  def check_truncation_allowed!
927
937
  check_modification_allowed!
@@ -1358,7 +1368,7 @@ module Sequel
1358
1368
 
1359
1369
  # Qualify the given expression e to the given table.
1360
1370
  def qualified_expression(e, table)
1361
- Qualifier.new(self, table).transform(e)
1371
+ Qualifier.new(table).transform(e)
1362
1372
  end
1363
1373
 
1364
1374
  def select_columns_sql(sql)
@@ -39,7 +39,7 @@ module Sequel
39
39
  # Print the message and possibly backtrace to the output.
40
40
  def self.deprecate(method, instead=nil)
41
41
  return unless output
42
- message = instead ? "#{method} is deprecated and will be removed in a future version of Sequel. #{instead}." : method
42
+ message = instead ? "#{method} is deprecated and will be removed in Sequel 5. #{instead}." : method
43
43
  message = "#{prefix}#{message}" if prefix
44
44
  output.puts(message)
45
45
  case b = backtrace_filter
@@ -56,5 +56,13 @@ module Sequel
56
56
  end
57
57
  nil
58
58
  end
59
+
60
+ # If using ruby 2.3+, use Module#deprecate_constant to deprecate the constant,
61
+ # otherwise do nothing as the ruby implementation does not support constant deprecation.
62
+ def self.deprecate_constant(mod, constant)
63
+ if RUBY_VERSION > '2.3'
64
+ mod.deprecate_constant(constant)
65
+ end
66
+ end
59
67
  end
60
68
  end