sequel 3.47.0 → 3.48.0

Sign up to get free protection for your applications and to get access to all the features.
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