sequel 5.27.0 → 5.28.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 512f72ad99402b33be776e759611a9299b638f49344fb1f349120c8cd1643107
4
- data.tar.gz: ea0852b3ea61ef9a5a192637a2b457fe47f2374c8ee2eb20d9b02e6eb25a25ac
3
+ metadata.gz: e206de897422ca8260c788bcfc20bcb154c9122dd17a12dc4b45ecdca023eb9a
4
+ data.tar.gz: 319df67cbb77d1b93d12cd0a1f429de0b674543ebd62b6407d40e1bd992e2352
5
5
  SHA512:
6
- metadata.gz: 4397a4a7530bd3234d7c1e3bf8b1c2b8a6845e659b86b7177dc704edf8ebf2185c499ac7ba04bb7d52006cf1367b8c0835787be1483e7bb481fa4ea2d775680b
7
- data.tar.gz: 653238c46ae32bd74127bddb87dc4c99637f5eadfb7515a51e8da5bc57df10de57c2e9a97d085828cc45b97303fa66580c1c8832a5f6fbb5cdaffd585ce0ff86
6
+ metadata.gz: a69c5b0bdfdb9c32503204b19d7dc18a7f78f7af7d46c44a7a4413ed4561c3ed3d0a796742045b158714a45f165957a0b9e5d6830bb110e53872a17a1ccb1ed8
7
+ data.tar.gz: 73a7df723afa66c70f72218e0327f10ef659a22614e5a4438d8fdc2ba16ec97d6e33213c4fd2ed08e806f2860f968786543015b34f38449093d71194aadb3655
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ === 5.28.0 (2020-01-01)
2
+
3
+ * Warn when calling Sequel::JDBC::Postgres::Dataset#with_fetch_size (jeremyevans) (#1665)
4
+
5
+ * Add exclude_or_null extension, for filtering datasets where the condition is false or NULL (jeremyevans)
6
+
7
+ * Add any_not_empty extension, for making Dataset#any? without a block mean !empty? (jeremyevans)
8
+
1
9
  === 5.27.0 (2019-12-01)
2
10
 
3
11
  * Add Sequel::DEFAULT for a DEFAULT expression, useful for assigning to default values (jeremyevans)
@@ -55,6 +55,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
55
55
 
56
56
  dataset.exclude(:active).delete
57
57
  dataset.where{price < 100}.update(:active => true)
58
+ dataset.where(:active).update(:price => Sequel[:price] * 0.90)
58
59
 
59
60
  == Datasets are Enumerable
60
61
 
@@ -0,0 +1,16 @@
1
+ = New Features
2
+
3
+ * An any_not_empty extension has been added, for making Dataset#any?
4
+ without a block be the same as !empty?. This can result in a
5
+ much faster database query.
6
+
7
+ * An exclude_or_null extension has been added, adding a
8
+ Dataset#exclude_or_null method that returns rows where the given
9
+ expression is false or NULL. This extension is supported on
10
+ PostgreSQL, SQLite, MySQL, H2, and HSQLDB.
11
+
12
+ = Other Improvements
13
+
14
+ * When using the jdbc/postgresql adapter, calling with_fetch_size
15
+ on a dataset will emit a warning. This is because the driver
16
+ will ignore the setting.
@@ -8,17 +8,20 @@ These run each test in its own transaction, the recommended way to test.
8
8
 
9
9
  === minitest/spec
10
10
 
11
- ==== with minitest-hooks
12
-
11
+ ==== with minitest-hooks
13
12
  require 'minitest/hooks/default'
13
+
14
+ DB = Sequel.postgres # change if using sqlite etc
15
+
14
16
  class Minitest::HooksSpec
15
17
  def around
16
18
  DB.transaction(:rollback=>:always, :auto_savepoint=>true){super}
17
19
  end
18
20
  end
19
21
 
20
- ==== without minitest-hooks
21
-
22
+ ==== without minitest-hooks
23
+ DB = Sequel.postgres # change if using sqlite etc
24
+
22
25
  class Minitest::Spec
23
26
  def run(*args, &block)
