sequel 4.45.0 → 4.46.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +108 -0
  3. data/doc/release_notes/4.46.0.txt +404 -0
  4. data/doc/security.rdoc +9 -0
  5. data/doc/sql.rdoc +2 -2
  6. data/doc/testing.rdoc +1 -1
  7. data/doc/validations.rdoc +1 -2
  8. data/lib/sequel/adapters/ado.rb +8 -3
  9. data/lib/sequel/adapters/ado/access.rb +8 -4
  10. data/lib/sequel/adapters/ado/mssql.rb +3 -1
  11. data/lib/sequel/adapters/amalgalite.rb +5 -0
  12. data/lib/sequel/adapters/cubrid.rb +16 -7
  13. data/lib/sequel/adapters/do.rb +7 -1
  14. data/lib/sequel/adapters/do/mysql.rb +8 -4
  15. data/lib/sequel/adapters/ibmdb.rb +10 -5
  16. data/lib/sequel/adapters/jdbc.rb +8 -2
  17. data/lib/sequel/adapters/jdbc/as400.rb +10 -3
  18. data/lib/sequel/adapters/jdbc/db2.rb +27 -16
  19. data/lib/sequel/adapters/jdbc/derby.rb +47 -20
  20. data/lib/sequel/adapters/jdbc/h2.rb +13 -7
  21. data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
  22. data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
  23. data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
  24. data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
  25. data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
  26. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
  27. data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
  28. data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
  29. data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
  30. data/lib/sequel/adapters/mock.rb +5 -0
  31. data/lib/sequel/adapters/mysql.rb +8 -1
  32. data/lib/sequel/adapters/mysql2.rb +6 -1
  33. data/lib/sequel/adapters/odbc.rb +20 -8
  34. data/lib/sequel/adapters/odbc/mssql.rb +6 -3
  35. data/lib/sequel/adapters/oracle.rb +12 -6
  36. data/lib/sequel/adapters/postgres.rb +20 -8
  37. data/lib/sequel/adapters/shared/access.rb +76 -47
  38. data/lib/sequel/adapters/shared/cubrid.rb +16 -11
  39. data/lib/sequel/adapters/shared/db2.rb +46 -19
  40. data/lib/sequel/adapters/shared/firebird.rb +20 -8
  41. data/lib/sequel/adapters/shared/informix.rb +6 -3
  42. data/lib/sequel/adapters/shared/mssql.rb +132 -72
  43. data/lib/sequel/adapters/shared/mysql.rb +112 -65
  44. data/lib/sequel/adapters/shared/oracle.rb +36 -21
  45. data/lib/sequel/adapters/shared/postgres.rb +91 -56
  46. data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
  47. data/lib/sequel/adapters/shared/sqlite.rb +67 -32
  48. data/lib/sequel/adapters/sqlanywhere.rb +9 -1
  49. data/lib/sequel/adapters/sqlite.rb +8 -1
  50. data/lib/sequel/adapters/swift.rb +5 -0
  51. data/lib/sequel/adapters/swift/mysql.rb +4 -2
  52. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  53. data/lib/sequel/adapters/tinytds.rb +10 -3
  54. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
  55. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  56. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
  57. data/lib/sequel/adapters/utils/pg_types.rb +14 -6
  58. data/lib/sequel/adapters/utils/replace.rb +4 -2
  59. data/lib/sequel/connection_pool/single.rb +2 -2
  60. data/lib/sequel/core.rb +24 -11
  61. data/lib/sequel/database/connecting.rb +9 -3
  62. data/lib/sequel/database/dataset_defaults.rb +7 -1
  63. data/lib/sequel/database/logging.rb +1 -0
  64. data/lib/sequel/database/misc.rb +5 -2
  65. data/lib/sequel/database/query.rb +7 -5
  66. data/lib/sequel/database/schema_generator.rb +1 -0
  67. data/lib/sequel/database/schema_methods.rb +50 -27
  68. data/lib/sequel/database/transactions.rb +19 -9
  69. data/lib/sequel/dataset/actions.rb +15 -6
  70. data/lib/sequel/dataset/graph.rb +15 -5
  71. data/lib/sequel/dataset/misc.rb +12 -4
  72. data/lib/sequel/dataset/mutation.rb +17 -8
  73. data/lib/sequel/dataset/prepared_statements.rb +3 -2
  74. data/lib/sequel/dataset/query.rb +84 -38
  75. data/lib/sequel/dataset/sql.rb +302 -191
  76. data/lib/sequel/deprecated.rb +26 -17
  77. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
  78. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  79. data/lib/sequel/extensions/from_block.rb +1 -0
  80. data/lib/sequel/extensions/graph_each.rb +1 -1
  81. data/lib/sequel/extensions/identifier_mangling.rb +2 -2
  82. data/lib/sequel/extensions/migration.rb +28 -4
  83. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
  84. data/lib/sequel/extensions/schema_dumper.rb +4 -4
  85. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
  86. data/lib/sequel/extensions/set_overrides.rb +2 -0
  87. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  88. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  89. data/lib/sequel/model.rb +11 -7
  90. data/lib/sequel/model/associations.rb +5 -7
  91. data/lib/sequel/model/base.rb +47 -45
  92. data/lib/sequel/model/dataset_module.rb +9 -14
  93. data/lib/sequel/model/plugins.rb +3 -0
  94. data/lib/sequel/no_core_ext.rb +1 -0
  95. data/lib/sequel/plugins/blacklist_security.rb +1 -1
  96. data/lib/sequel/plugins/boolean_subsets.rb +7 -5
  97. data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
  98. data/lib/sequel/plugins/dataset_associations.rb +1 -1
  99. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  100. data/lib/sequel/plugins/finder.rb +240 -0
  101. data/lib/sequel/plugins/inverted_subsets.rb +19 -12
  102. data/lib/sequel/plugins/many_through_many.rb +1 -1
  103. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  104. data/lib/sequel/plugins/schema.rb +1 -1
  105. data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
  106. data/lib/sequel/plugins/subset_conditions.rb +11 -3
  107. data/lib/sequel/plugins/whitelist_security.rb +118 -0
  108. data/lib/sequel/sql.rb +80 -36
  109. data/lib/sequel/timezones.rb +2 -0
  110. data/lib/sequel/version.rb +1 -1
  111. data/spec/adapters/mssql_spec.rb +20 -0
  112. data/spec/adapters/mysql_spec.rb +1 -1
  113. data/spec/adapters/oracle_spec.rb +12 -8
  114. data/spec/adapters/postgres_spec.rb +1 -1
  115. data/spec/adapters/spec_helper.rb +1 -1
  116. data/spec/adapters/sqlite_spec.rb +36 -34
  117. data/spec/core/connection_pool_spec.rb +2 -1
  118. data/spec/core/database_spec.rb +87 -9
  119. data/spec/core/dataset_spec.rb +501 -129
  120. data/spec/core/deprecated_spec.rb +1 -1
  121. data/spec/core/expression_filters_spec.rb +146 -60
  122. data/spec/core/mock_adapter_spec.rb +1 -1
  123. data/spec/core/object_graph_spec.rb +61 -9
  124. data/spec/core/placeholder_literalizer_spec.rb +20 -2
  125. data/spec/core/schema_generator_spec.rb +6 -6
  126. data/spec/core/schema_spec.rb +54 -5
  127. data/spec/core_extensions_spec.rb +122 -18
  128. data/spec/deprecation_helper.rb +27 -2
  129. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
  130. data/spec/extensions/association_proxies_spec.rb +2 -2
  131. data/spec/extensions/auto_literal_strings_spec.rb +212 -0
  132. data/spec/extensions/blacklist_security_spec.rb +1 -0
  133. data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
  134. data/spec/extensions/column_select_spec.rb +20 -8
  135. data/spec/extensions/columns_introspection_spec.rb +3 -3
  136. data/spec/extensions/core_refinements_spec.rb +29 -12
  137. data/spec/extensions/dataset_associations_spec.rb +12 -12
  138. data/spec/extensions/def_dataset_method_spec.rb +100 -0
  139. data/spec/extensions/error_sql_spec.rb +1 -1
  140. data/spec/extensions/finder_spec.rb +260 -0
  141. data/spec/extensions/graph_each_spec.rb +2 -2
  142. data/spec/extensions/identifier_mangling_spec.rb +14 -8
  143. data/spec/extensions/inverted_subsets_spec.rb +4 -4
  144. data/spec/extensions/lazy_attributes_spec.rb +7 -0
  145. data/spec/extensions/many_through_many_spec.rb +38 -14
  146. data/spec/extensions/nested_attributes_spec.rb +18 -6
  147. data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
  148. data/spec/extensions/pg_enum_spec.rb +16 -1
  149. data/spec/extensions/pg_interval_spec.rb +11 -2
  150. data/spec/extensions/pg_loose_count_spec.rb +5 -0
  151. data/spec/extensions/pg_row_spec.rb +25 -0
  152. data/spec/extensions/prepared_statements_spec.rb +10 -1
  153. data/spec/extensions/query_spec.rb +2 -2
  154. data/spec/extensions/schema_dumper_spec.rb +2 -2
  155. data/spec/extensions/schema_spec.rb +2 -2
  156. data/spec/extensions/set_overrides_spec.rb +7 -3
  157. data/spec/extensions/sql_expr_spec.rb +0 -1
  158. data/spec/extensions/subset_conditions_spec.rb +6 -6
  159. data/spec/extensions/table_select_spec.rb +24 -12
  160. data/spec/extensions/to_dot_spec.rb +4 -4
  161. data/spec/extensions/whitelist_security_spec.rb +131 -0
  162. data/spec/integration/dataset_test.rb +9 -5
  163. data/spec/integration/model_test.rb +2 -0
  164. data/spec/integration/plugin_test.rb +2 -2
  165. data/spec/integration/spec_helper.rb +1 -1
  166. data/spec/model/associations_spec.rb +39 -11
  167. data/spec/model/base_spec.rb +44 -24
  168. data/spec/model/class_dataset_methods_spec.rb +18 -16
  169. data/spec/model/dataset_methods_spec.rb +4 -4
  170. data/spec/model/eager_loading_spec.rb +84 -24
  171. data/spec/model/model_spec.rb +97 -63
  172. data/spec/model/record_spec.rb +21 -13
  173. metadata +13 -2
