sequel 3.47.0 → 3.48.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.
Files changed (243) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +230 -0
  3. data/README.rdoc +31 -40
  4. data/Rakefile +1 -14
  5. data/doc/active_record.rdoc +29 -29
  6. data/doc/association_basics.rdoc +4 -13
  7. data/doc/cheat_sheet.rdoc +8 -6
  8. data/doc/code_order.rdoc +89 -0
  9. data/doc/core_extensions.rdoc +3 -3
  10. data/doc/dataset_basics.rdoc +7 -8
  11. data/doc/dataset_filtering.rdoc +7 -2
  12. data/doc/mass_assignment.rdoc +2 -3
  13. data/doc/migration.rdoc +8 -8
  14. data/doc/model_hooks.rdoc +11 -7
  15. data/doc/object_model.rdoc +2 -2
  16. data/doc/opening_databases.rdoc +5 -14
  17. data/doc/prepared_statements.rdoc +5 -9
  18. data/doc/querying.rdoc +23 -28
  19. data/doc/reflection.rdoc +11 -0
  20. data/doc/release_notes/3.48.0.txt +477 -0
  21. data/doc/schema_modification.rdoc +12 -5
  22. data/doc/security.rdoc +2 -2
  23. data/doc/sharding.rdoc +1 -2
  24. data/doc/sql.rdoc +10 -13
  25. data/doc/testing.rdoc +8 -4
  26. data/doc/transactions.rdoc +2 -2
  27. data/doc/validations.rdoc +40 -17
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado.rb +25 -20
  30. data/lib/sequel/adapters/ado/access.rb +1 -0
  31. data/lib/sequel/adapters/ado/mssql.rb +1 -0
  32. data/lib/sequel/adapters/db2.rb +9 -7
  33. data/lib/sequel/adapters/dbi.rb +16 -16
  34. data/lib/sequel/adapters/do.rb +17 -18
  35. data/lib/sequel/adapters/do/mysql.rb +1 -0
  36. data/lib/sequel/adapters/do/postgres.rb +2 -0
  37. data/lib/sequel/adapters/do/sqlite.rb +1 -0
  38. data/lib/sequel/adapters/firebird.rb +5 -7
  39. data/lib/sequel/adapters/ibmdb.rb +23 -20
  40. data/lib/sequel/adapters/informix.rb +8 -2
  41. data/lib/sequel/adapters/jdbc.rb +39 -35
  42. data/lib/sequel/adapters/jdbc/as400.rb +1 -0
  43. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -0
  44. data/lib/sequel/adapters/jdbc/db2.rb +1 -0
  45. data/lib/sequel/adapters/jdbc/derby.rb +1 -0
  46. data/lib/sequel/adapters/jdbc/firebird.rb +1 -0
  47. data/lib/sequel/adapters/jdbc/h2.rb +1 -0
  48. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -0
  49. data/lib/sequel/adapters/jdbc/informix.rb +1 -0
  50. data/lib/sequel/adapters/jdbc/jtds.rb +1 -0
  51. data/lib/sequel/adapters/jdbc/mssql.rb +1 -0
  52. data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
  53. data/lib/sequel/adapters/jdbc/oracle.rb +1 -0
  54. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -0
  55. data/lib/sequel/adapters/jdbc/progress.rb +1 -0
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -0
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -0
  58. data/lib/sequel/adapters/mock.rb +30 -31
  59. data/lib/sequel/adapters/mysql.rb +6 -7
  60. data/lib/sequel/adapters/mysql2.rb +5 -6
  61. data/lib/sequel/adapters/odbc.rb +22 -20
  62. data/lib/sequel/adapters/odbc/mssql.rb +1 -0
  63. data/lib/sequel/adapters/openbase.rb +4 -1
  64. data/lib/sequel/adapters/oracle.rb +10 -8
  65. data/lib/sequel/adapters/postgres.rb +12 -10
  66. data/lib/sequel/adapters/shared/access.rb +6 -0
  67. data/lib/sequel/adapters/shared/cubrid.rb +2 -0
  68. data/lib/sequel/adapters/shared/db2.rb +2 -0
  69. data/lib/sequel/adapters/shared/firebird.rb +2 -0
  70. data/lib/sequel/adapters/shared/informix.rb +2 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +14 -8
  72. data/lib/sequel/adapters/shared/mysql.rb +6 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +2 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +14 -4
  75. data/lib/sequel/adapters/shared/progress.rb +1 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +4 -3
  77. data/lib/sequel/adapters/sqlite.rb +6 -7
  78. data/lib/sequel/adapters/swift.rb +20 -21
  79. data/lib/sequel/adapters/swift/mysql.rb +1 -0
  80. data/lib/sequel/adapters/swift/postgres.rb +2 -0
  81. data/lib/sequel/adapters/swift/sqlite.rb +1 -0
  82. data/lib/sequel/adapters/tinytds.rb +5 -6
  83. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +68 -0
  84. data/lib/sequel/connection_pool.rb +1 -1
  85. data/lib/sequel/core.rb +57 -50
  86. data/lib/sequel/database/connecting.rb +9 -10
  87. data/lib/sequel/database/dataset.rb +11 -6
  88. data/lib/sequel/database/dataset_defaults.rb +61 -69
  89. data/lib/sequel/database/features.rb +21 -0
  90. data/lib/sequel/database/misc.rb +23 -3
  91. data/lib/sequel/database/query.rb +13 -7
  92. data/lib/sequel/database/schema_methods.rb +6 -6
  93. data/lib/sequel/database/transactions.rb +1 -0
  94. data/lib/sequel/dataset/actions.rb +51 -38
  95. data/lib/sequel/dataset/features.rb +1 -0
  96. data/lib/sequel/dataset/graph.rb +9 -33
  97. data/lib/sequel/dataset/misc.rb +30 -5
  98. data/lib/sequel/dataset/mutation.rb +2 -3
  99. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  100. data/lib/sequel/dataset/query.rb +91 -27
  101. data/lib/sequel/dataset/sql.rb +40 -6
  102. data/lib/sequel/deprecated.rb +74 -0
  103. data/lib/sequel/deprecated_core_extensions.rb +135 -0
  104. data/lib/sequel/extensions/columns_introspection.rb +1 -5
  105. data/lib/sequel/extensions/core_extensions.rb +10 -3
  106. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  107. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +33 -0
  108. data/lib/sequel/extensions/filter_having.rb +58 -0
  109. data/lib/sequel/extensions/graph_each.rb +63 -0
  110. data/lib/sequel/extensions/hash_aliases.rb +44 -0
  111. data/lib/sequel/extensions/looser_typecasting.rb +14 -3
  112. data/lib/sequel/extensions/migration.rb +2 -3
  113. data/lib/sequel/extensions/named_timezones.rb +14 -1
  114. data/lib/sequel/extensions/null_dataset.rb +7 -1
  115. data/lib/sequel/extensions/pagination.rb +15 -5
  116. data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -0
  117. data/lib/sequel/extensions/pg_hstore_ops.rb +48 -14
  118. data/lib/sequel/extensions/pg_json.rb +7 -7
  119. data/lib/sequel/extensions/pg_range_ops.rb +8 -2
  120. data/lib/sequel/extensions/pg_statement_cache.rb +1 -0
  121. data/lib/sequel/extensions/pretty_table.rb +13 -4
  122. data/lib/sequel/extensions/query.rb +21 -4
  123. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +22 -0
  124. data/lib/sequel/extensions/schema_caching.rb +10 -7
  125. data/lib/sequel/extensions/schema_dumper.rb +35 -48
  126. data/lib/sequel/extensions/select_remove.rb +13 -4
  127. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +117 -0
  128. data/lib/sequel/extensions/set_overrides.rb +43 -0
  129. data/lib/sequel/extensions/to_dot.rb +6 -0
  130. data/lib/sequel/model.rb +12 -6
  131. data/lib/sequel/model/associations.rb +80 -38
  132. data/lib/sequel/model/base.rb +137 -52
  133. data/lib/sequel/model/errors.rb +7 -2
  134. data/lib/sequel/plugins/active_model.rb +13 -0
  135. data/lib/sequel/plugins/after_initialize.rb +43 -0
  136. data/lib/sequel/plugins/association_proxies.rb +63 -7
  137. data/lib/sequel/plugins/auto_validations.rb +56 -16
  138. data/lib/sequel/plugins/blacklist_security.rb +63 -0
  139. data/lib/sequel/plugins/class_table_inheritance.rb +9 -0
  140. data/lib/sequel/plugins/constraint_validations.rb +50 -8
  141. data/lib/sequel/plugins/dataset_associations.rb +2 -0
  142. data/lib/sequel/plugins/hook_class_methods.rb +7 -1
  143. data/lib/sequel/plugins/identity_map.rb +4 -0
  144. data/lib/sequel/plugins/json_serializer.rb +32 -13
  145. data/lib/sequel/plugins/optimistic_locking.rb +1 -1
  146. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  147. data/lib/sequel/plugins/scissors.rb +33 -0
  148. data/lib/sequel/plugins/serialization.rb +1 -1
  149. data/lib/sequel/plugins/single_table_inheritance.rb +6 -0
  150. data/lib/sequel/plugins/tree.rb +5 -1
  151. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  152. data/lib/sequel/plugins/validation_helpers.rb +15 -11
  153. data/lib/sequel/plugins/xml_serializer.rb +12 -3
  154. data/lib/sequel/sql.rb +12 -2
  155. data/lib/sequel/timezones.rb +1 -1
  156. data/lib/sequel/version.rb +1 -1
  157. data/lib/sequel_core.rb +1 -0
  158. data/lib/sequel_model.rb +1 -0
  159. data/spec/adapters/mssql_spec.rb +24 -57
  160. data/spec/adapters/postgres_spec.rb +27 -55
  161. data/spec/adapters/spec_helper.rb +1 -1
  162. data/spec/adapters/sqlite_spec.rb +1 -1
  163. data/spec/bin_spec.rb +251 -0
  164. data/spec/core/database_spec.rb +46 -32
  165. data/spec/core/dataset_spec.rb +233 -181
  166. data/spec/core/deprecated_spec.rb +78 -0
  167. data/spec/core/expression_filters_spec.rb +3 -4
  168. data/spec/core/mock_adapter_spec.rb +9 -9
  169. data/spec/core/object_graph_spec.rb +9 -19
  170. data/spec/core/schema_spec.rb +3 -1
  171. data/spec/core/spec_helper.rb +19 -0
  172. data/spec/core_extensions_spec.rb +80 -30
  173. data/spec/extensions/after_initialize_spec.rb +24 -0
  174. data/spec/extensions/association_proxies_spec.rb +37 -1
  175. data/spec/extensions/auto_validations_spec.rb +20 -4
  176. data/spec/extensions/blacklist_security_spec.rb +87 -0
  177. data/spec/extensions/boolean_readers_spec.rb +2 -1
  178. data/spec/extensions/class_table_inheritance_spec.rb +7 -0
  179. data/spec/extensions/columns_introspection_spec.rb +3 -3
  180. data/spec/extensions/constraint_validations_plugin_spec.rb +83 -5
  181. data/spec/extensions/core_refinements_spec.rb +7 -7
  182. data/spec/extensions/dataset_associations_spec.rb +2 -2
  183. data/spec/extensions/date_arithmetic_spec.rb +1 -1
  184. data/spec/extensions/defaults_setter_spec.rb +2 -1
  185. data/spec/extensions/empty_array_ignore_nulls_spec.rb +24 -0
  186. data/spec/extensions/filter_having_spec.rb +40 -0
  187. data/spec/extensions/graph_each_spec.rb +109 -0
  188. data/spec/extensions/hash_aliases_spec.rb +16 -0
  189. data/spec/extensions/hook_class_methods_spec.rb +2 -2
  190. data/spec/extensions/identity_map_spec.rb +3 -3
  191. data/spec/extensions/json_serializer_spec.rb +19 -19
  192. data/spec/extensions/lazy_attributes_spec.rb +1 -0
  193. data/spec/extensions/list_spec.rb +13 -13
  194. data/spec/extensions/looser_typecasting_spec.rb +10 -3
  195. data/spec/extensions/many_through_many_spec.rb +1 -1
  196. data/spec/extensions/migration_spec.rb +7 -7
  197. data/spec/extensions/named_timezones_spec.rb +6 -0
  198. data/spec/extensions/nested_attributes_spec.rb +2 -2
  199. data/spec/extensions/null_dataset_spec.rb +1 -1
  200. data/spec/extensions/pagination_spec.rb +2 -2
  201. data/spec/extensions/pg_hstore_ops_spec.rb +75 -0
  202. data/spec/extensions/pg_range_ops_spec.rb +4 -2
  203. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  204. data/spec/extensions/pretty_table_spec.rb +1 -1
  205. data/spec/extensions/query_literals_spec.rb +1 -1
  206. data/spec/extensions/query_spec.rb +3 -3
  207. data/spec/extensions/schema_caching_spec.rb +3 -3
  208. data/spec/extensions/schema_dumper_spec.rb +27 -2
  209. data/spec/extensions/schema_spec.rb +2 -2
  210. data/spec/extensions/scissors_spec.rb +26 -0
  211. data/spec/extensions/select_remove_spec.rb +1 -1
  212. data/spec/extensions/sequel_3_dataset_methods_spec.rb +102 -0
  213. data/spec/extensions/set_overrides_spec.rb +45 -0
  214. data/spec/extensions/single_table_inheritance_spec.rb +10 -0
  215. data/spec/extensions/spec_helper.rb +24 -1
  216. data/spec/extensions/static_cache_spec.rb +1 -1
  217. data/spec/extensions/string_stripper_spec.rb +2 -1
  218. data/spec/extensions/to_dot_spec.rb +1 -1
  219. data/spec/extensions/typecast_on_load_spec.rb +3 -2
  220. data/spec/extensions/update_primary_key_spec.rb +2 -2
  221. data/spec/extensions/validation_class_methods_spec.rb +19 -19
  222. data/spec/extensions/validation_helpers_spec.rb +30 -21
  223. data/spec/extensions/xml_serializer_spec.rb +5 -5
  224. data/spec/integration/associations_test.rb +10 -30
  225. data/spec/integration/dataset_test.rb +20 -24
  226. data/spec/integration/eager_loader_test.rb +5 -5
  227. data/spec/integration/model_test.rb +3 -3
  228. data/spec/integration/plugin_test.rb +7 -39
  229. data/spec/integration/schema_test.rb +4 -38
  230. data/spec/integration/spec_helper.rb +2 -1
  231. data/spec/model/association_reflection_spec.rb +70 -5
  232. data/spec/model/associations_spec.rb +11 -11
  233. data/spec/model/base_spec.rb +25 -8
  234. data/spec/model/class_dataset_methods_spec.rb +143 -0
  235. data/spec/model/dataset_methods_spec.rb +1 -1
  236. data/spec/model/eager_loading_spec.rb +25 -25
  237. data/spec/model/hooks_spec.rb +1 -1
  238. data/spec/model/model_spec.rb +22 -7
  239. data/spec/model/plugins_spec.rb +1 -6
  240. data/spec/model/record_spec.rb +37 -29
  241. data/spec/model/spec_helper.rb +23 -1
  242. data/spec/model/validations_spec.rb +15 -17
  243. metadata +32 -3
