sequel 3.29.0 → 3.30.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.
- data/CHANGELOG +35 -3
- data/Rakefile +2 -1
- data/doc/association_basics.rdoc +11 -0
- data/doc/opening_databases.rdoc +2 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/testing.rdoc +17 -3
- data/lib/sequel/adapters/amalgalite.rb +2 -2
- data/lib/sequel/adapters/do/mysql.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc.rb +126 -43
- data/lib/sequel/adapters/jdbc/as400.rb +11 -3
- data/lib/sequel/adapters/jdbc/db2.rb +2 -1
- data/lib/sequel/adapters/jdbc/derby.rb +44 -19
- data/lib/sequel/adapters/jdbc/h2.rb +32 -19
- data/lib/sequel/adapters/jdbc/hsqldb.rb +21 -17
- data/lib/sequel/adapters/jdbc/jtds.rb +9 -4
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -1
- data/lib/sequel/adapters/jdbc/mysql.rb +2 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +21 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +48 -18
- data/lib/sequel/adapters/mock.rb +2 -1
- data/lib/sequel/adapters/mysql.rb +4 -2
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +6 -6
- data/lib/sequel/adapters/postgres.rb +25 -12
- data/lib/sequel/adapters/shared/access.rb +14 -6
- data/lib/sequel/adapters/shared/db2.rb +36 -13
- data/lib/sequel/adapters/shared/firebird.rb +12 -5
- data/lib/sequel/adapters/shared/informix.rb +11 -3
- data/lib/sequel/adapters/shared/mssql.rb +94 -47
- data/lib/sequel/adapters/shared/mysql.rb +107 -49
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +2 -2
- data/lib/sequel/adapters/shared/oracle.rb +54 -27
- data/lib/sequel/adapters/shared/postgres.rb +65 -26
- data/lib/sequel/adapters/shared/progress.rb +4 -1
- data/lib/sequel/adapters/shared/sqlite.rb +36 -20
- data/lib/sequel/adapters/sqlite.rb +2 -3
- data/lib/sequel/adapters/swift/mysql.rb +3 -2
- data/lib/sequel/adapters/swift/sqlite.rb +2 -2
- data/lib/sequel/adapters/tinytds.rb +14 -8
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -4
- data/lib/sequel/database/misc.rb +6 -2
- data/lib/sequel/dataset/graph.rb +33 -7
- data/lib/sequel/dataset/prepared_statements.rb +19 -5
- data/lib/sequel/dataset/sql.rb +611 -201
- data/lib/sequel/model/associations.rb +12 -5
- data/lib/sequel/model/base.rb +20 -5
- data/lib/sequel/plugins/sharding.rb +9 -29
- data/lib/sequel/sql.rb +2 -1
- data/lib/sequel/timezones.rb +14 -4
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +10 -0
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/core/core_sql_spec.rb +3 -1
- data/spec/core/database_spec.rb +42 -0
- data/spec/core/dataset_spec.rb +10 -3
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/object_graph_spec.rb +38 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +35 -39
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +30 -82
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +33 -103
- data/spec/extensions/instance_filters_spec.rb +10 -21
- data/spec/extensions/instance_hooks_spec.rb +6 -24
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +135 -277
- data/spec/extensions/migration_spec.rb +18 -15
- data/spec/extensions/named_timezones_spec.rb +1 -1
- data/spec/extensions/nested_attributes_spec.rb +97 -92
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +22 -37
- data/spec/extensions/prepared_statements_safe_spec.rb +9 -27
- data/spec/extensions/prepared_statements_spec.rb +11 -30
- data/spec/extensions/prepared_statements_with_pk_spec.rb +6 -13
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +3 -6
- data/spec/extensions/serialization_spec.rb +20 -32
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +14 -36
- data/spec/extensions/spec_helper.rb +10 -64
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +1 -2
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/integration/dataset_test.rb +16 -4
- data/spec/integration/prepared_statement_test.rb +4 -2
- data/spec/model/eager_loading_spec.rb +16 -0
- data/spec/model/model_spec.rb +15 -1
- data/spec/model/record_spec.rb +60 -0
- metadata +23 -40
|
@@ -43,19 +43,17 @@ describe "Sequel::Schema::Generator dump methods" do
|
|
|
43
43
|
index [:b, :c], :unique=>true
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
t
|
|
46
|
+
g.dump_indexes(:add_index=>:t).should == (<<END_CODE).strip
|
|
47
47
|
add_index :t, [:a]
|
|
48
48
|
add_index :t, [:c, :e], :name=>:blah
|
|
49
49
|
add_index :t, [:b, :c], :unique=>true
|
|
50
50
|
END_CODE
|
|
51
|
-
g.dump_indexes(:add_index=>:t).should == t.strip
|
|
52
51
|
|
|
53
|
-
t
|
|
52
|
+
g.dump_indexes(:drop_index=>:t).should == (<<END_CODE).strip
|
|
54
53
|
drop_index :t, [:a]
|
|
55
54
|
drop_index :t, [:c, :e], :name=>:blah
|
|
56
55
|
drop_index :t, [:b, :c], :unique=>true
|
|
57
56
|
END_CODE
|
|
58
|
-
g.dump_indexes(:drop_index=>:t).should == t.strip
|
|
59
57
|
end
|
|
60
58
|
|
|
61
59
|
it "should raise an error if you try to dump a Generator that uses a constraint with a proc" do
|
|
@@ -296,7 +294,7 @@ END_MIG
|
|
|
296
294
|
i = 0
|
|
297
295
|
types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
|
|
298
296
|
end
|
|
299
|
-
|
|
297
|
+
@d.dump_table_schema(:x).should == (<<END_MIG).chomp
|
|
300
298
|
create_table(:x) do
|
|
301
299
|
Integer :c1
|
|
302
300
|
Integer :c2
|
|
@@ -365,6 +363,5 @@ create_table(:x) do
|
|
|
365
363
|
Bignum :c65
|
|
366
364
|
end
|
|
367
365
|
END_MIG
|
|
368
|
-
@d.dump_table_schema(:x).should == table.chomp
|
|
369
366
|
end
|
|
370
367
|
end
|
|
@@ -9,10 +9,6 @@ else
|
|
|
9
9
|
describe "Serialization plugin" do
|
|
10
10
|
before do
|
|
11
11
|
@c = Class.new(Sequel::Model(:items)) do
|
|
12
|
-
include(Module.new do
|
|
13
|
-
def before_save
|
|
14
|
-
end
|
|
15
|
-
end)
|
|
16
12
|
no_primary_key
|
|
17
13
|
columns :id, :abc, :def, :ghi
|
|
18
14
|
end
|
|
@@ -79,11 +75,7 @@ describe "Serialization plugin" do
|
|
|
79
75
|
@c.set_primary_key :id
|
|
80
76
|
@c.plugin :serialization, :yaml, :abc, :def
|
|
81
77
|
vals = nil
|
|
82
|
-
|
|
83
|
-
ds = @c.dataset
|
|
84
|
-
def ds.fetch_rows(sql, &block)
|
|
85
|
-
block.call(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
|
|
86
|
-
end
|
|
78
|
+
@c.dataset._fetch = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
|
|
87
79
|
|
|
88
80
|
o = @c.first
|
|
89
81
|
o.id.should == 1
|
|
@@ -94,18 +86,16 @@ describe "Serialization plugin" do
|
|
|
94
86
|
|
|
95
87
|
o.update(:abc => 23)
|
|
96
88
|
@c.create(:abc => [1, 2, 3])
|
|
97
|
-
MODEL_DB.sqls.should == ["
|
|
98
|
-
"
|
|
89
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
|
|
90
|
+
"UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)",
|
|
91
|
+
"INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')",
|
|
92
|
+
"SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
99
93
|
end
|
|
100
94
|
|
|
101
95
|
it "should translate values to and from marshal serialization format using accessor methods" do
|
|
102
96
|
@c.set_primary_key :id
|
|
103
97
|
@c.plugin :serialization, :marshal, :abc, :def
|
|
104
|
-
|
|
105
|
-
ds = @c.dataset
|
|
106
|
-
def ds.fetch_rows(sql, &block)
|
|
107
|
-
block.call(:id => 1, :abc =>[Marshal.dump(1)].pack('m'), :def =>[Marshal.dump('hello')].pack('m'))
|
|
108
|
-
end
|
|
98
|
+
@c.dataset._fetch = [:id => 1, :abc =>[Marshal.dump(1)].pack('m'), :def =>[Marshal.dump('hello')].pack('m')]
|
|
109
99
|
|
|
110
100
|
o = @c.first
|
|
111
101
|
o.id.should == 1
|
|
@@ -116,18 +106,16 @@ describe "Serialization plugin" do
|
|
|
116
106
|
|
|
117
107
|
o.update(:abc => 23)
|
|
118
108
|
@c.create(:abc => [1, 2, 3])
|
|
119
|
-
MODEL_DB.sqls.should == ["
|
|
120
|
-
"
|
|
109
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
|
|
110
|
+
"UPDATE items SET abc = '#{[Marshal.dump(23)].pack('m')}' WHERE (id = 1)",
|
|
111
|
+
"INSERT INTO items (abc) VALUES ('#{[Marshal.dump([1, 2, 3])].pack('m')}')",
|
|
112
|
+
"SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
121
113
|
end
|
|
122
114
|
|
|
123
115
|
it "should translate values to and from json serialization format using accessor methods" do
|
|
124
116
|
@c.set_primary_key :id
|
|
125
117
|
@c.plugin :serialization, :json, :abc, :def
|
|
126
|
-
|
|
127
|
-
ds = @c.dataset
|
|
128
|
-
def ds.fetch_rows(sql, &block)
|
|
129
|
-
block.call(:id => 1, :abc => [1].to_json, :def => ["hello"].to_json)
|
|
130
|
-
end
|
|
118
|
+
@c.dataset._fetch = {:id => 1, :abc => [1].to_json, :def => ["hello"].to_json}
|
|
131
119
|
|
|
132
120
|
o = @c.first
|
|
133
121
|
o.id.should == 1
|
|
@@ -139,18 +127,16 @@ describe "Serialization plugin" do
|
|
|
139
127
|
o.update(:abc => [23])
|
|
140
128
|
@c.create(:abc => [1,2,3])
|
|
141
129
|
|
|
142
|
-
MODEL_DB.sqls.should == ["
|
|
143
|
-
"
|
|
130
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
|
|
131
|
+
"UPDATE items SET abc = '#{[23].to_json}' WHERE (id = 1)",
|
|
132
|
+
"INSERT INTO items (abc) VALUES ('#{[1,2,3].to_json}')",
|
|
133
|
+
"SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
144
134
|
end
|
|
145
135
|
|
|
146
136
|
it "should copy serialization formats and columns to subclasses" do
|
|
147
137
|
@c.set_primary_key :id
|
|
148
138
|
@c.plugin :serialization, :yaml, :abc, :def
|
|
149
|
-
|
|
150
|
-
ds = @c.dataset
|
|
151
|
-
def ds.fetch_rows(sql, &block)
|
|
152
|
-
block.call(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
|
|
153
|
-
end
|
|
139
|
+
@c.dataset._fetch = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
|
|
154
140
|
|
|
155
141
|
o = Class.new(@c).first
|
|
156
142
|
o.id.should == 1
|
|
@@ -161,8 +147,10 @@ describe "Serialization plugin" do
|
|
|
161
147
|
|
|
162
148
|
o.update(:abc => 23)
|
|
163
149
|
Class.new(@c).create(:abc => [1, 2, 3])
|
|
164
|
-
MODEL_DB.sqls.should == ["
|
|
165
|
-
"
|
|
150
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items LIMIT 1",
|
|
151
|
+
"UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)",
|
|
152
|
+
"INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')",
|
|
153
|
+
"SELECT * FROM items WHERE (id = 10) LIMIT 1"]
|
|
166
154
|
end
|
|
167
155
|
|
|
168
156
|
it "should clear the deserialized columns when refreshing" do
|
|
@@ -2,271 +2,197 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "sharding plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@db = Sequel
|
|
5
|
+
@db = Sequel.mock(:numrows=>1, :autoid=>proc{1}, :servers=>{:s1=>{}, :s2=>{}, :s3=>{}, :s4=>{}})
|
|
6
6
|
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
7
7
|
@Artist.class_eval do
|
|
8
|
+
dataset._fetch = {:id=>2, :name=>'YJM'}
|
|
8
9
|
columns :id, :name
|
|
9
|
-
|
|
10
|
-
def self.y
|
|
11
|
-
{:id=>2, :name=>'YJM'}
|
|
12
|
-
end
|
|
10
|
+
plugin :sharding
|
|
13
11
|
end
|
|
14
12
|
@Album = Class.new(Sequel::Model(@db[:albums]))
|
|
15
13
|
@Album.class_eval do
|
|
14
|
+
dataset._fetch = {:id=>1, :name=>'RF', :artist_id=>2}
|
|
16
15
|
columns :id, :artist_id, :name
|
|
17
|
-
|
|
18
|
-
def self.ds_ext(m=nil)
|
|
19
|
-
@ds_ext = m if m
|
|
20
|
-
@ds_ext
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def self.y
|
|
24
|
-
{:id=>1, :name=>'RF', :artist_id=>2}
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
def _join_table_dataset(opts)
|
|
30
|
-
ds = super
|
|
31
|
-
m = model
|
|
32
|
-
ds.meta_def(:model){m}
|
|
33
|
-
ds.extend model.ds_ext
|
|
34
|
-
ds
|
|
35
|
-
end
|
|
16
|
+
plugin :sharding
|
|
36
17
|
end
|
|
37
18
|
@Tag = Class.new(Sequel::Model(@db[:tags]))
|
|
38
19
|
@Tag.class_eval do
|
|
20
|
+
dataset._fetch = {:id=>3, :name=>'M'}
|
|
39
21
|
columns :id, :name
|
|
40
|
-
|
|
41
|
-
def self.y
|
|
42
|
-
{:id=>3, :name=>'M'}
|
|
43
|
-
end
|
|
22
|
+
plugin :sharding
|
|
44
23
|
end
|
|
45
|
-
models = [@Artist, @Album, @Tag]
|
|
46
24
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
47
25
|
@Album.many_to_one :artist, :class=>@Artist
|
|
48
26
|
@Album.many_to_many :tags, :class=>@Tag, :left_key=>:album_id, :right_key=>:tag_id, :join_table=>:albums_tags
|
|
49
|
-
|
|
50
|
-
def actions
|
|
51
|
-
@actions ||= []
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
models.each do |model|
|
|
55
|
-
model.extend m
|
|
56
|
-
model.plugin :sharding
|
|
57
|
-
model.dataset.extend(ds_ext = Module.new do
|
|
58
|
-
def insert(h={})
|
|
59
|
-
model.actions << [:insert, h.dup, opts[:server]]
|
|
60
|
-
1
|
|
61
|
-
end
|
|
62
|
-
def delete
|
|
63
|
-
model.actions << [:delete,(literal(opts[:where]) if opts[:where]), opts[:server]]
|
|
64
|
-
1
|
|
65
|
-
end
|
|
66
|
-
def update(h={})
|
|
67
|
-
model.actions << [:update, h.dup, (literal(opts[:where]) if opts[:where]), opts[:server]]
|
|
68
|
-
1
|
|
69
|
-
end
|
|
70
|
-
def fetch_rows(sql)
|
|
71
|
-
model.actions << [:fetch, (literal(opts[:where] || opts[:join]) if opts[:where] || opts[:join]), opts[:server]]
|
|
72
|
-
yield(model.y)
|
|
73
|
-
end
|
|
74
|
-
end)
|
|
75
|
-
@Album.ds_ext(ds_ext)
|
|
76
|
-
end
|
|
77
|
-
def @db.actions; @actions ||= []; end
|
|
78
|
-
def @db.transaction(opts)
|
|
79
|
-
actions << [:transaction, opts[:server]]
|
|
80
|
-
super
|
|
81
|
-
end
|
|
27
|
+
@db.sqls
|
|
82
28
|
end
|
|
83
29
|
|
|
84
30
|
specify "should allow you to instantiate a new object for a specified shard" do
|
|
85
31
|
@Album.new_using_server(:s1, :name=>'RF').save
|
|
86
|
-
@
|
|
32
|
+
@db.sqls.should == ["INSERT INTO albums (name) VALUES ('RF') -- s1", "SELECT * FROM albums WHERE (id = 1) LIMIT 1 -- s1"]
|
|
87
33
|
|
|
88
|
-
@Album.actions.clear
|
|
89
34
|
@Album.new_using_server(:s2){|o| o.name = 'MO'}.save
|
|
90
|
-
@
|
|
35
|
+
@db.sqls.should == ["INSERT INTO albums (name) VALUES ('MO') -- s2", "SELECT * FROM albums WHERE (id = 1) LIMIT 1 -- s2"]
|
|
91
36
|
end
|
|
92
37
|
|
|
93
38
|
specify "should allow you to create and save a new object for a specified shard" do
|
|
94
39
|
@Album.create_using_server(:s1, :name=>'RF')
|
|
95
|
-
@
|
|
96
|
-
|
|
97
|
-
@Album.actions.clear
|
|
40
|
+
@db.sqls.should == ["INSERT INTO albums (name) VALUES ('RF') -- s1", "SELECT * FROM albums WHERE (id = 1) LIMIT 1 -- s1"]
|
|
41
|
+
|
|
98
42
|
@Album.create_using_server(:s2){|o| o.name = 'MO'}
|
|
99
|
-
@
|
|
43
|
+
@db.sqls.should == ["INSERT INTO albums (name) VALUES ('MO') -- s2", "SELECT * FROM albums WHERE (id = 1) LIMIT 1 -- s2"]
|
|
100
44
|
end
|
|
101
45
|
|
|
102
46
|
specify "should have objects retrieved from a specific shard update that shard" do
|
|
103
47
|
@Album.server(:s1).first.update(:name=>'MO')
|
|
104
|
-
@
|
|
48
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "UPDATE albums SET name = 'MO' WHERE (id = 1) -- s1"]
|
|
105
49
|
end
|
|
106
50
|
|
|
107
51
|
specify "should have objects retrieved from a specific shard delete from that shard" do
|
|
108
52
|
@Album.server(:s1).first.delete
|
|
109
|
-
@
|
|
53
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "DELETE FROM albums WHERE (id = 1) -- s1"]
|
|
110
54
|
end
|
|
111
55
|
|
|
112
56
|
specify "should have objects retrieved from a specific shard reload from that shard" do
|
|
113
57
|
@Album.server(:s1).first.reload
|
|
114
|
-
@
|
|
58
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "SELECT * FROM albums WHERE (id = 1) LIMIT 1 -- s1"]
|
|
115
59
|
end
|
|
116
60
|
|
|
117
61
|
specify "should use current dataset's shard when eager loading if eagerly loaded dataset doesn't have its own shard" do
|
|
118
62
|
albums = @Album.server(:s1).eager(:artist).all
|
|
119
|
-
@
|
|
120
|
-
|
|
121
|
-
@Artist.actions.clear
|
|
122
|
-
albums.length == 1
|
|
63
|
+
@db.sqls.should == ["SELECT * FROM albums -- s1", "SELECT * FROM artists WHERE (artists.id IN (2)) -- s1"]
|
|
64
|
+
albums.length.should == 1
|
|
123
65
|
albums.first.artist.save
|
|
124
|
-
@
|
|
66
|
+
@db.sqls.should == ["UPDATE artists SET name = 'YJM' WHERE (id = 2) -- s1"]
|
|
125
67
|
end
|
|
126
68
|
|
|
127
69
|
specify "should not use current dataset's shard when eager loading if eagerly loaded dataset has its own shard" do
|
|
128
70
|
@Artist.dataset.opts[:server] = :s2
|
|
129
71
|
albums = @Album.server(:s1).eager(:artist).all
|
|
130
|
-
@
|
|
131
|
-
|
|
132
|
-
@Artist.actions.clear
|
|
133
|
-
albums.length == 1
|
|
72
|
+
@db.sqls.should == ["SELECT * FROM albums -- s1", "SELECT * FROM artists WHERE (artists.id IN (2)) -- s2"]
|
|
73
|
+
albums.length.should == 1
|
|
134
74
|
albums.first.artist.save
|
|
135
|
-
@
|
|
75
|
+
@db.sqls.should == ["UPDATE artists SET name = 'YJM' WHERE (id = 2) -- s2"]
|
|
136
76
|
end
|
|
137
77
|
|
|
138
78
|
specify "should use current dataset's shard when eager graphing if eagerly graphed dataset doesn't have its own shard" do
|
|
139
79
|
ds = @Album.server(:s1).eager_graph(:artist)
|
|
140
|
-
|
|
141
|
-
super(sql)
|
|
142
|
-
yield({:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'})
|
|
143
|
-
end
|
|
80
|
+
ds._fetch = {:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'}
|
|
144
81
|
albums = ds.all
|
|
145
|
-
@
|
|
146
|
-
albums.length == 1
|
|
82
|
+
@db.sqls.should == ["SELECT albums.id, albums.artist_id, albums.name, artist.id AS artist_id_0, artist.name AS artist_name FROM albums LEFT OUTER JOIN artists AS artist ON (artist.id = albums.artist_id) -- s1"]
|
|
83
|
+
albums.length.should == 1
|
|
147
84
|
albums.first.artist.save
|
|
148
|
-
@
|
|
85
|
+
@db.sqls.should == ["UPDATE artists SET name = 'YJM' WHERE (id = 2) -- s1"]
|
|
149
86
|
end
|
|
150
87
|
|
|
151
88
|
specify "should not use current dataset's shard when eager graphing if eagerly graphed dataset has its own shard" do
|
|
152
89
|
@Artist.dataset.opts[:server] = :s2
|
|
153
90
|
ds = @Album.server(:s1).eager_graph(:artist)
|
|
154
|
-
|
|
155
|
-
super(sql)
|
|
156
|
-
yield({:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'})
|
|
157
|
-
end
|
|
91
|
+
ds._fetch = {:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'}
|
|
158
92
|
albums = ds.all
|
|
159
|
-
@
|
|
160
|
-
albums.length == 1
|
|
93
|
+
@db.sqls.should == ["SELECT albums.id, albums.artist_id, albums.name, artist.id AS artist_id_0, artist.name AS artist_name FROM albums LEFT OUTER JOIN artists AS artist ON (artist.id = albums.artist_id) -- s1"]
|
|
94
|
+
albums.length.should == 1
|
|
161
95
|
albums.first.artist.save
|
|
162
|
-
@
|
|
96
|
+
@db.sqls.should == ["UPDATE artists SET name = 'YJM' WHERE (id = 2) -- s2"]
|
|
163
97
|
end
|
|
164
98
|
|
|
165
99
|
specify "should use eagerly graphed dataset shard for eagerly graphed objects even if current dataset does not have a shard" do
|
|
166
100
|
@Artist.dataset.opts[:server] = :s2
|
|
167
101
|
ds = @Album.eager_graph(:artist)
|
|
168
|
-
|
|
169
|
-
super(sql)
|
|
170
|
-
yield({:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'})
|
|
171
|
-
end
|
|
102
|
+
ds._fetch = {:id=>1, :artist_id=>2, :name=>'RF', :artist_id_0=>2, :artist_name=>'YJM'}
|
|
172
103
|
albums = ds.all
|
|
173
|
-
@
|
|
174
|
-
albums.length == 1
|
|
104
|
+
@db.sqls.should == ["SELECT albums.id, albums.artist_id, albums.name, artist.id AS artist_id_0, artist.name AS artist_name FROM albums LEFT OUTER JOIN artists AS artist ON (artist.id = albums.artist_id)"]
|
|
105
|
+
albums.length.should == 1
|
|
175
106
|
albums.first.artist.save
|
|
176
|
-
@
|
|
107
|
+
@db.sqls.should == ["UPDATE artists SET name = 'YJM' WHERE (id = 2) -- s2"]
|
|
177
108
|
end
|
|
178
109
|
|
|
179
110
|
specify "should have objects retrieved from a specific shard use associated objects from that shard, with modifications to the associated objects using that shard" do
|
|
180
111
|
album = @Album.server(:s1).first
|
|
181
|
-
@
|
|
112
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1"]
|
|
182
113
|
album.artist.update(:name=>'AS')
|
|
183
|
-
@
|
|
114
|
+
@db.sqls.should == ["SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1 -- s1", "UPDATE artists SET name = 'AS' WHERE (id = 2) -- s1"]
|
|
184
115
|
album.tags.map{|a| a.update(:name=>'SR')}
|
|
185
|
-
@
|
|
186
|
-
|
|
187
|
-
@Album.actions.clear
|
|
188
|
-
@Artist.actions.clear
|
|
116
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.album_id = 1)) -- s1", "UPDATE tags SET name = 'SR' WHERE (id = 3) -- s1"]
|
|
189
117
|
@Artist.server(:s2).first.albums.map{|a| a.update(:name=>'MO')}
|
|
190
|
-
@
|
|
191
|
-
@Album.actions.should == [[:fetch, "(albums.artist_id = 2)", :s2], [:update, {:name=>"MO"}, "(id = 1)", :s2]]
|
|
118
|
+
@db.sqls.should == ["SELECT * FROM artists LIMIT 1 -- s2", "SELECT * FROM albums WHERE (albums.artist_id = 2) -- s2", "UPDATE albums SET name = 'MO' WHERE (id = 1) -- s2"]
|
|
192
119
|
end
|
|
193
120
|
|
|
194
121
|
specify "should have objects retrieved from a specific shard add associated objects to that shard" do
|
|
195
122
|
album = @Album.server(:s1).first
|
|
196
123
|
artist = @Artist.server(:s2).first
|
|
197
|
-
@
|
|
198
|
-
@Artist.actions.clear
|
|
124
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "SELECT * FROM artists LIMIT 1 -- s2"]
|
|
199
125
|
|
|
200
126
|
artist.add_album(:name=>'MO')
|
|
201
|
-
|
|
202
|
-
|
|
127
|
+
sqls = @db.sqls
|
|
128
|
+
["INSERT INTO albums (artist_id, name) VALUES (2, 'MO') -- s2", "INSERT INTO albums (name, artist_id) VALUES ('MO', 2) -- s2"].should include(sqls.shift)
|
|
129
|
+
sqls.should == ["SELECT * FROM albums WHERE (id = 1) LIMIT 1 -- s2"]
|
|
203
130
|
|
|
204
131
|
album.add_tag(:name=>'SR')
|
|
205
|
-
|
|
206
|
-
|
|
132
|
+
sqls = @db.sqls
|
|
133
|
+
["INSERT INTO albums_tags (album_id, tag_id) VALUES (1, 3) -- s1", "INSERT INTO albums_tags (tag_id, album_id) VALUES (3, 1) -- s1"].should include(sqls.pop)
|
|
134
|
+
sqls.should == ["INSERT INTO tags (name) VALUES ('SR') -- s1", "SELECT * FROM tags WHERE (id = 1) LIMIT 1 -- s1", ]
|
|
207
135
|
end
|
|
208
136
|
|
|
209
137
|
specify "should have objects retrieved from a specific shard remove associated objects from that shard" do
|
|
210
138
|
album = @Album.server(:s1).first
|
|
211
139
|
artist = @Artist.server(:s2).first
|
|
212
|
-
@
|
|
213
|
-
@Artist.actions.clear
|
|
140
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "SELECT * FROM artists LIMIT 1 -- s2"]
|
|
214
141
|
|
|
215
142
|
artist.remove_album(1)
|
|
216
|
-
|
|
217
|
-
|
|
143
|
+
sqls = @db.sqls
|
|
144
|
+
["UPDATE albums SET artist_id = NULL, name = 'RF' WHERE (id = 1) -- s2", "UPDATE albums SET name = 'RF', artist_id = NULL WHERE (id = 1) -- s2"].should include(sqls.pop)
|
|
145
|
+
sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 2) AND (albums.id = 1)) LIMIT 1 -- s2"]
|
|
218
146
|
|
|
219
147
|
album.remove_tag(3)
|
|
220
|
-
@
|
|
221
|
-
@Album.actions.should == [[:delete, "((album_id = 1) AND (tag_id = 3))", :s1]]
|
|
148
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.album_id = 1)) WHERE (tags.id = 3) LIMIT 1 -- s1", "DELETE FROM albums_tags WHERE ((album_id = 1) AND (tag_id = 3)) -- s1"]
|
|
222
149
|
end
|
|
223
150
|
|
|
224
151
|
specify "should have objects retrieved from a specific shard remove all associated objects from that shard" do
|
|
225
152
|
album = @Album.server(:s1).first
|
|
226
153
|
artist = @Artist.server(:s2).first
|
|
227
|
-
@
|
|
228
|
-
@Artist.actions.clear
|
|
154
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "SELECT * FROM artists LIMIT 1 -- s2"]
|
|
229
155
|
|
|
230
156
|
artist.remove_all_albums
|
|
231
|
-
@
|
|
232
|
-
@Album.actions.clear
|
|
157
|
+
@db.sqls.should == ["UPDATE albums SET artist_id = NULL WHERE (artist_id = 2) -- s2"]
|
|
233
158
|
|
|
234
159
|
album.remove_all_tags
|
|
235
|
-
@
|
|
160
|
+
@db.sqls.should == ["DELETE FROM albums_tags WHERE (album_id = 1) -- s1"]
|
|
236
161
|
end
|
|
237
162
|
|
|
238
163
|
specify "should not override a server already set on an associated object" do
|
|
239
164
|
album = @Album.server(:s1).first
|
|
240
165
|
artist = @Artist.server(:s2).first
|
|
241
|
-
@
|
|
242
|
-
@Artist.actions.clear
|
|
166
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "SELECT * FROM artists LIMIT 1 -- s2"]
|
|
243
167
|
|
|
244
168
|
artist.add_album(@Album.load(:id=>4, :name=>'MO').set_server(:s3))
|
|
245
|
-
|
|
246
|
-
@Album.actions.clear
|
|
169
|
+
["UPDATE albums SET artist_id = 2, name = 'MO' WHERE (id = 4) -- s3", "UPDATE albums SET name = 'MO', artist_id = 2 WHERE (id = 4) -- s3"].should include(@db.sqls.pop)
|
|
247
170
|
|
|
248
171
|
artist.remove_album(@Album.load(:id=>5, :name=>'T', :artist_id=>2).set_server(:s4))
|
|
249
172
|
# Should select from current object's shard to check existing association, but update associated object's shard
|
|
250
|
-
|
|
251
|
-
|
|
173
|
+
sqls = @db.sqls
|
|
174
|
+
["UPDATE albums SET artist_id = NULL, name = 'T' WHERE (id = 5) -- s4", "UPDATE albums SET name = 'T', artist_id = NULL WHERE (id = 5) -- s4"].should include(sqls.pop)
|
|
175
|
+
sqls.should == ["SELECT 1 FROM albums WHERE ((albums.artist_id = 2) AND (id = 5)) LIMIT 1 -- s2"]
|
|
252
176
|
end
|
|
253
177
|
|
|
254
178
|
specify "should be able to set a shard to use for any object using set_server" do
|
|
255
179
|
@Album.server(:s1).first.set_server(:s2).reload
|
|
256
|
-
@
|
|
180
|
+
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "SELECT * FROM albums WHERE (id = 1) LIMIT 1 -- s2"]
|
|
257
181
|
end
|
|
258
182
|
|
|
259
183
|
specify "should use transactions on the correct shard" do
|
|
260
184
|
@Album.use_transactions = true
|
|
261
185
|
@Album.server(:s2).first.save
|
|
262
|
-
|
|
263
|
-
|
|
186
|
+
sqls = @db.sqls
|
|
187
|
+
["UPDATE albums SET artist_id = 2, name = 'RF' WHERE (id = 1) -- s2", "UPDATE albums SET name = 'RF', artist_id = 2 WHERE (id = 1) -- s2"].should include(sqls.slice!(2))
|
|
188
|
+
sqls.should == ["SELECT * FROM albums LIMIT 1 -- s2", "BEGIN -- s2", "COMMIT -- s2"]
|
|
264
189
|
end
|
|
265
190
|
|
|
266
|
-
specify "should use
|
|
191
|
+
specify "should use override current shard when saving with given :server option" do
|
|
267
192
|
@Album.use_transactions = true
|
|
268
193
|
@Album.server(:s2).first.save(:server=>:s1)
|
|
269
|
-
|
|
270
|
-
|
|
194
|
+
sqls = @db.sqls
|
|
195
|
+
["UPDATE albums SET artist_id = 2, name = 'RF' WHERE (id = 1) -- s1", "UPDATE albums SET name = 'RF', artist_id = 2 WHERE (id = 1) -- s1"].should include(sqls.slice!(2))
|
|
196
|
+
sqls.should == ["SELECT * FROM albums LIMIT 1 -- s2", "BEGIN -- s1", "COMMIT -- s1"]
|
|
271
197
|
end
|
|
272
198
|
end
|