24
27
  DB.transaction(:rollback=>:always, :auto_savepoint=>true){super}
@@ -26,7 +29,8 @@ These run each test in its own transaction, the recommended way to test.
26
29
  end
27
30
 
28
31
  === minitest/test
29
-
32
+ DB = Sequel.postgres # change if using sqlite etc
33
+
30
34
  # Use this class as the base class for your tests
31
35
  class SequelTestCase < Minitest::Test
32
36
  def run(*args, &block)
@@ -35,7 +39,8 @@ These run each test in its own transaction, the recommended way to test.
35
39
  end
36
40
 
37
41
  === rspec >= 2.8
38
-
42
+ DB = Sequel.postgres # change the database if you are using sqlite etc.
43
+
39
44
  RSpec.configure do |c|
40
45
  c.around(:each) do |example|
41
46
  DB.transaction(:rollback=>:always, :auto_savepoint=>true){example.run}
@@ -180,6 +180,12 @@ module Sequel
180
180
 
181
181
  class Dataset < JDBC::Dataset
182
182
  include Sequel::Postgres::DatasetMethods
183
+
184
+ # Warn when calling as the fetch size is ignored by the JDBC adapter currently.
185
+ def with_fetch_size(size)
186
+ warn("Sequel::JDBC::Postgres::Dataset#with_fetch_size does not currently have an effect.", :uplevel=>1)
187
+ super
188
+ end
183
189
 
184
190
  private
185
191
 
@@ -1237,6 +1237,20 @@ module Sequel
1237
1237
  self
1238
1238
  end
1239
1239
 
1240
+ # If invert is true, invert the condition.
1241
+ def _invert_filter(cond, invert)
1242
+ if invert
1243
+ SQL::BooleanExpression.invert(cond)
1244
+ else
1245
+ cond
1246
+ end
1247
+ end
1248
+
1249
+ # Add the given filter condition. Arguments:
1250
+ # clause :: Symbol or which SQL clause to effect, should be :where or :having
1251
+ # cond :: The filter condition to add
1252
+ # invert :: Whether the condition should be inverted (true or false)
1253
+ # combine :: How to combine the condition with an existing condition, should be :AND or :OR
1240
1254
  def add_filter(clause, cond, invert=false, combine=:AND, &block)
1241
1255
  if cond == EMPTY_ARRAY && !block
1242
1256
  raise Error, "must provide an argument to a filtering method if not passing a block"
@@ -1256,8 +1270,7 @@ module Sequel
1256
1270
  cond = nil
1257
1271
  end
1258
1272
 
1259
- cond = filter_expr(cond, &block)
1260
- cond = SQL::BooleanExpression.invert(cond) if invert
1273
+ cond = _invert_filter(filter_expr(cond, &block), invert)
1261
1274
  cond = SQL::BooleanExpression.new(combine, @opts[clause], cond) if @opts[clause]
1262
1275
 
1263
1276
  if cond.nil?