@@ -13,6 +13,7 @@ module Sequel
13
13
  elsif db.respond_to?(:quote_identifiers?)
14
14
  @quote_identifiers = db.quote_identifiers?
15
15
  else
16
+ Sequel::Deprecation.deprecate('Calling Dataset#quote_identifiers? for a dataset where the database doesn\'t implement quote_identifiers? will raise a NoMethodError in Sequel 4.')
16
17
  @quote_identifiers = false
17
18
  end
18
19
  end
@@ -13,42 +13,18 @@ module Sequel
13
13
  #
14
14
  # DB[:table].add_graph_aliases(:some_alias=>[:table, :column])
15
15
  # # SELECT ..., table.column AS some_alias
16
- # # => {:table=>{:column=>some_alias_value, ...}, ...}
17
16
  def add_graph_aliases(graph_aliases)
17
+ unless ga = opts[:graph_aliases]
18
+ unless opts[:graph] && (ga = opts[:graph][:column_aliases])
19
+ Sequel::Deprecation.deprecate('Calling Dataset#add_graph_aliases before #graph or #set_graph_aliases', 'Please call it after #graph or #set_graph_aliases')
20
+ end
21
+ end
18
22
  columns, graph_aliases = graph_alias_columns(graph_aliases)
19
- ds = select_more(*columns)
20
- ds.opts[:graph_aliases] = (ds.opts[:graph_aliases] || (ds.opts[:graph][:column_aliases] rescue {}) || {}).merge(graph_aliases)
21
- ds
23
+ select_more(*columns).clone(:graph_aliases => ga.merge(graph_aliases))
22
24
  end