@@ -10,20 +10,29 @@ module Sequel
10
10
  # ---------------------
11
11
 
12
12
  SQL_BEGIN = 'BEGIN'.freeze
13
+ Sequel::Deprecation.deprecate_constant(self, :SQL_BEGIN)
13
14
  SQL_COMMIT = 'COMMIT'.freeze
15
+ Sequel::Deprecation.deprecate_constant(self, :SQL_COMMIT)
14
16
  SQL_RELEASE_SAVEPOINT = 'RELEASE SAVEPOINT autopoint_%d'.freeze
17
+ Sequel::Deprecation.deprecate_constant(self, :SQL_RELEASE_SAVEPOINT)
15
18
  SQL_ROLLBACK = 'ROLLBACK'.freeze
19
+ Sequel::Deprecation.deprecate_constant(self, :SQL_ROLLBACK)
16
20
  SQL_ROLLBACK_TO_SAVEPOINT = 'ROLLBACK TO SAVEPOINT autopoint_%d'.freeze
21
+ Sequel::Deprecation.deprecate_constant(self, :SQL_ROLLBACK_TO_SAVEPOINT)
17
22
  SQL_SAVEPOINT = 'SAVEPOINT autopoint_%d'.freeze
23
+ Sequel::Deprecation.deprecate_constant(self, :SQL_SAVEPOINT)
18
24
 
19
25
  TRANSACTION_BEGIN = 'Transaction.begin'.freeze
26
+ Sequel::Deprecation.deprecate_constant(self, :TRANSACTION_BEGIN)
20
27
  TRANSACTION_COMMIT = 'Transaction.commit'.freeze
28
+ Sequel::Deprecation.deprecate_constant(self, :TRANSACTION_COMMIT)
21
29
  TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
30
+ Sequel::Deprecation.deprecate_constant(self, :TRANSACTION_ROLLBACK)
22
31
 
23
32
  TRANSACTION_ISOLATION_LEVELS = {:uncommitted=>'READ UNCOMMITTED'.freeze,
24
33
  :committed=>'READ COMMITTED'.freeze,
25
34
  :repeatable=>'REPEATABLE READ'.freeze,
26
- :serializable=>'SERIALIZABLE'.freeze}
35
+ :serializable=>'SERIALIZABLE'.freeze}#.freeze # SEQUEL5
27
36
 