@@ -0,0 +1,45 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The any_not_empty extension changes the behavior of Dataset#any?
4
+ # if called without a block. By default, this method uses the
5
+ # standard Enumerable behavior of enumerating results and seeing
6
+ # if any result is not false or nil. With this extension, it
7
+ # just checks whether the dataset is empty. This approach can
8
+ # be much faster if the dataset is currently large.
9
+ #
10
+ # DB[:table].any?
11
+ # # SELECT * FROM table
12
+ #
13
+ # DB[:table].extension(:any_not_empty).any?
14
+ # # SELECT 1 as one FROM table LIMIT 1
15
+ #
16
+ # You can load this extension into specific datasets:
17
+ #
18
+ # ds = DB[:table]
19
+ # ds = ds.extension(:any_not_empty)
20
+ #
21
+ # Or you can load it into all of a database's datasets, which
22
+ # is probably the desired behavior if you are using this extension:
23
+ #
24
+ # DB.extension(:any_not_empty)
25
+ #
26
+ # Note that this can result in any? returning a different result if
27
+ # the dataset has a row_proc that can return false or nil.
28
+ #
29
+ # Related module: Sequel::AnyNotEmpty
30
+
31
+ #
32
+ module Sequel
33
+ module AnyNotEmpty
34
+ # If a block is not given, return whether the dataset is not empty.
35
+ def any?
36
+ if block_given?
37
+ super
38
+ else
39
+ !empty?
40
+ end
41
+ end
42
+ end
43
+
44
+ Dataset.register_extension(:any_not_empty, AnyNotEmpty)
45
+ end
@@ -0,0 +1,68 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The exclude_or_null extension adds Dataset#exclude_or_null and
4
+ # Dataset#exclude_or_null_having. These methods are similar to
5
+ # Dataset#exclude and Dataset#exclude_having, except that they
6
+ # will also exclude rows where the condition IS NULL.
7
+ #
8
+ # DB[:table].exclude_or_null(foo: 1)
9
+ # # SELECT * FROM table WHERE NOT coalesce((foo = 1), false)
10
+ #
11
+ # DB[:table].exclude_or_null{foo(bar) =~ 1}
12
+ # # SELECT * FROM table HAVING NOT coalesce((foo(bar) = 1), false))
13
+ #
14
+ # You can load this extension into specific datasets:
15
+ #
16
+ # ds = DB[:table]
17
+ # ds = ds.extension(:exclude_or_null)
18
+ #
19
+ # Or you can load it into all of a database's datasets, which
20
+ # is probably the desired behavior if you are using this extension:
21
+ #
22
+ # DB.extension(:exclude_or_null)
23
+ #
24
+ # Note, this extension works correctly on PostgreSQL, SQLite, MySQL,
25
+ # H2, and HSQLDB. However, it does not work correctly on Microsoft SQL Server,
26
+ # Oracle, DB2, SQLAnywhere, or Derby.
27
+ #
28
+ # Related module: Sequel::ExcludeOrNull
29
+
30
+ #
31
+ module Sequel
32
+ module ExcludeOrNull
33
+ # Performs the inverse of Dataset#where, but also excludes rows where the given
34
+ # condition IS NULL.
35
+ #
36
+ # DB[:items].exclude_or_null(category: 'software')
37
+ # # SELECT * FROM items WHERE NOT coalesce((category = 'software'), false)
38
+ #
39
+ # DB[:items].exclude_or_null(category: 'software', id: 3)
40
+ # # SELECT * FROM items WHERE NOT coalesce(((category = 'software') AND (id = 3)), false)
41
+ def exclude_or_null(*cond, &block)
42
+ add_filter(:where, cond, :or_null, &block)
43
+ end
44
+
45
+ # The same as exclude_or_null, but affecting the HAVING clause instead of the
46
+ # WHERE clause.
47
+ #
48
+ # DB[:items].select_group(:name).exclude_or_null_having{count(name) < 2}
49
+ # # SELECT name FROM items GROUP BY name HAVING NOT coalesce((count(name) < 2), true)
50
+ def exclude_or_null_having(*cond, &block)
51
+ add_filter(:having, cond, :or_null, &block)
52
+ end
53
+
54
+ private
55
+
56
+ # Recognize :or_null value for invert, returning an expression for
57
+ # the invert of the condition or the condition being null.
58
+ def _invert_filter(cond, invert)
59
+ if invert == :or_null
60
+ ~SQL::Function.new(:coalesce, cond, SQL::Constants::SQLFALSE)
61
+ else
62
+ super
63
+ end
64
+ end
65
+ end
66
+
67
+ Dataset.register_extension(:exclude_or_null, ExcludeOrNull)
68
+ end
@@ -6,7 +6,7 @@ module Sequel
6
6
 
7
7
  # The minor version of Sequel. Bumped for every non-patch level
8
8
  # release, generally around once a month.
9
- MINOR = 27
9
+ MINOR = 28
10
10
 
11
11
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
12
12
  # releases that fix regressions from previous versions.
@@ -3685,19 +3685,19 @@ describe 'PostgreSQL range types' do
3685
3685
  end if uses_pg_or_jdbc
3686
3686
 
3687
3687
  it 'handle endless ranges' do