23
25
 
24
- # Allows you to join multiple datasets/tables and have the result set
25
- # split into component tables.
26
- #
27
- # This differs from the usual usage of join, which returns the result set
28
- # as a single hash. For example:
29
- #
30
- # # CREATE TABLE artists (id INTEGER, name TEXT);
31
- # # CREATE TABLE albums (id INTEGER, name TEXT, artist_id INTEGER);
32
- #
33
- # DB[:artists].left_outer_join(:albums, :artist_id=>:id).first
34
- # #=> {:id=>albums.id, :name=>albums.name, :artist_id=>albums.artist_id}
35
- #
36
- # DB[:artists].graph(:albums, :artist_id=>:id).first
37
- # #=> {:artists=>{:id=>artists.id, :name=>artists.name}, :albums=>{:id=>albums.id, :name=>albums.name, :artist_id=>albums.artist_id}}
38
- #
39
- # Using a join such as left_outer_join, the attribute names that are shared between
40
- # the tables are combined in the single return hash. You can get around that by
41
- # using +select+ with correct aliases for all of the columns, but it is simpler to
42
- # use +graph+ and have the result set split for you. In addition, +graph+ respects
43
- # any +row_proc+ of the current dataset and the datasets you use with +graph+.
44
- #
45
- # If you are graphing a table and all columns for that table are nil, this
46
- # indicates that no matching rows existed in the table, so graph will return nil
47
- # instead of a hash with all nil values:
48
- #
49
- # # If the artist doesn't have any albums
50
- # DB[:artists].graph(:albums, :artist_id=>:id).first
51
- # => {:artists=>{:id=>artists.id, :name=>artists.name}, :albums=>nil}
26
+ # Similar to Dataset#join_table, but uses unambiguous aliases for selected
27
+ # columns and keeps metadata about the aliases for use in other methods.
52
28
  #
