sequel 5.8.0 → 5.9.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -0
  3. data/doc/release_notes/5.9.0.txt +99 -0
  4. data/doc/testing.rdoc +10 -10
  5. data/lib/sequel/adapters/ado.rb +1 -1
  6. data/lib/sequel/adapters/amalgalite.rb +1 -1
  7. data/lib/sequel/adapters/jdbc.rb +19 -7
  8. data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
  9. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -5
  10. data/lib/sequel/adapters/postgres.rb +3 -3
  11. data/lib/sequel/adapters/shared/access.rb +5 -6
  12. data/lib/sequel/adapters/shared/mysql.rb +28 -2
  13. data/lib/sequel/adapters/shared/postgres.rb +16 -6
  14. data/lib/sequel/adapters/shared/sqlite.rb +1 -1
  15. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  16. data/lib/sequel/adapters/sqlite.rb +2 -2
  17. data/lib/sequel/connection_pool.rb +2 -1
  18. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -4
  19. data/lib/sequel/connection_pool/threaded.rb +19 -7
  20. data/lib/sequel/core.rb +1 -1
  21. data/lib/sequel/database/connecting.rb +6 -6
  22. data/lib/sequel/database/misc.rb +3 -3
  23. data/lib/sequel/database/query.rb +2 -2
  24. data/lib/sequel/database/schema_generator.rb +9 -3
  25. data/lib/sequel/database/schema_methods.rb +12 -5
  26. data/lib/sequel/dataset/features.rb +5 -0
  27. data/lib/sequel/dataset/misc.rb +1 -1
  28. data/lib/sequel/dataset/prepared_statements.rb +4 -4
  29. data/lib/sequel/dataset/query.rb +5 -0
  30. data/lib/sequel/dataset/sql.rb +8 -6
  31. data/lib/sequel/extensions/escaped_like.rb +100 -0
  32. data/lib/sequel/extensions/eval_inspect.rb +3 -1
  33. data/lib/sequel/extensions/looser_typecasting.rb +3 -3
  34. data/lib/sequel/extensions/pg_extended_date_support.rb +23 -10
  35. data/lib/sequel/model/associations.rb +18 -4
  36. data/lib/sequel/model/base.rb +9 -2
  37. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  38. data/lib/sequel/plugins/many_through_many.rb +1 -1
  39. data/lib/sequel/plugins/nested_attributes.rb +2 -2
  40. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -2
  41. data/lib/sequel/plugins/rcte_tree.rb +5 -7
  42. data/lib/sequel/plugins/sharding.rb +2 -2
  43. data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
  44. data/lib/sequel/plugins/tree.rb +2 -2
  45. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  46. data/lib/sequel/sql.rb +2 -2
  47. data/lib/sequel/version.rb +4 -1
  48. data/spec/adapters/mysql_spec.rb +24 -0
  49. data/spec/adapters/postgres_spec.rb +9 -9
  50. data/spec/adapters/sqlite_spec.rb +10 -10
  51. data/spec/core/connection_pool_spec.rb +22 -0
  52. data/spec/core/database_spec.rb +6 -6
  53. data/spec/core/dataset_spec.rb +16 -5
  54. data/spec/core/expression_filters_spec.rb +1 -1
  55. data/spec/core/schema_spec.rb +1 -1
  56. data/spec/core/version_spec.rb +7 -0
  57. data/spec/extensions/connection_expiration_spec.rb +20 -2
  58. data/spec/extensions/connection_validator_spec.rb +20 -3
  59. data/spec/extensions/escaped_like_spec.rb +40 -0
  60. data/spec/extensions/eval_inspect_spec.rb +1 -1
  61. data/spec/extensions/nested_attributes_spec.rb +6 -0
  62. data/spec/extensions/pg_array_spec.rb +13 -13
  63. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -1
  64. data/spec/extensions/pg_range_spec.rb +1 -1
  65. data/spec/extensions/schema_dumper_spec.rb +2 -2
  66. data/spec/extensions/sql_expr_spec.rb +1 -1
  67. data/spec/extensions/string_agg_spec.rb +1 -1
  68. data/spec/extensions/timestamps_spec.rb +2 -2
  69. data/spec/extensions/validation_helpers_spec.rb +1 -1
  70. data/spec/integration/associations_test.rb +12 -0
  71. data/spec/integration/dataset_test.rb +21 -0
  72. data/spec/integration/type_test.rb +4 -4
  73. data/spec/model/base_spec.rb +9 -0
  74. data/spec/model/eager_loading_spec.rb +25 -0
  75. data/spec/model/record_spec.rb +1 -1
  76. metadata +6 -2