3688
- @db.get(Sequel.cast(eval('1...'), :int4range)).must_be :==, eval('1...')
3689
- @db.get(Sequel.cast(eval('1...'), :int4range)).wont_be :==, eval('2...')
3690
- @db.get(Sequel.cast(eval('1...'), :int4range)).wont_be :==, eval('1..')
3691
- @db.get(Sequel.cast(eval('2...'), :int4range)).must_be :==, eval('2...')
3692
- @db.get(Sequel.cast(eval('2...'), :int4range)).wont_be :==, eval('2..')
3693
- @db.get(Sequel.cast(eval('2...'), :int4range)).wont_be :==, eval('1...')
3688
+ @db.get(Sequel.cast(eval('(1...)'), :int4range)).must_be :==, eval('(1...)')
3689
+ @db.get(Sequel.cast(eval('(1...)'), :int4range)).wont_be :==, eval('(2...)')
3690
+ @db.get(Sequel.cast(eval('(1...)'), :int4range)).wont_be :==, eval('(1..)')
3691
+ @db.get(Sequel.cast(eval('(2...)'), :int4range)).must_be :==, eval('(2...)')
3692
+ @db.get(Sequel.cast(eval('(2...)'), :int4range)).wont_be :==, eval('(2..)')
3693
+ @db.get(Sequel.cast(eval('(2...)'), :int4range)).wont_be :==, eval('(1...)')
3694
3694
  end if RUBY_VERSION >= '2.6'
3695
3695
 
3696
3696
  it 'handle startless ranges' do