53
29
  # Arguments:
54
30
  # dataset :: Can be a symbol (specifying a table), another dataset,
@@ -226,7 +202,6 @@ module Sequel
226
202
  # :album_name=>[:albums, :name],
227
203
  # :forty_two=>[:albums, :fourtwo, 42]).first
228
204
  # # SELECT artists.name, albums.name AS album_name, 42 AS forty_two ...
229
- # # => {:artists=>{:name=>artists.name}, :albums=>{:name=>albums.name, :fourtwo=>42}}
230
205
  def set_graph_aliases(graph_aliases)
231
206
  columns, graph_aliases = graph_alias_columns(graph_aliases)
232
207
  ds = select(*columns)
@@ -262,6 +237,7 @@ module Sequel
262
237
  # tranform and run the row_proc on each part (if applicable),
263
238
  # and yield a hash of the parts.
264
239
  def graph_each
240
+ Sequel::Deprecation.deprecate('Dataset#graph_each', 'Load the graph_each extension if you want to continue using it')
265
241
  # Reject tables with nil datasets, as they are excluded from
266
242
  # the result set
267
243
  datasets = @opts[:graph][:table_aliases].to_a.reject{|ta,ds| ds.nil?}
@@ -12,11 +12,32 @@ module Sequel
12
12
 
13
13
  # The database related to this dataset. This is the Database instance that
14
14
  # will execute all of this dataset's queries.
15
- attr_accessor :db
15
+ attr_reader :db
16
16
 
17
17
  # The hash of options for this dataset, keys are symbols.