@@ -96,7 +96,7 @@ module Sequel
96
96
  name = opts[:name]
97
97
  if (!associations.include?(name) || dynamic_opts[:eager_reload]) && opts[:allow_eager] != false && retrieved_by && !frozen? && !dynamic_opts[:callback] && !dynamic_opts[:reload]
98
98
  begin
99
- retrieved_by.send(:eager_load, retrieved_with.reject(&:frozen?), name=>dynamic_opts[:eager] || {})
99
+ retrieved_by.send(:eager_load, retrieved_with.reject(&:frozen?), name=>dynamic_opts[:eager] || OPTS)
100
100
  rescue Sequel::UndefinedAssociation
101
101
  # This can happen if class table inheritance is used and the association
102
102
  # is only defined in a subclass. This particular instance can use the
@@ -38,10 +38,10 @@ module Sequel
38
38
  @tree_order = opts[:order]
39
39
  end
40
40
 
41
- par = opts.merge(opts.fetch(:parent, {}))
41
+ par = opts.merge(opts.fetch(:parent, OPTS))
42
42
  parent = par.fetch(:name, :parent)
43
43
 
44
- chi = opts.merge(opts.fetch(:children, {}))
44
+ chi = opts.merge(opts.fetch(:children, OPTS))
45
45
  children = chi.fetch(:name, :children)
46
46
 
47
47
  par[:reciprocal] = children
@@ -419,7 +419,7 @@ module Sequel
419
419
  # an empty hash is returned This method is useful when writing methods that
420
420
  # take an options hash as the last parameter.
421
421
  def extract_options!(array)
422
- array.last.is_a?(Hash) ? array.pop : {}
422
+ array.last.is_a?(Hash) ? array.pop : OPTS
423
423
  end
424
424
 
425
425
  # Add the validation reflection to the class's validations.
@@ -1366,7 +1366,7 @@ module Sequel
1366
1366
  end
1367
1367
 
1368
1368
  # Return a new function with an OVER clause (making it a window function).
1369
- # See {SQL::Window} for the list of options +over+ can receive.
1369
+ # See Sequel::SQL::Window for the list of options +over+ can receive.
1370
1370
  #
1371
1371
  # Sequel.function(:row_number).over(partition: :col) # row_number() OVER (PARTITION BY col)
1372
1372
  def over(window=OPTS)
@@ -1703,7 +1703,7 @@ module Sequel
1703
1703
  # StringExpression.like(:a, 'a%', /^a/i) # (("a" LIKE 'a%' ESCAPE '\') OR ("a" ~* '^a'))
1704
1704
  def self.like(l, *ces)
1705
1705
  l, lre, lci = like_element(l)
1706
- lci = (ces.last.is_a?(Hash) ? ces.pop : {})[:case_insensitive] ? true : lci
1706
+ lci = (ces.last.is_a?(Hash) ? ces.pop : OPTS)[:case_insensitive] ? true : lci
1707
1707
  ces.map! do |ce|
1708
1708
  r, rre, rci = like_element(ce)
1709
1709
  BooleanExpression.new(LIKE_MAP[[lre||rre, lci||rci]], l, r)
@@ -5,13 +5,16 @@ module Sequel
5
5
  MAJOR = 5
6
6
  # The minor version of Sequel. Bumped for every non-patch level
7
7
  # release, generally around once a month.
8
- MINOR = 8
8
+ MINOR = 9
9
9
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
10
10
  # releases that fix regressions from previous versions.
11
11
  TINY = 0
12
12
 
13
13
  # The version of Sequel you are using, as a string (e.g. "2.11.0")
14
14
  VERSION = [MAJOR, MINOR, TINY].join('.').freeze
15
+
16
+ # The version of Sequel you are using, as a number (2.11.0 -> 20110)
17
+ VERSION_NUMBER = MAJOR*10000 + MINOR*10 + TINY
15
18
 
16
19
  # The version of Sequel you are using, as a string (e.g. "2.11.0")
