sequel 3.28.0 → 3.29.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
@@ -0,0 +1,378 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe "Sequel Mock Adapter" do
|
4
|
+
specify "should have an adapter method" do
|
5
|
+
db = Sequel.mock
|
6
|
+
db.should be_a_kind_of(Sequel::Mock::Database)
|
7
|
+
db.adapter_scheme.should == :mock
|
8
|
+
end
|
9
|
+
|
10
|
+
specify "should each not return any rows by default" do
|
11
|
+
called = false
|
12
|
+
Sequel.mock[:t].each{|r| called = true}
|
13
|
+
called.should be_false
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "should return 0 for update and delete by default" do
|
17
|
+
Sequel.mock[:t].update(:a=>1).should == 0
|
18
|
+
Sequel.mock[:t].delete.should == 0
|
19
|
+
end
|
20
|
+
|
21
|
+
specify "should return nil for insert by default" do
|
22
|
+
Sequel.mock[:t].insert(:a=>1).should be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
specify "should be able to set the rows returned by each using :fetch option with a single hash" do
|
26
|
+
rs = []
|
27
|
+
db = Sequel.mock(:fetch=>{:a=>1})
|
28
|
+
db[:t].each{|r| rs << r}
|
29
|
+
rs.should == [{:a=>1}]
|
30
|
+
db[:t].each{|r| rs << r}
|
31
|
+
rs.should == [{:a=>1}, {:a=>1}]
|
32
|
+
db[:t].each{|r| r[:a] = 2; rs << r}
|
33
|
+
rs.should == [{:a=>1}, {:a=>1}, {:a=>2}]
|
34
|
+
db[:t].each{|r| rs << r}
|
35
|
+
rs.should == [{:a=>1}, {:a=>1}, {:a=>2}, {:a=>1}]
|
36
|
+
end
|
37
|
+
|
38
|
+
specify "should be able to set the rows returned by each using :fetch option with an array of hashes" do
|
39
|
+
rs = []
|
40
|
+
db = Sequel.mock(:fetch=>[{:a=>1}, {:a=>2}])
|
41
|
+
db[:t].each{|r| rs << r}
|
42
|
+
rs.should == [{:a=>1}, {:a=>2}]
|
43
|
+
db[:t].each{|r| rs << r}
|
44
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>1}, {:a=>2}]
|
45
|
+
db[:t].each{|r| r[:a] += 2; rs << r}
|
46
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
|
47
|
+
db[:t].each{|r| rs << r}
|
48
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}, {:a=>1}, {:a=>2}]
|
49
|
+
end
|
50
|
+
|
51
|
+
specify "should be able to set the rows returned by each using :fetch option with an array or arrays of hashes" do
|
52
|
+
rs = []
|
53
|
+
db = Sequel.mock(:fetch=>[[{:a=>1}, {:a=>2}], [{:a=>3}, {:a=>4}]])
|
54
|
+
db[:t].each{|r| rs << r}
|
55
|
+
rs.should == [{:a=>1}, {:a=>2}]
|
56
|
+
db[:t].each{|r| rs << r}
|
57
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
|
58
|
+
db[:t].each{|r| rs << r}
|
59
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
|
60
|
+
end
|
61
|
+
|
62
|
+
specify "should be able to set the rows returned by each using :fetch option with a proc that takes sql" do
|
63
|
+
rs = []
|
64
|
+
db = Sequel.mock(:fetch=>proc{|sql| sql =~ /FROM t/ ? {:b=>1} : [{:a=>1}, {:a=>2}]})
|
65
|
+
db[:t].each{|r| rs << r}
|
66
|
+
rs.should == [{:b=>1}]
|
67
|
+
db[:b].each{|r| rs << r}
|
68
|
+
rs.should == [{:b=>1}, {:a=>1}, {:a=>2}]
|
69
|
+
db[:t].each{|r| r[:b] += 1; rs << r}
|
70
|
+
db[:b].each{|r| r[:a] += 2; rs << r}
|
71
|
+
rs.should == [{:b=>1}, {:a=>1}, {:a=>2}, {:b=>2}, {:a=>3}, {:a=>4}]
|
72
|
+
db[:t].each{|r| rs << r}
|
73
|
+
db[:b].each{|r| rs << r}
|
74
|
+
rs.should == [{:b=>1}, {:a=>1}, {:a=>2}, {:b=>2}, {:a=>3}, {:a=>4}, {:b=>1}, {:a=>1}, {:a=>2}]
|
75
|
+
end
|
76
|
+
|
77
|
+
specify "should have a fetch= method for setting rows returned by each after the fact" do
|
78
|
+
rs = []
|
79
|
+
db = Sequel.mock
|
80
|
+
db.fetch = {:a=>1}
|
81
|
+
db[:t].each{|r| rs << r}
|
82
|
+
rs.should == [{:a=>1}]
|
83
|
+
db[:t].each{|r| rs << r}
|
84
|
+
rs.should == [{:a=>1}] * 2
|
85
|
+
end
|
86
|
+
|
87
|
+
specify "should be able to set an exception to raise by setting the :fetch option to an exception class " do
|
88
|
+
db = Sequel.mock(:fetch=>ArgumentError)
|
89
|
+
proc{db[:t].all}.should raise_error(Sequel::DatabaseError)
|
90
|
+
begin
|
91
|
+
db[:t].all
|
92
|
+
rescue => e
|
93
|
+
end
|
94
|
+
e.should be_a_kind_of(Sequel::DatabaseError)
|
95
|
+
e.wrapped_exception.should be_a_kind_of(ArgumentError)
|
96
|
+
end
|
97
|
+
|
98
|
+
specify "should be able to set separate kinds of results for fetch using an array" do
|
99
|
+
rs = []
|
100
|
+
db = Sequel.mock(:fetch=>[{:a=>1}, [{:a=>2}, {:a=>3}], proc{|s| {:a=>4}}, proc{|s| }, nil, ArgumentError])
|
101
|
+
db[:t].each{|r| rs << r}
|
102
|
+
rs.should == [{:a=>1}]
|
103
|
+
db[:t].each{|r| rs << r}
|
104
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>3}]
|
105
|
+
db[:t].each{|r| rs << r}
|
106
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
|
107
|
+
db[:t].each{|r| rs << r}
|
108
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
|
109
|
+
db[:t].each{|r| rs << r}
|
110
|
+
rs.should == [{:a=>1}, {:a=>2}, {:a=>3}, {:a=>4}]
|
111
|
+
proc{db[:t].all}.should raise_error(Sequel::DatabaseError)
|
112
|
+
end
|
113
|
+
|
114
|
+
specify "should be able to set the rows returned by each on a per dataset basis using _fetch" do
|
115
|
+
rs = []
|
116
|
+
db = Sequel.mock(:fetch=>{:a=>1})
|
117
|
+
ds = db[:t]
|
118
|
+
ds.each{|r| rs << r}
|
119
|
+
rs.should == [{:a=>1}]
|
120
|
+
ds._fetch = {:b=>2}
|
121
|
+
ds.each{|r| rs << r}
|
122
|
+
rs.should == [{:a=>1}, {:b=>2}]
|
123
|
+
end
|
124
|
+
|
125
|
+
specify "should be able to set the number of rows modified by update and delete using :numrows option as an integer" do
|
126
|
+
db = Sequel.mock(:numrows=>2)
|
127
|
+
db[:t].update(:a=>1).should == 2
|
128
|
+
db[:t].delete.should == 2
|
129
|
+
db[:t].update(:a=>1).should == 2
|
130
|
+
db[:t].delete.should == 2
|
131
|
+
end
|
132
|
+
|
133
|
+
specify "should be able to set the number of rows modified by update and delete using :numrows option as an array of integers" do
|
134
|
+
db = Sequel.mock(:numrows=>[2, 1])
|
135
|
+
db[:t].update(:a=>1).should == 2
|
136
|
+
db[:t].delete.should == 1
|
137
|
+
db[:t].update(:a=>1).should == 0
|
138
|
+
db[:t].delete.should == 0
|
139
|
+
end
|
140
|
+
|
141
|
+
specify "should be able to set the number of rows modified by update and delete using :numrows option as a proc" do
|
142
|
+
db = Sequel.mock(:numrows=>proc{|sql| sql =~ / t/ ? 2 : 1})
|
143
|
+
db[:t].update(:a=>1).should == 2
|
144
|
+
db[:t].delete.should == 2
|
145
|
+
db[:b].update(:a=>1).should == 1
|
146
|
+
db[:b].delete.should == 1
|
147
|
+
end
|
148
|
+
|
149
|
+
specify "should be able to set an exception to raise by setting the :numrows option to an exception class " do
|
150
|
+
db = Sequel.mock(:numrows=>ArgumentError)
|
151
|
+
proc{db[:t].update(:a=>1)}.should raise_error(Sequel::DatabaseError)
|
152
|
+
begin
|
153
|
+
db[:t].delete
|
154
|
+
rescue => e
|
155
|
+
end
|
156
|
+
e.should be_a_kind_of(Sequel::DatabaseError)
|
157
|
+
e.wrapped_exception.should be_a_kind_of(ArgumentError)
|
158
|
+
end
|
159
|
+
|
160
|
+
specify "should be able to set separate kinds of results for numrows using an array" do
|
161
|
+
db = Sequel.mock(:numrows=>[1, proc{|s| 2}, nil, ArgumentError])
|
162
|
+
db[:t].delete.should == 1
|
163
|
+
db[:t].update(:a=>1).should == 2
|
164
|
+
db[:t].delete.should == 0
|
165
|
+
proc{db[:t].delete}.should raise_error(Sequel::DatabaseError)
|
166
|
+
end
|
167
|
+
|
168
|
+
specify "should have a numrows= method to set the number of rows modified by update and delete after the fact" do
|
169
|
+
db = Sequel.mock
|
170
|
+
db.numrows = 2
|
171
|
+
db[:t].update(:a=>1).should == 2
|
172
|
+
db[:t].delete.should == 2
|
173
|
+
db[:t].update(:a=>1).should == 2
|
174
|
+
db[:t].delete.should == 2
|
175
|
+
end
|
176
|
+
|
177
|
+
specify "should be able to set the number of rows modified by update and delete on a per dataset basis" do
|
178
|
+
db = Sequel.mock(:numrows=>2)
|
179
|
+
ds = db[:t]
|
180
|
+
ds.update(:a=>1).should == 2
|
181
|
+
ds.delete.should == 2
|
182
|
+
ds.numrows = 3
|
183
|
+
ds.update(:a=>1).should == 3
|
184
|
+
ds.delete.should == 3
|
185
|
+
end
|
186
|
+
|
187
|
+
specify "should be able to set the autogenerated primary key returned by insert using :autoid option as an integer" do
|
188
|
+
db = Sequel.mock(:autoid=>1)
|
189
|
+
db[:t].insert(:a=>1).should == 1
|
190
|
+
db[:t].insert(:a=>1).should == 2
|
191
|
+
db[:t].insert(:a=>1).should == 3
|
192
|
+
end
|
193
|
+
|
194
|
+
specify "should be able to set the autogenerated primary key returned by insert using :autoid option as an array of integers" do
|
195
|
+
db = Sequel.mock(:autoid=>[1, 3, 5])
|
196
|
+
db[:t].insert(:a=>1).should == 1
|
197
|
+
db[:t].insert(:a=>1).should == 3
|
198
|
+
db[:t].insert(:a=>1).should == 5
|
199
|
+
db[:t].insert(:a=>1).should be_nil
|
200
|
+
end
|
201
|
+
|
202
|
+
specify "should be able to set the autogenerated primary key returned by insert using :autoid option as a proc" do
|
203
|
+
db = Sequel.mock(:autoid=>proc{|sql| sql =~ /INTO t / ? 2 : 1})
|
204
|
+
db[:t].insert(:a=>1).should == 2
|
205
|
+
db[:t].insert(:a=>1).should == 2
|
206
|
+
db[:b].insert(:a=>1).should == 1
|
207
|
+
db[:b].insert(:a=>1).should == 1
|
208
|
+
end
|
209
|
+
|
210
|
+
specify "should be able to set an exception to raise by setting the :autoid option to an exception class " do
|
211
|
+
db = Sequel.mock(:autoid=>ArgumentError)
|
212
|
+
proc{db[:t].insert(:a=>1)}.should raise_error(Sequel::DatabaseError)
|
213
|
+
begin
|
214
|
+
db[:t].insert
|
215
|
+
rescue => e
|
216
|
+
end
|
217
|
+
e.should be_a_kind_of(Sequel::DatabaseError)
|
218
|
+
e.wrapped_exception.should be_a_kind_of(ArgumentError)
|
219
|
+
end
|
220
|
+
|
221
|
+
specify "should be able to set separate kinds of results for autoid using an array" do
|
222
|
+
db = Sequel.mock(:autoid=>[1, proc{|s| 2}, nil, ArgumentError])
|
223
|
+
db[:t].insert.should == 1
|
224
|
+
db[:t].insert.should == 2
|
225
|
+
db[:t].insert.should == nil
|
226
|
+
proc{db[:t].insert}.should raise_error(Sequel::DatabaseError)
|
227
|
+
end
|
228
|
+
|
229
|
+
specify "should have an autoid= method to set the autogenerated primary key returned by insert after the fact" do
|
230
|
+
db = Sequel.mock
|
231
|
+
db.autoid = 1
|
232
|
+
db[:t].insert(:a=>1).should == 1
|
233
|
+
db[:t].insert(:a=>1).should == 2
|
234
|
+
db[:t].insert(:a=>1).should == 3
|
235
|
+
end
|
236
|
+
|
237
|
+
specify "should be able to set the autogenerated primary key returned by insert on a per dataset basis" do
|
238
|
+
db = Sequel.mock(:autoid=>1)
|
239
|
+
ds = db[:t]
|
240
|
+
ds.insert(:a=>1).should == 1
|
241
|
+
ds.autoid = 5
|
242
|
+
ds.insert(:a=>1).should == 5
|
243
|
+
ds.insert(:a=>1).should == 6
|
244
|
+
db[:t].insert(:a=>1).should == 2
|
245
|
+
end
|
246
|
+
|
247
|
+
specify "should be able to set the columns to set in the dataset as an array of symbols" do
|
248
|
+
db = Sequel.mock(:columns=>[:a, :b])
|
249
|
+
db[:t].columns.should == [:a, :b]
|
250
|
+
db.sqls.should == ["SELECT * FROM t LIMIT 1"]
|
251
|
+
ds = db[:t]
|
252
|
+
ds.all
|
253
|
+
db.sqls.should == ["SELECT * FROM t"]
|
254
|
+
ds.columns.should == [:a, :b]
|
255
|
+
db.sqls.should == []
|
256
|
+
db[:t].columns.should == [:a, :b]
|
257
|
+
end
|
258
|
+
|
259
|
+
specify "should be able to set the columns to set in the dataset as an array of arrays of symbols" do
|
260
|
+
db = Sequel.mock(:columns=>[[:a, :b], [:c, :d]])
|
261
|
+
db[:t].columns.should == [:a, :b]
|
262
|
+
db[:t].columns.should == [:c, :d]
|
263
|
+
end
|
264
|
+
|
265
|
+
specify "should be able to set the columns to set in the dataset as a proc" do
|
266
|
+
db = Sequel.mock(:columns=>proc{|sql| (sql =~ / t/) ? [:a, :b] : [:c, :d]})
|
267
|
+
db[:b].columns.should == [:c, :d]
|
268
|
+
db[:t].columns.should == [:a, :b]
|
269
|
+
end
|
270
|
+
|
271
|
+
specify "should have a columns= method to set the columns to set after the fact" do
|
272
|
+
db = Sequel.mock
|
273
|
+
db.columns = [[:a, :b], [:c, :d]]
|
274
|
+
db[:t].columns.should == [:a, :b]
|
275
|
+
db[:t].columns.should == [:c, :d]
|
276
|
+
end
|
277
|
+
|
278
|
+
specify "should keep a record of all executed SQL in #sqls" do
|
279
|
+
db = Sequel.mock
|
280
|
+
db[:t].all
|
281
|
+
db[:b].delete
|
282
|
+
db[:c].insert(:a=>1)
|
283
|
+
db[:d].update(:a=>1)
|
284
|
+
db.sqls.should == ['SELECT * FROM t', 'DELETE FROM b', 'INSERT INTO c (a) VALUES (1)', 'UPDATE d SET a = 1']
|
285
|
+
end
|
286
|
+
|
287
|
+
specify "should clear sqls on retrieval" do
|
288
|
+
db = Sequel.mock
|
289
|
+
db[:t].all
|
290
|
+
db.sqls.should == ['SELECT * FROM t']
|
291
|
+
db.sqls.should == []
|
292
|
+
end
|
293
|
+
|
294
|
+
specify "should also log SQL executed to the given loggers" do
|
295
|
+
a = []
|
296
|
+
def a.method_missing(m, *x) push(*x) end
|
297
|
+
db = Sequel.mock(:loggers=>[a])
|
298
|
+
db[:t].all
|
299
|
+
db[:b].delete
|
300
|
+
db[:c].insert(:a=>1)
|
301
|
+
db[:d].update(:a=>1)
|
302
|
+
a.should == ['SELECT * FROM t', 'DELETE FROM b', 'INSERT INTO c (a) VALUES (1)', 'UPDATE d SET a = 1']
|
303
|
+
end
|
304
|
+
|
305
|
+
specify "should correctly handle transactions" do
|
306
|
+
db = Sequel.mock
|
307
|
+
db.transaction{db[:a].all}
|
308
|
+
db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'COMMIT']
|
309
|
+
db.transaction{db[:a].all; raise Sequel::Rollback}
|
310
|
+
db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
|
311
|
+
proc{db.transaction{db[:a].all; raise ArgumentError}}.should raise_error(ArgumentError)
|
312
|
+
db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
|
313
|
+
proc{db.transaction(:rollback=>:reraise){db[:a].all; raise Sequel::Rollback}}.should raise_error(Sequel::Rollback)
|
314
|
+
db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
|
315
|
+
db.transaction(:rollback=>:always){db[:a].all}
|
316
|
+
db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
|
317
|
+
db.transaction{db.transaction{db[:a].all; raise Sequel::Rollback}}
|
318
|
+
db.sqls.should == ['BEGIN', 'SELECT * FROM a', 'ROLLBACK']
|
319
|
+
db.transaction{db.transaction(:savepoint=>true){db[:a].all; raise Sequel::Rollback}}
|
320
|
+
db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'SELECT * FROM a', 'ROLLBACK TO SAVEPOINT autopoint_1', 'COMMIT']
|
321
|
+
db.transaction{db.transaction(:savepoint=>true){db[:a].all}; raise Sequel::Rollback}
|
322
|
+
db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'SELECT * FROM a', 'RELEASE SAVEPOINT autopoint_1', 'ROLLBACK']
|
323
|
+
end
|
324
|
+
|
325
|
+
specify "should correctly handle transactions when sharding" do
|
326
|
+
db = Sequel.mock(:servers=>{:test=>{}})
|
327
|
+
db.transaction{db.transaction(:server=>:test){db[:a].all; db[:t].server(:test).all}}
|
328
|
+
db.sqls.should == ['BEGIN', 'BEGIN -- test', 'SELECT * FROM a', 'SELECT * FROM t -- test', 'COMMIT -- test', 'COMMIT']
|
329
|
+
end
|
330
|
+
|
331
|
+
specify "should yield a mock connection object from synchronize" do
|
332
|
+
c = Sequel.mock.synchronize{|conn| conn}
|
333
|
+
c.should be_a_kind_of(Sequel::Mock::Connection)
|
334
|
+
end
|
335
|
+
|
336
|
+
specify "should deal correctly with sharding" do
|
337
|
+
db = Sequel.mock(:servers=>{:test=>{}})
|
338
|
+
c1 = db.synchronize{|conn| conn}
|
339
|
+
c2 = db.synchronize(:test){|conn| conn}
|
340
|
+
c1.server.should == :default
|
341
|
+
c2.server.should == :test
|
342
|
+
end
|
343
|
+
|
344
|
+
specify "should disconnect correctly" do
|
345
|
+
db = Sequel.mock
|
346
|
+
db.test_connection
|
347
|
+
proc{db.disconnect}.should_not raise_error
|
348
|
+
end
|
349
|
+
|
350
|
+
specify "should accept :extend option for extending the object with a module" do
|
351
|
+
Sequel.mock(:extend=>Module.new{def foo(v) v * 2 end}).foo(3).should == 6
|
352
|
+
end
|
353
|
+
|
354
|
+
specify "should accept :sqls option for where to store the SQL queries" do
|
355
|
+
a = []
|
356
|
+
Sequel.mock(:sqls=>a)[:t].all
|
357
|
+
a.should == ['SELECT * FROM t']
|
358
|
+
end
|
359
|
+
|
360
|
+
specify "should include :append option in SQL if it is given" do
|
361
|
+
db = Sequel.mock(:append=>'a')
|
362
|
+
db[:t].all
|
363
|
+
db.sqls.should == ['SELECT * FROM t -- a']
|
364
|
+
end
|
365
|
+
|
366
|
+
specify "should append :arguments option to execute to the SQL if present" do
|
367
|
+
db = Sequel.mock
|
368
|
+
db.execute('SELECT * FROM t', :arguments=>[1, 2])
|
369
|
+
db.sqls.should == ['SELECT * FROM t -- args: [1, 2]']
|
370
|
+
end
|
371
|
+
|
372
|
+
specify "should have Dataset#columns take columns to set and return self" do
|
373
|
+
db = Sequel.mock
|
374
|
+
ds = db[:t].columns(:id, :a, :b)
|
375
|
+
ds.should be_a_kind_of(Sequel::Mock::Dataset)
|
376
|
+
ds.columns.should == [:id, :a, :b]
|
377
|
+
end
|
378
|
+
end
|
@@ -2,16 +2,21 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
3
3
|
describe Sequel::Dataset, " graphing" do
|
4
4
|
before do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
@db = Sequel.mock(:columns=>proc do |sql|
|
6
|
+
case sql
|
7
|
+
when /points/
|
8
|
+
[:id, :x, :y]
|
9
|
+
when /lines/
|
10
|
+
[:id, :x, :y, :graph_id]
|
11
|
+
else
|
12
|
+
[:id, :name, :x, :y, :lines_x]
|
13
|
+
end
|
14
|
+
end)
|
15
|
+
@ds1 = @db.from(:points)
|
16
|
+
@ds2 = @db.from(:lines)
|
17
|
+
@ds3 = @db.from(:graphs)
|
18
|
+
[@ds1, @ds2, @ds3].each{|ds| ds.columns}
|
19
|
+
@db.sqls
|
15
20
|
end
|
16
21
|
|
17
22
|
it "#graph should not modify the current dataset's opts" do
|
@@ -187,144 +192,73 @@ describe Sequel::Dataset, " graphing" do
|
|
187
192
|
end
|
188
193
|
|
189
194
|
it "#graph_each should split the result set into component tables" do
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
194
|
-
results = ds.all
|
195
|
-
results.length.should == 1
|
196
|
-
results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}}
|
197
|
-
|
198
|
-
ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
|
199
|
-
def ds.fetch_rows(sql, &block)
|
200
|
-
yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12})
|
201
|
-
end
|
202
|
-
results = ds.all
|
203
|
-
results.length.should == 1
|
204
|
-
results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}
|
195
|
+
@db.fetch = [[{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}],
|
196
|
+
[{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12}],
|
197
|
+
[{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graph_id_0=>8, :graph_x=>9, :graph_y=>10, :graph_graph_id=>11}]]
|
205
198
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end
|
210
|
-
results = ds.all
|
211
|
-
results.length.should == 1
|
212
|
-
results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graph=>{:id=>8, :x=>9, :y=>10, :graph_id=>11}}
|
199
|
+
@ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}}]
|
200
|
+
@ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}]
|
201
|
+
@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graph=>{:id=>8, :x=>9, :y=>10, :graph_id=>11}}]
|
213
202
|
end
|
214
203
|
|
215
204
|
it "#ungraphed should remove the splitting of result sets into component tables" do
|
216
|
-
|
217
|
-
|
218
|
-
yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7})
|
219
|
-
end
|
220
|
-
ds.all.should == [{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}]
|
205
|
+
@db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}
|
206
|
+
@ds1.graph(@ds2, :x=>:id).ungraphed.all.should == [{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}]
|
221
207
|
end
|
222
208
|
|
223
209
|
it "#graph_each should give a nil value instead of a hash when all values for a table are nil" do
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
results.length.should == 1
|
230
|
-
results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>nil}
|
210
|
+
@db.fetch = [[{:id=>1,:x=>2,:y=>3,:lines_id=>nil,:lines_x=>nil,:lines_y=>nil,:graph_id=>nil}],
|
211
|
+
[{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>nil, :name=>nil, :graphs_x=>nil, :graphs_y=>nil, :graphs_lines_x=>nil},
|
212
|
+
{:id=>2,:x=>4,:y=>5,:lines_id=>nil,:lines_x=>nil,:lines_y=>nil,:graph_id=>nil, :graphs_id=>nil, :name=>nil, :graphs_x=>nil, :graphs_y=>nil, :graphs_lines_x=>nil},
|
213
|
+
{:id=>3,:x=>5,:y=>6,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>7, :name=>8, :graphs_x=>9, :graphs_y=>10, :graphs_lines_x=>11},
|
214
|
+
{:id=>3,:x=>5,:y=>6,:lines_id=>7,:lines_x=>5,:lines_y=>8,:graph_id=>9, :graphs_id=>9, :name=>10, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12}]]
|
231
215
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
yield({:id=>3,:x=>5,:y=>6,:lines_id=>7,:lines_x=>5,:lines_y=>8,:graph_id=>9, :graphs_id=>9, :name=>10, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12})
|
238
|
-
end
|
239
|
-
results = ds.all
|
240
|
-
results.length.should == 4
|
241
|
-
results[0].should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>nil}
|
242
|
-
results[1].should == {:points=>{:id=>2, :x=>4, :y=>5}, :lines=>nil, :graphs=>nil}
|
243
|
-
results[2].should == {:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>7, :name=>8, :x=>9, :y=>10, :lines_x=>11}}
|
244
|
-
results[3].should == {:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>7, :x=>5, :y=>8, :graph_id=>9}, :graphs=>{:id=>9, :name=>10, :x=>10, :y=>11, :lines_x=>12}}
|
216
|
+
@ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>nil}]
|
217
|
+
@ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>nil},
|
218
|
+
{:points=>{:id=>2, :x=>4, :y=>5}, :lines=>nil, :graphs=>nil},
|
219
|
+
{:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>7, :name=>8, :x=>9, :y=>10, :lines_x=>11}},
|
220
|
+
{:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>7, :x=>5, :y=>8, :graph_id=>9}, :graphs=>{:id=>9, :name=>10, :x=>10, :y=>11, :lines_x=>12}}]
|
245
221
|
end
|
246
222
|
|
247
223
|
it "#graph_each should not give a nil value instead of a hash when any value for a table is false" do
|
248
|
-
|
249
|
-
|
250
|
-
block.call(:id=>1,:x=>2,:y=>3,:lines_id=>nil,:lines_x=>false,:lines_y=>nil,:graph_id=>nil)
|
251
|
-
end
|
252
|
-
ds.all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>nil, :x=>false, :y=>nil, :graph_id=>nil}}]
|
224
|
+
@db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>nil,:lines_x=>false,:lines_y=>nil,:graph_id=>nil}
|
225
|
+
@ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>nil, :x=>false, :y=>nil, :graph_id=>nil}}]
|
253
226
|
end
|
254
227
|
|
255
228
|
it "#graph_each should not included tables graphed with the :select => false option in the result set" do
|
256
|
-
|
257
|
-
|
258
|
-
yield({:id=>1,:x=>2,:y=>3,:graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :lines_x=>12})
|
259
|
-
end
|
260
|
-
results = ds.all
|
261
|
-
results.length.should == 1
|
262
|
-
results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}
|
229
|
+
@db.fetch = {:id=>1,:x=>2,:y=>3,:graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :lines_x=>12}
|
230
|
+
@ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}]
|
263
231
|
end
|
264
232
|
|
265
233
|
it "#graph_each should only include the columns selected with #set_graph_aliases and #add_graph_aliases, if called" do
|
266
|
-
|
267
|
-
def ds.fetch_rows(sql, &block)
|
268
|
-
yield({:x=>2,:y=>3})
|
269
|
-
end
|
270
|
-
results = ds.all
|
271
|
-
results.length.should == 1
|
272
|
-
results.first.should == {:points=>{:x=>2}, :lines=>{:y=>3}}
|
234
|
+
@db.fetch = [nil, [{:x=>2,:y=>3}], nil, [{:x=>2}], [{:x=>2, :q=>18}]]
|
273
235
|
|
236
|
+
@ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).all.should == [{:points=>{:x=>2}, :lines=>{:y=>3}}]
|
274
237
|
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x])
|
275
|
-
|
276
|
-
yield({:x=>2})
|
277
|
-
end
|
278
|
-
results = ds.all
|
279
|
-
results.length.should == 1
|
280
|
-
results.first.should == {:points=>{:x=>2}, :lines=>nil}
|
281
|
-
|
238
|
+
ds.all.should == [{:points=>{:x=>2}, :lines=>nil}]
|
282
239
|
ds = ds.add_graph_aliases(:q=>[:points, :r, 18])
|
283
|
-
def ds.fetch_rows(sql, &block)
|
284
|
-
yield({:x=>2, :q=>18})
|
285
|
-
end
|
286
240
|
ds.all.should == [{:points=>{:x=>2, :r=>18}, :lines=>nil}]
|
287
241
|
end
|
288
242
|
|
289
243
|
it "#graph_each should correctly map values when #set_graph_aliases is used with a third argument for each entry" do
|
290
|
-
|
291
|
-
|
292
|
-
yield({:x=>2,:y=>3})
|
293
|
-
end
|
294
|
-
results = ds.all
|
295
|
-
results.length.should == 1
|
296
|
-
results.first.should == {:points=>{:z1=>2}, :lines=>{:z2=>3}}
|
244
|
+
@db.fetch = [nil, {:x=>2,:y=>3}]
|
245
|
+
@ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :z1, 2], :y=>[:lines, :z2, :random.sql_function]).all.should == [{:points=>{:z1=>2}, :lines=>{:z2=>3}}]
|
297
246
|
end
|
298
247
|
|
299
248
|
it "#graph_each should correctly map values when #set_graph_aliases is used with a single argument for each entry" do
|
300
|
-
|
301
|
-
|
302
|
-
yield({:x=>2,:y=>3})
|
303
|
-
end
|
304
|
-
results = ds.all
|
305
|
-
results.length.should == 1
|
306
|
-
results.first.should == {:points=>{:x=>2}, :lines=>{:y=>3}}
|
249
|
+
@db.fetch = [nil, {:x=>2,:y=>3}]
|
250
|
+
@ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points], :y=>[:lines]).all.should == [{:points=>{:x=>2}, :lines=>{:y=>3}}]
|
307
251
|
end
|
308
252
|
|
309
253
|
it "#graph_each should correctly map values when #set_graph_aliases is used with a symbol for each entry" do
|
310
|
-
|
311
|
-
|
312
|
-
yield({:x=>2,:y=>3})
|
313
|
-
end
|
314
|
-
results = ds.all
|
315
|
-
results.length.should == 1
|
316
|
-
results.first.should == {:points=>{:x=>2}, :lines=>{:y=>3}}
|
254
|
+
@db.fetch = [nil, {:x=>2,:y=>3}]
|
255
|
+
@ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>:points, :y=>:lines).all.should == [{:points=>{:x=>2}, :lines=>{:y=>3}}]
|
317
256
|
end
|
318
257
|
|
319
258
|
it "#graph_each should run the row_proc for graphed datasets" do
|
320
259
|
@ds1.row_proc = proc{|h| h.keys.each{|k| h[k] *= 2}; h}
|
321
260
|
@ds2.row_proc = proc{|h| h.keys.each{|k| h[k] *= 3}; h}
|
322
|
-
|
323
|
-
|
324
|
-
yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7})
|
325
|
-
end
|
326
|
-
results = ds.all
|
327
|
-
results.length.should == 1
|
328
|
-
results.first.should == {:points=>{:id=>2, :x=>4, :y=>6}, :lines=>{:id=>12, :x=>15, :y=>18, :graph_id=>21}}
|
261
|
+
@db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}
|
262
|
+
@ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>2, :x=>4, :y=>6}, :lines=>{:id=>12, :x=>15, :y=>18, :graph_id=>21}}]
|
329
263
|
end
|
330
264
|
end
|