18
- attr_accessor :opts
19
-
18
+ attr_reader :opts
19
+
20
+ # REMOVE40
21
+ def db=(v)
22
+ Sequel::Deprecation.deprecate('Dataset#db=', 'Please load the sequel_3_dataset_methods extension to continue using it')
23
+ @db = v
24
+ end
25
+ def opts=(v)
26
+ Sequel::Deprecation.deprecate('Dataset#opts=', 'Please load the sequel_3_dataset_methods extension to continue using it')
27
+ @opts = v
28
+ end
29
+
30
+ module DeprecateModifyHash
31
+ %w'[]= merge! update clear delete delete_if keep_if reject! select! shift store'.each do |meth|
32
+ class_eval(<<-END, __FILE__, __LINE__+1)
33
+ def #{meth}(*)
34
+ Sequel::Deprecation.deprecate('Modifying the initial dataset opts hash is deprecated. Please dup the hash.')
35
+ super
36
+ end
37
+ END
38
+ end
39
+ end
40
+
20
41
  # Constructs a new Dataset instance with an associated database and
21
42
  # options. Datasets are usually constructed by invoking the Database#[] method:
22
43
  #
@@ -25,9 +46,11 @@ module Sequel
25
46
  # Sequel::Dataset is an abstract class that is not useful by itself. Each
26
47
  # database adapter provides a subclass of Sequel::Dataset, and has
27
48
  # the Database#dataset method return an instance of that subclass.
28
- def initialize(db, opts = nil)
49
+ def initialize(db, opts = (no_arg_given=true; nil))
29
50
  @db = db
30
- @opts = opts || {}
51
+ # REMOVE40
52
+ Sequel::Deprecation.deprecate('Passing the opts argument to Database#dataset or Dataset#initialize', 'Clone the dataset afterward to change the opts') unless no_arg_given
53
+ @opts = opts || {}.extend(DeprecateModifyHash)
31
54
  end
32
55
 
33
56
  # Define a hash value such that datasets with the same DB, opts, and SQL
@@ -127,6 +150,7 @@ module Sequel
127
150
  elsif db.respond_to?(:identifier_input_method)
128
151
  @identifier_input_method = db.identifier_input_method
129
152
  else
153
+ Sequel::Deprecation.deprecate('Calling Dataset#identifier_input_method for a dataset where the database doesn\'t implement identifier_input_method will raise a NoMethodError in Sequel 4.')
130
154
  @identifier_input_method = nil
131
155
  end
132
156
  end
@@ -139,6 +163,7 @@ module Sequel
139
163
  elsif db.respond_to?(:identifier_output_method)
140
164
  @identifier_output_method = db.identifier_output_method
141
165
  else
166
+ Sequel::Deprecation.deprecate('Calling Dataset#identifier_output_method for a dataset where the database doesn\'t implement identifier_output_method will raise a NoMethodError in Sequel 4.')
142
167
  @identifier_output_method = nil
143
168
  end
144
169
  end
@@ -58,7 +58,7 @@ module Sequel
58
58
 
59
59
  # Avoid self-referential dataset by cloning.
60
60
  def from_self!(*args, &block)
61
- @opts.merge!(clone.from_self(*args, &block).opts)
61
+ @opts = clone.from_self(*args, &block).opts
62
62
  self
63
63
  end
64
64
 
@@ -74,8 +74,7 @@ module Sequel
74
74
  # to the receiver and merging the options of the resulting dataset into
75
75
  # the receiver's options.
76
76
  def mutation_method(meth, *args, &block)
77
- copy = send(meth, *args, &block)
78
- @opts.merge!(copy.opts)
77
+ @opts = send(meth, *args, &block).opts
79
78
  self
80
79
  end
81
80
  end
@@ -29,7 +29,7 @@ module Sequel
29
29
  # Override the given *_sql method based on the type, and
30
30
  # cache the result of the sql.
31
31
  def prepared_sql
32
- return @prepared_sql if defined?(@prepared_sql) && @prepared_sql
32
+ return @prepared_sql if @prepared_sql
33
33
  @prepared_args ||= []
34
34
  @prepared_sql = super
35
35
  @opts[:sql] = @prepared_sql
@@ -41,6 +41,7 @@ module Sequel
41
41
  set_defaults set_graph_aliases set_overrides unfiltered ungraphed ungrouped union
42
42
  unlimited unordered where with with_recursive with_sql
43
43
  METHS
44
+ # REMOVE40: query paginate set_defaults set_overrides
44
45
 
45
46
  # Register an extension callback for Dataset objects. ext should be the
46
47
  # extension name symbol, and mod should either be a Module that the
@@ -69,18 +70,30 @@ module Sequel
69
70
  #
70
71
  # DB[:table].filter(:a).and(:b) # SELECT * FROM table WHERE a AND b
71
72
  def and(*cond, &block)
72
- raise(InvalidOperation, "No existing filter found.") unless @opts[:having] || @opts[:where]
73
- filter(*cond, &block)
73
+ unless @opts[:having] || @opts[:where]
74
+ Sequel::Deprecation.deprecate('Dataset#and will no longer raise for an unfilered dataset starting in Sequel 4.')
75
+ raise(InvalidOperation, "No existing filter found.")
76
+ end
77
+ if @opts[:having]
78
+ Sequel::Deprecation.deprecate('Dataset#and will no longer modify the HAVING clause starting in Sequel 4. Switch to using Dataset#having or use the filter_having extension.')
79
+ having(*cond, &block)
80
+ else
81
+ where(*cond, &block)
82
+ end
74
83
  end