17
20
  def self.version
@@ -69,6 +69,12 @@ describe "MySQL", '#create_table' do
69
69
  @db.set_column_type :dolls, :a, Integer, :auto_increment=>true
70
70
  @db.schema(:dolls).first.last[:auto_increment].must_equal true
71
71
  end
72
+
73
+ it "should create generated column" do
74
+ skip("generated columns not supported, skipping test") unless @db.supports_generated_columns?
75
+ @db.create_table(:dolls){String :a; String :b, generated_always_as: Sequel.function(:CONCAT, :a, 'plus')}
76
+ @db.schema(:dolls)[1][1][:generated].must_equal true
77
+ end
72
78
  end
73
79
 
74
80
  if [:mysql, :mysql2].include?(DB.adapter_scheme)
@@ -203,6 +209,13 @@ describe "A MySQL dataset" do
203
209
  ps.call(:v => 1, :n => 'b')
204
210
  ds.all.must_equal [{:value=>1, :name=>'b'}]
205
211
  end
212
+
213
+ it "should support generated columns" do
214
+ skip("generated columns not supported, skipping test") unless DB.supports_generated_columns?
215
+ DB.alter_table(:items) {add_column :b, String, :generated_always_as => Sequel.function(:CONCAT, :name, 'plus')}
216
+ @d.insert(name: 'hello')
217
+ @d.first[:b].must_equal 'helloplus'
218
+ end
206
219
  end
207
220
 
208
221
  describe "Dataset#distinct" do
@@ -219,6 +232,8 @@ describe "Dataset#distinct" do
219
232
  end
220
233
 
221
234
  it "#distinct with arguments should return results distinct on those arguments" do
235
+ skip("ONLY_FULL_GROUP_BY sql_mode set, skipping DISTINCT ON emulation test") if @db.get(Sequel.lit '@@sql_mode').include?('ONLY_FULL_GROUP_BY')
236
+
222
237
  @ds.insert(20, 10)
223
238
  @ds.insert(30, 10)
224
239
  @ds.order(:b, :a).distinct.map(:a).must_equal [20, 30]
@@ -501,6 +516,15 @@ describe "A MySQL database" do
501
516
  @db << 'DELETE FROM items'
502
517
  @db[:items].first.must_be_nil
503
518
  end
519
+
520
+ it "should have schema handle generated columns" do
521
+ skip("generated columns not supported, skipping test") unless @db.supports_generated_columns?
522
+ @db.create_table(:items) {String :a}
523
+ @db.alter_table(:items){add_column :b, String, :generated_always_as=>Sequel.function(:CONCAT, :a, 'plus'), :generated_type=>:stored, :unique=>true}
524
+ @db.schema(:items)[1][1][:generated].must_equal true
525
+ @db.alter_table(:items){add_column :c, String, :generated_always_as=>Sequel.function(:CONCAT, :a, 'minus'), :generated_type=>:virtual}
526
+ @db.schema(:items)[2][1][:generated].must_equal true
527
+ end
504
528
  end
505
529
 
506
530
  # Socket tests should only be run if the MySQL server is on localhost
@@ -2186,10 +2186,10 @@ describe 'PostgreSQL array handling' do
2186
2186
  column :n, 'numeric[]'
2187
2187
  end
2188
2188
  @tp.call.must_equal [:decimal_array]
2189
- @ds.insert(Sequel.pg_array([BigDecimal.new('1.000000000000000000001'), nil, BigDecimal.new('1')], :numeric))
2189
+ @ds.insert(Sequel.pg_array([BigDecimal('1.000000000000000000001'), nil, BigDecimal('1')], :numeric))
2190
2190
  @ds.count.must_equal 1
2191
2191
  rs = @ds.all
2192
- rs.must_equal [{:n=>[BigDecimal.new('1.000000000000000000001'), nil, BigDecimal.new('1')]}]
2192
+ rs.must_equal [{:n=>[BigDecimal('1.000000000000000000001'), nil, BigDecimal('1')]}]
2193
2193
  rs.first.values.each{|v| v.class.must_equal(Sequel::Postgres::PGArray)}
2194
2194
  rs.first.values.each{|v| v.to_a.must_be_kind_of(Array)}
2195
2195
  @ds.delete