28
37
  # The default transaction isolation level for this database,
29
38
  # used for all future transactions. For MSSQL, this should be set
@@ -122,7 +131,7 @@ module Sequel
122
131
  # use a savepoint you must use this option. If the surrounding transaction
123
132
  # uses :auto_savepoint, you can set this to false to not use a savepoint.
124
133
  # If the value given for this option is :only, it will only create a
125
- # savepoint if it is inside a transacation.
134
+ # savepoint if it is inside a transaction.
126
135
  #
127
136
  # PostgreSQL specific options:
128
137
  #
@@ -217,9 +226,10 @@ module Sequel
217
226
  rescue Exception => e
218
227
  begin
219
228
  rollback_transaction(conn, opts)
220
- rescue Exception
229
+ rescue Exception => e3
221
230
  end
222
231
  transaction_error(e, :conn=>conn, :rollback=>rollback)
232
+ raise e3 if e3
223
233
  ret
224
234
  ensure
225
235
  begin
@@ -292,7 +302,7 @@ module Sequel
292
302
 
293
303
  # SQL to start a new savepoint
294
304
  def begin_savepoint_sql(depth)
295
- SQL_SAVEPOINT % depth
305
+ "SAVEPOINT autopoint_#{depth}"
296
306
  end
297
307
 
298
308
  # Start a new database connection on the given connection
@@ -316,7 +326,7 @@ module Sequel
316
326
 
317
327
  # SQL to BEGIN a transaction.
318
328
  def begin_transaction_sql
319
- SQL_BEGIN
329
+ 'BEGIN'
320
330
  end
321
331
 
322
332
  # Whether to commit the current transaction. Thread.current.status is
@@ -340,7 +350,7 @@ module Sequel
340
350
 
341
351
  # SQL to commit a savepoint
342
352
  def commit_savepoint_sql(depth)
343
- SQL_RELEASE_SAVEPOINT % depth
353
+ "RELEASE SAVEPOINT autopoint_#{depth}"
344
354
  end
345
355
 
346
356
  # Commit the active transaction on the connection
@@ -355,7 +365,7 @@ module Sequel
355
365
 
356
366
  # SQL to COMMIT a transaction.
357
367
  def commit_transaction_sql
358
- SQL_COMMIT
368
+ 'COMMIT'
359
369
  end
360
370
 
361
371
  # Method called on the connection object to execute SQL on the database,
@@ -393,7 +403,7 @@ module Sequel
393
403
 
394
404
  # SQL to rollback to a savepoint
395
405
  def rollback_savepoint_sql(depth)
396
- SQL_ROLLBACK_TO_SAVEPOINT % depth
406
+ "ROLLBACK TO SAVEPOINT autopoint_#{depth}"
397
407
  end
398
408
 
399
409
  # Rollback the active transaction on the connection
@@ -408,7 +418,7 @@ module Sequel
408
418
 
409
419
  # SQL to ROLLBACK a transaction.
410
420
  def rollback_transaction_sql
411
- SQL_ROLLBACK
421
+ 'ROLLBACK'
412
422
  end
413
423
 
414
424
  # Set the transaction isolation level on the given connection
@@ -34,7 +34,7 @@ module Sequel
34
34
  # DB[:table][:id=>1] # SELECT * FROM table WHERE (id = 1) LIMIT 1
35
35
  # # => {:id=1}
36
36
  def [](*conditions)
37
- raise(Error, ARRAY_ACCESS_ERROR_MSG) if (conditions.length == 1 and conditions.first.is_a?(Integer)) or conditions.length == 0
37
+ raise(Error, 'You cannot call Dataset#[] with an integer or with no arguments') if (conditions.length == 1 and conditions.first.is_a?(Integer)) or conditions.length == 0
38
38
  first(*conditions)
39
39
  end
40
40
 
@@ -104,7 +104,8 @@ module Sequel
104
104
  def count(arg=(no_arg=true), &block)
105
105
  if no_arg && !block
106
106
  cached_dataset(:_count_ds) do
107
- aggregate_dataset.select{count{}.*.as(:count)}.single_value_ds
107
+ aggregate_dataset.select(Sequel.function(:count).*.as(:count)).single_value_ds
108
+ #aggregate_dataset.select(COUNT_SELECT).single_value_ds # SEQUEL5
108
109
  end.single_value!.to_i
109
110
  else
110
111
  if block
@@ -118,6 +119,9 @@ module Sequel
118
119
  _aggregate(:count, arg)
119
120
  end
120
121
  end
122
+ # SEQUEL5
123
+ #COUNT_SELECT = Sequel.function(:count).*.as(:count)
124
+ #private_constant :COUNT_SELECT
121
125
 
122
126
  # Deletes the records in the dataset. The returned value should be
123
127
  # number of records deleted, but that is adapter dependent.
@@ -158,8 +162,12 @@ module Sequel
158
162
  def empty?
159
163
  cached_dataset(:_empty_ds) do
160
164
  single_value_ds.unordered.select(Sequel::SQL::AliasedExpression.new(1, :one))
165
+ # single_value_ds.unordered.select(EMPTY_SELECT) # SEQUEL5
161
166
  end.single_value!.nil?
162
167
  end
168
+ # SEQUEL5
169
+ #EMPTY_SELECT = Sequel::SQL::AliasedExpression.new(1, :one)
170
+ #private_constant :EMPTY_SELECT
163
171
 
164
172
  # If a integer argument is given, it is interpreted as a limit, and then returns all
165
173
  # matching records up to that limit. If no argument is passed,
@@ -267,7 +275,7 @@ module Sequel
267
275
  def get(column=(no_arg=true; nil), &block)
268
276
  ds = naked
269
277
  if block
270
- raise(Error, ARG_BLOCK_ERROR_MSG) unless no_arg
278
+ raise(Error, 'Must call Dataset#get with an argument or a block, not both') unless no_arg
271
279
  ds = ds.select(&block)
272
280
  column = ds.opts[:select]
273
281
  column = nil if column.is_a?(Array) && column.length < 2
@@ -334,7 +342,7 @@ module Sequel
334
342
  return @db.transaction{insert(columns, values)} if values.is_a?(Dataset)
335
343
 
336
344
  return if values.empty?
