sequel 4.10.0 → 4.11.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/doc/association_basics.rdoc +1 -1
- data/doc/cheat_sheet.rdoc +0 -1
- data/doc/core_extensions.rdoc +2 -2
- data/doc/dataset_filtering.rdoc +5 -5
- data/doc/model_hooks.rdoc +9 -0
- data/doc/object_model.rdoc +7 -13
- data/doc/opening_databases.rdoc +3 -1
- data/doc/querying.rdoc +8 -8
- data/doc/release_notes/4.11.0.txt +147 -0
- data/doc/sql.rdoc +11 -7
- data/doc/virtual_rows.rdoc +4 -5
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/jdbc/h2.rb +5 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +5 -0
- data/lib/sequel/adapters/mock.rb +14 -2
- data/lib/sequel/adapters/shared/access.rb +6 -9
- data/lib/sequel/adapters/shared/cubrid.rb +5 -0
- data/lib/sequel/adapters/shared/db2.rb +5 -0
- data/lib/sequel/adapters/shared/firebird.rb +5 -0
- data/lib/sequel/adapters/shared/mssql.rb +23 -16
- data/lib/sequel/adapters/shared/mysql.rb +12 -2
- data/lib/sequel/adapters/shared/oracle.rb +31 -15
- data/lib/sequel/adapters/shared/postgres.rb +28 -4
- data/lib/sequel/adapters/shared/sqlanywhere.rb +5 -0
- data/lib/sequel/adapters/shared/sqlite.rb +12 -1
- data/lib/sequel/ast_transformer.rb +9 -7
- data/lib/sequel/connection_pool.rb +10 -4
- data/lib/sequel/database/features.rb +15 -0
- data/lib/sequel/database/schema_generator.rb +2 -2
- data/lib/sequel/database/schema_methods.rb +21 -3
- data/lib/sequel/database/transactions.rb +8 -4
- data/lib/sequel/dataset/actions.rb +13 -7
- data/lib/sequel/dataset/features.rb +7 -0
- data/lib/sequel/dataset/query.rb +28 -11
- data/lib/sequel/dataset/sql.rb +90 -14
- data/lib/sequel/extensions/constraint_validations.rb +2 -2
- data/lib/sequel/extensions/date_arithmetic.rb +1 -1
- data/lib/sequel/extensions/eval_inspect.rb +12 -6
- data/lib/sequel/extensions/pg_array_ops.rb +11 -2
- data/lib/sequel/extensions/pg_json.rb +130 -23
- data/lib/sequel/extensions/pg_json_ops.rb +196 -28
- data/lib/sequel/extensions/to_dot.rb +5 -7
- data/lib/sequel/model/associations.rb +0 -50
- data/lib/sequel/plugins/class_table_inheritance.rb +49 -21
- data/lib/sequel/plugins/many_through_many.rb +10 -11
- data/lib/sequel/plugins/serialization.rb +4 -1
- data/lib/sequel/plugins/sharding.rb +0 -9
- data/lib/sequel/plugins/single_table_inheritance.rb +4 -2
- data/lib/sequel/plugins/timestamps.rb +2 -2
- data/lib/sequel/sql.rb +166 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +199 -133
- data/spec/core/connection_pool_spec.rb +6 -0
- data/spec/core/database_spec.rb +12 -0
- data/spec/core/dataset_spec.rb +58 -3
- data/spec/core/expression_filters_spec.rb +67 -5
- data/spec/core/mock_adapter_spec.rb +8 -4
- data/spec/core/schema_spec.rb +7 -0
- data/spec/core_extensions_spec.rb +14 -0
- data/spec/extensions/class_table_inheritance_spec.rb +23 -3
- data/spec/extensions/core_refinements_spec.rb +14 -0
- data/spec/extensions/eval_inspect_spec.rb +8 -4
- data/spec/extensions/pg_array_ops_spec.rb +6 -0
- data/spec/extensions/pg_json_ops_spec.rb +99 -0
- data/spec/extensions/pg_json_spec.rb +104 -4
- data/spec/extensions/serialization_spec.rb +19 -0
- data/spec/extensions/single_table_inheritance_spec.rb +11 -3
- data/spec/extensions/timestamps_spec.rb +10 -0
- data/spec/extensions/to_dot_spec.rb +8 -4
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +9 -0
- data/spec/integration/schema_test.rb +27 -0
- metadata +4 -2
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sequel
|
|
3
3
|
MAJOR = 4
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
5
5
|
# release, generally around once a month.
|
6
|
-
MINOR =
|
6
|
+
MINOR = 11
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
9
|
TINY = 0
|
@@ -117,8 +117,8 @@ end
|
|
117
117
|
describe "PostgreSQL views" do
|
118
118
|
before do
|
119
119
|
@db = DB
|
120
|
-
@db.
|
121
|
-
@db.create_table
|
120
|
+
@db.drop_table?(:items, :cascade=>true)
|
121
|
+
@db.create_table(:items){Integer :number}
|
122
122
|
@db[:items].insert(10)
|
123
123
|
@db[:items].insert(20)
|
124
124
|
end
|
@@ -152,6 +152,15 @@ describe "PostgreSQL views" do
|
|
152
152
|
@db[:items_view].select_order_map(:number).should == [10, 15, 20]
|
153
153
|
end if DB.server_version >= 90300
|
154
154
|
|
155
|
+
specify "should support refreshing materialized views concurrently" do
|
156
|
+
@opts = {:materialized=>true}
|
157
|
+
@db.create_view(:items_view, @db[:items].where{number >= 10}, @opts)
|
158
|
+
@db.refresh_view(:items_view)
|
159
|
+
proc{@db.refresh_view(:items_view, :concurrently=>true)}.should raise_error(Sequel::DatabaseError)
|
160
|
+
@db.add_index :items_view, :number, :unique=>true
|
161
|
+
proc{@db.refresh_view(:items_view, :concurrently=>true)}.should_not raise_error
|
162
|
+
end if DB.server_version >= 90400
|
163
|
+
|
155
164
|
specify "should support :if_exists=>true for not raising an error if the view does not exist" do
|
156
165
|
proc{@db.drop_view(:items_view, :if_exists=>true)}.should_not raise_error
|
157
166
|
end
|
@@ -170,6 +179,14 @@ describe "A PostgreSQL database" do
|
|
170
179
|
@db.server_version.should > 70000
|
171
180
|
end
|
172
181
|
|
182
|
+
specify "should respect the :read_only option per-savepoint" do
|
183
|
+
proc{@db.transaction{@db.transaction(:savepoint=>true, :read_only=>true){@db[:public__testfk].insert}}}.should raise_error(Sequel::DatabaseError)
|
184
|
+
proc{@db.transaction(:auto_savepoint=>true, :read_only=>true){@db.transaction(:read_only=>false){@db[:public__testfk].insert}}}.should raise_error(Sequel::DatabaseError)
|
185
|
+
proc{@db.transaction{@db[:public__testfk].insert; @db.transaction(:savepoint=>true, :read_only=>true){@db[:public__testfk].all;}}}.should_not raise_error
|
186
|
+
proc{@db.transaction{@db.transaction(:savepoint=>true, :read_only=>true){}; @db[:public__testfk].insert}}.should_not raise_error
|
187
|
+
proc{@db.transaction{@db[:public__testfk].all; @db.transaction(:savepoint=>true, :read_only=>true){@db[:public__testfk].all;}}}.should_not raise_error
|
188
|
+
end
|
189
|
+
|
173
190
|
specify "should support disable_insert_returning" do
|
174
191
|
ds = @db[:public__testfk].disable_insert_returning
|
175
192
|
ds.delete
|
@@ -326,6 +343,22 @@ describe "A PostgreSQL dataset" do
|
|
326
343
|
@d.order(Sequel.asc(:value, :nulls=>:first), :name).reverse.select_map(:name).should == %w[bcd bcd abc]
|
327
344
|
end
|
328
345
|
|
346
|
+
specify "should support selecting from LATERAL functions" do
|
347
|
+
@d.from{[generate_series(1,3,1).as(:a), pow(:a, 2).lateral.as(:b)]}.select_map([:a, :b])== [[1, 1], [2, 4], [3, 9]]
|
348
|
+
end if DB.server_version >= 90300
|
349
|
+
|
350
|
+
specify "should support ordered-set and hypothetical-set aggregate functions" do
|
351
|
+
@d.from{generate_series(1,3,1).as(:a)}.select{(a.sql_number % 2).as(:a)}.from_self.get{mode{}.within_group(:a)}.should == 1
|
352
|
+
end if DB.server_version >= 90400
|
353
|
+
|
354
|
+
specify "should support filtered aggregate functions" do
|
355
|
+
@d.from{generate_series(1,3,1).as(:a)}.select{(a.sql_number % 2).as(:a)}.from_self.get{count(:a).filter(:a=>1)}.should == 2
|
356
|
+
end if DB.server_version >= 90400
|
357
|
+
|
358
|
+
specify "should support functions with ordinality" do
|
359
|
+
@d.from{generate_series(1,10,3).with_ordinality}.select_map([:generate_series, :ordinality]).should == [[1, 1], [4, 2], [7, 3], [10, 4]]
|
360
|
+
end if DB.server_version >= 90400
|
361
|
+
|
329
362
|
specify "#lock should lock tables and yield if a block is given" do
|
330
363
|
@d.lock('EXCLUSIVE'){@d.insert(:name=>'a')}
|
331
364
|
end
|
@@ -848,28 +881,14 @@ describe "A PostgreSQL database" do
|
|
848
881
|
|
849
882
|
specify "should support fulltext indexes and searching" do
|
850
883
|
@db.create_table(:posts){text :title; text :body; full_text_index [:title, :body]; full_text_index :title, :language => 'french', :index_type=>:gist}
|
851
|
-
check_sqls do
|
852
|
-
@db.sqls.should == [
|
853
|
-
%{CREATE TABLE "posts" ("title" text, "body" text)},
|
854
|
-
%{CREATE INDEX "posts_title_body_index" ON "posts" USING gin (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))))},
|
855
|
-
%{CREATE INDEX "posts_title_index" ON "posts" USING gist (to_tsvector('french'::regconfig, (COALESCE("title", ''))))}
|
856
|
-
]
|
857
|
-
end
|
858
884
|
|
859
885
|
@db[:posts].insert(:title=>'ruby rails', :body=>'yowsa')
|
860
886
|
@db[:posts].insert(:title=>'sequel', :body=>'ruby')
|
861
887
|
@db[:posts].insert(:title=>'ruby scooby', :body=>'x')
|
862
|
-
@db.sqls.clear
|
863
888
|
|
864
889
|
@db[:posts].full_text_search(:title, 'rails').all.should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
865
890
|
@db[:posts].full_text_search([:title, :body], ['yowsa', 'rails']).all.should == [:title=>'ruby rails', :body=>'yowsa']
|
866
891
|
@db[:posts].full_text_search(:title, 'scooby', :language => 'french').all.should == [{:title=>'ruby scooby', :body=>'x'}]
|
867
|
-
check_sqls do
|
868
|
-
@db.sqls.should == [
|
869
|
-
%{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('simple'::regconfig, 'rails'))},
|
870
|
-
%{SELECT * FROM "posts" WHERE (to_tsvector('simple'::regconfig, (COALESCE("title", '') || ' ' || COALESCE("body", ''))) @@ to_tsquery('simple'::regconfig, 'yowsa | rails'))},
|
871
|
-
%{SELECT * FROM "posts" WHERE (to_tsvector('french'::regconfig, (COALESCE("title", ''))) @@ to_tsquery('french'::regconfig, 'scooby'))}]
|
872
|
-
end
|
873
892
|
|
874
893
|
@db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
875
894
|
@db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').should == [{:title=>'ruby rails', :body=>'yowsa'}]
|
@@ -880,6 +899,13 @@ describe "A PostgreSQL database" do
|
|
880
899
|
@db[:posts].full_text_search(:title, 'jruby maglev', :phrase=>true).select_order_map(:title).should == ['ruby jruby maglev mri rubinius iron']
|
881
900
|
@db[:posts].full_text_search(:title, 'rubinius ruby', :plain=>true).select_order_map(:title).should == ['jruby rubinius ruby maglev mri iron', 'ruby jruby maglev mri rubinius iron']
|
882
901
|
@db[:posts].full_text_search(:title, 'jruby maglev', :plain=>true).select_order_map(:title).should == ['jruby rubinius ruby maglev mri iron', 'ruby jruby maglev mri rubinius iron']
|
902
|
+
|
903
|
+
@db[:posts].delete
|
904
|
+
t1 = "bork " * 1000 + "ruby sequel"
|
905
|
+
t2 = "ruby sequel " * 1000
|
906
|
+
@db[:posts].insert(:title=>t1)
|
907
|
+
@db[:posts].insert(:title=>t2)
|
908
|
+
@db[:posts].full_text_search(:title, 'ruby & sequel', :rank=>true).select_map(:title).should == [t1, t2]
|
883
909
|
end
|
884
910
|
|
885
911
|
specify "should support spatial indexes" do
|
@@ -2237,6 +2263,13 @@ describe 'PostgreSQL array handling' do
|
|
2237
2263
|
@ds.get(Sequel.pg_array(:i5).replace(1, 4).contains([1])).should == false
|
2238
2264
|
@ds.get(Sequel.pg_array(:i5).replace(1, 4).contains([4])).should == true
|
2239
2265
|
end
|
2266
|
+
if @db.server_version >= 90400
|
2267
|
+
@ds.get(Sequel.pg_array(:i).cardinality).should == 3
|
2268
|
+
@ds.get(Sequel.pg_array(:i4).cardinality).should == 4
|
2269
|
+
@ds.get(Sequel.pg_array(:i5).cardinality).should == 3
|
2270
|
+
|
2271
|
+
@ds.from{Sequel.pg_array([1,2,3]).op.unnest([4,5,6], [7,8]).as(:t1, [:a, :b, :c])}.select_order_map([:a, :b, :c]).should == [[1, 4, 7], [2, 5, 8], [3, 6, nil]]
|
2272
|
+
end
|
2240
2273
|
|
2241
2274
|
if @native
|
2242
2275
|
@ds.get(Sequel.pg_array(:i).push(4)).should == [1, 2, 3, 4]
|
@@ -2515,133 +2548,166 @@ describe 'PostgreSQL json type' do
|
|
2515
2548
|
@db.drop_table?(:items)
|
2516
2549
|
end
|
2517
2550
|
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2528
|
-
|
2551
|
+
json_types = [:json]
|
2552
|
+
json_types << :jsonb if DB.server_version >= 90400
|
2553
|
+
json_types.each do |json_type|
|
2554
|
+
json_array_type = "#{json_type}[]"
|
2555
|
+
pg_json = lambda{|v| Sequel.send(:"pg_#{json_type}", v)}
|
2556
|
+
|
2557
|
+
specify 'insert and retrieve json values' do
|
2558
|
+
@db.create_table!(:items){column :j, json_type}
|
2559
|
+
@ds.insert(pg_json.call(@h))
|
2560
|
+
@ds.count.should == 1
|
2561
|
+
if @native
|
2562
|
+
rs = @ds.all
|
2563
|
+
v = rs.first[:j]
|
2564
|
+
v.should_not be_a_kind_of(Hash)
|
2565
|
+
v.to_hash.should be_a_kind_of(Hash)
|
2566
|
+
v.should == @h
|
2567
|
+
v.to_hash.should == @h
|
2568
|
+
@ds.delete
|
2569
|
+
@ds.insert(rs.first)
|
2570
|
+
@ds.all.should == rs
|
2571
|
+
end
|
2572
|
+
|
2529
2573
|
@ds.delete
|
2530
|
-
@ds.insert(
|
2531
|
-
@ds.
|
2574
|
+
@ds.insert(pg_json.call(@a))
|
2575
|
+
@ds.count.should == 1
|
2576
|
+
if @native
|
2577
|
+
rs = @ds.all
|
2578
|
+
v = rs.first[:j]
|
2579
|
+
v.should_not be_a_kind_of(Array)
|
2580
|
+
v.to_a.should be_a_kind_of(Array)
|
2581
|
+
v.should == @a
|
2582
|
+
v.to_a.should == @a
|
2583
|
+
@ds.delete
|
2584
|
+
@ds.insert(rs.first)
|
2585
|
+
@ds.all.should == rs
|
2586
|
+
end
|
2532
2587
|
end
|
2533
2588
|
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2589
|
+
specify 'insert and retrieve json[] values' do
|
2590
|
+
@db.create_table!(:items){column :j, json_array_type}
|
2591
|
+
j = Sequel.pg_array([pg_json.call('a'=>1), pg_json.call(['b', 2])])
|
2592
|
+
@ds.insert(j)
|
2593
|
+
@ds.count.should == 1
|
2594
|
+
if @native
|
2595
|
+
rs = @ds.all
|
2596
|
+
v = rs.first[:j]
|
2597
|
+
v.should_not be_a_kind_of(Array)
|
2598
|
+
v.to_a.should be_a_kind_of(Array)
|
2599
|
+
v.should == j
|
2600
|
+
v.to_a.should == j
|
2601
|
+
@ds.delete
|
2602
|
+
@ds.insert(rs.first)
|
2603
|
+
@ds.all.should == rs
|
2604
|
+
end
|
2547
2605
|
end
|
2548
|
-
end
|
2549
2606
|
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
v.to_a.should be_a_kind_of(Array)
|
2560
|
-
v.should == j
|
2561
|
-
v.to_a.should == j
|
2562
|
-
@ds.delete
|
2563
|
-
@ds.insert(rs.first)
|
2564
|
-
@ds.all.should == rs
|
2607
|
+
specify 'with models' do
|
2608
|
+
@db.create_table!(:items) do
|
2609
|
+
primary_key :id
|
2610
|
+
column :h, json_type
|
2611
|
+
end
|
2612
|
+
c = Class.new(Sequel::Model(@db[:items]))
|
2613
|
+
c.plugin :pg_typecast_on_load, :h unless @native
|
2614
|
+
c.create(:h=>pg_json.call(@h)).h.should == @h
|
2615
|
+
c.create(:h=>pg_json.call(@a)).h.should == @a
|
2565
2616
|
end
|
2566
|
-
end
|
2567
2617
|
|
2568
|
-
|
2569
|
-
|
2570
|
-
|
2571
|
-
|
2572
|
-
@ds.filter(Sequel.cast(:i, String)=>:$i).call(:first, :i=>Sequel.pg_json(@h)).should == {:i=>@h}
|
2573
|
-
@ds.filter(Sequel.cast(:i, String)=>:$i).call(:first, :i=>Sequel.pg_json({})).should == nil
|
2574
|
-
@ds.filter(Sequel.cast(:i, String)=>:$i).call(:delete, :i=>Sequel.pg_json(@h)).should == 1
|
2618
|
+
specify 'use json in bound variables' do
|
2619
|
+
@db.create_table!(:items){column :i, json_type}
|
2620
|
+
@ds.call(:insert, {:i=>pg_json.call(@h)}, {:i=>:$i})
|
2621
|
+
@ds.get(:i).should == @h
|
2575
2622
|
|
2576
|
-
|
2577
|
-
|
2578
|
-
|
2579
|
-
@ds.filter(Sequel.cast(:i, String)=>:$i).call(:first, :i=>Sequel.pg_json([])).should == nil
|
2623
|
+
@ds.delete
|
2624
|
+
@ds.call(:insert, {:i=>pg_json.call('a'=>nil)}, {:i=>:$i})
|
2625
|
+
@ds.get(:i).should == pg_json.call('a'=>nil)
|
2580
2626
|
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
2584
|
-
|
2585
|
-
|
2586
|
-
j = Sequel.pg_array([Sequel.pg_json('a'=>1), Sequel.pg_json(['b', 2])], :text)
|
2587
|
-
@ds.call(:insert, {:i=>j}, {:i=>:$i})
|
2588
|
-
@ds.get(:i).should == j
|
2589
|
-
@ds.filter(Sequel.cast(:i, 'text[]')=>:$i).call(:first, :i=>j).should == {:i=>j}
|
2590
|
-
@ds.filter(Sequel.cast(:i, 'text[]')=>:$i).call(:first, :i=>Sequel.pg_array([])).should == nil
|
2591
|
-
end if DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG
|
2627
|
+
@db.create_table!(:items){column :i, json_array_type}
|
2628
|
+
j = Sequel.pg_array([pg_json.call('a'=>1), pg_json.call(['b', 2])], json_type)
|
2629
|
+
@ds.call(:insert, {:i=>j}, {:i=>:$i})
|
2630
|
+
@ds.get(:i).should == j
|
2631
|
+
end if DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG
|
2592
2632
|
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2604
|
-
|
2605
|
-
|
2606
|
-
|
2607
|
-
|
2608
|
-
|
2609
|
-
|
2610
|
-
|
2611
|
-
|
2612
|
-
|
2613
|
-
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2619
|
-
|
2620
|
-
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
2624
|
-
|
2625
|
-
|
2626
|
-
|
2627
|
-
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2636
|
-
|
2637
|
-
|
2638
|
-
|
2639
|
-
|
2640
|
-
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2633
|
+
specify 'operations/functions with pg_json_ops' do
|
2634
|
+
Sequel.extension :pg_json_ops
|
2635
|
+
jo = pg_json.call('a'=>1, 'b'=>{'c'=>2, 'd'=>{'e'=>3}}).op
|
2636
|
+
ja = pg_json.call([2, 3, %w'a b']).op
|
2637
|
+
|
2638
|
+
@db.get(jo['a']).should == 1
|
2639
|
+
@db.get(jo['b']['c']).should == 2
|
2640
|
+
@db.get(jo[%w'b c']).should == 2
|
2641
|
+
@db.get(jo['b'].get_text(%w'd e')).should == "3"
|
2642
|
+
@db.get(jo[%w'b d'].get_text('e')).should == "3"
|
2643
|
+
@db.get(ja[1]).should == 3
|
2644
|
+
@db.get(ja[%w'2 1']).should == 'b'
|
2645
|
+
|
2646
|
+
@db.get(jo.extract('a')).should == 1
|
2647
|
+
@db.get(jo.extract('b').extract('c')).should == 2
|
2648
|
+
@db.get(jo.extract('b', 'c')).should == 2
|
2649
|
+
@db.get(jo.extract('b', 'd', 'e')).should == 3
|
2650
|
+
@db.get(jo.extract_text('b', 'd')).gsub(' ', '').should == '{"e":3}'
|
2651
|
+
@db.get(jo.extract_text('b', 'd', 'e')).should == '3'
|
2652
|
+
|
2653
|
+
@db.get(ja.array_length).should == 3
|
2654
|
+
@db.from(ja.array_elements.as(:v)).select_map(:v).should == [2, 3, %w'a b']
|
2655
|
+
|
2656
|
+
if DB.server_version >= 90400
|
2657
|
+
@db.get(jo.typeof).should == 'object'
|
2658
|
+
@db.get(ja.typeof).should == 'array'
|
2659
|
+
@db.from(ja.array_elements_text.as(:v)).select_map(:v).map{|s| s.gsub(' ', '')}.should == ['2', '3', '["a","b"]']
|
2660
|
+
@db.from(jo.to_record(true).as(:v, [Sequel.lit('a integer'), Sequel.lit('b text')])).select_map(:a).should == [1]
|
2661
|
+
@db.from(pg_json.call([{'a'=>1, 'b'=>1}]).op.to_recordset.as(:v, [Sequel.lit('a integer'), Sequel.lit('b integer')])).select_map(:a).should == [1]
|
2662
|
+
|
2663
|
+
if json_type == :jsonb
|
2664
|
+
@db.get(jo.has_key?('a')).should == true
|
2665
|
+
@db.get(jo.has_key?('c')).should == false
|
2666
|
+
@db.get(pg_json.call(['2', '3', %w'a b']).op.include?('2')).should == true
|
2667
|
+
@db.get(pg_json.call(['2', '3', %w'a b']).op.include?('4')).should == false
|
2668
|
+
|
2669
|
+
@db.get(jo.contain_all(['a', 'b'])).should == true
|
2670
|
+
@db.get(jo.contain_all(['a', 'c'])).should == false
|
2671
|
+
@db.get(jo.contain_all(['d', 'c'])).should == false
|
2672
|
+
@db.get(jo.contain_any(['a', 'b'])).should == true
|
2673
|
+
@db.get(jo.contain_any(['a', 'c'])).should == true
|
2674
|
+
@db.get(jo.contain_any(['d', 'c'])).should == false
|
2675
|
+
|
2676
|
+
@db.get(jo.contains(jo)).should == true
|
2677
|
+
@db.get(jo.contained_by(jo)).should == true
|
2678
|
+
@db.get(jo.contains('a'=>1)).should == true
|
2679
|
+
@db.get(jo.contained_by('a'=>1)).should == false
|
2680
|
+
@db.get(pg_json.call('a'=>1).op.contains(jo)).should == false
|
2681
|
+
@db.get(pg_json.call('a'=>1).op.contained_by(jo)).should == true
|
2682
|
+
|
2683
|
+
@db.get(ja.contains(ja)).should == true
|
2684
|
+
@db.get(ja.contained_by(ja)).should == true
|
2685
|
+
@db.get(ja.contains([2,3])).should == true
|
2686
|
+
@db.get(ja.contained_by([2,3])).should == false
|
2687
|
+
@db.get(pg_json.call([2,3]).op.contains(ja)).should == false
|
2688
|
+
@db.get(pg_json.call([2,3]).op.contained_by(ja)).should == true
|
2689
|
+
end
|
2690
|
+
end
|
2691
|
+
|
2692
|
+
@db.from(jo.keys.as(:k)).select_order_map(:k).should == %w'a b'
|
2693
|
+
@db.from(jo.each).select_order_map(:key).should == %w'a b'
|
2694
|
+
@db.from(jo.each).order(:key).select_map(:value).should == [1, {'c'=>2, 'd'=>{'e'=>3}}]
|
2695
|
+
@db.from(jo.each_text).select_order_map(:key).should == %w'a b'
|
2696
|
+
@db.from(jo.each_text).order(:key).where(:key=>'b').get(:value).gsub(' ', '').should =~ /\{"d":\{"e":3\},"c":2\}|\{"c":2,"d":\{"e":3\}\}/
|
2697
|
+
|
2698
|
+
Sequel.extension :pg_row_ops
|
2699
|
+
@db.create_table!(:items) do
|
2700
|
+
Integer :a
|
2701
|
+
String :b
|
2702
|
+
end
|
2703
|
+
j = Sequel.pg_json('a'=>1, 'b'=>'c').op
|
2704
|
+
@db.get(j.populate(Sequel.cast(nil, :items)).pg_row[:a]).should == 1
|
2705
|
+
@db.get(j.populate(Sequel.cast(nil, :items)).pg_row[:b]).should == 'c'
|
2706
|
+
j = Sequel.pg_json([{'a'=>1, 'b'=>'c'}, {'a'=>2, 'b'=>'d'}]).op
|
2707
|
+
@db.from(j.populate_set(Sequel.cast(nil, :items))).select_order_map(:a).should == [1, 2]
|
2708
|
+
@db.from(j.populate_set(Sequel.cast(nil, :items))).select_order_map(:b).should == %w'c d'
|
2709
|
+
end if DB.server_version >= 90300 && (DB.adapter_scheme == :postgres || DB.adapter_scheme == :jdbc)
|
2710
|
+
end
|
2645
2711
|
end if DB.server_version >= 90200
|
2646
2712
|
|
2647
2713
|
describe 'PostgreSQL inet/cidr types' do
|
@@ -911,6 +911,12 @@ shared_examples_for "All connection pools classes" do
|
|
911
911
|
x = nil
|
912
912
|
@class.new(mock_db.call{123}, :after_connect=>proc{|c| x = [c, c]}).hold{}
|
913
913
|
x.should == [123, 123]
|
914
|
+
@class.new(mock_db.call{123}, :after_connect=>lambda{|c| x = [c, c]}).hold{}
|
915
|
+
x.should == [123, 123]
|
916
|
+
@class.new(mock_db.call{123}, :after_connect=>proc{|c, s| x = [c, s]}).hold{}
|
917
|
+
x.should == [123, :default]
|
918
|
+
@class.new(mock_db.call{123}, :after_connect=>lambda{|c, s| x = [c, s]}).hold{}
|
919
|
+
x.should == [123, :default]
|
914
920
|
end
|
915
921
|
|
916
922
|
specify "should raise a DatabaseConnectionError if the connection raises an exception" do
|
data/spec/core/database_spec.rb
CHANGED
@@ -2184,6 +2184,18 @@ describe "Database#supports_savepoints?" do
|
|
2184
2184
|
end
|
2185
2185
|
end
|
2186
2186
|
|
2187
|
+
describe "Database#supports_views_with_check_option?" do
|
2188
|
+
specify "should be false by default" do
|
2189
|
+
Sequel::Database.new.supports_views_with_check_option?.should == false
|
2190
|
+
end
|
2191
|
+
end
|
2192
|
+
|
2193
|
+
describe "Database#supports_views_with_local_check_option?" do
|
2194
|
+
specify "should be false by default" do
|
2195
|
+
Sequel::Database.new.supports_views_with_local_check_option?.should == false
|
2196
|
+
end
|
2197
|
+
end
|
2198
|
+
|
2187
2199
|
describe "Database#supports_savepoints_in_prepared_transactions?" do
|
2188
2200
|
specify "should be false by default" do
|
2189
2201
|
Sequel::Database.new.supports_savepoints_in_prepared_transactions?.should == false
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -870,6 +870,7 @@ describe "Dataset#as" do
|
|
870
870
|
specify "should set up an alias" do
|
871
871
|
dataset = Sequel.mock.dataset.from(:test)
|
872
872
|
dataset.select(dataset.limit(1).select(:name).as(:n)).sql.should == 'SELECT (SELECT name FROM test LIMIT 1) AS n FROM test'
|
873
|
+
dataset.select(dataset.limit(1).select(:name).as(:n, [:nm])).sql.should == 'SELECT (SELECT name FROM test LIMIT 1) AS n(nm) FROM test'
|
873
874
|
end
|
874
875
|
end
|
875
876
|
|
@@ -2046,6 +2047,10 @@ describe "Dataset#from_self" do
|
|
2046
2047
|
@ds.from_self(:alias=>:some_name).sql.should == 'SELECT * FROM (SELECT name FROM test LIMIT 1) AS some_name'
|
2047
2048
|
end
|
2048
2049
|
|
2050
|
+
specify "should use the user-specified column aliases" do
|
2051
|
+
@ds.from_self(:alias=>:some_name, :column_aliases=>[:c1, :c2]).sql.should == 'SELECT * FROM (SELECT name FROM test LIMIT 1) AS some_name(c1, c2)'
|
2052
|
+
end
|
2053
|
+
|
2049
2054
|
specify "should use the user-specified alias for joins" do
|
2050
2055
|
@ds.from_self(:alias=>:some_name).inner_join(:posts, :alias=>:name).sql.should == \
|
2051
2056
|
'SELECT * FROM (SELECT name FROM test LIMIT 1) AS some_name INNER JOIN posts ON (posts.alias = some_name.name)'
|
@@ -2154,6 +2159,10 @@ describe "Dataset#join_table" do
|
|
2154
2159
|
@d.from('stats').join(Sequel.expr(:players).as(:p), {:id => :player_id}).sql.should == 'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
|
2155
2160
|
end
|
2156
2161
|
|
2162
|
+
specify "should support aliased tables with an implicit column aliases" do
|
2163
|
+
@d.from('stats').join(Sequel.expr(:players).as(:p, [:c1, :c2]), {:id => :player_id}).sql.should == 'SELECT * FROM "stats" INNER JOIN "players" AS "p"("c1", "c2") ON ("p"."id" = "stats"."player_id")'
|
2164
|
+
end
|
2165
|
+
|
2157
2166
|
specify "should support using an alias for the FROM when doing the first join with unqualified condition columns" do
|
2158
2167
|
@d.from(Sequel.as(:foo, :f)).join_table(:inner, :bar, :id => :bar_id).sql.should == 'SELECT * FROM "foo" AS "f" INNER JOIN "bar" ON ("bar"."id" = "f"."bar_id")'
|
2159
2168
|
end
|
@@ -2894,11 +2903,32 @@ describe "Dataset#import" do
|
|
2894
2903
|
'COMMIT']
|
2895
2904
|
end
|
2896
2905
|
|
2906
|
+
specify "should slice based on the default_import_slice option" do
|
2907
|
+
def @ds.default_import_slice; 2 end
|
2908
|
+
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]])
|
2909
|
+
@db.sqls.should == ['BEGIN',
|
2910
|
+
"INSERT INTO items (x, y) VALUES (1, 2)",
|
2911
|
+
"INSERT INTO items (x, y) VALUES (3, 4)",
|
2912
|
+
'COMMIT',
|
2913
|
+
'BEGIN',
|
2914
|
+
"INSERT INTO items (x, y) VALUES (5, 6)",
|
2915
|
+
'COMMIT']
|
2916
|
+
|
2917
|
+
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice=>nil)
|
2918
|
+
@db.sqls.should == ['BEGIN',
|
2919
|
+
"INSERT INTO items (x, y) VALUES (1, 2)",
|
2920
|
+
"INSERT INTO items (x, y) VALUES (3, 4)",
|
2921
|
+
"INSERT INTO items (x, y) VALUES (5, 6)",
|
2922
|
+
'COMMIT']
|
2923
|
+
end
|
2924
|
+
|
2897
2925
|
specify "should accept a columns array and a values array with :commit_every option" do
|
2898
|
-
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :commit_every =>
|
2926
|
+
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :commit_every => 2)
|
2899
2927
|
@db.sqls.should == ['BEGIN',
|
2900
2928
|
"INSERT INTO items (x, y) VALUES (1, 2)",
|
2901
2929
|
"INSERT INTO items (x, y) VALUES (3, 4)",
|
2930
|
+
'COMMIT',
|
2931
|
+
'BEGIN',
|
2902
2932
|
"INSERT INTO items (x, y) VALUES (5, 6)",
|
2903
2933
|
'COMMIT']
|
2904
2934
|
end
|
@@ -2920,6 +2950,14 @@ describe "Dataset#import" do
|
|
2920
2950
|
@db.sqls.should == ['BEGIN',
|
2921
2951
|
"INSERT INTO items (x, y) VALUES (1, 2), (3, 4), (5, 6)",
|
2922
2952
|
'COMMIT']
|
2953
|
+
|
2954
|
+
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice=>2)
|
2955
|
+
@db.sqls.should == ['BEGIN',
|
2956
|
+
"INSERT INTO items (x, y) VALUES (1, 2), (3, 4)",
|
2957
|
+
'COMMIT',
|
2958
|
+
'BEGIN',
|
2959
|
+
"INSERT INTO items (x, y) VALUES (5, 6)",
|
2960
|
+
'COMMIT']
|
2923
2961
|
end
|
2924
2962
|
|
2925
2963
|
specify "should use correct sql for :union strategy" do
|
@@ -2928,6 +2966,14 @@ describe "Dataset#import" do
|
|
2928
2966
|
@db.sqls.should == ['BEGIN',
|
2929
2967
|
"INSERT INTO items (x, y) SELECT 1, 2 UNION ALL SELECT 3, 4 UNION ALL SELECT 5, 6",
|
2930
2968
|
'COMMIT']
|
2969
|
+
|
2970
|
+
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice=>2)
|
2971
|
+
@db.sqls.should == ['BEGIN',
|
2972
|
+
"INSERT INTO items (x, y) SELECT 1, 2 UNION ALL SELECT 3, 4",
|
2973
|
+
'COMMIT',
|
2974
|
+
'BEGIN',
|
2975
|
+
"INSERT INTO items (x, y) SELECT 5, 6",
|
2976
|
+
'COMMIT']
|
2931
2977
|
end
|
2932
2978
|
|
2933
2979
|
specify "should use correct sql for :union strategy when FROM is required" do
|
@@ -2937,6 +2983,14 @@ describe "Dataset#import" do
|
|
2937
2983
|
@db.sqls.should == ['BEGIN',
|
2938
2984
|
"INSERT INTO items (x, y) SELECT 1, 2 FROM foo UNION ALL SELECT 3, 4 FROM foo UNION ALL SELECT 5, 6 FROM foo",
|
2939
2985
|
'COMMIT']
|
2986
|
+
|
2987
|
+
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice=>2)
|
2988
|
+
@db.sqls.should == ['BEGIN',
|
2989
|
+
"INSERT INTO items (x, y) SELECT 1, 2 FROM foo UNION ALL SELECT 3, 4 FROM foo",
|
2990
|
+
'COMMIT',
|
2991
|
+
'BEGIN',
|
2992
|
+
"INSERT INTO items (x, y) SELECT 5, 6 FROM foo",
|
2993
|
+
'COMMIT']
|
2940
2994
|
end
|
2941
2995
|
end
|
2942
2996
|
|
@@ -3622,6 +3676,7 @@ describe "Sequel::Dataset#qualify" do
|
|
3622
3676
|
|
3623
3677
|
specify "should handle SQL::AliasedExpressions" do
|
3624
3678
|
@ds.select(Sequel.expr(:a).as(:b)).qualify.sql.should == 'SELECT t.a AS b FROM t'
|
3679
|
+
@ds.select(Sequel.expr(:a).as(:b, [:c, :d])).qualify.sql.should == 'SELECT t.a AS b(c, d) FROM t'
|
3625
3680
|
end
|
3626
3681
|
|
3627
3682
|
specify "should handle SQL::CaseExpressions" do
|
@@ -3660,7 +3715,7 @@ describe "Sequel::Dataset#qualify" do
|
|
3660
3715
|
@ds.filter(Sequel::SQL::Wrapper.new(:a)).qualify.sql.should == 'SELECT t.* FROM t WHERE t.a'
|
3661
3716
|
end
|
3662
3717
|
|
3663
|
-
specify "should handle SQL::
|
3718
|
+
specify "should handle SQL::Functions with windows" do
|
3664
3719
|
meta_def(@ds, :supports_window_functions?){true}
|
3665
3720
|
@ds.select{sum(:a).over(:partition=>:b, :order=>:c)}.qualify.sql.should == 'SELECT sum(t.a) OVER (PARTITION BY t.b ORDER BY t.c) FROM t'
|
3666
3721
|
end
|
@@ -4345,7 +4400,7 @@ describe "Custom ASTTransformer" do
|
|
4345
4400
|
end.new
|
4346
4401
|
ds = Sequel.mock.dataset.from(:t).cross_join(:a___g).join(:b___h, [:c]).join(:d___i, :e=>:f)
|
4347
4402
|
ds.sql.should == 'SELECT * FROM t CROSS JOIN a AS g INNER JOIN b AS h USING (c) INNER JOIN d AS i ON (i.e = h.f)'
|
4348
|
-
ds.clone(:from=>c.transform(ds.opts[:from]), :join=>c.transform(ds.opts[:join])).sql.should == 'SELECT * FROM tt CROSS JOIN aa AS
|
4403
|
+
ds.clone(:from=>c.transform(ds.opts[:from]), :join=>c.transform(ds.opts[:join])).sql.should == 'SELECT * FROM tt CROSS JOIN aa AS g INNER JOIN bb AS h USING (cc) INNER JOIN dd AS i ON (ii.ee = hh.ff)'
|
4349
4404
|
end
|
4350
4405
|
end
|
4351
4406
|
|