@@ -2197,9 +2197,9 @@ describe 'PostgreSQL array handling' do
2197
2197
  @ds.all.must_equal rs
2198
2198
 
2199
2199
  @ds.delete
2200
- @ds.insert(Sequel.pg_array([[BigDecimal.new('1.0000000000000000000000000000001'), nil], [nil, BigDecimal.new('1')]], :numeric))
2200
+ @ds.insert(Sequel.pg_array([[BigDecimal('1.0000000000000000000000000000001'), nil], [nil, BigDecimal('1')]], :numeric))
2201
2201
  rs = @ds.all
2202
- rs.must_equal [{:n=>[[BigDecimal.new('1.0000000000000000000000000000001'), nil], [nil, BigDecimal.new('1')]]}]
2202
+ rs.must_equal [{:n=>[[BigDecimal('1.0000000000000000000000000000001'), nil], [nil, BigDecimal('1')]]}]
2203
2203
  rs.first.values.each{|v| v.class.must_equal(Sequel::Postgres::PGArray)}
2204
2204
  rs.first.values.each{|v| v.to_a.must_be_kind_of(Array)}
2205
2205
  @ds.delete
@@ -2469,11 +2469,11 @@ describe 'PostgreSQL array handling' do
2469
2469
  column :t, 'text[]'
2470
2470
  end
2471
2471
  c = Class.new(Sequel::Model(@db[:items]))
2472
- h = {:i=>[1,2, nil], :f=>[[1, 2.5], [3, 4.5]], :d=>[1, BigDecimal.new('1.000000000000000000001')], :t=>[%w'a b c', ['NULL', nil, '1']]}
2472
+ h = {:i=>[1,2, nil], :f=>[[1, 2.5], [3, 4.5]], :d=>[1, BigDecimal('1.000000000000000000001')], :t=>[%w'a b c', ['NULL', nil, '1']]}
2473
2473
  o = c.create(h)
2474
2474
  o.i.must_equal [1, 2, nil]
2475
2475
  o.f.must_equal [[1, 2.5], [3, 4.5]]
2476
- o.d.must_equal [BigDecimal.new('1'), BigDecimal.new('1.000000000000000000001')]
2476
+ o.d.must_equal [BigDecimal('1'), BigDecimal('1.000000000000000000001')]
2477
2477
  o.t.must_equal [%w'a b c', ['NULL', nil, '1']]
2478
2478
  c.where(:i=>o.i, :f=>o.f, :d=>o.d, :t=>o.t).all.must_equal [o]
2479
2479
  o2 = c.new(h)
@@ -2487,10 +2487,10 @@ describe 'PostgreSQL array handling' do
2487
2487
  column :t, 'varchar[]'
2488
2488
  end
2489
2489
  c = Class.new(Sequel::Model(@db[:items]))
2490
- o = c.create(:i=>[1,2, nil], :f=>[[1, 2.5], [3, 4.5]], :d=>[1, BigDecimal.new('1.000000000000000000001')], :t=>[%w'a b c', ['NULL', nil, '1']])
2490
+ o = c.create(:i=>[1,2, nil], :f=>[[1, 2.5], [3, 4.5]], :d=>[1, BigDecimal('1.000000000000000000001')], :t=>[%w'a b c', ['NULL', nil, '1']])
2491
2491
  o.i.must_equal [1, 2, nil]
2492
2492
  o.f.must_equal [[1, 2.5], [3, 4.5]]
2493
- o.d.must_equal [BigDecimal.new('1'), BigDecimal.new('1.000000000000000000001')]
2493
+ o.d.must_equal [BigDecimal('1'), BigDecimal('1.000000000000000000001')]
2494
2494
  o.t.must_equal [%w'a b c', ['NULL', nil, '1']]
2495
2495
  c.where(:i=>o.i, :f=>o.f, :d=>o.d, :t=>o.t).all.must_equal [o]
2496
2496
  o2 = c.new(h)
@@ -3225,7 +3225,7 @@ describe 'PostgreSQL range types' do
3225
3225
  @db = DB
3226
3226
  @ds = @db[:items]
3227
3227
  @map = {:i4=>'int4range', :i8=>'int8range', :n=>'numrange', :d=>'daterange', :t=>'tsrange', :tz=>'tstzrange'}
