sequel 5.21.0 → 5.22.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33b35675e5f68471b8216acbbe10085992616ae93b6f47191c44bb3860b38285
4
- data.tar.gz: e1be4ce80c4810a9022505f7e5d0becaa11912f6e91344b860195e6b11438d27
3
+ metadata.gz: dab3e09e5e2003ee0c53b63f8b628b723be5aeb019bb5b1d2669f7583f589ef3
4
+ data.tar.gz: 422d4fc893082e88256f0f2ba8b2f82288aea6f7438c0ef68793f30acc2307e0
5
5
  SHA512:
6
- metadata.gz: fedb31816a3c56136b007317f135072c318e71938c3375feff8c0ab2ec7ddc5744457008266434dff285095b09bfdf78ab33a24b0b4ac255119f9e80ae6758f1
7
- data.tar.gz: eea67a798eedf2cb8b10bbf20eaf3b0deb7e9eabd1c9b8f238754ffbbd4afea394caa8b4574db7bda6373db987a8a088f83732ea353591eeca37ee4583d57730
6
+ metadata.gz: 844854b68bf2b57c802422496b88dc54d9ec97549da18a5b1d5c04a2ac294286de8cff74c6e8e25f21b35e188c1d9abb97ab9eae427b1bce7c0040779f602da2
7
+ data.tar.gz: 52317931ac3e82d63bc307c7c970bed264e1412af59ba979069ebb4867e89138901a388419a80b41c88b6d581d959ba2650bced6bc146911913d230fd890aec5
data/CHANGELOG CHANGED
@@ -1,3 +1,17 @@
1
+ === 5.22.0 (2019-07-01)
2
+
3
+ * Fix Dataset#multi_insert and #import with return: :primary_key on MSSQL when the dataset has a row_proc (jeremyevans) (#1627)
4
+
5
+ * Support Dataset#with :materialized option on PostgreSQL 12 for [NOT] MATERIALIZED (jeremyevans)
6
+
7
+ * Make Database#primary_key_sequence work on tables without serial sequences on PostgreSQL 12 (jeremyevans)
8
+
9
+ * Support ruby 2.7+ startless ranges in the pg_range extension (jeremyevans)
10
+
11
+ * Support ruby 2.7+ startless, endless ranges in filters, using an always true condition for them (jeremyevans)
12
+
13
+ * Support ruby 2.7+ startless ranges in filters, using just a <= or < operator for them (jeremyevans)
14
+
1
15
  === 5.21.0 (2019-06-01)
2
16
 
3
17
  * Recognize additional DatabaseLockTimeout errors in mysql and mysql2 adapters (jeremyevans)
@@ -0,0 +1,48 @@
1
+ = New Features
2
+
3
+ * Sequel now supports Ruby 2.7+ startless ranges in filters:
4
+
5
+ DB[:table].where(:column=>(..10))
6
+ # SELECT * FROM table WHERE (column <= 10)
7
+
8
+ DB[:table].where(:column=>(...10))
9
+ # SELECT * FROM table WHERE (column < 10)
10
+
11
+ It also supports startless, endless ranges in filters, using a
12
+ condition that is always true:
13
+
14
+ DB[:table].where(:column=>(nil..nil))
15
+ # SELECT * FROM table WHERE (1 = 1)
16
+
17
+ * Sequel now supports startless ranges in the pg_range extension:
18
+
19
+ DB.extension :pg_range
20
+
21
+ DB[:table].insert(:column=>(..10))
22
+ # INSERT INTO "table" ("column") VALUES ('[,10]') RETURNING "id"
23
+
24
+ DB[:table].insert(:column=>(...10))
25
+ # INSERT INTO "table" ("column") VALUES ('[,10)') RETURNING "id"
26
+
27
+ DB[:table].insert(:column=>(nil..nil))
28
+ # INSERT INTO "table" ("column") VALUES ('[,]') RETURNING "id"
29
+
30
+ * Sequel now supports a :materialized option in Dataset#with on
31
+ PostgreSQL 12+, to control the inlining of common table expressions:
32
+
33
+ DB[:t].with(:t, DB[:t2], :materialized=>false)
34
+ # WITH "t" AS NOT MATERIALIZED (SELECT * FROM "t2")
35
+ # SELECT * FROM "t"
36
+
37
+ DB[:t].with(:t, DB[:t2], :materialized=>true)
38
+ # WITH "t" AS MATERIALIZED (SELECT * FROM "t2")
39
+ # SELECT * FROM "t"
40
+
41
+ = Other Improvements
42
+
43
+ * Database#primary_key_sequence now works for tables without serial
44
+ sequences on PostgreSQL 12+.
45
+
46
+ * Dataset#multi_insert and #import with return: :primary_key option
47
+ on Microsoft SQL Server now work correctly if the dataset uses
48
+ a row_proc (e.g. for model datasets).
@@ -765,8 +765,9 @@ module Sequel
765
765
  output(nil, [SQL::QualifiedIdentifier.new(:inserted, first_primary_key)])._import(columns, values, opts)
