sequel 5.21.0 → 5.22.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: 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