75
84
 
76
85
  # Returns a new clone of the dataset with with the given options merged.
77
86
  # If the options changed include options in COLUMN_CHANGE_OPTS, the cached
78
87
  # columns are deleted. This method should generally not be called
79
88
  # directly by user code.
80
- def clone(opts = {})
89
+ def clone(opts = nil)
81
90
  c = super()
82
- c.opts = @opts.merge(opts)
83
- c.instance_variable_set(:@columns, nil) if opts.keys.any?{|o| COLUMN_CHANGE_OPTS.include?(o)}
91
+ if opts
92
+ c.instance_variable_set(:@opts, @opts.merge(opts))
93
+ c.instance_variable_set(:@columns, nil) if @columns && !opts.each_key{|o| break if COLUMN_CHANGE_OPTS.include?(o)}
94
+ else
95
+ c.instance_variable_set(:@opts, @opts.dup)
96
+ end
84
97
  c
85
98
  end
86
99
 
@@ -116,7 +129,10 @@ module Sequel
116
129
  # DB[:items].except(DB[:other_items], :alias=>:i)
117
130
  # # SELECT * FROM (SELECT * FROM items EXCEPT SELECT * FROM other_items) AS i
118
131
  def except(dataset, opts={})
119
- opts = {:all=>opts} unless opts.is_a?(Hash)
132
+ unless opts.is_a?(Hash)
133
+ Sequel::Deprecation.deprecate('Passing a non-hash as the second argument to Dataset#except', "Please switch to an options hash with the :all option")
134
+ opts = {:all=>opts}
135
+ end
120
136
  raise(InvalidOperation, "EXCEPT not supported") unless supports_intersect_except?
121
137
  raise(InvalidOperation, "EXCEPT ALL not supported") if opts[:all] && !supports_intersect_except_all?
122
138
  compound_clone(:except, dataset, opts)
@@ -131,6 +147,7 @@ module Sequel
131
147
  # DB[:items].exclude(:category => 'software', :id=>3)
132
148
  # # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
133
149
  def exclude(*cond, &block)
150
+ Sequel::Deprecation.deprecate('Dataset#exclude will no longer modify the HAVING clause starting in Sequel 4. Switch to using Dataset#exclude_having or use the filter_having extension.') if @opts[:having]
134
151
  _filter_or_exclude(true, @opts[:having] ? :having : :where, *cond, &block)
135
152
  end
136
153
 
@@ -214,6 +231,7 @@ module Sequel
214
231
  #
215
232
  # See the the {"Dataset Filtering" guide}[link:files/doc/dataset_filtering_rdoc.html] for more examples and details.
216
233
  def filter(*cond, &block)
234
+ Sequel::Deprecation.deprecate('Dataset#filter will no longer modify the HAVING clause starting in Sequel 4. Switch to using Dataset#having or use the filter_having extension.') if @opts[:having]
217
235
  _filter(@opts[:having] ? :having : :where, *cond, &block)
218
236
  end
219
237
 
@@ -238,6 +256,7 @@ module Sequel
238
256
  source.each do |s|
239
257
  case s
240
258
  when Hash
259
+ Sequel::Deprecation.deprecate('Dataset#from will no longer treat an input hash as an alias specifier. Switch to aliasing using Sequel.as or use the hash_aliases extension.')
241
260
  s.each{|k,v| sources << SQL::AliasedExpression.new(k,v)}
242
261
  when Dataset
243
262
  if hoist_cte?(s)
@@ -406,7 +425,10 @@ module Sequel
406
425
  # DB[:items].intersect(DB[:other_items], :alias=>:i)
407
426
  # # SELECT * FROM (SELECT * FROM items INTERSECT SELECT * FROM other_items) AS i
408
427
  def intersect(dataset, opts={})
409
- opts = {:all=>opts} unless opts.is_a?(Hash)
428
+ unless opts.is_a?(Hash)
429
+ Sequel::Deprecation.deprecate('Passing a non-hash as the second argument to Dataset#intersect', "Please switch to an options hash with the :all option")
430
+ opts = {:all=>opts}
431
+ end
410
432
  raise(InvalidOperation, "INTERSECT not supported") unless supports_intersect_except?
411
433
  raise(InvalidOperation, "INTERSECT ALL not supported") if opts[:all] && !supports_intersect_except_all?
412
434
  compound_clone(:intersect, dataset, opts)
@@ -421,7 +443,10 @@ module Sequel
421
443
  # # SELECT * FROM items WHERE ((category != 'software') OR (id != 3))
422
444
  def invert
423
445
  having, where = @opts[:having], @opts[:where]
424
- raise(Error, "No current filter") unless having || where
446
+ unless having || where
447
+ Sequel::Deprecation.deprecate('Dataset#invert will no longer raise for an unfilered dataset starting in Sequel 4.')
448
+ raise(Error, "No current filter")
449
+ end
425
450
  o = {}
426
451
  o[:having] = SQL::BooleanExpression.invert(having) if having