766
766
  elsif @opts[:output]
767
767
  statements = multi_insert_sql(columns, values)
768
+ ds = naked
768
769
  @db.transaction(opts.merge(:server=>@opts[:server])) do
769
- statements.map{|st| with_sql(st)}
770
+ statements.map{|st| ds.with_sql(st)}
770
771
  end.first.map{|v| v.length == 1 ? v.values.first : v}
771
772
  else
772
773
  super
@@ -147,10 +147,10 @@ module Sequel
147
147
  SELECT_CUSTOM_SEQUENCE_SQL = (<<-end_sql
148
148
  SELECT name.nspname AS "schema",
149
149
  CASE
150
- WHEN split_part(def.adsrc, '''', 2) ~ '.' THEN
151
- substr(split_part(def.adsrc, '''', 2),
152
- strpos(split_part(def.adsrc, '''', 2), '.')+1)
153
- ELSE split_part(def.adsrc, '''', 2)
150
+ WHEN split_part(pg_get_expr(def.adbin, attr.attrelid), '''', 2) ~ '.' THEN
151
+ substr(split_part(pg_get_expr(def.adbin, attr.attrelid), '''', 2),
152
+ strpos(split_part(pg_get_expr(def.adbin, attr.attrelid), '''', 2), '.')+1)
153
+ ELSE split_part(pg_get_expr(def.adbin, attr.attrelid), '''', 2)
154
154
  END AS "sequence"
155
155
  FROM pg_class t
156
156
  JOIN pg_namespace name ON (t.relnamespace = name.oid)
@@ -158,7 +158,7 @@ module Sequel
158
158
  JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum)
159
159
  JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1])
160
160
  WHERE cons.contype = 'p'
161
- AND def.adsrc ~* 'nextval'
161
+ AND pg_get_expr(def.adbin, attr.attrelid) ~* 'nextval'
162
162
  end_sql
163
163
  ).strip.gsub(/\s+/, ' ').freeze
164
164
 
@@ -1920,6 +1920,18 @@ module Sequel
1920
1920
  opts[:with].any?{|w| w[:recursive]} ? "WITH RECURSIVE " : super
1921
1921
  end
1922
1922
 
1923
+ # Support WITH AS [NOT] MATERIALIZED if :materialized option is used.
1924
+ def select_with_sql_prefix(sql, w)
1925
+ super
1926
+
1927
+ case w[:materialized]
1928
+ when true
1929
+ sql << "MATERIALIZED "
1930
+ when false
1931
+ sql << "NOT MATERIALIZED "
1932
+ end
1933
+ end
1934
+
1923
1935
  # The version of the database server
1924
1936
  def server_version
1925
1937
  db.server_version(@opts[:server])
@@ -20,8 +20,10 @@ module Sequel
20
20
  # old_posts = posts.where{stamp < Date.today - 7}
21
21
  # davids_old_posts = davids_posts.where{stamp < Date.today - 7}
22
22
  #
23
- # Datasets are Enumerable objects, so they can be manipulated using any
24
- # of the Enumerable methods, such as map, inject, etc.
23
+ # Datasets are Enumerable objects, so they can be manipulated using many
24
+ # of the Enumerable methods, such as +map+ and +inject+. Note that there are some methods
25
+ # that Dataset defines that override methods defined in Enumerable and result in different
26
+ # behavior, such as +select+ and +group_by+.
25
27
  #
26
28
  # For more information, see the {"Dataset Basics" guide}[rdoc-ref:doc/dataset_basics.rdoc].
27
29
  class Dataset
@@ -1062,6 +1062,10 @@ module Sequel
1062
1062
  # :args :: Specify the arguments/columns for the CTE, should be an array of symbols.
1063
1063
  # :recursive :: Specify that this is a recursive CTE
1064
1064
  #
1065
+ # PostgreSQL Specific Options:
1066
+ # :materialized :: Set to false to force inlining of the CTE, or true to force not inlining
1067
+ # the CTE (PostgreSQL 12+).
1068
+ #
1065
1069
  # DB[:items].with(:items, DB[:syx].where(Sequel[:name].like('A%')))
1066
1070
  # # WITH items AS (SELECT * FROM syx WHERE (name LIKE 'A%' ESCAPE '\')) SELECT * FROM items
1067
1071
  def with(name, dataset, opts=OPTS)
@@ -1510,13 +1510,7 @@ module Sequel
1510
1510
  comma = ', '
1511
1511
  ws.each do |w|
1512
1512
  sql << comma if c
1513
- quote_identifier_append(sql, w[:name])
1514
- if args = w[:args]
1515
- sql << '('
1516
- identifier_list_append(sql, args)
1517
- sql << ')'
1518
- end
1519
- sql << ' AS '
1513
+ select_with_sql_prefix(sql, w)
1520
1514
  literal_dataset_append(sql, w[:dataset])
1521
1515
  c ||= true
1522
1516
  end
@@ -1530,6 +1524,16 @@ module Sequel
1530
1524
  "WITH "
1531
1525
  end
1532
1526
 
1527
+ def select_with_sql_prefix(sql, w)
1528
+ quote_identifier_append(sql, w[:name])
1529
+ if args = w[:args]
1530
+ sql << '('
1531
+ identifier_list_append(sql, args)
1532
+ sql << ')'
1533
+ end
1534
+ sql << ' AS '
1535
+ end
1536
+
1533
1537
  # Whether the symbol cache should be skipped when literalizing the dataset
1534
1538
  def skip_symbol_cache?
1535
1539
  @opts[:skip_symbol_cache]
@@ -453,13 +453,14 @@ module Sequel
453
453
  end
454
454
 
455
455
  ENDLESS_RANGE_NOT_SUPPORTED = RUBY_VERSION < '2.6'
456
+ STARTLESS_RANGE_NOT_SUPPORTED = RUBY_VERSION < '2.7'
456
457
 
457
458
  # Return a ruby Range object for this instance, if one can be created.
458
459
  def to_range
459
460
  return @range if @range
460
461
  raise(Error, "cannot create ruby range for an empty PostgreSQL range") if empty?
461
462
  raise(Error, "cannot create ruby range when PostgreSQL range excludes beginning element") if exclude_begin?
462
- raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") unless self.begin
463
+ raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") if STARTLESS_RANGE_NOT_SUPPORTED && !self.begin
463
464
  raise(Error, "cannot create ruby range when PostgreSQL range has unbounded ending") if ENDLESS_RANGE_NOT_SUPPORTED && !self.end
464
465
  @range = Range.new(self.begin, self.end, exclude_end?)
465
466
  end
@@ -468,7 +469,7 @@ module Sequel
468
469
  # it must have a beginning and an ending (no unbounded ranges), and it cannot exclude
469
470
  # the beginning element.
470
471
  def valid_ruby_range?
471
- !(empty? || exclude_begin? || !self.begin || (ENDLESS_RANGE_NOT_SUPPORTED && !self.end))
472
+ !(empty? || exclude_begin? || (STARTLESS_RANGE_NOT_SUPPORTED && !self.begin) || (ENDLESS_RANGE_NOT_SUPPORTED && !self.end))
472
473
  end
473
474
 
474
475
  # Whether the beginning of the range is unbounded.
@@ -1086,11 +1086,23 @@ module Sequel
1086
1086
  def self.from_value_pair(l, r)
1087
1087
  case r
1088
1088
  when Range
1089
- expr = new(:>=, l, r.begin)
1089
+ unless r.begin.nil?
1090
+ begin_expr = new(:>=, l, r.begin)
1091
+ end
1090
1092
  unless r.end.nil?
1091
- expr = new(:AND, expr, new(r.exclude_end? ? :< : :<=, l, r.end))
1093
+ end_expr = new(r.exclude_end? ? :< : :<=, l, r.end)
1094
+ end
1095
+ if begin_expr
1096
+ if end_expr
1097
+ new(:AND, begin_expr, end_expr)
1098
+ else
1099
+ begin_expr
1100
+ end
1101
+ elsif end_expr
1102
+ end_expr
1103
+ else
1104
+ new(:'=', 1, 1)
1092
1105
  end
1093
- expr
1094
1106
  when ::Array
1095
1107
  r = r.dup.freeze unless r.frozen?
1096
1108
  new(:IN, l, r)
@@ -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 = 21
9
+ MINOR = 22
10
10
 
11
11
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
12
12
  # releases that fix regressions from previous versions.
@@ -352,6 +352,26 @@ describe "PostgreSQL", 'INSERT ON CONFLICT' do
352
352
  end
353
353
  end if DB.server_version >= 90500
354
354
 
355
+ describe "A PostgreSQL database" do
356
+ before do
357
+ @db = DB
358
+ @db.create_table!(:cte_test){Integer :id}
359
+ end
360
+ after do
361
+ @db.drop_table?(:cte_test)
362
+ end
363
+
364
+ it "should give correct results for WITH AS [NOT] MATERIALIZED" do
365
+ @ds = @db[:cte_test]
366
+ @ds.insert(1)
367
+ @ds.insert(2)
368
+
369
+ @db[:t].with(:t, @ds, :materialized=>nil).order(:id).map(:id).must_equal [1, 2]
370
+ @db[:t].with(:t, @ds, :materialized=>true).order(:id).map(:id).must_equal [1, 2]
371
+ @db[:t].with(:t, @ds, :materialized=>false).order(:id).map(:id).must_equal [1, 2]
372
+ end
373
+ end if DB.server_version >= 120000
374
+
355
375
  describe "A PostgreSQL database" do
356
376
  before(:all) do
357
377
  @db = DB
@@ -3581,6 +3601,30 @@ describe 'PostgreSQL range types' do
3581
3601
  @ds.filter(h).call(:delete, @ra).must_equal 1
3582
3602
  end if uses_pg_or_jdbc
3583
3603
 
3604
+ it 'handle endless ranges' do
3605
+ @db.get(Sequel.cast(eval('1...'), :int4range)).must_be :==, eval('1...')
3606
+ @db.get(Sequel.cast(eval('1...'), :int4range)).wont_be :==, eval('2...')
3607
+ @db.get(Sequel.cast(eval('1...'), :int4range)).wont_be :==, eval('1..')
3608
+ @db.get(Sequel.cast(eval('2...'), :int4range)).must_be :==, eval('2...')
3609
+ @db.get(Sequel.cast(eval('2...'), :int4range)).wont_be :==, eval('2..')
3610
+ @db.get(Sequel.cast(eval('2...'), :int4range)).wont_be :==, eval('1...')
3611
+ end if RUBY_VERSION >= '2.6'
3612
+
3613
+ it 'handle startless ranges' do
3614
+ @db.get(Sequel.cast(eval('...1'), :int4range)).must_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_begin=>true, :exclude_end=>true, :db_type=>"int4range")
3615
+ @db.get(Sequel.cast(eval('...1'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 2, :exclude_begin=>true, :exclude_end=>true, :db_type=>"int4range")
3616
+ @db.get(Sequel.cast(eval('...1'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_end=>true, :db_type=>"int4range")
3617
+ @db.get(Sequel.cast(eval('...1'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_begin=>true, :db_type=>"int4range")
3618
+ end if RUBY_VERSION >= '2.7'
3619
+
3620
+ it 'handle startless ranges' do
3621
+ @db.get(Sequel.cast(eval('nil...nil'), :int4range)).must_be :==, Sequel::Postgres::PGRange.new(nil, nil, :exclude_begin=>true, :exclude_end=>true, :db_type=>"int4range")
3622
+ @db.get(Sequel.cast(eval('nil...nil'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, nil, :exclude_begin=>true, :db_type=>"int4range")
3623
+ @db.get(Sequel.cast(eval('nil...nil'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, nil, :exclude_end=>true, :db_type=>"int4range")
3624
+ @db.get(Sequel.cast(eval('nil...nil'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(1, nil, :exclude_begin=>true, :db_type=>"int4range")
3625
+ @db.get(Sequel.cast(eval('nil...nil'), :int4range)).wont_be :==, Sequel::Postgres::PGRange.new(nil, 1, :exclude_begin=>true, :db_type=>"int4range")
3626
+ end if RUBY_VERSION >= '2.7'
3627
+
3584
3628
  it 'parse default values for schema' do
3585
3629
  @db.create_table!(:items) do
3586
3630
  Integer :j
@@ -3434,6 +3434,16 @@ describe "Dataset#multi_insert" do
3434
3434
  'COMMIT']
3435
3435
  end
3436
3436
 
3437
+ it "should handle :return=>:primary_key option if dataset has a row_proc" do
3438
+ @db.autoid = 1
3439
+ @ds.with_row_proc(lambda{|h| Object.new}).multi_insert(@list, :return=>:primary_key).must_equal [1, 2, 3]
3440
+ @db.sqls.must_equal ['BEGIN',
3441
+ "INSERT INTO items (name) VALUES ('abc')",
3442
+ "INSERT INTO items (name) VALUES ('def')",
3443
+ "INSERT INTO items (name) VALUES ('ghi')",
3444
+ 'COMMIT']
3445
+ end
3446
+
3437
3447
  with_symbol_splitting "should handle splittable symbols for tables" do
3438
3448
  @ds = @ds.from(:sch__tab)
3439
3449
  @ds.multi_insert(@list)
@@ -526,11 +526,35 @@ describe "Blockless Ruby Filters" do
526
526
  dsc.new(@d.db).literal(Sequel.trim(:a)).must_equal 'trimFOO(lower(a))'
527
527
  end
528
528
 
529
- it "should endless ranges" do
529
+ it "should handle endless ranges" do
530
530
  endless = eval('1..')
531
531
  @d.l{x =~ endless}.must_equal '(x >= 1)'
532
532
  @d.l(:x => endless).must_equal '(x >= 1)'
533
+
534
+ endless = eval('1...')
535
+ @d.l{x =~ endless}.must_equal '(x >= 1)'
536
+ @d.l(:x => endless).must_equal '(x >= 1)'
533
537
  end if RUBY_VERSION >= '2.6'
538
+
539
+ it "should handle startless ranges" do
540
+ endless = eval('..1')
541
+ @d.l{x =~ endless}.must_equal '(x <= 1)'
542
+ @d.l(:x => endless).must_equal '(x <= 1)'
543
+
544
+ endless = eval('...1')
545
+ @d.l{x =~ endless}.must_equal '(x < 1)'
546
+ @d.l(:x => endless).must_equal '(x < 1)'
547
+ end if RUBY_VERSION >= '2.7'
548
+
549
+ it "should handle startless, endless ranges" do
550
+ endless = eval('nil..nil')
551
+ @d.l{x =~ endless}.must_equal '(1 = 1)'
552
+ @d.l(:x => endless).must_equal '(1 = 1)'
553
+
554
+ endless = eval('nil...nil')
555
+ @d.l{x =~ endless}.must_equal '(1 = 1)'
556
+ @d.l(:x => endless).must_equal '(1 = 1)'
557
+ end if RUBY_VERSION >= '2.7'
534
558
  end
535
559
 
536
560
  describe Sequel::SQL::VirtualRow do
@@ -17,6 +17,7 @@ describe "pg_range extension" do
17
17
  end
18
18
 
19
19
  endless_range_support = RUBY_VERSION >= '2.6'
20
+ startless_range_support = RUBY_VERSION >= '2.7'
20
21
 
21
22
  it "should set up conversion procs correctly" do
22
23
  cp = @db.conversion_procs
@@ -52,8 +53,19 @@ describe "pg_range extension" do
52
53
 
53
54
  it "should literalize endless Range instances to strings correctly" do
54
55
  @db.literal(eval('1..')).must_equal "'[1,]'"
56
+ @db.literal(eval('1...')).must_equal "'[1,)'"
55
57
  end if endless_range_support
56
58
 
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)'"
62
+ end if startless_range_support
63
+
64
+ it "should literalize startless, endless Range instances to strings correctly" do
65
+ @db.literal(eval('nil..nil')).must_equal "'[,]'"
66
+ @db.literal(eval('nil...nil')).must_equal "'[,)'"
67
+ end if startless_range_support
68
+
57
69
  it "should literalize PGRange instances to strings correctly" do
58
70
  @db.literal(@R.new(1, 2)).must_equal "'[1,2]'"
59
71
  @db.literal(@R.new(true, false)).must_equal "'[true,false]'"
@@ -79,8 +91,19 @@ describe "pg_range extension" do
79
91
 
80
92
  it "should support using endless Range instances as bound variables" do
81
93
  @db.bound_variable_arg(eval('1..'), nil).must_equal "[1,]"
94
+ @db.bound_variable_arg(eval('1...'), nil).must_equal "[1,)"
82
95
  end if endless_range_support
83
96
 
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)"
100
+ end if startless_range_support
101
+
102
+ it "should support using startless, endless Range instances as bound variables" do
103
+ @db.bound_variable_arg(eval('nil..nil'), nil).must_equal "[,]"
104
+ @db.bound_variable_arg(eval('nil...nil'), nil).must_equal "[,)"
105
+ end if startless_range_support
106
+
84
107
  it "should support using PGRange instances as bound variables" do
85
108
  @db.bound_variable_arg(@R.new(1, 2), nil).must_equal "[1,2]"
86
109
  end
@@ -431,12 +454,32 @@ describe "pg_range extension" do
431
454
 
432
455
  it "should consider PGRanges equal with a endless Range they represent" do
433
456
  @R.new(1, nil).must_be :==, eval('1..')
434
- end if endless_range_support
435
-
436
- it "should not consider a PGRange equal with a Range if it can't be expressed as a range" do
457
+ @R.new(1, nil, :exclude_end=>true).must_be :==, eval('1...')
458
+ @R.new(1, nil).wont_be :==, eval('1...')
459
+ @R.new(1, nil, :exclude_end=>true).wont_be :==, eval('1..')
437
460
  @R.new(1, nil).wont_be :==, eval('2..')
461
+ @R.new(1, nil, :exclude_end=>true).wont_be :==, eval('2...')
438
462
  end if endless_range_support
439
463
 
464
+ it "should consider PGRanges equal with a startless Range they represent" do
465
+ @R.new(nil, 1).must_be :==, eval('..1')
466
+ @R.new(nil, 1, :exclude_end=>true).must_be :==, eval('...1')
467
+ @R.new(nil, 1).wont_be :==, eval('...1')
468
+ @R.new(nil, 1, :exclude_end=>true).wont_be :==, eval('..1')
469
+ @R.new(nil, 1).wont_be :==, eval('..2')
470
+ @R.new(nil, 1, :exclude_end=>true).wont_be :==, eval('...2')
471
+ end if startless_range_support
472
+
473
+ it "should consider PGRanges equal with a startless, endless Range they represent" do
474
+ @R.new(nil, nil).must_be :==, eval('nil..nil')
475
+ @R.new(nil, nil, :exclude_end=>true).must_be :==, eval('nil...nil')
476
+ @R.new(nil, nil).wont_be :==, eval('nil...nil')
477
+ @R.new(nil, nil, :exclude_end=>true).wont_be :==, eval('nil..nil')
478
+ @R.new(nil, nil).wont_be :==, eval('nil..1')
479
+ @R.new(nil, nil).wont_be :==, eval('1..nil')
480
+ @R.new(1, nil).wont_be :==, eval('nil..nil')
481
+ end if startless_range_support
482
+
440
483
  it "should not consider a PGRange equal to other objects" do
441
484
  @R.new(nil, nil).wont_equal 1
442
485
  end
@@ -444,7 +487,6 @@ describe "pg_range extension" do
444
487
  it "should have #=== be true if given an equal PGRange" do
445
488
  @R.new(1, 2).must_be :===, @R.new(1, 2)
446
489
  @R.new(1, 2).wont_be :===, @R.new(1, 3)
447
-
448
490
  end
449
491
 
450
492
  it "should have #=== be true if it would be true for the Range represented by the PGRange" do
@@ -453,7 +495,7 @@ describe "pg_range extension" do
453
495
  end
454
496
 
455
497
  it "should have #=== be false if the PGRange cannot be represented by a Range" do
456
- @R.new(nil, nil).wont_be :===, 1.5
498
+ @R.new(1, 2, :exclude_begin=>true).wont_be :===, 1.5
457
499
  end
458
500
 
459
501
  it "should have #empty? indicate whether the range is empty" do
@@ -471,7 +513,6 @@ describe "pg_range extension" do
471
513
  end
472
514
 
473
515
  it "should have #to_range raise an exception if the PGRange cannot be represented by a Range" do
474
- proc{@R.new(nil, 1).to_range}.must_raise(Sequel::Error)
475
516
  proc{@R.new(0, 1, :exclude_begin=>true).to_range}.must_raise(Sequel::Error)
476
517
  proc{@R.empty.to_range}.must_raise(Sequel::Error)
477
518
  end
@@ -488,6 +529,22 @@ describe "pg_range extension" do
488
529
  proc{@R.new(1, nil).to_range}.must_raise(Sequel::Error)
489
530
  end unless endless_range_support
490
531
 
532
+ it "should have #to_range return the represented range for startless ranges" do
533
+ @R.new(nil, 1).to_range.must_be :==, eval('..1')
534
+ end if startless_range_support
535
+
536
+ it "should have #to_range raise an exception for startless ranges" do
537
+ proc{@R.new(nil, 1).to_range}.must_raise(Sequel::Error)
538
+ end unless startless_range_support
539
+
540
+ it "should have #to_range return the represented range for startless, endless ranges" do
541
+ @R.new(nil, nil).to_range.must_be :==, eval('nil..nil')
542
+ end if startless_range_support
543
+
544
+ it "should have #to_range raise an exception for startless, endless ranges" do
545
+ proc{@R.new(nil, nil).to_range}.must_raise(Sequel::Error)
546
+ end unless startless_range_support
547
+
491
548
  it "should have #to_range cache the returned value" do
492
549
  @r1.to_range.must_be_same_as(@r1.to_range)
493
550
  end
@@ -507,7 +564,6 @@ describe "pg_range extension" do
507
564
  end
508
565
 
509
566
  it "should have #valid_ruby_range? return false if the PGRange cannot be represented as a Range" do
510
- @R.new(nil, 1).valid_ruby_range?.must_equal false
511
567
  @R.new(0, 1, :exclude_begin=>true).valid_ruby_range?.must_equal false
512
568
  @R.empty.valid_ruby_range?.must_equal false
513
569
  end
@@ -515,5 +571,13 @@ describe "pg_range extension" do
515
571
  it "should have #valid_ruby_range return #{endless_range_support} for endless ranges" do
516
572
  @R.new(1, nil).valid_ruby_range?.must_equal(endless_range_support)
517
573
  end
574
+
575
+ it "should have #valid_ruby_range return #{startless_range_support} for endless ranges" do
576
+ @R.new(nil, 1).valid_ruby_range?.must_equal(startless_range_support)
577
+ end
578
+
579
+ it "should have #valid_ruby_range return #{startless_range_support} for startless, endless ranges" do
580
+ @R.new(nil, nil).valid_ruby_range?.must_equal(startless_range_support)
581
+ end
518
582
  end
519
583
  end
@@ -1109,6 +1109,12 @@ describe "Sequel::Dataset#import and #multi_insert :return=>:primary_key " do
1109
1109
  @ds.order(:id).map([:id, :i]).must_equal [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
1110
1110
  end
1111
1111
 
1112
+ it "should handle dataset with row_proc" do
1113
+ ds = @ds.with_row_proc(lambda{|h| Object.new})
1114
+ ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key).must_equal [1, 2, 3]
1115
+ ds.import([:i], [[40], [50], [60]], :return=>:primary_key).must_equal [4, 5, 6]
1116
+ end
1117
+
1112
1118
  it "should return primary key values when :slice is used" do
1113
1119
  @ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key, :slice=>2).must_equal [1, 2, 3]
1114
1120
  @ds.import([:i], [[40], [50], [60]], :return=>:primary_key, :slice=>2).must_equal [4, 5, 6]
@@ -1545,15 +1551,25 @@ describe "Sequel::Dataset DSL support" do
1545
1551
  @ds.exclude(:a=>[20, 10]).all.must_equal []
1546
1552
  end
1547
1553
 
1548
- it "should work with ranges as hash values" do
1554
+ it "should work with endless ranges as hash values" do
1549
1555
  @ds.insert(20, 10)
1550
- @ds.filter(:a=>(10..30)).all.must_equal [{:a=>20, :b=>10}]
1551
- @ds.filter(:a=>(25..30)).all.must_equal []
1552
- @ds.filter(:a=>(10..15)).all.must_equal []
1553
- @ds.exclude(:a=>(10..30)).all.must_equal []
1554
- @ds.exclude(:a=>(25..30)).all.must_equal [{:a=>20, :b=>10}]
1555
- @ds.exclude(:a=>(10..15)).all.must_equal [{:a=>20, :b=>10}]
1556
- end
1556
+ @ds.filter(:a=>eval('30..')).all.must_equal []
1557
+ @ds.filter(:a=>eval('20...')).all.must_equal [{:a=>20, :b=>10}]
1558
+ @ds.filter(:a=>eval('20..')).all.must_equal [{:a=>20, :b=>10}]
1559
+ @ds.filter(:a=>eval('10..')).all.must_equal [{:a=>20, :b=>10}]
1560
+ end if RUBY_VERSION >= '2.6'
1561
+
1562
+ it "should work with startless ranges as hash values" do
1563
+ @ds.insert(20, 10)
1564
+ @ds.filter(:a=>eval('..30')).all.must_equal [{:a=>20, :b=>10}]
1565
+ @ds.filter(:a=>eval('...30')).all.must_equal [{:a=>20, :b=>10}]
1566
+ @ds.filter(:a=>eval('..20')).all.must_equal [{:a=>20, :b=>10}]
1567
+ @ds.filter(:a=>eval('...20')).all.must_equal []
1568
+ @ds.filter(:a=>eval('..10')).all.must_equal []
1569
+ @ds.filter(:a=>eval('...10')).all.must_equal []
1570
+
1571
+ @ds.filter(:a=>eval('nil..nil')).all.must_equal [{:a=>20, :b=>10}]
1572
+ end if RUBY_VERSION >= '2.7'
1557
1573
 
1558
1574
  it "should work with CASE statements" do
1559
1575
  @ds.insert(20, 10)
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.21.0
4
+ version: 5.22.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-06-01 00:00:00.000000000 Z
11
+ date: 2019-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -205,6 +205,7 @@ extra_rdoc_files:
205
205
  - doc/release_notes/5.19.0.txt
206
206
  - doc/release_notes/5.20.0.txt
207
207
  - doc/release_notes/5.21.0.txt
208
+ - doc/release_notes/5.22.0.txt
208
209
  files:
209
210
  - CHANGELOG
210
211
  - MIT-LICENSE
@@ -297,6 +298,7 @@ files:
297
298
  - doc/release_notes/5.2.0.txt
298
299
  - doc/release_notes/5.20.0.txt
299
300
  - doc/release_notes/5.21.0.txt
301
+ - doc/release_notes/5.22.0.txt
300
302
  - doc/release_notes/5.3.0.txt
301
303
  - doc/release_notes/5.4.0.txt
302
304
  - doc/release_notes/5.5.0.txt