3697
- @db.get(Sequel.cast(eval('...1'), :int4range)).must_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_begin=>true, :exclude_end=>true, :db_type=>"int4range")
3698
- @db.get(Sequel.cast(eval('...1'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 2, :exclude_begin=>true, :exclude_end=>true, :db_type=>"int4range")
3699
- @db.get(Sequel.cast(eval('...1'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_end=>true, :db_type=>"int4range")
3700
- @db.get(Sequel.cast(eval('...1'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_begin=>true, :db_type=>"int4range")
3697
+ @db.get(Sequel.cast(eval('(...1)'), :int4range)).must_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_begin=>true, :exclude_end=>true, :db_type=>"int4range")
3698
+ @db.get(Sequel.cast(eval('(...1)'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 2, :exclude_begin=>true, :exclude_end=>true, :db_type=>"int4range")
3699
+ @db.get(Sequel.cast(eval('(...1)'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_end=>true, :db_type=>"int4range")
3700
+ @db.get(Sequel.cast(eval('(...1)'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_begin=>true, :db_type=>"int4range")
3701
3701
  end if RUBY_VERSION >= '2.7'
3702
3702
 
3703
3703
  it 'handle startless ranges' do
@@ -2467,7 +2467,7 @@ describe "Database#typecast_value" do
2467
2467
  @db.typecast_value(:date, 'a')
2468
2468
  true.must_equal false
2469
2469
  rescue Sequel::InvalidValue => e
2470
- e.inspect.must_equal '#<Sequel::InvalidValue: ArgumentError: invalid date>'
2470
+ e.inspect.must_match(/\A#\<Sequel::InvalidValue: (Argument|Date::)Error: invalid date\>\z/)
2471
2471
  end
2472
2472
  end
2473
2473
  end
@@ -537,21 +537,21 @@ describe "Blockless Ruby Filters" do
537
537
  end
538
538
 
539
539
  it "should handle endless ranges" do
540
- endless = eval('1..')
540
+ endless = eval('(1..)')
541
541
  @d.l{x =~ endless}.must_equal '(x >= 1)'
542
542
  @d.l(:x => endless).must_equal '(x >= 1)'
543
543
 
544
- endless = eval('1...')
544
+ endless = eval('(1...)')
545
545
  @d.l{x =~ endless}.must_equal '(x >= 1)'
546
546
  @d.l(:x => endless).must_equal '(x >= 1)'
547
547
  end if RUBY_VERSION >= '2.6'
548
548
 
549
549
  it "should handle startless ranges" do
550
- endless = eval('..1')
550
+ endless = eval('(..1)')
551
551
  @d.l{x =~ endless}.must_equal '(x <= 1)'
552
552
  @d.l(:x => endless).must_equal '(x <= 1)'
553
553
 
554
- endless = eval('...1')
554
+ endless = eval('(...1)')
555
555
  @d.l{x =~ endless}.must_equal '(x < 1)'
556
556
  @d.l(:x => endless).must_equal '(x < 1)'
557
557
  end if RUBY_VERSION >= '2.7'
@@ -0,0 +1,23 @@
1
+ require_relative "spec_helper"
2
+
3
+ describe "any_not_empty extension" do
4
+ before do
5
+ @ds = Sequel.mock[:t].extension(:any_not_empty)
6
+ end
7
+
8
+ it "should use a limited query if no block is given" do
9
+ @ds.with_fetch(:one=>1).any?.must_equal true
10
+ @ds.db.sqls.must_equal ["SELECT 1 AS one FROM t LIMIT 1"]
11
+ @ds.with_fetch([]).any?.must_equal false
12
+ @ds.db.sqls.must_equal ["SELECT 1 AS one FROM t LIMIT 1"]
13
+ end
14
+
15
+ it "should use default behavior if block is given" do
16
+ @ds.with_fetch(:one=>1).any?{|x| x[:one] == 1}.must_equal true
17
+ @ds.db.sqls.must_equal ["SELECT * FROM t"]
18
+ @ds.with_fetch(:one=>1).any?{|x| x[:one] != 1}.must_equal false
19
+ @ds.db.sqls.must_equal ["SELECT * FROM t"]
20
+ @ds.with_fetch([]).any?{|x| x[:one] == 1}.must_equal false
21
+ @ds.db.sqls.must_equal ["SELECT * FROM t"]
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ require_relative "spec_helper"
2
+
3
+ describe "exclude_or_null extension" do
4
+ before do
5
+ @ds = Sequel.mock[:t].extension(:exclude_or_null)
6
+ end
7
+
8
+ it "should add condition where a is false or NULL" do
9
+ @ds.exclude_or_null(:a).sql.must_equal "SELECT * FROM t WHERE NOT coalesce(a, 'f')"
10
+ end
11
+
12
+ it "should not effect normal exclude" do
13
+ @ds.exclude(:a).sql.must_equal "SELECT * FROM t WHERE NOT a"
14
+ end
15
+ end
@@ -52,13 +52,13 @@ describe "pg_range extension" do
52
52
  end
53
53
 
54
54
  it "should literalize endless Range instances to strings correctly" do
55
- @db.literal(eval('1..')).must_equal "'[1,]'"
56
- @db.literal(eval('1...')).must_equal "'[1,)'"
55
+ @db.literal(eval('(1..)')).must_equal "'[1,]'"
56
+ @db.literal(eval('(1...)')).must_equal "'[1,)'"
57
57
  end if endless_range_support
58
58
 
59
59
  it "should literalize startless Range instances to strings correctly" do
60
- @db.literal(eval('..1')).must_equal "'[,1]'"
61
- @db.literal(eval('...1')).must_equal "'[,1)'"
60
+ @db.literal(eval('(..1)')).must_equal "'[,1]'"
61
+ @db.literal(eval('(...1)')).must_equal "'[,1)'"
62
62
  end if startless_range_support
63
63
 
64
64
  it "should literalize startless, endless Range instances to strings correctly" do
@@ -90,13 +90,13 @@ describe "pg_range extension" do
90
90
  end
91
91
 
92
92
  it "should support using endless Range instances as bound variables" do
93
- @db.bound_variable_arg(eval('1..'), nil).must_equal "[1,]"
94
- @db.bound_variable_arg(eval('1...'), nil).must_equal "[1,)"
93
+ @db.bound_variable_arg(eval('(1..)'), nil).must_equal "[1,]"
94
+ @db.bound_variable_arg(eval('(1...)'), nil).must_equal "[1,)"
95
95
  end if endless_range_support
96
96
 
97
97
  it "should support using startless Range instances as bound variables" do
98
- @db.bound_variable_arg(eval('..1'), nil).must_equal "[,1]"
99
- @db.bound_variable_arg(eval('...1'), nil).must_equal "[,1)"
98
+ @db.bound_variable_arg(eval('(..1)'), nil).must_equal "[,1]"
99
+ @db.bound_variable_arg(eval('(...1)'), nil).must_equal "[,1)"
100
100
  end if startless_range_support
101
101
 
102
102
  it "should support using startless, endless Range instances as bound variables" do
@@ -113,7 +113,7 @@ describe "pg_range extension" do
113
113
  end
114
114
 
115
115
  it "should support using arrays of endless Range instances as bound variables" do
116
- @db.bound_variable_arg([eval('1..'), eval('2..')], nil).must_equal '{"[1,]","[2,]"}'
116
+ @db.bound_variable_arg([eval('(1..)'), eval('(2..)')], nil).must_equal '{"[1,]","[2,]"}'
117
117
  end if endless_range_support
118
118
 
119
119
  it "should support using PGRange instances as bound variables" do
@@ -470,21 +470,21 @@ describe "pg_range extension" do
470
470
  end
471
471
 
472
472
  it "should consider PGRanges equal with a endless Range they represent" do
473
- @R.new(1, nil).must_be :==, eval('1..')
474
- @R.new(1, nil, :exclude_end=>true).must_be :==, eval('1...')
475
- @R.new(1, nil).wont_be :==, eval('1...')
476
- @R.new(1, nil, :exclude_end=>true).wont_be :==, eval('1..')
477
- @R.new(1, nil).wont_be :==, eval('2..')
478
- @R.new(1, nil, :exclude_end=>true).wont_be :==, eval('2...')
473
+ @R.new(1, nil).must_be :==, eval('(1..)')
474
+ @R.new(1, nil, :exclude_end=>true).must_be :==, eval('(1...)')
475
+ @R.new(1, nil).wont_be :==, eval('(1...)')
476
+ @R.new(1, nil, :exclude_end=>true).wont_be :==, eval('(1..)')
477
+ @R.new(1, nil).wont_be :==, eval('(2..)')
478
+ @R.new(1, nil, :exclude_end=>true).wont_be :==, eval('(2...)')
479
479
  end if endless_range_support
480
480
 
481
481
  it "should consider PGRanges equal with a startless Range they represent" do
482
- @R.new(nil, 1).must_be :==, eval('..1')
483
- @R.new(nil, 1, :exclude_end=>true).must_be :==, eval('...1')
484
- @R.new(nil, 1).wont_be :==, eval('...1')
485
- @R.new(nil, 1, :exclude_end=>true).wont_be :==, eval('..1')
486
- @R.new(nil, 1).wont_be :==, eval('..2')
487
- @R.new(nil, 1, :exclude_end=>true).wont_be :==, eval('...2')
482
+ @R.new(nil, 1).must_be :==, eval('(..1)')
483
+ @R.new(nil, 1, :exclude_end=>true).must_be :==, eval('(...1)')
484
+ @R.new(nil, 1).wont_be :==, eval('(...1)')
485
+ @R.new(nil, 1, :exclude_end=>true).wont_be :==, eval('(..1)')
486
+ @R.new(nil, 1).wont_be :==, eval('(..2)')
487
+ @R.new(nil, 1, :exclude_end=>true).wont_be :==, eval('(...2)')
488
488
  end if startless_range_support
489
489
 
490
490
  it "should consider PGRanges equal with a startless, endless Range they represent" do
@@ -593,22 +593,21 @@ describe Sequel::Dataset do
593
593
  end
594
594
 
595
595
  describe "Simple Dataset operations" do
596
- before do
596
+ before(:all) do
597
597
  DB.create_table!(:items) do
598
598
  Integer :number
599
599
  TrueClass :flag
600
600
  end
601
- @ds = DB[:items]
601
+ @ds = DB[:items].order(:number)
602
+ @ds.insert(:number=>1, :flag=>true)
603
+ @ds.insert(:number=>2, :flag=>false)
604
+ @ds.insert(:number=>3, :flag=>nil)
602
605
  end
603
- after do
606
+ after(:all) do
604
607
  DB.drop_table?(:items)
605
608
  end
606
609
 
607
610
  it "should deal with boolean conditions correctly" do
608
- @ds.insert(:number=>1, :flag=>true)
609
- @ds.insert(:number=>2, :flag=>false)
610
- @ds.insert(:number=>3, :flag=>nil)
611
- @ds = @ds.order(:number)
612
611
  @ds.filter(:flag=>true).map(:number).must_equal [1]
613
612
  @ds.filter(:flag=>false).map(:number).must_equal [2]
614
613
  @ds.filter(:flag=>nil).map(:number).must_equal [3]
@@ -616,6 +615,22 @@ describe "Simple Dataset operations" do
616
615
  @ds.exclude(:flag=>false).map(:number).must_equal [1, 3]
617
616
  @ds.exclude(:flag=>nil).map(:number).must_equal [1, 2]
618
617
  end
618
+
619
+ cspecify "should deal with boolean equality conditions correctly", :derby do
620
+ @ds.filter(true=>:flag).map(:number).must_equal [1]
621
+ @ds.filter(false=>:flag).map(:number).must_equal [2]
622
+ @ds.filter(nil=>:flag).map(:number).must_equal []
623
+ @ds.exclude(true=>:flag).map(:number).must_equal [2]
624
+ @ds.exclude(false=>:flag).map(:number).must_equal [1]
625
+ @ds.exclude(nil=>:flag).map(:number).must_equal []
626
+ end
627
+
628
+ cspecify "should have exclude_or_null work correctly", :mssql, :derby, :oracle, :db2, :sqlanywhere do
629
+ @ds = @ds.extension(:exclude_or_null)
630
+ @ds.exclude_or_null(true=>:flag).map(:number).must_equal [2, 3]
631
+ @ds.exclude_or_null(false=>:flag).map(:number).must_equal [1, 3]
632
+ @ds.exclude_or_null(nil=>:flag).map(:number).must_equal [1, 2, 3]
633
+ end
619
634
  end
620
635
 
621
636
  describe "Simple Dataset operations in transactions" do
@@ -1578,20 +1593,20 @@ describe "Sequel::Dataset DSL support" do
1578
1593
 
1579
1594
  it "should work with endless ranges as hash values" do
1580
1595
  @ds.insert(20, 10)
1581
- @ds.filter(:a=>eval('30..')).all.must_equal []
1582
- @ds.filter(:a=>eval('20...')).all.must_equal [{:a=>20, :b=>10}]
1583
- @ds.filter(:a=>eval('20..')).all.must_equal [{:a=>20, :b=>10}]
1584
- @ds.filter(:a=>eval('10..')).all.must_equal [{:a=>20, :b=>10}]
1596
+ @ds.filter(:a=>eval('(30..)')).all.must_equal []
1597
+ @ds.filter(:a=>eval('(20...)')).all.must_equal [{:a=>20, :b=>10}]
1598
+ @ds.filter(:a=>eval('(20..)')).all.must_equal [{:a=>20, :b=>10}]
1599
+ @ds.filter(:a=>eval('(10..)')).all.must_equal [{:a=>20, :b=>10}]
1585
1600
  end if RUBY_VERSION >= '2.6'
1586
1601
 
1587
1602
  it "should work with startless ranges as hash values" do
1588
1603
  @ds.insert(20, 10)
1589
- @ds.filter(:a=>eval('..30')).all.must_equal [{:a=>20, :b=>10}]
1590
- @ds.filter(:a=>eval('...30')).all.must_equal [{:a=>20, :b=>10}]
1591
- @ds.filter(:a=>eval('..20')).all.must_equal [{:a=>20, :b=>10}]
1592
- @ds.filter(:a=>eval('...20')).all.must_equal []
1593
- @ds.filter(:a=>eval('..10')).all.must_equal []
1594
- @ds.filter(:a=>eval('...10')).all.must_equal []
1604
+ @ds.filter(:a=>eval('(..30)')).all.must_equal [{:a=>20, :b=>10}]
1605
+ @ds.filter(:a=>eval('(...30)')).all.must_equal [{:a=>20, :b=>10}]
1606
+ @ds.filter(:a=>eval('(..20)')).all.must_equal [{:a=>20, :b=>10}]
1607
+ @ds.filter(:a=>eval('(...20)')).all.must_equal []
1608
+ @ds.filter(:a=>eval('(..10)')).all.must_equal []
1609
+ @ds.filter(:a=>eval('(...10)')).all.must_equal []
1595
1610
 
1596
1611
  @ds.filter(:a=>eval('nil..nil')).all.must_equal [{:a=>20, :b=>10}]
1597
1612
  end if RUBY_VERSION >= '2.7'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.27.0
4
+ version: 5.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-01 00:00:00.000000000 Z
11
+ date: 2020-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -225,6 +225,7 @@ extra_rdoc_files:
225
225
  - doc/release_notes/5.25.0.txt
226
226
  - doc/release_notes/5.26.0.txt
227
227
  - doc/release_notes/5.27.0.txt
228
+ - doc/release_notes/5.28.0.txt
228
229
  files:
229
230
  - CHANGELOG
230
231
  - MIT-LICENSE
@@ -323,6 +324,7 @@ files:
323
324
  - doc/release_notes/5.25.0.txt
324
325
  - doc/release_notes/5.26.0.txt
325
326
  - doc/release_notes/5.27.0.txt
327
+ - doc/release_notes/5.28.0.txt
326
328
  - doc/release_notes/5.3.0.txt
327
329
  - doc/release_notes/5.4.0.txt
328
330
  - doc/release_notes/5.5.0.txt
@@ -421,6 +423,7 @@ files:
421
423
  - lib/sequel/extensions/_model_constraint_validations.rb
422
424
  - lib/sequel/extensions/_model_pg_row.rb
423
425
  - lib/sequel/extensions/_pretty_table.rb
426
+ - lib/sequel/extensions/any_not_empty.rb
424
427
  - lib/sequel/extensions/arbitrary_servers.rb
425
428
  - lib/sequel/extensions/auto_literal_strings.rb
426
429
  - lib/sequel/extensions/blank.rb
@@ -441,6 +444,7 @@ files:
441
444
  - lib/sequel/extensions/error_sql.rb
442
445
  - lib/sequel/extensions/escaped_like.rb
443
446
  - lib/sequel/extensions/eval_inspect.rb
447
+ - lib/sequel/extensions/exclude_or_null.rb
444
448
  - lib/sequel/extensions/freeze_datasets.rb
445
449
  - lib/sequel/extensions/from_block.rb
446
450
  - lib/sequel/extensions/graph_each.rb
@@ -619,6 +623,7 @@ files:
619
623
  - spec/extensions/accessed_columns_spec.rb
620
624
  - spec/extensions/active_model_spec.rb
621
625
  - spec/extensions/after_initialize_spec.rb
626
+ - spec/extensions/any_not_empty_spec.rb
622
627
  - spec/extensions/arbitrary_servers_spec.rb
623
628
  - spec/extensions/association_dependencies_spec.rb
624
629
  - spec/extensions/association_multi_add_remove_spec.rb
@@ -662,6 +667,7 @@ files:
662
667
  - spec/extensions/error_sql_spec.rb
663
668
  - spec/extensions/escaped_like_spec.rb
664
669
  - spec/extensions/eval_inspect_spec.rb
670
+ - spec/extensions/exclude_or_null_spec.rb
665
671
  - spec/extensions/finder_spec.rb
666
672
  - spec/extensions/force_encoding_spec.rb
667
673
  - spec/extensions/freeze_datasets_spec.rb
@@ -883,7 +889,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
883
889
  - !ruby/object:Gem::Version
884
890
  version: '0'
885
891
  requirements: []
886
- rubygems_version: 3.0.3
892
+ rubygems_version: 3.1.2
887
893
  signing_key:
888
894
  specification_version: 4
889
895
  summary: The Database Toolkit for Ruby