sequel 4.1.1 → 4.2.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 +4 -4
- data/CHANGELOG +32 -0
- data/doc/opening_databases.rdoc +4 -0
- data/doc/release_notes/4.2.0.txt +129 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +5 -0
- data/lib/sequel/adapters/mysql2.rb +2 -1
- data/lib/sequel/adapters/postgres.rb +8 -4
- data/lib/sequel/adapters/shared/db2.rb +5 -0
- data/lib/sequel/adapters/shared/mssql.rb +15 -4
- data/lib/sequel/adapters/shared/mysql.rb +1 -0
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +10 -0
- data/lib/sequel/adapters/shared/sqlite.rb +5 -0
- data/lib/sequel/database/features.rb +6 -1
- data/lib/sequel/database/schema_methods.rb +3 -7
- data/lib/sequel/dataset/actions.rb +3 -4
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/misc.rb +28 -3
- data/lib/sequel/dataset/mutation.rb +37 -11
- data/lib/sequel/dataset/prepared_statements.rb +1 -3
- data/lib/sequel/dataset/query.rb +12 -3
- data/lib/sequel/dataset/sql.rb +12 -6
- data/lib/sequel/deprecated.rb +1 -1
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/core_extensions.rb +0 -2
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +1 -1
- data/lib/sequel/extensions/filter_having.rb +1 -1
- data/lib/sequel/extensions/from_block.rb +31 -0
- data/lib/sequel/extensions/graph_each.rb +1 -1
- data/lib/sequel/extensions/hash_aliases.rb +1 -1
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +78 -0
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_loose_count.rb +32 -0
- data/lib/sequel/extensions/pg_static_cache_updater.rb +133 -0
- data/lib/sequel/extensions/pretty_table.rb +1 -1
- data/lib/sequel/extensions/query.rb +3 -1
- data/lib/sequel/extensions/query_literals.rb +1 -1
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +1 -1
- data/lib/sequel/extensions/set_overrides.rb +1 -1
- data/lib/sequel/model.rb +1 -1
- data/lib/sequel/model/base.rb +20 -6
- data/lib/sequel/model/exceptions.rb +1 -1
- data/lib/sequel/plugins/composition.rb +9 -0
- data/lib/sequel/plugins/dirty.rb +19 -8
- data/lib/sequel/plugins/instance_filters.rb +9 -0
- data/lib/sequel/plugins/serialization.rb +9 -0
- data/lib/sequel/plugins/serialization_modification_detection.rb +9 -0
- data/lib/sequel/plugins/static_cache.rb +96 -28
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/mssql_spec.rb +1 -1
- data/spec/adapters/postgres_spec.rb +70 -0
- data/spec/core/dataset_spec.rb +58 -1
- data/spec/core/deprecated_spec.rb +1 -1
- data/spec/core/schema_spec.rb +18 -0
- data/spec/extensions/composition_spec.rb +7 -0
- data/spec/extensions/dirty_spec.rb +9 -0
- data/spec/extensions/from_block_spec.rb +21 -0
- data/spec/extensions/instance_filters_spec.rb +6 -0
- data/spec/extensions/pg_loose_count_spec.rb +17 -0
- data/spec/extensions/pg_static_cache_updater_spec.rb +80 -0
- data/spec/extensions/query_spec.rb +8 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +9 -0
- data/spec/extensions/serialization_spec.rb +7 -0
- data/spec/extensions/set_overrides_spec.rb +12 -0
- data/spec/extensions/static_cache_spec.rb +314 -154
- data/spec/integration/dataset_test.rb +12 -2
- data/spec/integration/schema_test.rb +13 -0
- data/spec/model/record_spec.rb +74 -0
- metadata +13 -3
data/lib/sequel/version.rb
CHANGED
@@ -3,10 +3,10 @@ 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 = 2
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
|
-
TINY =
|
9
|
+
TINY = 0
|
10
10
|
|
11
11
|
# The version of Sequel you are using, as a string (e.g. "2.11.0")
|
12
12
|
VERSION = [MAJOR, MINOR, TINY].join('.')
|
data/spec/adapters/mssql_spec.rb
CHANGED
@@ -612,7 +612,7 @@ describe "Database#foreign_key_list" do
|
|
612
612
|
DB.execute_ddl "drop schema vendor"
|
613
613
|
end
|
614
614
|
it "should support mixed schema bound tables" do
|
615
|
-
DB.foreign_key_list(:vendor__mapping).sort_by{|h| h[:name].to_s}.should == [{:name => :fk_mapping_item, :table => :items, :columns => [:item_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }, {:name => :fk_mapping_vendor, :table => :
|
615
|
+
DB.foreign_key_list(:vendor__mapping).sort_by{|h| h[:name].to_s}.should == [{:name => :fk_mapping_item, :table => :items, :columns => [:item_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }, {:name => :fk_mapping_vendor, :table => Sequel.qualify(:vendor, :vendors), :columns => [:vendor_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }]
|
616
616
|
end
|
617
617
|
end
|
618
618
|
end
|
@@ -60,6 +60,18 @@ describe "PostgreSQL", '#create_table' do
|
|
60
60
|
@db.create_table(:temp_unlogged_dolls, :temp => true, :unlogged => true){text :name}
|
61
61
|
end.should raise_error(Sequel::Error, "can't provide both :temp and :unlogged to create_table")
|
62
62
|
end
|
63
|
+
|
64
|
+
specify "should support pg_loose_count extension" do
|
65
|
+
@db.extension :pg_loose_count
|
66
|
+
@db.create_table(:tmp_dolls){text :name}
|
67
|
+
@db.loose_count(:tmp_dolls).should be_a_kind_of(Integer)
|
68
|
+
@db.loose_count(:tmp_dolls).should == 0
|
69
|
+
@db.loose_count(:public__tmp_dolls).should == 0
|
70
|
+
@db[:tmp_dolls].insert('a')
|
71
|
+
@db << 'VACUUM ANALYZE tmp_dolls'
|
72
|
+
@db.loose_count(:tmp_dolls).should == 1
|
73
|
+
@db.loose_count(:public__tmp_dolls).should == 1
|
74
|
+
end
|
63
75
|
end
|
64
76
|
|
65
77
|
describe "PostgreSQL views" do
|
@@ -1411,6 +1423,21 @@ if DB.adapter_scheme == :postgres
|
|
1411
1423
|
end
|
1412
1424
|
end
|
1413
1425
|
|
1426
|
+
specify "should respect the :cursor_name option" do
|
1427
|
+
one_rows = []
|
1428
|
+
two_rows = []
|
1429
|
+
@ds.order(:x).use_cursor(:cursor_name => 'cursor_one').each do |one|
|
1430
|
+
one_rows << one
|
1431
|
+
if one[:x] % 1000 == 500
|
1432
|
+
two_rows = []
|
1433
|
+
@ds.order(:x).use_cursor(:cursor_name => 'cursor_two').each do |two|
|
1434
|
+
two_rows << two
|
1435
|
+
end
|
1436
|
+
end
|
1437
|
+
end
|
1438
|
+
one_rows.should == two_rows
|
1439
|
+
end
|
1440
|
+
|
1414
1441
|
specify "should handle returning inside block" do
|
1415
1442
|
def @ds.check_return
|
1416
1443
|
use_cursor.each{|r| return}
|
@@ -3135,3 +3162,46 @@ describe 'PostgreSQL row-valued/composite types' do
|
|
3135
3162
|
end
|
3136
3163
|
end
|
3137
3164
|
end
|
3165
|
+
|
3166
|
+
describe 'pg_static_cache_updater extension' do
|
3167
|
+
before(:all) do
|
3168
|
+
@db = DB
|
3169
|
+
@db.extension :pg_static_cache_updater
|
3170
|
+
@db.drop_function(@db.default_static_cache_update_name, :cascade=>true, :if_exists=>true)
|
3171
|
+
@db.create_static_cache_update_function
|
3172
|
+
|
3173
|
+
@db.create_table!(:things) do
|
3174
|
+
primary_key :id
|
3175
|
+
String :name
|
3176
|
+
end
|
3177
|
+
@Thing = Class.new(Sequel::Model(:things))
|
3178
|
+
@Thing.plugin :static_cache
|
3179
|
+
@db.create_static_cache_update_trigger(:things)
|
3180
|
+
end
|
3181
|
+
after(:all) do
|
3182
|
+
@db.drop_table(:things)
|
3183
|
+
@db.drop_function(@db.default_static_cache_update_name)
|
3184
|
+
end
|
3185
|
+
|
3186
|
+
specify "should reload model static cache when underlying table changes" do
|
3187
|
+
@Thing.all.should == []
|
3188
|
+
q = Queue.new
|
3189
|
+
q1 = Queue.new
|
3190
|
+
|
3191
|
+
@db.listen_for_static_cache_updates(@Thing, :timeout=>0, :loop=>proc{q.push(nil); q1.pop.call})
|
3192
|
+
q.pop
|
3193
|
+
q1.push(proc{@db[:things].insert(1, 'A')})
|
3194
|
+
q.pop
|
3195
|
+
@Thing.all.should == [@Thing.load(:id=>1, :name=>'A')]
|
3196
|
+
|
3197
|
+
q1.push(proc{@db[:things].update(:name=>'B')})
|
3198
|
+
q.pop
|
3199
|
+
@Thing.all.should == [@Thing.load(:id=>1, :name=>'B')]
|
3200
|
+
|
3201
|
+
q1.push(proc{@db[:things].delete})
|
3202
|
+
q.pop
|
3203
|
+
@Thing.all.should == []
|
3204
|
+
|
3205
|
+
q1.push(proc{throw :stop})
|
3206
|
+
end
|
3207
|
+
end if DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && DB.server_version >= 90000
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -421,7 +421,12 @@ describe "Dataset#where" do
|
|
421
421
|
specify "should handle partial names" do
|
422
422
|
@dataset.where('price < :price AND id = :p', :p=>2, :price=>100).select_sql.should == "SELECT * FROM test WHERE (price < 100 AND id = 2)"
|
423
423
|
end
|
424
|
-
|
424
|
+
|
425
|
+
specify "should handle ::cast syntax when no parameters are supplied" do
|
426
|
+
@dataset.where('price::float = 10', {}).select_sql.should == "SELECT * FROM test WHERE (price::float = 10)"
|
427
|
+
@dataset.where('price::float ? 10', {}).select_sql.should == "SELECT * FROM test WHERE (price::float ? 10)"
|
428
|
+
end
|
429
|
+
|
425
430
|
specify "should affect select, delete and update statements" do
|
426
431
|
@d1.select_sql.should == "SELECT * FROM test WHERE (region = 'Asia')"
|
427
432
|
@d1.delete_sql.should == "DELETE FROM test WHERE (region = 'Asia')"
|
@@ -1139,6 +1144,10 @@ describe "Dataset#from" do
|
|
1139
1144
|
@dataset.from(:a, :b){[i, abc(de)]}.select_sql.should == "SELECT * FROM a, b, i, abc(de)"
|
1140
1145
|
end
|
1141
1146
|
|
1147
|
+
specify "should handle LATERAL subqueries" do
|
1148
|
+
@dataset.from(:a, @dataset.from(:b).lateral).select_sql.should == "SELECT * FROM a, LATERAL (SELECT * FROM b) AS t1"
|
1149
|
+
end
|
1150
|
+
|
1142
1151
|
specify "should accept :schema__table___alias symbol format" do
|
1143
1152
|
@dataset.from(:abc__def).select_sql.should == "SELECT * FROM abc.def"
|
1144
1153
|
@dataset.from(:a_b__c).select_sql.should == "SELECT * FROM a_b.c"
|
@@ -2039,6 +2048,12 @@ describe "Dataset#join_table" do
|
|
2039
2048
|
specify "should support multiple joins" do
|
2040
2049
|
@d.join_table(:inner, :b, :items_id=>:id).join_table(:left_outer, :c, :b_id => :b__id).sql.should == 'SELECT * FROM "items" INNER JOIN "b" ON ("b"."items_id" = "items"."id") LEFT OUTER JOIN "c" ON ("c"."b_id" = "b"."id")'
|
2041
2050
|
end
|
2051
|
+
|
2052
|
+
specify "should handle LATERAL subqueries" do
|
2053
|
+
@d.join(@d.lateral, :a=>:b).select_sql.should == 'SELECT * FROM "items" INNER JOIN LATERAL (SELECT * FROM "items") AS "t1" ON ("t1"."a" = "items"."b")'
|
2054
|
+
@d.left_join(@d.lateral, :a=>:b).select_sql.should == 'SELECT * FROM "items" LEFT JOIN LATERAL (SELECT * FROM "items") AS "t1" ON ("t1"."a" = "items"."b")'
|
2055
|
+
@d.cross_join(@d.lateral).select_sql.should == 'SELECT * FROM "items" CROSS JOIN LATERAL (SELECT * FROM "items") AS "t1"'
|
2056
|
+
end
|
2042
2057
|
|
2043
2058
|
specify "should support arbitrary join types" do
|
2044
2059
|
@d.join_table(:magic, :categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" MAGIC JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
@@ -4513,3 +4528,45 @@ describe "Dataset#supports_replace?" do
|
|
4513
4528
|
Sequel::Dataset.new(nil).supports_replace?.should be_false
|
4514
4529
|
end
|
4515
4530
|
end
|
4531
|
+
|
4532
|
+
describe "Frozen Datasets" do
|
4533
|
+
before do
|
4534
|
+
@ds = Sequel.mock[:test].freeze
|
4535
|
+
end
|
4536
|
+
|
4537
|
+
it "should be returned by Dataset#freeze" do
|
4538
|
+
@ds.should be_frozen
|
4539
|
+
end
|
4540
|
+
|
4541
|
+
it "should have Dataset#freeze return receiver" do
|
4542
|
+
@ds = Sequel.mock[:test]
|
4543
|
+
@ds.freeze.should equal(@ds)
|
4544
|
+
end
|
4545
|
+
|
4546
|
+
it "should have Dataset#freeze be a no-op" do
|
4547
|
+
@ds.freeze.should equal(@ds)
|
4548
|
+
end
|
4549
|
+
|
4550
|
+
it "should have clones be frozen" do
|
4551
|
+
@ds.clone.should be_frozen
|
4552
|
+
end
|
4553
|
+
|
4554
|
+
it "should have dups not be frozen" do
|
4555
|
+
@ds.dup.should_not be_frozen
|
4556
|
+
end
|
4557
|
+
|
4558
|
+
it "should raise an error when calling mutation methods" do
|
4559
|
+
proc{@ds.select!(:a)}.should raise_error
|
4560
|
+
proc{@ds.identifier_input_method = :a}.should raise_error
|
4561
|
+
proc{@ds.identifier_output_method = :a}.should raise_error
|
4562
|
+
proc{@ds.quote_identifiers = false}.should raise_error
|
4563
|
+
proc{@ds.row_proc = proc{}}.should raise_error
|
4564
|
+
proc{@ds.extension! :query}.should raise_error
|
4565
|
+
proc{@ds.naked!}.should raise_error
|
4566
|
+
proc{@ds.from_self!}.should raise_error
|
4567
|
+
end
|
4568
|
+
|
4569
|
+
it "should not raise an error when calling query methods" do
|
4570
|
+
@ds.select(:a).sql.should == 'SELECT a FROM test'
|
4571
|
+
end
|
4572
|
+
end
|
@@ -27,7 +27,7 @@ describe "Sequel::Deprecated" do
|
|
27
27
|
|
28
28
|
specify "should consider two arguments to be a method name and additional text" do
|
29
29
|
@d.deprecate("foo", "Use bar instead")
|
30
|
-
@output.should == ['foo is deprecated and will be removed in Sequel
|
30
|
+
@output.should == ['foo is deprecated and will be removed in a future version of Sequel. Use bar instead.']
|
31
31
|
end
|
32
32
|
|
33
33
|
specify "should include a prefix if set" do
|
data/spec/core/schema_spec.rb
CHANGED
@@ -397,6 +397,24 @@ describe "DB#create_table" do
|
|
397
397
|
@db.sqls.should == ["CREATE TABLE cats (name text, UNIQUE (name))"]
|
398
398
|
end
|
399
399
|
|
400
|
+
specify "should accept partial index definitions" do
|
401
|
+
def @db.supports_partial_indexes?() true end
|
402
|
+
@db.create_table(:cats) do
|
403
|
+
integer :id
|
404
|
+
index :id, :where=>proc{id > 1}
|
405
|
+
end
|
406
|
+
@db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_id_index ON cats (id) WHERE (id > 1)"]
|
407
|
+
end
|
408
|
+
|
409
|
+
specify "should raise an error if partial indexes are not supported" do
|
410
|
+
proc do
|
411
|
+
@db.create_table(:cats) do
|
412
|
+
integer :id
|
413
|
+
index :id, :where=>proc{id > 1}
|
414
|
+
end
|
415
|
+
end.should raise_error(Sequel::Error)
|
416
|
+
end
|
417
|
+
|
400
418
|
specify "should not raise on index error for unsupported index definitions if ignore_index_errors is used" do
|
401
419
|
proc {
|
402
420
|
@db.create_table(:cats, :ignore_index_errors=>true) do
|
@@ -201,6 +201,13 @@ describe "Composition plugin" do
|
|
201
201
|
proc{@o.date = Date.today}.should raise_error
|
202
202
|
end
|
203
203
|
|
204
|
+
it "should have #dup duplicate compositions" do
|
205
|
+
@c.composition :date, :mapping=>[:year, :month, :day]
|
206
|
+
@o.date.should == Date.new(1, 2, 3)
|
207
|
+
@o.dup.compositions.should == @o.compositions
|
208
|
+
@o.dup.compositions.should_not equal(@o.compositions)
|
209
|
+
end
|
210
|
+
|
204
211
|
it "should work correctly with subclasses" do
|
205
212
|
@c.composition :date, :mapping=>[:year, :month, :day]
|
206
213
|
c = Class.new(@c)
|
@@ -122,6 +122,15 @@ describe "Sequel::Plugins::Dirty" do
|
|
122
122
|
@o.initial_value(:initial).should == 'i'
|
123
123
|
proc{@o.initial = 'b'}.should raise_error
|
124
124
|
end
|
125
|
+
|
126
|
+
it "should have #dup duplicate structures" do
|
127
|
+
@o.dup.initial_values.should == @o.initial_values
|
128
|
+
@o.dup.initial_values.should_not equal(@o.initial_values)
|
129
|
+
@o.dup.instance_variable_get(:@missing_initial_values).should == @o.instance_variable_get(:@missing_initial_values)
|
130
|
+
@o.dup.instance_variable_get(:@missing_initial_values).should_not equal(@o.instance_variable_get(:@missing_initial_values))
|
131
|
+
@o.dup.previous_changes.should == @o.previous_changes
|
132
|
+
@o.dup.previous_changes.should_not equal(@o.previous_changes) if @o.previous_changes
|
133
|
+
end
|
125
134
|
end
|
126
135
|
|
127
136
|
describe "with new instance" do
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe "from_block extension" do
|
4
|
+
before do
|
5
|
+
@db = Sequel.mock
|
6
|
+
@db.extension(:from_block)
|
7
|
+
end
|
8
|
+
|
9
|
+
specify "should make Database#from blocks apply to FROM" do
|
10
|
+
@db.from{f}.sql.should == 'SELECT * FROM f'
|
11
|
+
@db.from{[f, g(f)]}.sql.should == 'SELECT * FROM f, g(f)'
|
12
|
+
end
|
13
|
+
|
14
|
+
specify "should handle from blocks with method arguments" do
|
15
|
+
@db.from(:f){g(f)}.sql.should == 'SELECT * FROM f, g(f)'
|
16
|
+
end
|
17
|
+
|
18
|
+
specify "should handle from without block" do
|
19
|
+
@db.from(:f).sql.should == 'SELECT * FROM f'
|
20
|
+
end
|
21
|
+
end
|
@@ -70,4 +70,10 @@ describe "instance_filters plugin" do
|
|
70
70
|
@p.freeze
|
71
71
|
proc{@p.instance_filter(:name=>'Jim')}.should raise_error
|
72
72
|
end
|
73
|
+
|
74
|
+
specify "should have dup duplicate internal structures" do
|
75
|
+
@p.instance_filter(:name=>'Joe')
|
76
|
+
@p.dup.send(:instance_filters).should == @p.send(:instance_filters)
|
77
|
+
@p.dup.send(:instance_filters).should_not equal(@p.send(:instance_filters))
|
78
|
+
end
|
73
79
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe "pg_loose_count extension" do
|
4
|
+
before do
|
5
|
+
@db = Sequel.mock(:host=>'postgres', :fetch=>{:v=>1}).extension(:pg_loose_count)
|
6
|
+
end
|
7
|
+
|
8
|
+
specify "should add loose_count method getting fast count for entire table using table statistics" do
|
9
|
+
@db.loose_count(:a).should == 1
|
10
|
+
@db.sqls.should == ["SELECT CAST(reltuples AS integer) AS v FROM pg_class WHERE (oid = CAST(CAST('a' AS regclass) AS oid)) LIMIT 1"]
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "should support schema qualified tables" do
|
14
|
+
@db.loose_count(:a__b).should == 1
|
15
|
+
@db.sqls.should == ["SELECT CAST(reltuples AS integer) AS v FROM pg_class WHERE (oid = CAST(CAST('a.b' AS regclass) AS oid)) LIMIT 1"]
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe "pg_static_cache_updater extension" do
|
4
|
+
before do
|
5
|
+
@db = Sequel.mock(:host=>'postgres')
|
6
|
+
def @db.listen(chan, opts={})
|
7
|
+
execute("LISTEN #{chan}")
|
8
|
+
yield(*opts[:yield])
|
9
|
+
end
|
10
|
+
@db.extension(:pg_static_cache_updater)
|
11
|
+
@model = Class.new(Sequel::Model(@db[:table]))
|
12
|
+
@model.plugin :static_cache
|
13
|
+
@db.sqls
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "#create_static_cache_update_function should create a function in the database" do
|
17
|
+
@db.create_static_cache_update_function
|
18
|
+
@db.sqls.first.gsub(/\s+/, ' ').should == " CREATE FUNCTION sequel_static_cache_update() RETURNS trigger LANGUAGE plpgsql AS 'BEGIN PERFORM pg_notify(''sequel_static_cache_update'', TG_RELID::text); RETURN NULL; END ' "
|
19
|
+
end
|
20
|
+
|
21
|
+
specify "#create_static_cache_update_function should support :channel_name and :function_name options" do
|
22
|
+
@db.create_static_cache_update_function(:channel_name=>'foo', :function_name=>'bar')
|
23
|
+
@db.sqls.first.gsub(/\s+/, ' ').should == " CREATE FUNCTION bar() RETURNS trigger LANGUAGE plpgsql AS 'BEGIN PERFORM pg_notify(''foo'', TG_RELID::text); RETURN NULL; END ' "
|
24
|
+
end
|
25
|
+
|
26
|
+
specify "#create_static_cache_update_trigger should create a trigger for the database table" do
|
27
|
+
@db.create_static_cache_update_trigger(:tab)
|
28
|
+
@db.sqls.first.gsub(/\s+/, ' ').should == "CREATE TRIGGER sequel_static_cache_update AFTER INSERT OR UPDATE OR DELETE ON tab EXECUTE PROCEDURE sequel_static_cache_update()"
|
29
|
+
end
|
30
|
+
|
31
|
+
specify "#create_static_cache_update_trigger should support :trigger_name and :function_name options" do
|
32
|
+
@db.create_static_cache_update_trigger(:tab, :trigger_name=>'foo', :function_name=>'bar')
|
33
|
+
@db.sqls.first.gsub(/\s+/, ' ').should == "CREATE TRIGGER foo AFTER INSERT OR UPDATE OR DELETE ON tab EXECUTE PROCEDURE bar()"
|
34
|
+
end
|
35
|
+
|
36
|
+
specify "#default_static_cache_update_name should return the default name for function, trigger, and channel" do
|
37
|
+
@db.default_static_cache_update_name.should == :sequel_static_cache_update
|
38
|
+
end
|
39
|
+
|
40
|
+
specify "#listen_for_static_cache_updates should listen for changes to model tables and reload model classes" do
|
41
|
+
@db.fetch = {:v=>1234}
|
42
|
+
@db.listen_for_static_cache_updates([@model], :yield=>[nil, nil, 1234]).join
|
43
|
+
@db.sqls.should == ["SELECT CAST(CAST('table' AS regclass) AS oid) AS v LIMIT 1", "LISTEN sequel_static_cache_update", "SELECT * FROM table"]
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "#listen_for_static_cache_updates should not reload model classes if oid doesn't match" do
|
47
|
+
@db.fetch = {:v=>1234}
|
48
|
+
@db.listen_for_static_cache_updates([@model], :yield=>[nil, nil, 12345]).join
|
49
|
+
@db.sqls.should == ["SELECT CAST(CAST('table' AS regclass) AS oid) AS v LIMIT 1", "LISTEN sequel_static_cache_update"]
|
50
|
+
end
|
51
|
+
|
52
|
+
specify "#listen_for_static_cache_updates should support a single model argument" do
|
53
|
+
@db.fetch = {:v=>1234}
|
54
|
+
@db.listen_for_static_cache_updates(@model, :yield=>[nil, nil, 1234]).join
|
55
|
+
@db.sqls.should == ["SELECT CAST(CAST('table' AS regclass) AS oid) AS v LIMIT 1", "LISTEN sequel_static_cache_update", "SELECT * FROM table"]
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "#listen_for_static_cache_updates should support the :channel_name option" do
|
59
|
+
@db.fetch = {:v=>1234}
|
60
|
+
@db.listen_for_static_cache_updates([@model], :yield=>[nil, nil, 12345], :channel_name=>:foo).join
|
61
|
+
@db.sqls.should == ["SELECT CAST(CAST('table' AS regclass) AS oid) AS v LIMIT 1", "LISTEN foo"]
|
62
|
+
end
|
63
|
+
|
64
|
+
specify "#listen_for_static_cache_updates should raise an error if given an empty array" do
|
65
|
+
@db.fetch = {:v=>1234}
|
66
|
+
proc{@db.listen_for_static_cache_updates([])}.should raise_error(Sequel::Error)
|
67
|
+
end
|
68
|
+
|
69
|
+
specify "#listen_for_static_cache_updates should raise an error if one of the models is not using the static cache plugin" do
|
70
|
+
@db.fetch = {:v=>1234}
|
71
|
+
proc{@db.listen_for_static_cache_updates(Class.new(Sequel::Model(@db[:table])))}.should raise_error(Sequel::Error)
|
72
|
+
end
|
73
|
+
|
74
|
+
specify "#listen_for_static_cache_updates should raise an error if the database doesn't respond to listen" do
|
75
|
+
@db = Sequel.mock(:host=>'postgres')
|
76
|
+
@db.extension(:pg_static_cache_updater)
|
77
|
+
@db.fetch = {:v=>1234}
|
78
|
+
proc{@db.listen_for_static_cache_updates(Class.new(Sequel::Model(@db[:table])))}.should raise_error(Sequel::Error)
|
79
|
+
end
|
80
|
+
end
|
@@ -87,6 +87,14 @@ describe "Dataset#query" do
|
|
87
87
|
q.sql.should == "SELECT * FROM xyz"
|
88
88
|
end
|
89
89
|
|
90
|
+
specify "should have an appropriate mutation method" do
|
91
|
+
@d.query! do
|
92
|
+
select :a, :b___mongo
|
93
|
+
from :yyy
|
94
|
+
end
|
95
|
+
@d.sql.should == "SELECT a, b AS mongo FROM yyy"
|
96
|
+
end
|
97
|
+
|
90
98
|
specify "should raise on non-chainable method calls" do
|
91
99
|
proc {@d.query {row_proc}}.should raise_error(Sequel::Error)
|
92
100
|
proc {@d.query {all}}.should raise_error(Sequel::Error)
|
@@ -77,4 +77,13 @@ describe "serialization_modification_detection plugin" do
|
|
77
77
|
@o1.h[1] = 2
|
78
78
|
@o1.changed_columns.should == [:h]
|
79
79
|
end
|
80
|
+
|
81
|
+
it "should work with frozen objects" do
|
82
|
+
@o2.changed_columns.should == []
|
83
|
+
o = @o2.dup
|
84
|
+
@o2.h.should == {}
|
85
|
+
@o2.h[1] = 2
|
86
|
+
@o2.changed_columns.should == [:h]
|
87
|
+
o.changed_columns.should == []
|
88
|
+
end
|
80
89
|
end
|
@@ -293,4 +293,11 @@ describe "Serialization plugin" do
|
|
293
293
|
proc{o.abc = 2}.should raise_error
|
294
294
|
proc{o.def = 'h'}.should raise_error
|
295
295
|
end
|
296
|
+
|
297
|
+
it "should have dup duplicate internal structures" do
|
298
|
+
@c.plugin :serialization, :yaml, :abc, :def
|
299
|
+
o = @c.new
|
300
|
+
o.dup.deserialized_values.should == o.deserialized_values
|
301
|
+
o.dup.deserialized_values.should_not equal(o.deserialized_values)
|
302
|
+
end
|
296
303
|
end
|
@@ -24,6 +24,12 @@ describe "Sequel::Dataset #set_defaults" do
|
|
24
24
|
specify "should not affect String update arguments" do
|
25
25
|
@ds.update_sql('y = 2').should == "UPDATE items SET y = 2"
|
26
26
|
end
|
27
|
+
|
28
|
+
specify "should have working mutation method" do
|
29
|
+
@ds = Sequel.mock.dataset.from(:items).extension(:set_overrides)
|
30
|
+
@ds.set_defaults!(:x=>1)
|
31
|
+
@ds.insert_sql.should == "INSERT INTO items (x) VALUES (1)"
|
32
|
+
end
|
27
33
|
end
|
28
34
|
|
29
35
|
describe "Sequel::Dataset #set_overrides" do
|
@@ -46,4 +52,10 @@ describe "Sequel::Dataset #set_overrides" do
|
|
46
52
|
@ds.set_overrides(:y=>2).update_sql.should =~ /UPDATE items SET (x = 1|y = 2), (x = 1|y = 2)/
|
47
53
|
@ds.set_overrides(:x=>2).update_sql.should == "UPDATE items SET x = 1"
|
48
54
|
end
|
55
|
+
|
56
|
+
specify "should have working mutation method" do
|
57
|
+
@ds = Sequel.mock.dataset.from(:items).extension(:set_overrides)
|
58
|
+
@ds.set_overrides!(:x=>1)
|
59
|
+
@ds.insert_sql.should == "INSERT INTO items (x) VALUES (1)"
|
60
|
+
end
|
49
61
|
end
|