3228
- @r = {:i4=>1...2, :i8=>2...3, :n=>BigDecimal.new('1.0')..BigDecimal.new('2.0'), :d=>Date.today...(Date.today+1), :t=>Time.local(2011, 1)..Time.local(2011, 2), :tz=>Time.local(2011, 1)..Time.local(2011, 2)}
3228
+ @r = {:i4=>1...2, :i8=>2...3, :n=>BigDecimal('1.0')..BigDecimal('2.0'), :d=>Date.today...(Date.today+1), :t=>Time.local(2011, 1)..Time.local(2011, 2), :tz=>Time.local(2011, 1)..Time.local(2011, 2)}
3229
3229
  @ra = {}
3230
3230
  @pgr = {}
3231
3231
  @pgra = {}
@@ -77,12 +77,12 @@ describe "An SQLite database" do
77
77
  it "should handle and return BigDecimal values for numeric columns" do
78
78
  DB.create_table!(:fk){numeric :d}
79
79
  d = DB[:fk]
80
- d.insert(:d=>BigDecimal.new('80.0'))
81
- d.insert(:d=>BigDecimal.new('NaN'))
82
- d.insert(:d=>BigDecimal.new('Infinity'))
83
- d.insert(:d=>BigDecimal.new('-Infinity'))
80
+ d.insert(:d=>BigDecimal('80.0'))
81
+ d.insert(:d=>BigDecimal('NaN'))
82
+ d.insert(:d=>BigDecimal('Infinity'))
83
+ d.insert(:d=>BigDecimal('-Infinity'))
84
84
  ds = d.all
85
- ds.shift.must_equal(:d=>BigDecimal.new('80.0'))
85
+ ds.shift.must_equal(:d=>BigDecimal('80.0'))
86
86
  ds.map{|x| x[:d].to_s}.must_equal %w'NaN Infinity -Infinity'
87
87
  DB
88
88
  end
@@ -153,19 +153,19 @@ describe "SQLite type conversion" do
153
153
  it "should handle integers/floats/strings/decimals in numeric/decimal columns" do
154
154
  @db.create_table(:items){Numeric :a}
155
155
  @db[:items].insert(100)
156
- @db[:items].select_map(:a).must_equal [BigDecimal.new('100')]
156
+ @db[:items].select_map(:a).must_equal [BigDecimal('100')]
157
157
  @db[:items].get(:a).must_be_kind_of(BigDecimal)
158
158
 
159
159
  @db[:items].update(:a=>100.1)
160
- @db[:items].select_map(:a).must_equal [BigDecimal.new('100.1')]
160
+ @db[:items].select_map(:a).must_equal [BigDecimal('100.1')]
161
161
  @db[:items].get(:a).must_be_kind_of(BigDecimal)
162
162
 
163
163
  @db[:items].update(:a=>'100.1')
164
- @db[:items].select_map(:a).must_equal [BigDecimal.new('100.1')]
164
+ @db[:items].select_map(:a).must_equal [BigDecimal('100.1')]
165
165
  @db[:items].get(:a).must_be_kind_of(BigDecimal)
166
166
 
167
- @db[:items].update(:a=>BigDecimal.new('100.1'))
168
- @db[:items].select_map(:a).must_equal [BigDecimal.new('100.1')]
167
+ @db[:items].update(:a=>BigDecimal('100.1'))
168
+ @db[:items].select_map(:a).must_equal [BigDecimal('100.1')]
169
169
  @db[:items].get(:a).must_be_kind_of(BigDecimal)
170
170
  end
171
171
 
@@ -549,6 +549,28 @@ ThreadedConnectionPoolSpecs = shared_description do
549
549
  @pool.size.must_equal 0
550
550
  d.must_equal [2, 1, 3, 4]
551
551
  end
552
+
553
+
554
+ it "should handle dead threads with checked out connections" do
555
+ pool = Sequel::ConnectionPool.get_pool(mock_db.call(&@icpp), @cp_opts.merge(:max_connections=>1))
556
+
557
+ skip = true
558
+ # Leave allocated connection to emulate dead thread with checked out connection
559
+ pool.define_singleton_method(:release){|*a| return if skip; super(*a)}
560
+ Thread.new{pool.hold{Thread.current.kill}}.join
561
+ skip = false
562
+
563
+ pool.allocated.wont_be :empty?
564
+ pool.available_connections.must_be :empty?
565
+
566
+ pool.hold{|c1| c1}
567
+ pool.allocated.must_be :empty?
568
+ pool.available_connections.wont_be :empty?
569
+
570
+ pool.disconnect
571
+ pool.allocated.must_be :empty?
572
+ pool.available_connections.must_be :empty?
573
+ end
552
574
  end