427
452
  o[:where] = SQL::BooleanExpression.invert(where) if where
@@ -464,7 +489,8 @@ module Sequel
464
489
  # the last joined or primary table is used.
465
490
  # * :qualify - Can be set to false to not do any implicit qualification. Can be set
466
491
  # to :deep to use the Qualifier AST Transformer, which will attempt to qualify
467
- # subexpressions of the expression tree.
492
+ # subexpressions of the expression tree. Defaults to the value of
493
+ # default_join_table_qualification.
468
494
  # * block - The block argument should only be given if a JOIN with an ON clause is used,
469
495
  # in which case it yields the table alias/name for the table currently being joined,
470
496
  # the table alias/name for the last joined (or first table), and an array of previous
@@ -505,13 +531,14 @@ module Sequel
505
531
  last_alias = options[:implicit_qualifier]
506
532
  qualify_type = options[:qualify]
507
533
  when Symbol, String, SQL::Identifier
534
+ Sequel::Deprecation.deprecate('Passing a non-hash as the options hash to Dataset#join_table', "Please switch to an options hash with the :table_alias option")
508
535
  table_alias = options
509
536
  last_alias = nil
510
537
  else
511
538
  raise Error, "invalid options format for join_table: #{options.inspect}"
512
539
  end
513
540
 
514
- if Dataset === table
541
+ if table.is_a?(Dataset)
515
542
  if table_alias.nil?
516
543
  table_alias_num = (@opts[:num_dataset_sources] || 0) + 1
517
544
  table_alias = dataset_alias(table_alias_num)
@@ -532,6 +559,7 @@ module Sequel
532
559
  last_alias ||= @opts[:last_joined_table] || first_source_alias
533
560
  if Sequel.condition_specifier?(expr)
534
561
  expr = expr.collect do |k, v|
562
+ qualify_type = default_join_table_qualification if qualify_type.nil?
535
563
  case qualify_type
536
564
  when false
537
565
  nil # Do no qualification
@@ -578,7 +606,7 @@ module Sequel
578
606
  def limit(l, o = (no_offset = true; nil))
579
607
  return from_self.limit(l, o) if @opts[:sql]
580
608
 
581
- if Range === l
609
+ if l.is_a?(Range)
582
610
  o = l.first
583
611
  l = l.last - l.first + (l.exclude_end? ? 0 : 1)
584
612
  end
@@ -630,9 +658,17 @@ module Sequel
630
658
  # DB[:items].filter(:a).or(:b) # SELECT * FROM items WHERE a OR b
631
659
  def or(*cond, &block)
632
660
  clause = (@opts[:having] ? :having : :where)
633
- raise(InvalidOperation, "No existing filter found.") unless @opts[clause]
661
+ unless @opts[clause]
662
+ Sequel::Deprecation.deprecate('Dataset#or will no longer raise for an unfilered dataset starting in Sequel 4.')
663
+ raise(InvalidOperation, "No existing filter found.")
664
+ end
665
+ Sequel::Deprecation.deprecate('Dataset#or will no longer modify the HAVING clause starting in Sequel 4. You can use the filter_having extension to continue to use the current behavior.') if clause == :having
634
666
  cond = cond.first if cond.size == 1
635
- clone(clause => SQL::BooleanExpression.new(:OR, @opts[clause], filter_expr(cond, &block)))
667
+ if cond.respond_to?(:empty?) && cond.empty? && !block
668
+ clone
669
+ else
670
+ clone(clause => SQL::BooleanExpression.new(:OR, @opts[clause], filter_expr(cond, &block)))
671
+ end
636
672
  end
637
673
 
638
674
  # Returns a copy of the dataset with the order changed. If the dataset has an
@@ -692,7 +728,14 @@ module Sequel
692
728
  # DB[:items].filter(:id=>1).qualify(:i)
693
729
  # # SELECT i.* FROM items WHERE (i.id = 1)
694
730
  def qualify(table=first_source)
695
- qualify_to(table)
731
+ o = @opts
732
+ return clone if o[:sql]
733
+ h = {}
734
+ (o.keys & QUALIFY_KEYS).each do |k|
735
+ h[k] = qualified_expression(o[k], table)
736
+ end
737
+ h[:select] = [SQL::ColumnAll.new(table)] if !o[:select] || o[:select].empty?
738
+ clone(h)
696
739
  end
697
740
 
698
741
  # Return a copy of the dataset with unqualified identifiers in the
@@ -703,14 +746,8 @@ module Sequel
703
746
  # DB[:items].filter(:id=>1).qualify_to(:i)
704
747
  # # SELECT i.* FROM items WHERE (i.id = 1)
705
748
  def qualify_to(table)
706
- o = @opts
707
- return clone if o[:sql]
708
- h = {}
709
- (o.keys & QUALIFY_KEYS).each do |k|
710
- h[k] = qualified_expression(o[k], table)
711
- end
712
- h[:select] = [SQL::ColumnAll.new(table)] if !o[:select] || o[:select].empty?
713
- clone(h)
749
+ Sequel::Deprecation.deprecate('Dataset#qualify_to', 'Switch to Dataset#qualify or use the sequel_3_dataset_methods extension')
750
+ qualify(table)
714
751
  end