337
- raise(Error, IMPORT_ERROR_MSG) if columns.empty?
345
+ raise(Error, 'Using Sequel::Dataset#import with an empty column array is not allowed') if columns.empty?
338
346
  ds = opts[:server] ? server(opts[:server]) : self
339
347
 
340
348
  if slice_size = opts.fetch(:commit_every, opts.fetch(:slice, default_import_slice))
@@ -444,7 +452,7 @@ module Sequel
444
452
  # # => [[1, 'A'], [2, 'B'], [3, 'C'], ...]
445
453
  def map(column=nil, &block)
446
454
  if column
447
- raise(Error, ARG_BLOCK_ERROR_MSG) if block
455
+ raise(Error, 'Must call Dataset#map with either an argument or a block, not both') if block
448
456
  return naked.map(column) if row_proc
449
457
  if column.is_a?(Array)
450
458
  super(){|r| r.values_at(*column)}
@@ -972,7 +980,8 @@ module Sequel
972
980
 
973
981
  # Returns an array of the first value in each row.
974
982
  def _select_map_single
975
- map{|r| r.values.first}
983
+ k = nil
984
+ map{|r| r[k||=r.keys.first]}
976
985
  end
977
986
 
978
987
  # A dataset for returning single values from the current dataset.
@@ -16,11 +16,16 @@ module Sequel
16
16
  # DB[:table].add_graph_aliases(:some_alias=>[:table, :column])
17
17
  # # SELECT ..., table.column AS some_alias
18
18
  def add_graph_aliases(graph_aliases)
19
- unless (ga = opts[:graph_aliases]) || (opts[:graph] && (ga = opts[:graph][:column_aliases]))
19
+ graph = opts[:graph]
20
+ unless (ga = opts[:graph_aliases]) || (graph && (ga = graph[:column_aliases])) # SEQUEL5: Remove graph_aliases support
20
21
  raise Error, "cannot call add_graph_aliases on a dataset that has not been called with graph or set_graph_aliases"
21
22
  end
22
23
  columns, graph_aliases = graph_alias_columns(graph_aliases)
23
- select_append(*columns).clone(:graph_aliases => Hash[ga].merge!(graph_aliases).freeze)
24
+ if opts[:graph_aliases]
25
+ select_append(*columns).clone(:graph_aliases => Hash[ga].merge!(graph_aliases).freeze) # SEQUEL5: Remove
26
+ else
27
+ select_append(*columns).clone(:graph => Hash[graph].merge!(:column_aliases=>Hash[ga].merge!(graph_aliases).freeze).freeze)
28
+ end
24
29
  end
25
30
 
26
31
  # Similar to Dataset#join_table, but uses unambiguous aliases for selected
@@ -114,7 +119,7 @@ module Sequel
114
119
  # Whether to include the table in the result set
115
120
  add_table = options[:select] == false ? false : true
116
121
  # Whether to add the columns to the list of column aliases
117
- add_columns = !ds.opts.include?(:graph_aliases)
122
+ add_columns = !ds.opts.include?(:graph_aliases) # SEQUEL5: Remove graph_aliases support
118
123
 
119
124
  if graph = opts[:graph]
120
125
  graph = graph.dup
@@ -230,13 +235,18 @@ module Sequel
230
235
  # # SELECT artists.name, albums.name AS album_name, 42 AS forty_two ...
231
236
  def set_graph_aliases(graph_aliases)
232
237
  columns, graph_aliases = graph_alias_columns(graph_aliases)
233
- select(*columns).clone(:graph_aliases=>graph_aliases.freeze)
238
+ if graph = opts[:graph]
239
+ select(*columns).clone(:graph => Hash[graph].merge!(:column_aliases=>graph_aliases.freeze).freeze)
240
+ else
241
+ Sequel::Deprecation.deprecate("Calling Dataset#set_graph_aliases before Dataset#graph", "Call Dataset#set_graph_aliases after Dataset#graph now")
242
+ select(*columns).clone(:graph_aliases=>graph_aliases.freeze) # SEQUEL5: Remove
243
+ end
234
244
  end
235
245
 
236
246
  # Remove the splitting of results into subhashes, and all metadata
237
247
  # related to the current graph (if any).
238
248
  def ungraphed
239
- clone(:graph=>nil, :graph_aliases=>nil)
249
+ clone(:graph=>nil, :graph_aliases=>nil) # SEQUEL5: Remove :graph_aliases
240
250
  end
241
251
 
242
252
  private
@@ -8,9 +8,13 @@ module Sequel
8
8
  # ---------------------
9
9
 
10
10
  NOTIMPL_MSG = "This method must be overridden in Sequel adapters".freeze
11
+ Sequel::Deprecation.deprecate_constant(self, :NOTIMPL_MSG)
11
12
  ARRAY_ACCESS_ERROR_MSG = 'You cannot call Dataset#[] with an integer or with no arguments.'.freeze
13
+ Sequel::Deprecation.deprecate_constant(self, :ARRAY_ACCESS_ERROR_MSG)
12
14
  ARG_BLOCK_ERROR_MSG = 'Must use either an argument or a block, not both'.freeze
15
+ Sequel::Deprecation.deprecate_constant(self, :ARG_BLOCK_ERROR_MSG)
13
16
  IMPORT_ERROR_MSG = 'Using Sequel::Dataset#import an empty column array is not allowed'.freeze
17
+ Sequel::Deprecation.deprecate_constant(self, :IMPORT_ERROR_MSG)
14
18
 
15
19
  # The database related to this dataset. This is the Database instance that
16
20
  # will execute all of this dataset's queries.
@@ -29,7 +33,7 @@ module Sequel
29
33
  # the Database#dataset method return an instance of that subclass.
30
34
  def initialize(db)
31
35
  @db = db
32
- @opts = {}
36
+ @opts = {} # OPTS # SEQUEL5
33
37
  @cache = {}
34
38
  end
35
39
 
@@ -50,6 +54,10 @@ module Sequel
50
54
  self == o
51
55
  end
52
56
 
57
+ # SEQUEL5: Remove other dup methods
58
+ # def dup
59
+ # self
60
+ # end
53
61
  if TRUE_FREEZE
54
62
  # Similar to #clone, but returns an unfrozen clone if the receiver is frozen.
55
63
  def dup
@@ -92,12 +100,12 @@ module Sequel
92
100
  else
