sequel 4.45.0 → 4.46.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +108 -0
- data/doc/release_notes/4.46.0.txt +404 -0
- data/doc/security.rdoc +9 -0
- data/doc/sql.rdoc +2 -2
- data/doc/testing.rdoc +1 -1
- data/doc/validations.rdoc +1 -2
- data/lib/sequel/adapters/ado.rb +8 -3
- data/lib/sequel/adapters/ado/access.rb +8 -4
- data/lib/sequel/adapters/ado/mssql.rb +3 -1
- data/lib/sequel/adapters/amalgalite.rb +5 -0
- data/lib/sequel/adapters/cubrid.rb +16 -7
- data/lib/sequel/adapters/do.rb +7 -1
- data/lib/sequel/adapters/do/mysql.rb +8 -4
- data/lib/sequel/adapters/ibmdb.rb +10 -5
- data/lib/sequel/adapters/jdbc.rb +8 -2
- data/lib/sequel/adapters/jdbc/as400.rb +10 -3
- data/lib/sequel/adapters/jdbc/db2.rb +27 -16
- data/lib/sequel/adapters/jdbc/derby.rb +47 -20
- data/lib/sequel/adapters/jdbc/h2.rb +13 -7
- data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
- data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
- data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
- data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
- data/lib/sequel/adapters/mock.rb +5 -0
- data/lib/sequel/adapters/mysql.rb +8 -1
- data/lib/sequel/adapters/mysql2.rb +6 -1
- data/lib/sequel/adapters/odbc.rb +20 -8
- data/lib/sequel/adapters/odbc/mssql.rb +6 -3
- data/lib/sequel/adapters/oracle.rb +12 -6
- data/lib/sequel/adapters/postgres.rb +20 -8
- data/lib/sequel/adapters/shared/access.rb +76 -47
- data/lib/sequel/adapters/shared/cubrid.rb +16 -11
- data/lib/sequel/adapters/shared/db2.rb +46 -19
- data/lib/sequel/adapters/shared/firebird.rb +20 -8
- data/lib/sequel/adapters/shared/informix.rb +6 -3
- data/lib/sequel/adapters/shared/mssql.rb +132 -72
- data/lib/sequel/adapters/shared/mysql.rb +112 -65
- data/lib/sequel/adapters/shared/oracle.rb +36 -21
- data/lib/sequel/adapters/shared/postgres.rb +91 -56
- data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
- data/lib/sequel/adapters/shared/sqlite.rb +67 -32
- data/lib/sequel/adapters/sqlanywhere.rb +9 -1
- data/lib/sequel/adapters/sqlite.rb +8 -1
- data/lib/sequel/adapters/swift.rb +5 -0
- data/lib/sequel/adapters/swift/mysql.rb +4 -2
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +10 -3
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
- data/lib/sequel/adapters/utils/pg_types.rb +14 -6
- data/lib/sequel/adapters/utils/replace.rb +4 -2
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/core.rb +24 -11
- data/lib/sequel/database/connecting.rb +9 -3
- data/lib/sequel/database/dataset_defaults.rb +7 -1
- data/lib/sequel/database/logging.rb +1 -0
- data/lib/sequel/database/misc.rb +5 -2
- data/lib/sequel/database/query.rb +7 -5
- data/lib/sequel/database/schema_generator.rb +1 -0
- data/lib/sequel/database/schema_methods.rb +50 -27
- data/lib/sequel/database/transactions.rb +19 -9
- data/lib/sequel/dataset/actions.rb +15 -6
- data/lib/sequel/dataset/graph.rb +15 -5
- data/lib/sequel/dataset/misc.rb +12 -4
- data/lib/sequel/dataset/mutation.rb +17 -8
- data/lib/sequel/dataset/prepared_statements.rb +3 -2
- data/lib/sequel/dataset/query.rb +84 -38
- data/lib/sequel/dataset/sql.rb +302 -191
- data/lib/sequel/deprecated.rb +26 -17
- data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/from_block.rb +1 -0
- data/lib/sequel/extensions/graph_each.rb +1 -1
- data/lib/sequel/extensions/identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/migration.rb +28 -4
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +4 -4
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
- data/lib/sequel/extensions/set_overrides.rb +2 -0
- data/lib/sequel/extensions/split_array_nil.rb +2 -2
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model.rb +11 -7
- data/lib/sequel/model/associations.rb +5 -7
- data/lib/sequel/model/base.rb +47 -45
- data/lib/sequel/model/dataset_module.rb +9 -14
- data/lib/sequel/model/plugins.rb +3 -0
- data/lib/sequel/no_core_ext.rb +1 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -1
- data/lib/sequel/plugins/boolean_subsets.rb +7 -5
- data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
- data/lib/sequel/plugins/dataset_associations.rb +1 -1
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/finder.rb +240 -0
- data/lib/sequel/plugins/inverted_subsets.rb +19 -12
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/schema.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
- data/lib/sequel/plugins/subset_conditions.rb +11 -3
- data/lib/sequel/plugins/whitelist_security.rb +118 -0
- data/lib/sequel/sql.rb +80 -36
- data/lib/sequel/timezones.rb +2 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +20 -0
- data/spec/adapters/mysql_spec.rb +1 -1
- data/spec/adapters/oracle_spec.rb +12 -8
- data/spec/adapters/postgres_spec.rb +1 -1
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +36 -34
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +87 -9
- data/spec/core/dataset_spec.rb +501 -129
- data/spec/core/deprecated_spec.rb +1 -1
- data/spec/core/expression_filters_spec.rb +146 -60
- data/spec/core/mock_adapter_spec.rb +1 -1
- data/spec/core/object_graph_spec.rb +61 -9
- data/spec/core/placeholder_literalizer_spec.rb +20 -2
- data/spec/core/schema_generator_spec.rb +6 -6
- data/spec/core/schema_spec.rb +54 -5
- data/spec/core_extensions_spec.rb +122 -18
- data/spec/deprecation_helper.rb +27 -2
- data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
- data/spec/extensions/association_proxies_spec.rb +2 -2
- data/spec/extensions/auto_literal_strings_spec.rb +212 -0
- data/spec/extensions/blacklist_security_spec.rb +1 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
- data/spec/extensions/column_select_spec.rb +20 -8
- data/spec/extensions/columns_introspection_spec.rb +3 -3
- data/spec/extensions/core_refinements_spec.rb +29 -12
- data/spec/extensions/dataset_associations_spec.rb +12 -12
- data/spec/extensions/def_dataset_method_spec.rb +100 -0
- data/spec/extensions/error_sql_spec.rb +1 -1
- data/spec/extensions/finder_spec.rb +260 -0
- data/spec/extensions/graph_each_spec.rb +2 -2
- data/spec/extensions/identifier_mangling_spec.rb +14 -8
- data/spec/extensions/inverted_subsets_spec.rb +4 -4
- data/spec/extensions/lazy_attributes_spec.rb +7 -0
- data/spec/extensions/many_through_many_spec.rb +38 -14
- data/spec/extensions/nested_attributes_spec.rb +18 -6
- data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
- data/spec/extensions/pg_enum_spec.rb +16 -1
- data/spec/extensions/pg_interval_spec.rb +11 -2
- data/spec/extensions/pg_loose_count_spec.rb +5 -0
- data/spec/extensions/pg_row_spec.rb +25 -0
- data/spec/extensions/prepared_statements_spec.rb +10 -1
- data/spec/extensions/query_spec.rb +2 -2
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/set_overrides_spec.rb +7 -3
- data/spec/extensions/sql_expr_spec.rb +0 -1
- data/spec/extensions/subset_conditions_spec.rb +6 -6
- data/spec/extensions/table_select_spec.rb +24 -12
- data/spec/extensions/to_dot_spec.rb +4 -4
- data/spec/extensions/whitelist_security_spec.rb +131 -0
- data/spec/integration/dataset_test.rb +9 -5
- data/spec/integration/model_test.rb +2 -0
- data/spec/integration/plugin_test.rb +2 -2
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/model/associations_spec.rb +39 -11
- data/spec/model/base_spec.rb +44 -24
- data/spec/model/class_dataset_methods_spec.rb +18 -16
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +84 -24
- data/spec/model/model_spec.rb +97 -63
- data/spec/model/record_spec.rb +21 -13
- 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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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
|
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,
|
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,
|
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,
|
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
|
-
|
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.
|
data/lib/sequel/dataset/graph.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/sequel/dataset/misc.rb
CHANGED
@@ -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(*
|
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
|
-
|
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 =
|
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
|
216
|
+
case prepared_type[0]
|
216
217
|
when :map, :to_hash, :to_hash_groups
|
217
218
|
send(*prepared_type, &block)
|
218
219
|
end
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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] ||
|
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
|
-
|
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
|
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] ||
|
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
|
698
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
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]||
|
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]||
|
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
|
-
|
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
|
-
|
1211
|
-
|
1212
|
-
|
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
|
-
|
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(
|
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
|
-
#
|
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
|
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
|
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] ||
|
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
|
1344
|
+
return unless order
|
1299
1345
|
order.map do |f|
|
1300
1346
|
case f
|
1301
1347
|
when SQL::OrderedExpression
|