715
752
 
716
753
  # Qualify the dataset to its current first source. This is useful
@@ -722,7 +759,8 @@ module Sequel
722
759
  # DB[:items].filter(:id=>1).qualify_to_first_source
723
760
  # # SELECT items.* FROM items WHERE (items.id = 1)
724
761
  def qualify_to_first_source
725
- qualify_to(first_source)
762
+ Sequel::Deprecation.deprecate('Dataset#qualify_to_first_source', 'Switch to Dataset#qualify or use the sequel_3_dataset_methods extension')
763
+ qualify
726
764
  end
727
765
 
728
766
  # Modify the RETURNING clause, only supported on a few databases. If returning
@@ -765,7 +803,12 @@ module Sequel
765
803
  virtual_row_columns(columns, block)
766
804
  m = []
767
805
  columns.each do |i|
768
- i.is_a?(Hash) ? m.concat(i.map{|k, v| SQL::AliasedExpression.new(k,v)}) : m << i
806
+ if i.is_a?(Hash)
807
+ Sequel::Deprecation.deprecate('Dataset#select will no longer treat an input hash as an alias specifier. Switch to aliasing using Sequel.as or use the hash_aliases extension.')
808
+ m.concat(i.map{|k, v| SQL::AliasedExpression.new(k,v)})
809
+ else
810
+ m << i
811
+ end
769
812
  end
770
813
  clone(:select => m)
771
814
  end
@@ -825,7 +868,11 @@ module Sequel
825
868
  # DB[:items].select(:a).select_more(:b) # SELECT a, b FROM items
826
869
  # DB[:items].select_more(:b) # SELECT b FROM items
827
870
  def select_more(*columns, &block)
828
- columns = @opts[:select] + columns if @opts[:select]
871
+ if @opts[:select]
872
+ columns = @opts[:select] + columns
873
+ else
874
+ Sequel::Deprecation.deprecate('Dataset#select_more will no longer remove the wildcard selection from the Dataset starting in Sequel 4. Switch to using Dataset#select if you want that behavior.')
875
+ end
829
876
  select(*columns, &block)
830
877
  end
831
878
 
@@ -849,6 +896,7 @@ module Sequel
849
896
  # DB[:items].set_defaults(:a=>'a', :c=>'c').insert(:a=>'d', :b=>'b')
850
897
  # # INSERT INTO items (a, c, b) VALUES ('d', 'c', 'b')
851
898
  def set_defaults(hash)
899
+ Sequel::Deprecation.deprecate('Dataset#set_defaults', 'Please use the dataset_set_overrides extension if you want to continue using it')
852
900
  clone(:defaults=>(@opts[:defaults]||{}).merge(hash))
853
901
  end
854
902
 
@@ -859,6 +907,7 @@ module Sequel
859
907
  # DB[:items].set_overrides(:a=>'a', :c=>'c').insert(:a=>'d', :b=>'b')
860
908
  # # INSERT INTO items (a, c, b) VALUES ('a', 'c', 'b')
861
909
  def set_overrides(hash)
910
+ Sequel::Deprecation.deprecate('Dataset#set_overrides', 'Please use the dataset_set_overrides extension if you want to continue using it')
862
911
  clone(:overrides=>hash.merge(@opts[:overrides]||{}))
863
912
  end
864
913
 
@@ -911,7 +960,10 @@ module Sequel
911
960
  # DB[:items].union(DB[:other_items], :alias=>:i)
912
961
  # # SELECT * FROM (SELECT * FROM items UNION SELECT * FROM other_items) AS i
913
962
  def union(dataset, opts={})
914
- opts = {:all=>opts} unless opts.is_a?(Hash)
963
+ unless opts.is_a?(Hash)
964
+ Sequel::Deprecation.deprecate('Passing a non-hash as the second argument to Dataset#union', "Please switch to an options hash with the :all option")
965
+ opts = {:all=>opts}
966
+ end
915
967
  compound_clone(:union, dataset, opts)
916
968
  end
917
969
 
@@ -1051,6 +1103,11 @@ module Sequel
1051
1103
  _filter_or_exclude(false, clause, *cond, &block)
1052
1104
  end
1053
1105
 
1106
+ # The default :qualify option to use for join tables if one is not specified.
1107
+ def default_join_table_qualification
1108
+ :symbol
1109
+ end
1110
+
1054
1111
  # SQL expression object based on the expr type. See +filter+.
1055
1112
  def filter_expr(expr = nil, &block)
1056
1113
  expr = nil if expr == []
@@ -1129,7 +1186,14 @@ module Sequel
1129
1186
  # Treat the +block+ as a virtual_row block if not +nil+ and
1130
1187
  # add the resulting columns to the +columns+ array (modifies +columns+).
1131
1188
  def virtual_row_columns(columns, block)
1132
- columns.concat(Array(Sequel.virtual_row(&block))) if block
1189
+ if block
1190
+ v = Sequel.virtual_row(&block)
1191
+ if v.is_a?(Array)
1192
+ columns.concat(v)
1193
+ else
1194
+ columns << v
1195
+ end
1196
+ end
1133
1197
  end
1134
1198
  end
1135
1199
  end