93
101
  # :nocov:
94
102
  def freeze # :nodoc:
95
- @opts.freeze
103
+ @opts.freeze # SEQUEL5: remove
96
104
  self
97
105
  end
98
106
 
99
107
  def frozen? # :nodoc:
100
- @opts.frozen?
108
+ @opts.frozen? # SEQUEL5: true
101
109
  end
102
110
  # :nocov:
103
111
  end
@@ -295,7 +303,7 @@ module Sequel
295
303
  def cached_dataset(key)
296
304
  unless ds = cache_get(key)
297
305
  ds = yield
298
- cache_set(key, ds) if frozen?
306
+ cache_set(key, ds) if frozen? # SEQUEL5: Remove if frozen?
299
307
  end
300
308
 
301
309
  ds
@@ -9,6 +9,7 @@ module Sequel
9
9
 
10
10
  # All methods that should have a ! method added that modifies the receiver.
11
11
  MUTATION_METHODS = QUERY_METHODS - [:naked, :from_self]
12
+ Sequel::Deprecation.deprecate_constant(self, :MUTATION_METHODS)
12
13
 
13
14
  # Setup mutation (e.g. filter!) methods. These operate the same as the
14
15
  # non-! methods, but replace the options of the current dataset with the
@@ -26,38 +27,38 @@ module Sequel
26
27
  end
27
28
 
28
29
  # Add the mutation methods via metaprogramming
29
- def_mutation_method(*MUTATION_METHODS)
30
+ def_mutation_method(*(QUERY_METHODS - [:naked, :from_self]))
30
31
 
31
32
  # Like #extension, but modifies and returns the receiver instead of returning a modified clone.
32
33
  def extension!(*exts)
33
- raise_if_frozen!("extension!")
34
+ raise_if_frozen!(%w"extension! extension")
34
35
  _extension!(exts)
35
36
  end
36
37
 
37
38
  # Avoid self-referential dataset by cloning.
38
39
  def from_self!(*args, &block)
39
- raise_if_frozen!("from_self!")
40
+ raise_if_frozen!(%w"from_self! from_self")
40
41
  @opts = clone.from_self(*args, &block).opts
41
42
  self
42
43
  end
43
44
 
44
45
  # Remove the row_proc from the current dataset.
45
46
  def naked!
46
- raise_if_frozen!("naked=")
47
+ raise_if_frozen!(%w"naked! naked")
47
48
  @opts[:row_proc] = nil
48
49
  self
49
50
  end
50
51
 
51
52
  # Set whether to quote identifiers for this dataset
52
53
  def quote_identifiers=(v)
53
- raise_if_frozen!("quote_identifiers=")
54
+ raise_if_frozen!(%w"quote_identifiers= with_quote_identifiers")
54
55
  skip_symbol_cache!
55
56
  @opts[:quote_identifiers] = v
56
57
  end
57
58
 
58
59
  # Override the row_proc for this dataset
59
60
  def row_proc=(v)
60
- raise_if_frozen!("row_proc=")
61
+ raise_if_frozen!(%w"row_proc= with_row_proc")
61
62
  @opts[:row_proc] = v
62
63
  end
63
64
 
@@ -67,7 +68,7 @@ module Sequel
67
68
  # to the receiver and merging the options of the resulting dataset into
68
69
  # the receiver's options.
69
70
  def mutation_method(meth, *args, &block)
70
- raise_if_frozen!("#{meth}!")
71
+ raise_if_frozen!(["#{meth}!", meth])
71
72
  @opts = send(meth, *args, &block).opts
72
73
  @cache = {}
73
74
  self
@@ -78,7 +79,15 @@ module Sequel
78
79
  if frozen?
79
80
  raise RuntimeError, "can't modify frozen #{visible_class_name}"
80
81
  end
