sequel 5.24.0 → 5.29.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +58 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/doc/cheat_sheet.rdoc +1 -0
- data/doc/postgresql.rdoc +2 -2
- data/doc/release_notes/5.25.0.txt +32 -0
- data/doc/release_notes/5.26.0.txt +35 -0
- data/doc/release_notes/5.27.0.txt +21 -0
- data/doc/release_notes/5.28.0.txt +16 -0
- data/doc/release_notes/5.29.0.txt +22 -0
- data/doc/testing.rdoc +11 -6
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
- data/lib/sequel/adapters/postgres.rb +5 -1
- data/lib/sequel/adapters/shared/mssql.rb +4 -2
- data/lib/sequel/adapters/shared/mysql.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +15 -0
- data/lib/sequel/adapters/shared/sqlite.rb +7 -2
- data/lib/sequel/adapters/tinytds.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/transactions.rb +3 -3
- data/lib/sequel/dataset/features.rb +6 -0
- data/lib/sequel/dataset/misc.rb +2 -2
- data/lib/sequel/dataset/query.rb +15 -2
- data/lib/sequel/dataset/sql.rb +17 -4
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/exclude_or_null.rb +68 -0
- data/lib/sequel/extensions/pg_array_ops.rb +10 -6
- data/lib/sequel/extensions/pg_enum.rb +4 -1
- data/lib/sequel/extensions/pg_json.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +124 -0
- data/lib/sequel/extensions/pg_range.rb +9 -0
- data/lib/sequel/extensions/sql_comments.rb +2 -2
- data/lib/sequel/model/base.rb +12 -5
- data/lib/sequel/plugins/association_multi_add_remove.rb +83 -0
- data/lib/sequel/plugins/caching.rb +3 -0
- data/lib/sequel/plugins/csv_serializer.rb +26 -9
- data/lib/sequel/plugins/dirty.rb +3 -9
- data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
- data/lib/sequel/plugins/json_serializer.rb +15 -4
- data/lib/sequel/plugins/nested_attributes.rb +7 -0
- data/lib/sequel/plugins/sharding.rb +11 -5
- data/lib/sequel/plugins/throw_failures.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +3 -2
- data/lib/sequel/sql.rb +4 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +82 -17
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/bin_spec.rb +1 -1
- data/spec/core/database_spec.rb +1 -1
- data/spec/core/dataset_spec.rb +0 -3
- data/spec/core/expression_filters_spec.rb +26 -7
- data/spec/core/spec_helper.rb +1 -1
- data/spec/core_extensions_spec.rb +1 -1
- data/spec/extensions/any_not_empty_spec.rb +23 -0
- data/spec/extensions/association_multi_add_remove_spec.rb +1041 -0
- data/spec/extensions/caller_logging_spec.rb +1 -1
- data/spec/extensions/dirty_spec.rb +33 -0
- data/spec/extensions/empty_failure_backtraces_spec.rb +60 -0
- data/spec/extensions/exclude_or_null_spec.rb +15 -0
- data/spec/extensions/json_serializer_spec.rb +10 -0
- data/spec/extensions/named_timezones_spec.rb +5 -5
- data/spec/extensions/nested_attributes_spec.rb +48 -0
- data/spec/extensions/pg_array_ops_spec.rb +3 -3
- data/spec/extensions/pg_json_ops_spec.rb +67 -0
- data/spec/extensions/pg_range_spec.rb +35 -21
- data/spec/extensions/sharding_spec.rb +8 -0
- data/spec/extensions/spec_helper.rb +1 -1
- data/spec/guards_helper.rb +1 -1
- data/spec/integration/associations_test.rb +1 -1
- data/spec/integration/dataset_test.rb +57 -17
- data/spec/integration/plugin_test.rb +1 -1
- data/spec/integration/schema_test.rb +9 -0
- data/spec/integration/spec_helper.rb +7 -1
- data/spec/model/plugins_spec.rb +2 -2
- data/spec/model/spec_helper.rb +1 -1
- data/spec/sequel_warning.rb +1 -0
- metadata +35 -3
@@ -42,7 +42,7 @@ describe "caller_logging extension" do
|
|
42
42
|
|
43
43
|
it "should not log caller information if all callers lines are filtered" do
|
44
44
|
@db.caller_logging_ignore = /./
|
45
|
-
exec_sql("SELECT * FROM items")
|
45
|
+
exec_sql("SELECT * FROM items")
|
46
46
|
@log_stream.rewind
|
47
47
|
lines = @log_stream.read.split("\n")
|
48
48
|
lines.length.must_equal 1
|
@@ -162,6 +162,39 @@ describe "Sequel::Plugins::Dirty" do
|
|
162
162
|
@o.save
|
163
163
|
@o.column_changes.must_equal({})
|
164
164
|
end
|
165
|
+
|
166
|
+
it "should work with the typecast_on_load plugin" do
|
167
|
+
@c.instance_variable_set(:@db_schema, :initial=>{:type=>:integer})
|
168
|
+
@c.plugin :typecast_on_load, :initial
|
169
|
+
|
170
|
+
@o = @c.call(:initial=>'1')
|
171
|
+
@o.column_changes.must_equal({})
|
172
|
+
@o.save
|
173
|
+
@o.previous_changes.must_equal({})
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should have column_changes work with the typecast_on_load in after hooks" do
|
177
|
+
@c.instance_variable_set(:@db_schema, :initial=>{:type=>:integer})
|
178
|
+
@c.plugin :typecast_on_load, :initial
|
179
|
+
|
180
|
+
@o = @c.new
|
181
|
+
@o.initial = 1
|
182
|
+
@o.column_changes.must_equal({:initial=>[nil, 1]})
|
183
|
+
column_changes_in_after_save = nil
|
184
|
+
@o.define_singleton_method(:after_save) do
|
185
|
+
column_changes_in_after_save = column_changes
|
186
|
+
super()
|
187
|
+
end
|
188
|
+
@db.fetch = {:initial=>1}
|
189
|
+
@o.save
|
190
|
+
column_changes_in_after_save.must_equal({:initial=>[nil, 1]})
|
191
|
+
|
192
|
+
@o.initial = 2
|
193
|
+
@o.column_changes.must_equal({:initial=>[1, 2]})
|
194
|
+
@o.save
|
195
|
+
column_changes_in_after_save.must_equal({:initial=>[1, 2]})
|
196
|
+
@o.previous_changes.must_equal({:initial=>[1, 2]})
|
197
|
+
end
|
165
198
|
end
|
166
199
|
|
167
200
|
describe "with existing instance" do
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe "empty_failure_backtraces plugin" do
|
4
|
+
before do
|
5
|
+
@c = Class.new(Sequel::Model(:items)) do
|
6
|
+
plugin :empty_failure_backtraces
|
7
|
+
columns :x
|
8
|
+
set_primary_key :x
|
9
|
+
unrestrict_primary_key
|
10
|
+
def before_create
|
11
|
+
super
|
12
|
+
cancel_action 'bc' if x == 2
|
13
|
+
end
|
14
|
+
def before_destroy
|
15
|
+
super
|
16
|
+
cancel_action 'bd' if x == 2
|
17
|
+
end
|
18
|
+
def validate
|
19
|
+
super
|
20
|
+
errors.add(:x, "3") if x == 3
|
21
|
+
end
|
22
|
+
end
|
23
|
+
DB.reset
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should work normally if no exceptions are thrown/raised" do
|
27
|
+
o = @c.create(:x=>1)
|
28
|
+
o.must_be_kind_of @c
|
29
|
+
o.valid?.must_equal true
|
30
|
+
o.destroy.must_equal o
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should work normally when not rescuing exceptions internally when calling save" do
|
34
|
+
@c.new.set(:x => 2).save(:raise_on_failure=>false).must_be_nil
|
35
|
+
@c.raise_on_save_failure = false
|
36
|
+
@c.create(:x => 2).must_be_nil
|
37
|
+
@c.load(:x => 2).destroy(:raise_on_failure=>false).must_be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should work normally when not rescuing exceptions internally when calling valid?" do
|
41
|
+
@c.send(:define_method, :before_validation){cancel_action "bv"}
|
42
|
+
@c.new(:x => 2).valid?.must_equal false
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should raise exceptions with empty backtraces" do
|
46
|
+
begin
|
47
|
+
@c.create(:x => 2)
|
48
|
+
rescue Sequel::HookFailed => e
|
49
|
+
e.backtrace.must_be_empty
|
50
|
+
1
|
51
|
+
end.must_equal 1
|
52
|
+
|
53
|
+
begin
|
54
|
+
@c.create(:x => 3)
|
55
|
+
rescue Sequel::ValidationFailed => e
|
56
|
+
e.backtrace.must_be_empty
|
57
|
+
1
|
58
|
+
end.must_equal 1
|
59
|
+
end
|
60
|
+
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
|
@@ -187,6 +187,16 @@ describe "Sequel::Plugins::JsonSerializer" do
|
|
187
187
|
Album.array_from_json(Album.dataset.to_json(:only=>:name)).must_equal [Album.load(:name=>@album.name)]
|
188
188
|
end
|
189
189
|
|
190
|
+
it "should support setting json_serializer_opts for datasets" do
|
191
|
+
Album.dataset = Album.dataset.with_fetch(:id=>1, :name=>'RF', :artist_id=>2)
|
192
|
+
Album.array_from_json(Album.dataset.json_serializer_opts(:only=>:name).to_json).must_equal [Album.load(:name=>@album.name)]
|
193
|
+
Album.plugin :json_serializer, :only=>:id
|
194
|
+
Album.array_from_json(Album.dataset.json_serializer_opts(:only=>:name).to_json).must_equal [Album.load(:name=>@album.name)]
|
195
|
+
Album.array_from_json(Album.dataset.json_serializer_opts(:only=>:name).to_json(:only=>:artist_id)).must_equal [Album.load(:artist_id=>2)]
|
196
|
+
json = Album.dataset.json_serializer_opts(:only=>:name, :root=>true).to_json(:only=>:artist_id)
|
197
|
+
Album.array_from_json(JSON.parse(json)['albums'].to_json).must_equal [Album.load(:artist_id=>2)]
|
198
|
+
end
|
199
|
+
|
190
200
|
it "should have dataset to_json method work with eager_graph datasets" do
|
191
201
|
ds = Album.dataset.eager_graph(:artist).with_fetch(:id=>1, :name=>'RF', :artist_id=>2, :artist_id_0=>2, :artist_name=>'YM')
|
192
202
|
Sequel.parse_json(ds.to_json(:only=>:name, :include=>{:artist=>{:only=>:name}})).must_equal [{"name"=>"RF", "artist"=>{"name"=>"YM"}}]
|
@@ -158,12 +158,12 @@ describe "Sequel named_timezones extension with Time class" do
|
|
158
158
|
dt = Sequel.database_to_application_timestamp('2009-06-01 06:20:30-0400')
|
159
159
|
dt.must_be_instance_of Time
|
160
160
|
dt.must_equal Time.new(2009,6,1,3,20,30,-25200)
|
161
|
-
dt.utc_offset.must_equal
|
161
|
+
dt.utc_offset.must_equal(-25200)
|
162
162
|
|
163
163
|
dt = Sequel.database_to_application_timestamp('2009-06-01 10:20:30+0000')
|
164
164
|
dt.must_be_instance_of Time
|
165
165
|
dt.must_equal Time.new(2009,6,1,3,20,30,-25200)
|
166
|
-
dt.utc_offset.must_equal
|
166
|
+
dt.utc_offset.must_equal(-25200)
|
167
167
|
end
|
168
168
|
|
169
169
|
it "should raise an error for ambiguous timezones by default" do
|
@@ -175,19 +175,19 @@ describe "Sequel named_timezones extension with Time class" do
|
|
175
175
|
Sequel.database_to_application_timestamp('2004-10-31T01:30:00').must_equal Time.new(2004, 10, 30, 22, 30, 0, -25200)
|
176
176
|
dt = Sequel.database_to_application_timestamp('2004-10-31T01:30:00')
|
177
177
|
dt.must_equal Time.new(2004, 10, 30, 22, 30, 0, -25200)
|
178
|
-
dt.utc_offset.must_equal
|
178
|
+
dt.utc_offset.must_equal(-25200)
|
179
179
|
end
|
180
180
|
|
181
181
|
it "should assume datetimes coming out of the database that don't have an offset as coming from database_timezone" do
|
182
182
|
dt = Sequel.database_to_application_timestamp('2009-06-01 06:20:30')
|
183
183
|
dt.must_be_instance_of Time
|
184
184
|
dt.must_equal Time.new(2009,6,1,3,20,30, -25200)
|
185
|
-
dt.utc_offset.must_equal
|
185
|
+
dt.utc_offset.must_equal(-25200)
|
186
186
|
|
187
187
|
dt = Sequel.database_to_application_timestamp('2009-06-01 10:20:30')
|
188
188
|
dt.must_be_instance_of Time
|
189
189
|
dt.must_equal Time.new(2009,6,1,7,20,30, -25200)
|
190
|
-
dt.utc_offset.must_equal
|
190
|
+
dt.utc_offset.must_equal(-25200)
|
191
191
|
end
|
192
192
|
|
193
193
|
it "should work with the thread_local_timezones extension" do
|
@@ -492,6 +492,54 @@ describe "NestedAttributes plugin" do
|
|
492
492
|
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 10)"]
|
493
493
|
end
|
494
494
|
|
495
|
+
it "should raise a NoExistingObject error if object to be updated no longer exists, if the :require_modification=>true option is used" do
|
496
|
+
@Artist.nested_attributes :albums, :require_modification=>true, :destroy=>true
|
497
|
+
al = @Album.load(:id=>10, :name=>'Al')
|
498
|
+
ar = @Artist.load(:id=>20, :name=>'Ar')
|
499
|
+
ar.associations[:albums] = [al]
|
500
|
+
ar.set(:albums_attributes=>[{:id=>10, :name=>'L'}])
|
501
|
+
@db.sqls.must_equal []
|
502
|
+
@db.numrows = [1, 0]
|
503
|
+
proc{ar.save}.must_raise Sequel::NoExistingObject
|
504
|
+
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'L' WHERE (id = 10)"]
|
505
|
+
end
|
506
|
+
|
507
|
+
it "should not raise an Error if object to be updated no longer exists, if the :require_modification=>false option is used" do
|
508
|
+
@Artist.nested_attributes :albums, :require_modification=>false, :destroy=>true
|
509
|
+
al = @Album.load(:id=>10, :name=>'Al')
|
510
|
+
ar = @Artist.load(:id=>20, :name=>'Ar')
|
511
|
+
ar.associations[:albums] = [al]
|
512
|
+
ar.set(:albums_attributes=>[{:id=>10, :name=>'L'}])
|
513
|
+
@db.sqls.must_equal []
|
514
|
+
@db.numrows = [1, 0]
|
515
|
+
ar.save
|
516
|
+
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "UPDATE albums SET name = 'L' WHERE (id = 10)"]
|
517
|
+
end
|
518
|
+
|
519
|
+
it "should raise a NoExistingObject error if object to be deleted no longer exists, if the :require_modification=>true option is used" do
|
520
|
+
@Artist.nested_attributes :albums, :require_modification=>true, :destroy=>true
|
521
|
+
al = @Album.load(:id=>10, :name=>'Al')
|
522
|
+
ar = @Artist.load(:id=>20, :name=>'Ar')
|
523
|
+
ar.associations[:albums] = [al]
|
524
|
+
ar.set(:albums_attributes=>[{:id=>10, :_delete=>'t'}])
|
525
|
+
@db.sqls.must_equal []
|
526
|
+
@db.numrows = [1, 0]
|
527
|
+
proc{ar.save}.must_raise Sequel::NoExistingObject
|
528
|
+
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
529
|
+
end
|
530
|
+
|
531
|
+
it "should not raise an Error if object to be deleted no longer exists, if the :require_modification=>false option is used" do
|
532
|
+
@Artist.nested_attributes :albums, :require_modification=>false, :destroy=>true
|
533
|
+
al = @Album.load(:id=>10, :name=>'Al')
|
534
|
+
ar = @Artist.load(:id=>20, :name=>'Ar')
|
535
|
+
ar.associations[:albums] = [al]
|
536
|
+
ar.set(:albums_attributes=>[{:id=>10, :_delete=>'t'}])
|
537
|
+
@db.sqls.must_equal []
|
538
|
+
@db.numrows = [1, 0]
|
539
|
+
ar.save
|
540
|
+
@db.sqls.must_equal ["UPDATE artists SET name = 'Ar' WHERE (id = 20)", "DELETE FROM albums WHERE (id = 10)"]
|
541
|
+
end
|
542
|
+
|
495
543
|
it "should not attempt to validate nested attributes twice for one_to_many associations when creating them" do
|
496
544
|
@Artist.nested_attributes :albums
|
497
545
|
validated = []
|
@@ -83,9 +83,9 @@ describe "Sequel::Postgres::ArrayOp" do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it "#to_string/join should use the array_to_string function" do
|
86
|
-
@db.literal(@a.to_string).must_equal "array_to_string(a, ''
|
87
|
-
@db.literal(@a.join).must_equal "array_to_string(a, ''
|
88
|
-
@db.literal(@a.join(':')).must_equal "array_to_string(a, ':'
|
86
|
+
@db.literal(@a.to_string).must_equal "array_to_string(a, '')"
|
87
|
+
@db.literal(@a.join).must_equal "array_to_string(a, '')"
|
88
|
+
@db.literal(@a.join(':')).must_equal "array_to_string(a, ':')"
|
89
89
|
@db.literal(@a.join(':', '*')).must_equal "array_to_string(a, ':', '*')"
|
90
90
|
end
|
91
91
|
|
@@ -286,4 +286,71 @@ describe "Sequel::Postgres::JSONOp" do
|
|
286
286
|
it "should allow transforming JSONBHash instances into ArrayOp instances" do
|
287
287
|
@db.literal(Sequel.pg_jsonb('a'=>1).op['a']).must_equal "('{\"a\":1}'::jsonb -> 'a')"
|
288
288
|
end
|
289
|
+
|
290
|
+
it "#path_exists should use the @? operator" do
|
291
|
+
@l[@jb.path_exists('$')].must_equal "(j @? '$')"
|
292
|
+
end
|
293
|
+
|
294
|
+
it "#path_exists result should be a boolean expression" do
|
295
|
+
@jb.path_exists('$').must_be_kind_of Sequel::SQL::BooleanExpression
|
296
|
+
end
|
297
|
+
|
298
|
+
it "#path_match should use the @@ operator" do
|
299
|
+
@l[@jb.path_match('$')].must_equal "(j @@ '$')"
|
300
|
+
end
|
301
|
+
|
302
|
+
it "#path_match result should be a boolean expression" do
|
303
|
+
@jb.path_match('$').must_be_kind_of Sequel::SQL::BooleanExpression
|
304
|
+
end
|
305
|
+
|
306
|
+
it "#path_exists! should use the jsonb_path_exists function" do
|
307
|
+
@l[@jb.path_exists!('$')].must_equal "jsonb_path_exists(j, '$')"
|
308
|
+
@l[@jb.path_exists!('$', '{"x":2}')].must_equal "jsonb_path_exists(j, '$', '{\"x\":2}')"
|
309
|
+
@l[@jb.path_exists!('$', x: 2)].must_equal "jsonb_path_exists(j, '$', '{\"x\":2}')"
|
310
|
+
@l[@jb.path_exists!('$', {x: 2}, true)].must_equal "jsonb_path_exists(j, '$', '{\"x\":2}', true)"
|
311
|
+
end
|
312
|
+
|
313
|
+
it "#path_exists! result should be a boolean expression" do
|
314
|
+
@jb.path_exists!('$').must_be_kind_of Sequel::SQL::BooleanExpression
|
315
|
+
end
|
316
|
+
|
317
|
+
it "#path_match! should use the jsonb_path_match function" do
|
318
|
+
@l[@jb.path_match!('$')].must_equal "jsonb_path_match(j, '$')"
|
319
|
+
@l[@jb.path_match!('$', '{"x":2}')].must_equal "jsonb_path_match(j, '$', '{\"x\":2}')"
|
320
|
+
@l[@jb.path_match!('$', x: 2)].must_equal "jsonb_path_match(j, '$', '{\"x\":2}')"
|
321
|
+
@l[@jb.path_match!('$', {x: 2}, true)].must_equal "jsonb_path_match(j, '$', '{\"x\":2}', true)"
|
322
|
+
end
|
323
|
+
|
324
|
+
it "#path_match! result should be a boolean expression" do
|
325
|
+
@jb.path_match!('$').must_be_kind_of Sequel::SQL::BooleanExpression
|
326
|
+
end
|
327
|
+
|
328
|
+
it "#path_query should use the jsonb_path_query function" do
|
329
|
+
@l[@jb.path_query('$')].must_equal "jsonb_path_query(j, '$')"
|
330
|
+
@l[@jb.path_query('$', '{"x":2}')].must_equal "jsonb_path_query(j, '$', '{\"x\":2}')"
|
331
|
+
@l[@jb.path_query('$', x: 2)].must_equal "jsonb_path_query(j, '$', '{\"x\":2}')"
|
332
|
+
@l[@jb.path_query('$', {x: 2}, true)].must_equal "jsonb_path_query(j, '$', '{\"x\":2}', true)"
|
333
|
+
end
|
334
|
+
|
335
|
+
it "#path_query_array should use the jsonb_path_query_array function" do
|
336
|
+
@l[@jb.path_query_array('$')].must_equal "jsonb_path_query_array(j, '$')"
|
337
|
+
@l[@jb.path_query_array('$', '{"x":2}')].must_equal "jsonb_path_query_array(j, '$', '{\"x\":2}')"
|
338
|
+
@l[@jb.path_query_array('$', x: 2)].must_equal "jsonb_path_query_array(j, '$', '{\"x\":2}')"
|
339
|
+
@l[@jb.path_query_array('$', {x: 2}, true)].must_equal "jsonb_path_query_array(j, '$', '{\"x\":2}', true)"
|
340
|
+
end
|
341
|
+
|
342
|
+
it "#path_query_array result should be a JSONBOp" do
|
343
|
+
@l[@jb.path_query_array('$').path_query_array('$')].must_equal "jsonb_path_query_array(jsonb_path_query_array(j, '$'), '$')"
|
344
|
+
end
|
345
|
+
|
346
|
+
it "#path_query_first should use the jsonb_path_query_first function" do
|
347
|
+
@l[@jb.path_query_first('$')].must_equal "jsonb_path_query_first(j, '$')"
|
348
|
+
@l[@jb.path_query_first('$', '{"x":2}')].must_equal "jsonb_path_query_first(j, '$', '{\"x\":2}')"
|
349
|
+
@l[@jb.path_query_first('$', x: 2)].must_equal "jsonb_path_query_first(j, '$', '{\"x\":2}')"
|
350
|
+
@l[@jb.path_query_first('$', {x: 2}, true)].must_equal "jsonb_path_query_first(j, '$', '{\"x\":2}', true)"
|
351
|
+
end
|
352
|
+
|
353
|
+
it "#path_query_first result should be a JSONBOp" do
|
354
|
+
@l[@jb.path_query_first('$').path_query_first('$')].must_equal "jsonb_path_query_first(jsonb_path_query_first(j, '$'), '$')"
|
355
|
+
end
|
289
356
|
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
|
@@ -136,6 +136,20 @@ describe "pg_range extension" do
|
|
136
136
|
s[1][1][:ruby_default].must_equal Sequel::Postgres::PGRange.new(1, 5, :exclude_end=>true, :db_type=>'int4range')
|
137
137
|
end
|
138
138
|
|
139
|
+
it "should work correctly in hashes" do
|
140
|
+
h = Hash.new(1)
|
141
|
+
h[@R.new(1, 2)] = 2
|
142
|
+
h[@R.new(nil, nil, :empty => true)] = 3
|
143
|
+
h[@R.new(1, 2)].must_equal 2
|
144
|
+
h[@R.new(1, 3)].must_equal 1
|
145
|
+
h[@R.new(2, 2)].must_equal 1
|
146
|
+
h[@R.new(1, 2, :exclude_begin => true)].must_equal 1
|
147
|
+
h[@R.new(1, 2, :exclude_end => true)].must_equal 1
|
148
|
+
h[@R.new(1, 2, :db_type => :int)].must_equal 1
|
149
|
+
h[@R.new(nil, nil, :empty => true)].must_equal 3
|
150
|
+
h[@R.new(nil, nil, :empty => true, :db_type => :int)].must_equal 1
|
151
|
+
end
|
152
|
+
|
139
153
|
describe "database typecasting" do
|
140
154
|
before do
|
141
155
|
@o = @R.new(1, 2, :db_type=>'int4range')
|
@@ -456,21 +470,21 @@ describe "pg_range extension" do
|
|
456
470
|
end
|
457
471
|
|
458
472
|
it "should consider PGRanges equal with a endless Range they represent" do
|
459
|
-
@R.new(1, nil).must_be :==, eval('1..')
|
460
|
-
@R.new(1, nil, :exclude_end=>true).must_be :==, eval('1...')
|
461
|
-
@R.new(1, nil).wont_be :==, eval('1...')
|
462
|
-
@R.new(1, nil, :exclude_end=>true).wont_be :==, eval('1..')
|
463
|
-
@R.new(1, nil).wont_be :==, eval('2..')
|
464
|
-
@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...)')
|
465
479
|
end if endless_range_support
|
466
480
|
|
467
481
|
it "should consider PGRanges equal with a startless Range they represent" do
|
468
|
-
@R.new(nil, 1).must_be :==, eval('..1')
|
469
|
-
@R.new(nil, 1, :exclude_end=>true).must_be :==, eval('...1')
|
470
|
-
@R.new(nil, 1).wont_be :==, eval('...1')
|
471
|
-
@R.new(nil, 1, :exclude_end=>true).wont_be :==, eval('..1')
|
472
|
-
@R.new(nil, 1).wont_be :==, eval('..2')
|
473
|
-
@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)')
|
474
488
|
end if startless_range_support
|
475
489
|
|
476
490
|
it "should consider PGRanges equal with a startless, endless Range they represent" do
|
@@ -186,4 +186,12 @@ describe "sharding plugin" do
|
|
186
186
|
["UPDATE albums SET artist_id = 2, name = 'RF' WHERE (id = 1) -- s1", "UPDATE albums SET name = 'RF', artist_id = 2 WHERE (id = 1) -- s1"].must_include(sqls.slice!(2))
|
187
187
|
sqls.must_equal ["SELECT * FROM albums LIMIT 1 -- s2", "BEGIN -- s1", "COMMIT -- s1"]
|
188
188
|
end
|
189
|
+
|
190
|
+
it "should have objects retrieved from a specific shard using with_server from server_block extension" do
|
191
|
+
album = @db.extension(:server_block).with_server(:s1) do
|
192
|
+
@Album.first
|
193
|
+
end
|
194
|
+
album.update(:name=>'MO')
|
195
|
+
@db.sqls.must_equal ["SELECT * FROM albums LIMIT 1 -- s1", "UPDATE albums SET name = 'MO' WHERE (id = 1) -- s1"]
|
196
|
+
end
|
189
197
|
end
|
data/spec/guards_helper.rb
CHANGED