553
575
 
554
576
  describe "Threaded Unsharded Connection Pool" do
@@ -2167,7 +2167,7 @@ describe "Database#typecast_value" do
2167
2167
  [1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
2168
2168
  v = @db.typecast_value(:decimal, i)
2169
2169
  v.must_be_kind_of(BigDecimal)
2170
- v.must_equal BigDecimal.new('1.0')
2170
+ v.must_equal BigDecimal('1.0')
2171
2171
  end
2172
2172
  end
2173
2173
 
@@ -2426,8 +2426,8 @@ describe "Database#column_schema_to_ruby_default" do
2426
2426
  p[1.0, :float].must_equal 1.0
2427
2427
  p['1.0', :float].must_equal 1.0
2428
2428
  p['-1.0', :float].must_equal(-1.0)
2429
- p['1.0', :decimal].must_equal BigDecimal.new('1.0')
2430
- p['-1.0', :decimal].must_equal BigDecimal.new('-1.0')
2429
+ p['1.0', :decimal].must_equal BigDecimal('1.0')
2430
+ p['-1.0', :decimal].must_equal BigDecimal('-1.0')
2431
2431
  p[true, :boolean].must_equal true
2432
2432
  p[false, :boolean].must_equal false
2433
2433
  p['1', :boolean].must_equal true
@@ -2463,7 +2463,7 @@ describe "Database#column_schema_to_ruby_default" do
2463
2463
  p["'a'::bpchar", :string].must_equal "a"
2464
2464
  p["(-1)", :integer].must_equal(-1)
2465
2465
  p["(-1.0)", :float].must_equal(-1.0)
2466
- p['(-1.0)', :decimal].must_equal BigDecimal.new('-1.0')
2466
+ p['(-1.0)', :decimal].must_equal BigDecimal('-1.0')
2467
2467
  p["'a'::bytea", :blob].must_equal Sequel.blob('a')
2468
2468
  p["'a'::bytea", :blob].must_be_kind_of(Sequel::SQL::Blob)
2469
2469
  p["'2009-10-29'::date", :date].must_equal Date.new(2009,10,29)
@@ -2475,7 +2475,7 @@ describe "Database#column_schema_to_ruby_default" do
2475
2475
  p["a", :string].must_equal "a"
2476
2476
  p["NULL", :string].must_equal "NULL"
2477
2477
  p["-1", :float].must_equal(-1.0)
2478
- p['-1', :decimal].must_equal BigDecimal.new('-1.0')
2478
+ p['-1', :decimal].must_equal BigDecimal('-1.0')
2479
2479
  p["2009-10-29", :date].must_equal Date.new(2009,10,29)
2480
2480
  p["2009-10-29 10:20:30", :datetime].must_equal DateTime.parse('2009-10-29 10:20:30')
2481
2481
  p["10:20:30", :time].must_equal Time.parse('10:20:30')
@@ -2486,7 +2486,7 @@ describe "Database#column_schema_to_ruby_default" do
2486
2486
  p["(N'a')", :string].must_equal "a"
2487
2487
  p["((-12))", :integer].must_equal(-12)
2488
2488
  p["((12.1))", :float].must_equal 12.1
2489
- p["((-12.1))", :decimal].must_equal BigDecimal.new('-12.1')
2489
+ p["((-12.1))", :decimal].must_equal BigDecimal('-12.1')
2490
2490
  end
2491
2491
  end
2492
2492
 
@@ -623,7 +623,7 @@ describe "Dataset#where" do
623
623
  it "should raise an error if an numeric is used" do
624
624
  proc{@dataset.filter(1)}.must_raise(Sequel::Error)
625
625
  proc{@dataset.filter(1.0)}.must_raise(Sequel::Error)
626
- proc{@dataset.filter(BigDecimal.new('1.0'))}.must_raise(Sequel::Error)
626
+ proc{@dataset.filter(BigDecimal('1.0'))}.must_raise(Sequel::Error)
627
627
  end
628
628
 
629
629
  it "should raise an error if a NumericExpression or StringExpression is used" do
@@ -1082,10 +1082,10 @@ describe "Dataset#literal" do
1082
1082
  end
1083
1083
 
1084
1084
  it "should literalize BigDecimal instances correctly" do
1085
- @dataset.literal(BigDecimal.new("80")).must_equal "80.0"
1086
- @dataset.literal(BigDecimal.new("NaN")).must_equal "'NaN'"
1087
- @dataset.literal(BigDecimal.new("Infinity")).must_equal "'Infinity'"
1088
- @dataset.literal(BigDecimal.new("-Infinity")).must_equal "'-Infinity'"
1085
+ @dataset.literal(BigDecimal("80")).must_equal "80.0"
1086
+ @dataset.literal(BigDecimal("NaN")).must_equal "'NaN'"
1087
+ @dataset.literal(BigDecimal("Infinity")).must_equal "'Infinity'"
1088
+ @dataset.literal(BigDecimal("-Infinity")).must_equal "'-Infinity'"
1089
1089
  end
1090
1090
 
1091
1091
  it "should literalize PlaceholderLiteralStrings correctly" do
@@ -3799,6 +3799,17 @@ describe "Dataset#with_sql_*" do
3799
3799
  @ds.with_sql_single_value('SELECT * FROM foo')
3800
3800
  @ds.columns.must_equal [:x]
3801
3801
  end
3802
+
3803
+ it "#_with_sql_dataset (private) should return a clone that doesn't use separate dataset for columns" do
3804
+ @ds = @ds.with_extend{def fetch_rows(sql) self.columns = [:id]; super end}
3805
+ @ds.send(:cache_set, :_columns, [:foo])
3806
+ ds = @ds.send(:_with_sql_dataset)
3807
+ ds.must_be_same_as ds.send(:_with_sql_dataset)
3808
+ ds.with_sql_first('SELECT * FROM foo').must_equal(:id=>1)
3809
+ ds.columns.must_equal [:id]
3810
+ @ds.with_sql_first('SELECT * FROM foo').must_equal(:id=>1)
3811
+ @ds.columns.must_equal [:foo]
3812
+ end
3802
3813
  end
3803
3814
 
3804
3815
  describe "Dataset prepared statements and bound variables " do
@@ -186,7 +186,7 @@ describe "Blockless Ruby Filters" do
186
186
  @d.lit(1 + Sequel.expr(:x)).must_equal '(1 + x)'
187
187
  @d.lit(2**65 - Sequel.+(:x, 1)).must_equal "(#{2**65} - (x + 1))"
188
188
  @d.lit(1.0 / Sequel.function(:x)).must_equal '(1.0 / x())'
189
- @d.lit(BigDecimal.new('1.0') * Sequel[:a][:y]).must_equal '(1.0 * a.y)'
189
+ @d.lit(BigDecimal('1.0') * Sequel[:a][:y]).must_equal '(1.0 * a.y)'
190
190
  @d.lit(2 ** Sequel.cast(:x, Integer)).must_equal 'power(2, CAST(x AS integer))'
191
191
  @d.lit(1 + Sequel.lit('x')).must_equal '(1 + x)'
192
192
  @d.lit(1 + Sequel.lit('?', :x)).must_equal '(1 + x)'
@@ -1679,7 +1679,7 @@ describe "Schema Parser" do
1679
1679
  sch = @db.schema(:x)
1680
1680
  sch.must_equal [[:a, {:db_type=>"x", :ruby_default=>nil}], [:b, {:db_type=>"x", :ruby_default=>nil}]]
1681
1681
  sch[0][1][:db_type].must_be_same_as(sch[1][1][:db_type])
1682
- end if RUBY_VERSION >= '2.5'
1682
+ end if RUBY_VERSION >= '2.5' && !defined?(JRUBY_VERSION)
1683
1683
 
1684
1684
  it "should set :auto_increment to true by default if unset and a single integer primary key is used" do
1685
1685
  @db.define_singleton_method(:schema_parse_table){|*| [[:a, {:primary_key=>true, :db_type=>'integer'}]]}
@@ -4,4 +4,11 @@ describe "Sequel.version" do
4
4
  it "should be in the form X.Y.Z with all being numbers" do
5
5
  Sequel.version.must_match(/\A\d+\.\d+\.\d+\z/)
6
6
  end
7
+
8
+ it "MAJOR/MINOR/TINY/VERSION_NUMBER should be integers" do
9
+ Sequel::MAJOR.must_be_kind_of(Integer)
10
+ Sequel::MINOR.must_be_kind_of(Integer)
11
+ Sequel::TINY.must_be_kind_of(Integer)
12
+ Sequel::VERSION_NUMBER.must_be_kind_of(Integer)
13
+ end
7
14
  end
@@ -3,11 +3,12 @@ require_relative "spec_helper"
3
3
  connection_expiration_specs = shared_description do
4
4
  describe "connection expiration" do
5
5
  before do
6
- @db.extend(Module.new do
6
+ @m = Module.new do
7
7
  def disconnect_connection(conn)
8
8
  @sqls << 'disconnect'
9
9
  end
10
- end)
10
+ end
11
+ @db.extend @m
11
12
  @db.extension(:connection_expiration)
12
13
  @db.pool.connection_expiration_timeout = 2
13
14
  end
@@ -21,6 +22,23 @@ connection_expiration_specs = shared_description do
21
22
  @db.pool.connection_expiration_timeout.must_equal 2
22
23
  end
23
24
 
25
+ it "should handle Database#disconnect calls while the connection is checked out" do
26
+ @db.synchronize{|c| @db.disconnect}
27
+ end
28
+
29
+ it "should handle disconnected connections" do
30
+ proc{@db.synchronize{|c| raise Sequel::DatabaseDisconnectError}}.must_raise Sequel::DatabaseDisconnectError
31
+ @db.sqls.must_equal ['disconnect']
32
+ end
33
+
34
+ it "should handle :connection_handling => :disconnect setting" do
35
+ @db = Sequel.mock(@db.opts.merge(:connection_handling => :disconnect))
36
+ @db.extend @m
37
+ @db.extension(:connection_expiration)
38
+ @db.synchronize{}
39
+ @db.sqls.must_equal ['disconnect']
40
+ end
41
+
24
42
  it "should only expire if older than timeout" do
25
43
  c1 = @db.synchronize{|c| c}
26
44
  @db.sqls.must_equal []
@@ -3,7 +3,7 @@ require_relative "spec_helper"
3
3
  connection_validator_specs = shared_description do
4
4
  describe "connection validator" do
5
5
  before do
6
- @db.extend(Module.new do
6
+ @m = Module.new do
7
7
  def disconnect_connection(conn)
8
8
  @sqls << 'disconnect'
9
9
  end
@@ -19,7 +19,8 @@ connection_validator_specs = shared_description do
19
19
  conn.valid = true
20
20
  conn
21
21
  end
22
- end)
22
+ end
23
+ @db.extend @m
23
24
  @db.extension(:connection_validator)
24
25
  end
25
26
 
@@ -52,6 +53,23 @@ connection_validator_specs = shared_description do
52
53
  c2.wont_be_same_as(c1)
53
54
  end
54
55
 
56
+ it "should handle Database#disconnect calls while the connection is checked out" do
57
+ @db.synchronize{|c| @db.disconnect}
58
+ end
59
+
60
+ it "should handle disconnected connections" do
61
+ proc{@db.synchronize{|c| raise Sequel::DatabaseDisconnectError}}.must_raise Sequel::DatabaseDisconnectError
62
+ @db.sqls.must_equal ['disconnect']
63
+ end
64
+
65
+ it "should handle :connection_handling => :disconnect setting" do
66
+ @db = Sequel.mock(@db.opts.merge(:connection_handling => :disconnect))
67
+ @db.extend @m
68
+ @db.extension(:connection_validator)
69
+ @db.synchronize{}
70
+ @db.sqls.must_equal ['disconnect']
71
+ end
72
+
55
73
  it "should disconnect multiple connections repeatedly if they are not valid" do
56
74
  q, q1 = Queue.new, Queue.new
57
75
  c1 = nil
@@ -124,4 +142,3 @@ describe "Sequel::ConnectionValidator with sharded threaded pool" do
124
142
  end
125
143
  include connection_validator_specs
126
144
  end
127
-