81
- Sequel::Deprecation.deprecate("Dataset mutation is deprecated and will be removed in Sequel 5#{" (method called: #{meth})" if meth}")
82
+ case meth
83
+ when Array
84
+ meth = " (method called: #{meth.first}, non-mutating replacement: #{meth.last})"
85
+ when String
86
+ # :nocov:
87
+ meth = " (method called: #{meth})"
88
+ # :nocov:
89
+ end
90
+ Sequel::Deprecation.deprecate("Dataset mutation is deprecated and will be removed in Sequel 5#{meth}")
82
91
  end
83
92
 
84
93
  # Set the dataset to skip the symbol cache
@@ -92,6 +92,7 @@ module Sequel
92
92
  Dataset.def_deprecated_opts_setter(self, :log_sql, :prepared_type, :prepared_args, :orig_dataset, :prepared_modify_values)
93
93
 
94
94
  PLACEHOLDER_RE = /\A\$(.*)\z/
95
+ Sequel::Deprecation.deprecate_constant(self, :PLACEHOLDER_RE)
95
96
 
96
97
  # Whether to log the full SQL query. By default, just the prepared statement
97
98
  # name is generally logged on adapters that support native prepared statements.
@@ -166,7 +167,7 @@ module Sequel
166
167
  # prepared_args is present. If so, they are considered placeholders,
167
168
  # and they are substituted using prepared_arg.
168
169
  def literal_symbol_append(sql, v)
169
- if @opts[:bind_vars] and match = PLACEHOLDER_RE.match(v.to_s)
170
+ if @opts[:bind_vars] and match = /\A\$(.*)\z/.match(v.to_s)
170
171
  s = match[1].to_sym
171
172
  if prepared_arg?(s)
172
173
  literal_append(sql, prepared_arg(s))
@@ -212,7 +213,7 @@ module Sequel
212
213
  when :insert_pk
213
214
  fetch_rows(prepared_sql){|r| return r.values.first}
214
215
  when Array
215
- case prepared_type.at(0)
216
+ case prepared_type[0]
216
217
  when :map, :to_hash, :to_hash_groups
217
218
  send(*prepared_type, &block)
218
219
  end
@@ -12,13 +12,15 @@ module Sequel
12
12
  # in the extension).
13
13
  EXTENSIONS = {}
14
14
 
15
+ EMPTY_ARRAY = [].freeze
16
+
15
17
  # The dataset options that require the removal of cached columns
16
18
  # if changed.
17
19
  COLUMN_CHANGE_OPTS = [:select, :sql, :from, :join].freeze
18
20
 
19
21
  # Which options don't affect the SQL generation. Used by simple_select_all?
20
22
  # to determine if this is a simple SELECT * FROM table.
21
- NON_SQL_OPTIONS = [:server, :graph, :eager, :eager_graph, :graph_aliases, :row_proc, :quote_identifiers, :identifier_input_method, :identifier_output_method, :skip_symbol_cache, :model, :model_object, :association_reflection, :fetch, :numrows, :autoid].freeze
23
+ NON_SQL_OPTIONS = [:server, :graph, :eager, :eager_graph, :graph_aliases, :row_proc, :quote_identifiers, :identifier_input_method, :identifier_output_method, :skip_symbol_cache, :model, :model_object, :association_reflection, :fetch, :numrows, :autoid].freeze # SEQUEL5: Remove graph_aliases
22
24
 
23
25
  # These symbols have _join methods created (e.g. inner_join) that
24
26
  # call join_table with the symbol, passing along the arguments and
@@ -91,7 +93,7 @@ module Sequel
91
93
  unless opts.each_key{|o| break if COLUMN_CHANGE_OPTS.include?(o)}
92
94
  c.clear_columns_cache
93
95
  end
94
- c.freeze if frozen?
96
+ c.freeze if frozen? # SEQUEL5: Remove if frozen?
95
97
  c
96
98
  end
97
99
  else
@@ -102,7 +104,7 @@ module Sequel
102
104
  unless opts.each_key{|o| break if COLUMN_CHANGE_OPTS.include?(o)}
103
105
  c.clear_columns_cache
104
106
  end
105
- c.freeze if frozen?
107
+ c.freeze if frozen? # SEQUEL5: c.opts.freeze
106
108
  c
107
109
  end
108
110
  # :nocov:
@@ -172,7 +174,7 @@ module Sequel
172
174
  # DB[:items].exclude(Sequel.~(:category=>nil) & {:category => 'software'})
173
175
  # # SELECT * FROM items WHERE ((category IS NULL) OR (category != 'software'))
174
176
  def exclude(*cond, &block)
175
- _filter_or_exclude(true, :where, *cond, &block)
177
+ add_filter(:where, cond, true, &block)
176
178
  end
177
179
 
178
180
  # Inverts the given conditions and adds them to the HAVING clause.
@@ -183,7 +185,7 @@ module Sequel
183
185
  # See documentation for exclude for how inversion is handled in regards
184
186
  # to SQL 3-valued boolean logic.
185
187
  def exclude_having(*cond, &block)
186
- _filter_or_exclude(true, :having, *cond, &block)
188
+ add_filter(:having, cond, true, &block)
187
189
  end
188
190
 
189
191
  # Alias for exclude.
@@ -198,7 +200,7 @@ module Sequel
198
200
  def extension(*a)
199
201
  c = _clone(:freeze=>false)
200
202
  c.send(:_extension!, a)
201
- c.freeze if frozen?
203
+ c.freeze if frozen? # SEQUEL5: Remove if frozen?
202
204
  c
203
205
  end
204
206
  else
@@ -258,7 +260,7 @@ module Sequel
258
260
  end
259
261
  end
260
262
  o = {:from=>source.empty? ? nil : source.freeze}
261
- o[:with] = ((opts[:with] || []) + ctes).freeze if ctes
263
+ o[:with] = ((opts[:with] || EMPTY_ARRAY) + ctes).freeze if ctes
262
264
  o[:num_dataset_sources] = table_alias_num if table_alias_num > 0
263
265
  clone(o)
264
266
  end
@@ -413,7 +415,7 @@ module Sequel
413
415
  # DB[:items].group(:sum).having(:sum=>10)
414
416
  # # SELECT * FROM items GROUP BY sum HAVING (sum = 10)
415
417
  def having(*cond, &block)
416
- _filter(:having, *cond, &block)
418
+ add_filter(:having, cond, &block)
417
419
  end
418
420
 
419
421
  # Adds an INTERSECT clause using a second dataset object.
@@ -542,8 +544,6 @@ module Sequel
542
544
  end
543
545
 
544
546
  table_alias = options[:table_alias]
545
- last_alias = options[:implicit_qualifier]
546
- qualify_type = options[:qualify]
547
547
 
548
548
  if table.is_a?(SQL::AliasedExpression)
549
549
  table_expr = if table_alias
@@ -573,7 +573,8 @@ module Sequel
573
573
  raise(Sequel::Error, "can't use a block if providing an array of symbols as expr") if block
574
574
  SQL::JoinUsingClause.new(expr, type, table_expr)
575
575
  else
576
- last_alias ||= @opts[:last_joined_table] || first_source_alias
576
+ last_alias = options[:implicit_qualifier] || @opts[:last_joined_table] || first_source_alias
577
+ qualify_type = options[:qualify]
577
578
  if Sequel.condition_specifier?(expr)
578
579
  expr = expr.collect do |k, v|
579
580
  qualify_type = default_join_table_qualification if qualify_type.nil?
@@ -592,13 +593,13 @@ module Sequel
592
593
  expr = SQL::BooleanExpression.from_value_pairs(expr)
593
594
  end
594
595
  if block
595
- expr2 = yield(table_name, last_alias, @opts[:join] || [])
596
+ expr2 = yield(table_name, last_alias, @opts[:join] || EMPTY_ARRAY)
596
597
  expr = expr ? SQL::BooleanExpression.new(:AND, expr, expr2) : expr2
597
598
  end
598
599
  SQL::JoinOnClause.new(expr, type, table_expr)
599
600
  end
600
601
 
601
- opts = {:join => ((@opts[:join] || []) + [join]).freeze}
602
+ opts = {:join => ((@opts[:join] || EMPTY_ARRAY) + [join]).freeze}
602
603
  opts[:last_joined_table] = table_name unless options[:reset_implicit_qualifier] == false
603
604
  opts[:num_dataset_sources] = table_alias_num if table_alias_num
604
605
  clone(opts)
@@ -694,17 +695,17 @@ module Sequel
694
695
  clone(:offset => o)
695
696
  end
696
697
 
697
- # Adds an alternate filter to an existing filter using OR. If no filter
698
- # exists an +Error+ is raised.
698
+ # Adds an alternate filter to an existing WHERE clause using OR. If there
699
+ # is no WHERE clause, then the default is WHERE true, and OR would be redundant,
700
+ # so return an unmodified clone of the dataset in that case.
699
701
  #
700
702
  # DB[:items].where(:a).or(:b) # SELECT * FROM items WHERE a OR b
703
+ # DB[:items].or(:b) # SELECT * FROM items
701
704
  def or(*cond, &block)
702
- cond = cond.first if cond.size == 1
703
- v = @opts[:where]
704
- if v.nil? || (cond.respond_to?(:empty?) && cond.empty? && !block)
705
+ if @opts[:where].nil?
705
706
  clone
706
707
  else
707
- clone(:where => SQL::BooleanExpression.new(:OR, v, filter_expr(cond, &block)))
708
+ add_filter(:where, cond, false, :OR, &block)
708
709
  end
709
710
  end
710
711
 
@@ -766,7 +767,7 @@ module Sequel
766
767
  # # SELECT i.* FROM items WHERE (i.id = 1)
767
768
  def qualify(table=first_source)
768
769
  o = @opts
769
- return clone if o[:sql]
770
+ return clone if o[:sql] # SEQUEL5: return self
770
771
  h = {}
771
772
  (o.keys & QUALIFY_KEYS).each do |k|
772
773
  h[k] = qualified_expression(o[k], table)
@@ -1030,7 +1031,7 @@ module Sequel
1030
1031
  #
1031
1032
  # See the {"Dataset Filtering" guide}[rdoc-ref:doc/dataset_filtering.rdoc] for more examples and details.
1032
1033
  def where(*cond, &block)
1033
- _filter(:where, *cond, &block)
1034
+ add_filter(:where, cond, &block)
1034
1035
  end
1035
1036
 
1036
1037
  # Add a common table expression (CTE) with the given name and a dataset that defines the CTE.
@@ -1047,7 +1048,7 @@ module Sequel
1047
1048
  s, ds = hoist_cte(dataset)
1048
1049
  s.with(name, ds, opts)
1049
1050
  else
1050
- clone(:with=>((@opts[:with]||[]) + [Hash[opts].merge!(:name=>name, :dataset=>dataset)]).freeze)
1051
+ clone(:with=>((@opts[:with]||EMPTY_ARRAY) + [Hash[opts].merge!(:name=>name, :dataset=>dataset)]).freeze)
1051
1052
  end
1052
1053
  end
1053
1054
 
@@ -1076,7 +1077,7 @@ module Sequel
1076
1077
  s, ds = hoist_cte(recursive)
1077
1078
  s.with_recursive(name, nonrecursive, ds, opts)
1078
1079
  else
1079
- clone(:with=>((@opts[:with]||[]) + [Hash[opts].merge!(:recursive=>true, :name=>name, :dataset=>nonrecursive.union(recursive, {:all=>opts[:union_all] != false, :from_self=>false}))]).freeze)
1080
+ clone(:with=>((@opts[:with]||EMPTY_ARRAY) + [Hash[opts].merge!(:recursive=>true, :name=>name, :dataset=>nonrecursive.union(recursive, {:all=>opts[:union_all] != false, :from_self=>false}))]).freeze)
1080
1081
  end
1081
1082
  end
1082
1083
 
@@ -1090,7 +1091,7 @@ module Sequel
1090
1091
  c = _clone(:freeze=>false)
1091
1092
  c.extend(*mods) unless mods.empty?
1092
1093
  c.extend(Module.new(&block)) if block
1093
- c.freeze if frozen?
1094
+ c.freeze if frozen? # SEQUEL5: Remove if frozen?
1094
1095
  c
1095
1096
  end
1096
1097
  else
@@ -1171,14 +1172,21 @@ module Sequel
1171
1172
  !(@opts.collect{|k,v| k unless v.nil?}.compact & opts).empty?
1172
1173
  end
1173
1174
 
1175
+ # From types allowed to be considered a simple_select_all
1176
+ SIMPLE_SELECT_ALL_ALLOWED_FROM = [Symbol, SQL::Identifier, SQL::QualifiedIdentifier].freeze
1177
+
1174
1178
  # Whether this dataset is a simple select from an underlying table, such as:
1175
1179
  #
1176
1180
  # SELECT * FROM table
1177
1181
  # SELECT table.* FROM table
1178
1182
  def simple_select_all?
1183
+ return false unless (f = @opts[:from]) && f.length == 1
1179
1184
  non_sql = non_sql_options
1180
1185
  o = @opts.reject{|k,v| v.nil? || non_sql.include?(k)}
1181
- if (f = o[:from]) && f.length == 1 && (f.first.is_a?(Symbol) || f.first.is_a?(SQL::AliasedExpression))
1186
+ from = f.first
1187
+ from = from.expression if from.is_a?(SQL::AliasedExpression)
1188
+
1189
+ if SIMPLE_SELECT_ALL_ALLOWED_FROM.any?{|x| from.is_a?(x)}
1182
1190
  case o.length
1183
1191
  when 1
1184
1192
  true
@@ -1207,24 +1215,54 @@ module Sequel
1207
1215
  self
1208
1216
  end
1209
1217
 
1210
- # Internal filtering method so it works on either the WHERE or HAVING clauses, with or
1211
- # without inversion.
1212
- def _filter_or_exclude(invert, clause, *cond, &block)
1218
+ def add_filter(clause, cond, invert=false, combine=:AND, &block)
1219
+ if cond == EMPTY_ARRAY && !block
1220
+ Sequel::Deprecation.deprecate("Passing no arguments and no block to a filtering method", "Include at least one argument or a block when calling a filtering method")
1221
+ #raise Error, "must provide an argument to a filtering method if not passing a block" # SEQUEL5
1222
+ end
1223
+
1213
1224
  cond = cond.first if cond.size == 1
1214
- if cond.respond_to?(:empty?) && cond.empty? && !block
1225
+
1226
+ empty = cond == OPTS || cond == EMPTY_ARRAY
1227
+ old_empty = cond.respond_to?(:empty?) && cond.empty?
1228
+ if old_empty && !empty
1229
+ Sequel::Deprecation.deprecate("Treating #{cond.inspect} as a empty filter expression", "Only {} and [] are considered empty expressions now")
1230
+ empty = true
1231
+ end
1232
+
1233
+ if empty && !block
1215
1234
  clone
1216
1235
  else
1236
+ if cond == nil
1237
+ if block
1238
+ Sequel::Deprecation.deprecate("Ignoring explicit nil argument when passing a block to a filtering method", "Do not pass an explicit nil argument to the filtering method, only pass the block")
1239
+ end
1240
+ unless @opts[clause]
1241
+ Sequel::Deprecation.deprecate("Ignoring explicit nil argument to a filtering method if dataset has no explicit filter", "Starting in Sequel 5, this will add a NULL condition")
1242
+ end
1243
+ #cond = Sequel::NULL # SEQUEL5
1244
+ end
1245
+ if empty && block
1246
+ cond = nil
1247
+ end
1248
+
1217
1249
  cond = filter_expr(cond, &block)
1218
1250
  cond = SQL::BooleanExpression.invert(cond) if invert
1219
- cond = SQL::BooleanExpression.new(:AND, @opts[clause], cond) if @opts[clause]
1251
+ cond = SQL::BooleanExpression.new(combine, @opts[clause], cond) if @opts[clause]
1220
1252
  clone(clause => cond)
1221
1253
  end
1222
1254
  end
1223
1255
 
1224
- # Internal filter method so it works on either the having or where clauses.
1256
+ # :nocov:
1257
+ def _filter_or_exclude(invert, clause, *cond, &block)
1258
+ Sequel::Deprecation.deprecate("Sequel::Dataset#_filter/_filter_or_exclude (private methods)", "Switch to calling a public dataset filtering method directly")
1259
+ add_filter(clause, cond, invert, &block)
1260
+ end
1261
+
1225
1262
  def _filter(clause, *cond, &block)
1226
1263
  _filter_or_exclude(false, clause, *cond, &block)
1227
1264
  end
1265
+ # :nocov:
1228
1266
 
1229
1267
  # The default :qualify option to use for join tables if one is not specified.
1230
1268
  def default_join_table_qualification
@@ -1233,7 +1271,7 @@ module Sequel
1233
1271
 
1234
1272
  # SQL expression object based on the expr type. See +where+.
1235
1273
  def filter_expr(expr = nil, &block)
1236
- expr = nil if expr == []
1274
+ expr = nil if expr == EMPTY_ARRAY
1237
1275
 
1238
1276
  if block
1239
1277
  if expr
@@ -1247,10 +1285,13 @@ module Sequel
1247
1285
  when Hash
1248
1286
  SQL::BooleanExpression.from_value_pairs(expr)
1249
1287
  when Array
1250
- if (sexpr = expr.at(0)).is_a?(String)
1251
- SQL::PlaceholderLiteralString.new(sexpr, expr[1..-1], true)
1252
- elsif Sequel.condition_specifier?(expr)
1288
+ if Sequel.condition_specifier?(expr)
1253
1289
  SQL::BooleanExpression.from_value_pairs(expr)
1290
+ #else # SEQUEL5
1291
+ # raise(Error, "Invalid filter expression: #{expr.inspect}")
1292
+ elsif (sexpr = expr[0]).is_a?(String)
1293
+ Sequel::Deprecation.deprecate("Calling a dataset filtering method with multiple arguments or an array where the first argument/element is a string", "Use Sequel.lit(#{sexpr.inspect}#{", #{expr[1..-1].map(&:inspect).join(', ')}" if expr.length > 1}) to create an SQL fragment expression and pass that to the dataset filtering method, or use the auto_literal_strings extension")
1294
+ SQL::PlaceholderLiteralString.new(sexpr, expr[1..-1], true)
1254
1295
  else
1255
1296
  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")
1256
1297
  SQL::BooleanExpression.new(:AND, *expr.map{|x| filter_expr(x)})
@@ -1258,7 +1299,9 @@ module Sequel
1258
1299
  when Proc
1259
1300
  Sequel::Deprecation.deprecate("Passing Proc objects as filter arguments", "Pass them as blocks to the filtering methods or to Sequel.expr")
1260
1301
  filter_expr(Sequel.virtual_row(&expr))
1261
- when Numeric, SQL::NumericExpression, SQL::StringExpression #, Proc # SEQUEL5
1302
+ when LiteralString
1303
+ LiteralString.new("(#{expr})")
1304
+ when Numeric, SQL::NumericExpression, SQL::StringExpression #, Proc, String # SEQUEL5
1262
1305
  raise(Error, "Invalid filter expression: #{expr.inspect}")
1263
1306
  when TrueClass, FalseClass
1264
1307
  if supports_where_true?
@@ -1269,9 +1312,12 @@ module Sequel
1269
1312
  SQL::Constants::SQLFALSE
1270
1313
  end
1271
1314
  when String
1315
+ Sequel::Deprecation.deprecate("Calling a dataset filtering method with a plain string", "Use Sequel.lit(#{expr.inspect}) to create a literal string and pass that to the dataset filtering method, or use the auto_literal_strings extension")
1272
1316
  LiteralString.new("(#{expr})")
1273
1317
  when PlaceholderLiteralizer::Argument
1274
1318
  expr.transform{|v| filter_expr(v)}
1319
+ when SQL::PlaceholderLiteralString
1320
+ expr.with_parens
1275
1321
  else
1276
1322
  expr
1277
1323
  end
@@ -1281,7 +1327,7 @@ module Sequel
1281
1327
  # clause from the given dataset added to it, and the second a clone of
1282
1328
  # the given dataset with the WITH clause removed.
1283
1329
  def hoist_cte(ds)
1284
- [clone(:with => ((opts[:with] || []) + ds.opts[:with]).freeze), ds.clone(:with => nil)]
1330
+ [clone(:with => ((opts[:with] || EMPTY_ARRAY) + ds.opts[:with]).freeze), ds.clone(:with => nil)]
1285
1331
  end
1286
1332
 
1287
1333
  # Whether CTEs need to be hoisted from the given ds into the current ds.
@@ -1295,7 +1341,7 @@ module Sequel
1295
1341
  # DB[:items].invert_order([Sequel.desc(:id)]]) #=> [Sequel.asc(:id)]
1296
1342
  # DB[:items].invert_order([:category, Sequel.desc(:price)]) #=> [Sequel.desc(:category), Sequel.asc(:price)]
1297
1343
  def invert_order(order)
1298
- return nil unless order
1344
+ return unless order
1299
1345
  order.map do |f|
1300
1346
  case f
1301
1347
  when SQL::OrderedExpression