sequel 4.45.0 → 4.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|