sequel 4.44.0 → 4.45.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 +110 -0
- data/README.rdoc +8 -9
- data/doc/active_record.rdoc +2 -3
- data/doc/model_plugins.rdoc +1 -1
- data/doc/opening_databases.rdoc +0 -46
- data/doc/release_notes/4.45.0.txt +370 -0
- data/lib/sequel/adapters/cubrid.rb +2 -0
- data/lib/sequel/adapters/do.rb +2 -0
- data/lib/sequel/adapters/jdbc/as400.rb +2 -0
- data/lib/sequel/adapters/jdbc/cubrid.rb +2 -0
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +2 -0
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +2 -0
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +2 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +5 -0
- data/lib/sequel/adapters/mysql.rb +1 -0
- data/lib/sequel/adapters/mysql2.rb +1 -0
- data/lib/sequel/adapters/odbc/oracle.rb +11 -0
- data/lib/sequel/adapters/odbc/progress.rb +2 -0
- data/lib/sequel/adapters/postgres.rb +0 -2
- data/lib/sequel/adapters/shared/cubrid.rb +2 -0
- data/lib/sequel/adapters/shared/firebird.rb +2 -0
- data/lib/sequel/adapters/shared/informix.rb +2 -0
- data/lib/sequel/adapters/shared/mssql.rb +47 -7
- data/lib/sequel/adapters/shared/mysql.rb +16 -1
- data/lib/sequel/adapters/shared/postgres.rb +9 -1
- data/lib/sequel/adapters/shared/progress.rb +2 -0
- data/lib/sequel/adapters/shared/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/swift.rb +2 -0
- data/lib/sequel/ast_transformer.rb +13 -6
- data/lib/sequel/core.rb +13 -16
- data/lib/sequel/database/connecting.rb +25 -10
- data/lib/sequel/database/dataset.rb +6 -1
- data/lib/sequel/database/dataset_defaults.rb +9 -2
- data/lib/sequel/database/misc.rb +10 -3
- data/lib/sequel/database/schema_methods.rb +4 -0
- data/lib/sequel/dataset/mutation.rb +8 -20
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +32 -7
- data/lib/sequel/dataset/sql.rb +13 -3
- data/lib/sequel/deprecated.rb +9 -1
- data/lib/sequel/exceptions.rb +37 -8
- data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +117 -0
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/identifier_mangling.rb +3 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -5
- data/lib/sequel/extensions/schema_dumper.rb +3 -1
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +1 -0
- data/lib/sequel/model.rb +23 -10
- data/lib/sequel/model/associations.rb +17 -5
- data/lib/sequel/model/base.rb +115 -62
- data/lib/sequel/model/dataset_module.rb +10 -3
- data/lib/sequel/model/exceptions.rb +7 -5
- data/lib/sequel/plugins/association_pks.rb +13 -1
- data/lib/sequel/plugins/association_proxies.rb +8 -1
- data/lib/sequel/plugins/before_after_save.rb +1 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +7 -3
- data/lib/sequel/plugins/columns_updated.rb +42 -0
- data/lib/sequel/plugins/composition.rb +10 -5
- data/lib/sequel/plugins/error_splitter.rb +1 -1
- data/lib/sequel/plugins/hook_class_methods.rb +39 -5
- data/lib/sequel/plugins/instance_hooks.rb +58 -5
- data/lib/sequel/plugins/lazy_attributes.rb +10 -5
- data/lib/sequel/plugins/nested_attributes.rb +10 -5
- data/lib/sequel/plugins/prepared_statements.rb +7 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +2 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +2 -0
- data/lib/sequel/plugins/schema.rb +2 -0
- data/lib/sequel/plugins/scissors.rb +2 -0
- data/lib/sequel/plugins/serialization.rb +10 -5
- data/lib/sequel/plugins/split_values.rb +5 -1
- data/lib/sequel/plugins/static_cache.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
- data/lib/sequel/plugins/validation_contexts.rb +49 -0
- data/lib/sequel/plugins/validation_helpers.rb +1 -0
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +31 -0
- data/spec/adapters/mysql_spec.rb +20 -2
- data/spec/adapters/postgres_spec.rb +43 -12
- data/spec/adapters/spec_helper.rb +5 -8
- data/spec/core/database_spec.rb +47 -12
- data/spec/core/dataset_mutation_spec.rb +22 -22
- data/spec/core/dataset_spec.rb +88 -20
- data/spec/core/deprecated_spec.rb +1 -1
- data/spec/core/expression_filters_spec.rb +1 -1
- data/spec/core/mock_adapter_spec.rb +0 -3
- data/spec/core/placeholder_literalizer_spec.rb +1 -1
- data/spec/core/schema_spec.rb +8 -1
- data/spec/core/spec_helper.rb +6 -1
- data/spec/core_extensions_spec.rb +4 -0
- data/spec/deprecation_helper.rb +17 -0
- data/spec/extensions/_deprecated_identifier_mangling_spec.rb +314 -0
- data/spec/extensions/association_pks_spec.rb +61 -13
- data/spec/extensions/association_proxies_spec.rb +3 -3
- data/spec/extensions/class_table_inheritance_spec.rb +39 -0
- data/spec/extensions/columns_updated_spec.rb +35 -0
- data/spec/extensions/composition_spec.rb +6 -1
- data/spec/extensions/hook_class_methods_spec.rb +114 -26
- data/spec/extensions/identifier_mangling_spec.rb +107 -73
- data/spec/extensions/instance_hooks_spec.rb +78 -14
- data/spec/extensions/lazy_attributes_spec.rb +8 -2
- data/spec/extensions/many_through_many_spec.rb +2 -2
- data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
- data/spec/extensions/nested_attributes_spec.rb +8 -2
- data/spec/extensions/pg_array_spec.rb +18 -4
- data/spec/extensions/prepared_statements_associations_spec.rb +48 -39
- data/spec/extensions/prepared_statements_with_pk_spec.rb +13 -11
- data/spec/extensions/query_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +34 -6
- data/spec/extensions/schema_spec.rb +13 -7
- data/spec/extensions/scissors_spec.rb +3 -1
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +4 -4
- data/spec/extensions/serialization_spec.rb +7 -1
- data/spec/extensions/set_overrides_spec.rb +2 -2
- data/spec/extensions/shared_caching_spec.rb +19 -15
- data/spec/extensions/spec_helper.rb +7 -3
- data/spec/extensions/split_values_spec.rb +45 -10
- data/spec/extensions/string_agg_spec.rb +2 -2
- data/spec/extensions/subset_conditions_spec.rb +3 -3
- data/spec/extensions/tactical_eager_loading_spec.rb +1 -1
- data/spec/extensions/validation_contexts_spec.rb +31 -0
- data/spec/guards_helper.rb +2 -0
- data/spec/integration/associations_test.rb +22 -20
- data/spec/integration/dataset_test.rb +25 -2
- data/spec/integration/model_test.rb +1 -1
- data/spec/integration/plugin_test.rb +11 -16
- data/spec/integration/prepared_statement_test.rb +40 -32
- data/spec/integration/spec_helper.rb +5 -8
- data/spec/model/association_reflection_spec.rb +4 -0
- data/spec/model/associations_spec.rb +37 -10
- data/spec/model/base_spec.rb +6 -0
- data/spec/model/hooks_spec.rb +56 -35
- data/spec/model/model_spec.rb +21 -5
- data/spec/model/record_spec.rb +14 -11
- data/spec/model/spec_helper.rb +7 -1
- data/spec/sequel_warning.rb +11 -0
- metadata +13 -3
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
3
|
describe "InstanceHooks plugin" do
|
|
4
|
-
def r(x)
|
|
4
|
+
def r(x=nil)
|
|
5
5
|
@r << x
|
|
6
|
+
yield if block_given?
|
|
6
7
|
x
|
|
7
8
|
end
|
|
8
9
|
|
|
@@ -24,7 +25,7 @@ describe "InstanceHooks plugin" do
|
|
|
24
25
|
@r.must_equal [4, 2, 1, 3]
|
|
25
26
|
end
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
deprecated "should cancel the save if before_create_hook block returns false" do
|
|
28
29
|
@o.after_create_hook{r 1}
|
|
29
30
|
@o.before_create_hook{r false}
|
|
30
31
|
@o.before_create_hook{r 4}
|
|
@@ -35,6 +36,17 @@ describe "InstanceHooks plugin" do
|
|
|
35
36
|
@r.must_equal [4, false]
|
|
36
37
|
end
|
|
37
38
|
|
|
39
|
+
it "should cancel the save if before_create_hook block calls cancel_action" do
|
|
40
|
+
@o.after_create_hook{r 1}
|
|
41
|
+
@o.before_create_hook{r{@o.cancel_action}}
|
|
42
|
+
@o.before_create_hook{r 4}
|
|
43
|
+
@o.save.must_be_nil
|
|
44
|
+
@r.must_equal [4, nil]
|
|
45
|
+
@r.clear
|
|
46
|
+
@o.save.must_be_nil
|
|
47
|
+
@r.must_equal [4, nil]
|
|
48
|
+
end
|
|
49
|
+
|
|
38
50
|
it "should support before_update_hook and after_update_hook" do
|
|
39
51
|
@x.after_update_hook{r 1}
|
|
40
52
|
@x.before_update_hook{r 2}
|
|
@@ -46,7 +58,7 @@ describe "InstanceHooks plugin" do
|
|
|
46
58
|
@r.must_equal [4, 2, 1, 3]
|
|
47
59
|
end
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
deprecated "should cancel the save if before_update_hook block returns false" do
|
|
50
62
|
@x.after_update_hook{r 1}
|
|
51
63
|
@x.before_update_hook{r false}
|
|
52
64
|
@x.before_update_hook{r 4}
|
|
@@ -57,6 +69,17 @@ describe "InstanceHooks plugin" do
|
|
|
57
69
|
@r.must_equal [4, false]
|
|
58
70
|
end
|
|
59
71
|
|
|
72
|
+
it "should cancel the save if before_update_hook block calls cancel_action" do
|
|
73
|
+
@x.after_update_hook{r 1}
|
|
74
|
+
@x.before_update_hook{r{@x.cancel_action}}
|
|
75
|
+
@x.before_update_hook{r 4}
|
|
76
|
+
@x.save.must_be_nil
|
|
77
|
+
@r.must_equal [4, nil]
|
|
78
|
+
@r.clear
|
|
79
|
+
@x.save.must_be_nil
|
|
80
|
+
@r.must_equal [4, nil]
|
|
81
|
+
end
|
|
82
|
+
|
|
60
83
|
it "should support before_save_hook and after_save_hook" do
|
|
61
84
|
@o.after_save_hook{r 1}
|
|
62
85
|
@o.before_save_hook{r 2}
|
|
@@ -76,7 +99,7 @@ describe "InstanceHooks plugin" do
|
|
|
76
99
|
@r.must_equal [4, 2, 1, 3]
|
|
77
100
|
end
|
|
78
101
|
|
|
79
|
-
|
|
102
|
+
deprecated "should cancel the save if before_save_hook block returns false" do
|
|
80
103
|
@x.after_save_hook{r 1}
|
|
81
104
|
@x.before_save_hook{r false}
|
|
82
105
|
@x.before_save_hook{r 4}
|
|
@@ -94,6 +117,24 @@ describe "InstanceHooks plugin" do
|
|
|
94
117
|
@r.must_equal [4, false]
|
|
95
118
|
end
|
|
96
119
|
|
|
120
|
+
it "should cancel the save if before_save_hook block calls cancel_action" do
|
|
121
|
+
@x.after_save_hook{r 1}
|
|
122
|
+
@x.before_save_hook{r{@x.cancel_action}}
|
|
123
|
+
@x.before_save_hook{r 4}
|
|
124
|
+
@x.save.must_be_nil
|
|
125
|
+
@r.must_equal [4, nil]
|
|
126
|
+
@r.clear
|
|
127
|
+
|
|
128
|
+
@x.after_save_hook{r 1}
|
|
129
|
+
@x.before_save_hook{r{@x.cancel_action}}
|
|
130
|
+
@x.before_save_hook{r 4}
|
|
131
|
+
@x.save.must_be_nil
|
|
132
|
+
@r.must_equal [4, nil]
|
|
133
|
+
@r.clear
|
|
134
|
+
@x.save.must_be_nil
|
|
135
|
+
@r.must_equal [4, nil]
|
|
136
|
+
end
|
|
137
|
+
|
|
97
138
|
it "should support before_destroy_hook and after_destroy_hook" do
|
|
98
139
|
@x.after_destroy_hook{r 1}
|
|
99
140
|
@x.before_destroy_hook{r 2}
|
|
@@ -103,7 +144,7 @@ describe "InstanceHooks plugin" do
|
|
|
103
144
|
@r.must_equal [4, 2, 1, 3]
|
|
104
145
|
end
|
|
105
146
|
|
|
106
|
-
|
|
147
|
+
deprecated "should cancel the destroy if before_destroy_hook block returns false" do
|
|
107
148
|
@x.after_destroy_hook{r 1}
|
|
108
149
|
@x.before_destroy_hook{r false}
|
|
109
150
|
@x.before_destroy_hook{r 4}
|
|
@@ -111,6 +152,14 @@ describe "InstanceHooks plugin" do
|
|
|
111
152
|
@r.must_equal [4, false]
|
|
112
153
|
end
|
|
113
154
|
|
|
155
|
+
it "should cancel the destroy if before_destroy_hook block calls cancel_action" do
|
|
156
|
+
@x.after_destroy_hook{r 1}
|
|
157
|
+
@x.before_destroy_hook{r{@x.cancel_action}}
|
|
158
|
+
@x.before_destroy_hook{r 4}
|
|
159
|
+
@x.destroy.must_be_nil
|
|
160
|
+
@r.must_equal [4, nil]
|
|
161
|
+
end
|
|
162
|
+
|
|
114
163
|
it "should support before_validation_hook and after_validation_hook" do
|
|
115
164
|
@o.after_validation_hook{r 1}
|
|
116
165
|
@o.before_validation_hook{r 2}
|
|
@@ -120,7 +169,7 @@ describe "InstanceHooks plugin" do
|
|
|
120
169
|
@r.must_equal [4, 2, 1, 3]
|
|
121
170
|
end
|
|
122
171
|
|
|
123
|
-
|
|
172
|
+
deprecated "should cancel the save if before_validation_hook block returns false" do
|
|
124
173
|
@o.after_validation_hook{r 1}
|
|
125
174
|
@o.before_validation_hook{r false}
|
|
126
175
|
@o.before_validation_hook{r 4}
|
|
@@ -131,6 +180,17 @@ describe "InstanceHooks plugin" do
|
|
|
131
180
|
@r.must_equal [4, false]
|
|
132
181
|
end
|
|
133
182
|
|
|
183
|
+
it "should cancel the save if before_validation_hook block calls cancel_action" do
|
|
184
|
+
@o.after_validation_hook{r 1}
|
|
185
|
+
@o.before_validation_hook{r{@o.cancel_action}}
|
|
186
|
+
@o.before_validation_hook{r 4}
|
|
187
|
+
@o.valid?.must_equal false
|
|
188
|
+
@r.must_equal [4, nil]
|
|
189
|
+
@r.clear
|
|
190
|
+
@o.valid?.must_equal false
|
|
191
|
+
@r.must_equal [4, nil]
|
|
192
|
+
end
|
|
193
|
+
|
|
134
194
|
it "should clear only related hooks on successful create" do
|
|
135
195
|
@o.after_destroy_hook{r 1}
|
|
136
196
|
@o.before_destroy_hook{r 2}
|
|
@@ -210,10 +270,12 @@ describe "InstanceHooks plugin with transactions" do
|
|
|
210
270
|
@c = Class.new(Sequel::Model(@db[:items])) do
|
|
211
271
|
attr_accessor :rb
|
|
212
272
|
def after_save
|
|
273
|
+
super
|
|
213
274
|
db.execute('as')
|
|
214
275
|
raise Sequel::Rollback if rb
|
|
215
276
|
end
|
|
216
277
|
def after_destroy
|
|
278
|
+
super
|
|
217
279
|
db.execute('ad')
|
|
218
280
|
raise Sequel::Rollback if rb
|
|
219
281
|
end
|
|
@@ -227,28 +289,28 @@ describe "InstanceHooks plugin with transactions" do
|
|
|
227
289
|
@db.sqls
|
|
228
290
|
end
|
|
229
291
|
|
|
230
|
-
|
|
292
|
+
deprecated "should support after_commit_hook" do
|
|
231
293
|
@o.after_commit_hook{@db.execute('ac1')}
|
|
232
294
|
@o.after_commit_hook{@db.execute('ac2')}
|
|
233
295
|
@o.save.wont_equal nil
|
|
234
296
|
@db.sqls.must_equal ['BEGIN', 'as', 'COMMIT', 'ac1', 'ac2']
|
|
235
297
|
end
|
|
236
298
|
|
|
237
|
-
|
|
299
|
+
deprecated "should support after_rollback_hook" do
|
|
238
300
|
@or.after_rollback_hook{@db.execute('ar1')}
|
|
239
301
|
@or.after_rollback_hook{@db.execute('ar2')}
|
|
240
302
|
@or.save.must_be_nil
|
|
241
303
|
@db.sqls.must_equal ['BEGIN', 'as', 'ROLLBACK', 'ar1', 'ar2']
|
|
242
304
|
end
|
|
243
305
|
|
|
244
|
-
|
|
306
|
+
deprecated "should support after_destroy_commit_hook" do
|
|
245
307
|
@o.after_destroy_commit_hook{@db.execute('adc1')}
|
|
246
308
|
@o.after_destroy_commit_hook{@db.execute('adc2')}
|
|
247
309
|
@o.destroy.wont_equal nil
|
|
248
310
|
@db.sqls.must_equal ['BEGIN', "DELETE FROM items WHERE (id = 1)", 'ad', 'COMMIT', 'adc1', 'adc2']
|
|
249
311
|
end
|
|
250
312
|
|
|
251
|
-
|
|
313
|
+
deprecated "should support after_destroy_rollback_hook" do
|
|
252
314
|
@or.after_destroy_rollback_hook{@db.execute('adr1')}
|
|
253
315
|
@or.after_destroy_rollback_hook{@db.execute('adr2')}
|
|
254
316
|
@or.destroy.must_be_nil
|
|
@@ -267,10 +329,12 @@ describe "InstanceHooks plugin with transactions" do
|
|
|
267
329
|
@o.after_save_hook{r 1}.must_be_same_as(@o)
|
|
268
330
|
@o.after_update_hook{r 1}.must_be_same_as(@o)
|
|
269
331
|
@o.after_create_hook{r 1}.must_be_same_as(@o)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
332
|
+
deprecated do
|
|
333
|
+
@o.after_commit_hook{r 1}.must_be_same_as(@o)
|
|
334
|
+
@o.after_rollback_hook{r 1}.must_be_same_as(@o)
|
|
335
|
+
@o.after_destroy_commit_hook{r 1}.must_be_same_as(@o)
|
|
336
|
+
@o.after_destroy_rollback_hook{r 1}.must_be_same_as(@o)
|
|
337
|
+
end
|
|
274
338
|
end
|
|
275
339
|
|
|
276
340
|
end
|
|
@@ -42,6 +42,12 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
|
42
42
|
Object.send(:remove_const, :LazyAttributesModel)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
deprecated "should allow access to lazy_attributes_module" do
|
|
46
|
+
@c.lazy_attributes_module.must_be_kind_of Module
|
|
47
|
+
@c.lazy_attributes_module = v = Module.new
|
|
48
|
+
@c.lazy_attributes_module.must_equal v
|
|
49
|
+
end
|
|
50
|
+
|
|
45
51
|
it "should allowing adding additional lazy attributes via plugin :lazy_attributes" do
|
|
46
52
|
@c.set_dataset(@ds.select(:id, :blah))
|
|
47
53
|
@c.dataset.sql.must_equal 'SELECT id, blah FROM la'
|
|
@@ -168,9 +174,9 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
|
168
174
|
@db.sqls.must_equal ["SELECT la.id FROM la LIMIT 1", "SELECT la.name FROM la WHERE (id = 1) LIMIT 1"]
|
|
169
175
|
end
|
|
170
176
|
|
|
171
|
-
it "should
|
|
177
|
+
it "should not allow additional lazy attributes after freezing" do
|
|
172
178
|
@c.plugin :lazy_attributes, :blah
|
|
173
179
|
@c.freeze
|
|
174
|
-
@c.
|
|
180
|
+
proc{@c.lazy_attributes :name}.must_raise RuntimeError, TypeError
|
|
175
181
|
end
|
|
176
182
|
end
|
|
@@ -440,7 +440,7 @@ describe Sequel::Model, "many_through_many" do
|
|
|
440
440
|
n = @c1.load(:id => 1234)
|
|
441
441
|
n.associations[:tags] = []
|
|
442
442
|
DB.sqls.must_equal []
|
|
443
|
-
n.tags(true).must_equal [@c2.load(:id=>1)]
|
|
443
|
+
n.tags(:reload=>true).must_equal [@c2.load(:id=>1)]
|
|
444
444
|
DB.sqls.must_equal ['SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE (albums_artists.artist_id = 1234)']
|
|
445
445
|
n.associations[:tags].must_equal n.tags
|
|
446
446
|
DB.sqls.length.must_equal 0
|
|
@@ -1558,7 +1558,7 @@ describe Sequel::Model, "one_through_many" do
|
|
|
1558
1558
|
n = @c1.load(:id => 1234)
|
|
1559
1559
|
n.associations[:tag] = nil
|
|
1560
1560
|
DB.sqls.must_equal []
|
|
1561
|
-
n.tag(true).must_equal @c2.load(:id=>1)
|
|
1561
|
+
n.tag(:reload=>true).must_equal @c2.load(:id=>1)
|
|
1562
1562
|
DB.sqls.must_equal ['SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) INNER JOIN albums_artists ON (albums_artists.album_id = albums.id) WHERE (albums_artists.artist_id = 1234) LIMIT 1']
|
|
1563
1563
|
n.associations[:tag].must_equal n.tag
|
|
1564
1564
|
DB.sqls.length.must_equal 0
|
|
@@ -35,7 +35,7 @@ describe "MSSSQL optimistic locking plugin" do
|
|
|
35
35
|
@db.numrows = 0
|
|
36
36
|
@o.timestamp = '2345'
|
|
37
37
|
proc{@o.destroy}.must_raise(Sequel::NoExistingObject)
|
|
38
|
-
@db.sqls.must_equal ["DELETE FROM items WHERE ((id = 1) AND (timestamp = 0x32333435))"]
|
|
38
|
+
@db.sqls.must_equal ["DELETE TOP (1) FROM items WHERE ((id = 1) AND (timestamp = 0x32333435))"]
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
it "should allow refresh after failed save" do
|
|
@@ -49,6 +49,12 @@ describe "NestedAttributes plugin" do
|
|
|
49
49
|
@db.sqls
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
deprecated "should allow access to nested_attributes_module" do
|
|
53
|
+
@Artist.nested_attributes_module.must_be_kind_of Module
|
|
54
|
+
@Artist.nested_attributes_module = v = Module.new
|
|
55
|
+
@Artist.nested_attributes_module.must_equal v
|
|
56
|
+
end
|
|
57
|
+
|
|
52
58
|
it "should support creating new many_to_one objects" do
|
|
53
59
|
a = @Album.new({:name=>'Al', :artist_attributes=>{:name=>'Ar'}})
|
|
54
60
|
@db.sqls.must_equal []
|
|
@@ -695,8 +701,8 @@ describe "NestedAttributes plugin" do
|
|
|
695
701
|
proc{@Album.load(:id=>10, :name=>'Al').set_nested_attributes(:tags, [{:id=>30, :name=>'T2', :number=>3}], :fields=>[:name])}.must_raise(Sequel::Error)
|
|
696
702
|
end
|
|
697
703
|
|
|
698
|
-
it "should
|
|
704
|
+
it "should not allow modifying ensted attributes after freezing" do
|
|
699
705
|
@Artist.freeze
|
|
700
|
-
@Artist.
|
|
706
|
+
proc{@Artist.nested_attributes :albums}.must_raise RuntimeError, TypeError
|
|
701
707
|
end
|
|
702
708
|
end
|
|
@@ -4,11 +4,9 @@ describe "pg_array extension" do
|
|
|
4
4
|
before(:all) do
|
|
5
5
|
Sequel.extension :pg_array
|
|
6
6
|
@pg_types = Sequel::Postgres::PG_TYPES.dup
|
|
7
|
-
@pg_named_types = Sequel::Postgres::PG_NAMED_TYPES.dup
|
|
8
7
|
end
|
|
9
8
|
after(:all) do
|
|
10
9
|
Sequel::Postgres::PG_TYPES.replace(@pg_types)
|
|
11
|
-
Sequel::Postgres::PG_NAMED_TYPES.replace(@pg_named_types)
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
before do
|
|
@@ -375,10 +373,10 @@ describe "pg_array extension" do
|
|
|
375
373
|
@db.typecast_value(:banana_array, %w'1 2').must_equal [1,2]
|
|
376
374
|
end
|
|
377
375
|
|
|
378
|
-
it "should set appropriate timestamp conversion procs when
|
|
379
|
-
Sequel::Postgres::PG_NAMED_TYPES[:foo] = proc{|v| v*2}
|
|
376
|
+
it "should set appropriate timestamp conversion procs when adding conversion procs" do
|
|
380
377
|
@db.fetch = [[{:oid=>2222, :typname=>'foo'}], [{:oid=>2222, :typarray=>2223, :typname=>'foo'}]]
|
|
381
378
|
@db.reset_conversion_procs
|
|
379
|
+
@db.add_named_conversion_proc(:foo){|v| v*2}
|
|
382
380
|
procs = @db.conversion_procs
|
|
383
381
|
procs[1185].call('{"2011-10-20 11:12:13"}').must_equal [Time.local(2011, 10, 20, 11, 12, 13)]
|
|
384
382
|
procs[1115].call('{"2011-10-20 11:12:13"}').must_equal [Time.local(2011, 10, 20, 11, 12, 13)]
|
|
@@ -386,6 +384,22 @@ describe "pg_array extension" do
|
|
|
386
384
|
procs[2223].call('{"2"}').must_equal ['22']
|
|
387
385
|
end
|
|
388
386
|
|
|
387
|
+
deprecated "should set appropriate timestamp conversion procs when resetting conversion procs when modifying PG_NAMED_TYPES" do
|
|
388
|
+
@pg_named_types = Sequel::Postgres::PG_NAMED_TYPES.dup
|
|
389
|
+
begin
|
|
390
|
+
Sequel::Postgres::PG_NAMED_TYPES[:foo] = proc{|v| v*2}
|
|
391
|
+
@db.fetch = [[{:oid=>2222, :typname=>'foo'}], [{:oid=>2222, :typarray=>2223, :typname=>'foo'}]]
|
|
392
|
+
@db.reset_conversion_procs
|
|
393
|
+
procs = @db.conversion_procs
|
|
394
|
+
procs[1185].call('{"2011-10-20 11:12:13"}').must_equal [Time.local(2011, 10, 20, 11, 12, 13)]
|
|
395
|
+
procs[1115].call('{"2011-10-20 11:12:13"}').must_equal [Time.local(2011, 10, 20, 11, 12, 13)]
|
|
396
|
+
procs[2222].call('1').must_equal '11'
|
|
397
|
+
procs[2223].call('{"2"}').must_equal ['22']
|
|
398
|
+
ensure
|
|
399
|
+
Sequel::Postgres::PG_NAMED_TYPES.replace(@pg_named_types)
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
389
403
|
it "should return correct results for Database#schema_type_class" do
|
|
390
404
|
@db.register_array_type('banana', :oid=>7866, :scalar_typecast=>:integer){|s| s.to_i}
|
|
391
405
|
@db.schema_type_class(:banana_array).must_equal Sequel::Postgres::PGArray
|
|
@@ -2,34 +2,36 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
4
4
|
before do
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
deprecated do
|
|
6
|
+
@db = Sequel.mock(:servers=>{:foo=>{}})
|
|
7
|
+
@db.extend_datasets do
|
|
8
|
+
def select_sql
|
|
9
|
+
sql = super
|
|
10
|
+
sql << ' -- prepared' if is_a?(Sequel::Dataset::PreparedStatementMethods)
|
|
11
|
+
sql
|
|
12
|
+
end
|
|
11
13
|
end
|
|
14
|
+
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
15
|
+
@Artist.columns :id, :id2
|
|
16
|
+
@Album= Class.new(Sequel::Model(@db[:albums]))
|
|
17
|
+
@Album.columns :id, :artist_id, :id2, :artist_id2
|
|
18
|
+
@Tag = Class.new(Sequel::Model(@db[:tags]))
|
|
19
|
+
@Tag.columns :id, :id2
|
|
20
|
+
@Artist.plugin :prepared_statements_associations
|
|
21
|
+
@Album.plugin :prepared_statements_associations
|
|
22
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
23
|
+
@Artist.one_to_one :album, :class=>@Album, :key=>:artist_id
|
|
24
|
+
@Album.many_to_one :artist, :class=>@Artist
|
|
25
|
+
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
|
|
26
|
+
@Album.one_through_one :tag, :clone=>:tags
|
|
27
|
+
@Artist.plugin :many_through_many
|
|
28
|
+
@Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
|
29
|
+
@Artist.one_through_many :tag, :clone=>:tags
|
|
30
|
+
@db.sqls
|
|
12
31
|
end
|
|
13
|
-
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
14
|
-
@Artist.columns :id, :id2
|
|
15
|
-
@Album= Class.new(Sequel::Model(@db[:albums]))
|
|
16
|
-
@Album.columns :id, :artist_id, :id2, :artist_id2
|
|
17
|
-
@Tag = Class.new(Sequel::Model(@db[:tags]))
|
|
18
|
-
@Tag.columns :id, :id2
|
|
19
|
-
@Artist.plugin :prepared_statements_associations
|
|
20
|
-
@Album.plugin :prepared_statements_associations
|
|
21
|
-
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
22
|
-
@Artist.one_to_one :album, :class=>@Album, :key=>:artist_id
|
|
23
|
-
@Album.many_to_one :artist, :class=>@Artist
|
|
24
|
-
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
|
|
25
|
-
@Album.one_through_one :tag, :clone=>:tags
|
|
26
|
-
@Artist.plugin :many_through_many
|
|
27
|
-
@Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
|
28
|
-
@Artist.one_through_many :tag, :clone=>:tags
|
|
29
|
-
@db.sqls
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
deprecated "should run correct SQL for associations" do
|
|
33
35
|
@Artist.load(:id=>1).albums
|
|
34
36
|
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE (albums.artist_id = 1) -- prepared"]
|
|
35
37
|
|
|
@@ -52,7 +54,7 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
|
52
54
|
@db.sqls.must_equal ["SELECT tags.id, tags.id2 FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) WHERE (albums.artist_id = 1) LIMIT 1 -- prepared"]
|
|
53
55
|
end
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
deprecated "should run correct shard for associations when also using sharding plugin" do
|
|
56
58
|
@Artist.plugin :sharding
|
|
57
59
|
@Album.plugin :sharding
|
|
58
60
|
|
|
@@ -84,12 +86,12 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
|
84
86
|
@db.sqls.must_equal ["SELECT albums.id, albums.artist_id, albums.id2, albums.artist_id2 FROM albums INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE (albums_tags.tag_id = 1) -- prepared -- foo"]
|
|
85
87
|
end
|
|
86
88
|
|
|
87
|
-
|
|
89
|
+
deprecated "should not override the shard for associations if not using the sharding plugin" do
|
|
88
90
|
@Artist.load(:id=>1).set_server(:foo).albums
|
|
89
91
|
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE (albums.artist_id = 1) -- prepared"]
|
|
90
92
|
end
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
deprecated "should run correct SQL for composite key associations" do
|
|
93
95
|
@Artist.one_to_many :albums, :class=>@Album, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
|
94
96
|
@Artist.one_to_one :album, :class=>@Album, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
|
95
97
|
@Album.many_to_one :artist, :class=>@Artist, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
|
@@ -121,13 +123,13 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
|
121
123
|
@db.sqls.must_equal ["SELECT tags.id, tags.id2 FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)) INNER JOIN albums ON ((albums.id = albums_tags.album_id) AND (albums.id2 = albums_tags.album_id2)) WHERE ((albums.artist_id = 1) AND (albums.artist_id2 = 2)) LIMIT 1 -- prepared"]
|
|
122
124
|
end
|
|
123
125
|
|
|
124
|
-
|
|
126
|
+
deprecated "should not run query if no objects can be associated" do
|
|
125
127
|
@Artist.new.albums.must_equal []
|
|
126
128
|
@Album.new.artist.must_be_nil
|
|
127
129
|
@db.sqls.must_equal []
|
|
128
130
|
end
|
|
129
131
|
|
|
130
|
-
|
|
132
|
+
deprecated "should run a regular query if not caching association metadata" do
|
|
131
133
|
@Artist.cache_associations = false
|
|
132
134
|
@Artist.load(:id=>1).albums
|
|
133
135
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
@@ -135,66 +137,73 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
|
135
137
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1) LIMIT 1"]
|
|
136
138
|
end
|
|
137
139
|
|
|
138
|
-
|
|
140
|
+
deprecated "should run a regular query if there is a callback" do
|
|
139
141
|
@Artist.load(:id=>1).albums(proc{|ds| ds})
|
|
140
142
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
141
143
|
@Artist.load(:id=>1).album(proc{|ds| ds})
|
|
142
144
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1) LIMIT 1"]
|
|
143
145
|
end
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
deprecated "should run a regular query if there is a block" do
|
|
148
|
+
@Artist.load(:id=>1).albums{|ds| ds}
|
|
149
|
+
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
150
|
+
@Artist.load(:id=>1).album{|ds| ds}
|
|
151
|
+
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1) LIMIT 1"]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
deprecated "should run a regular query if :prepared_statement=>false option is used for the association" do
|
|
146
155
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :prepared_statement=>false
|
|
147
156
|
@Artist.load(:id=>1).albums
|
|
148
157
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
149
158
|
end
|
|
150
159
|
|
|
151
|
-
|
|
160
|
+
deprecated "should run a regular query if unrecognized association is used" do
|
|
152
161
|
a = @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
153
162
|
a[:type] = :foo
|
|
154
163
|
@Artist.load(:id=>1).albums
|
|
155
164
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
156
165
|
end
|
|
157
166
|
|
|
158
|
-
|
|
167
|
+
deprecated "should run a regular query if a block is used when defining the association" do
|
|
159
168
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id do |ds| ds end
|
|
160
169
|
@Artist.load(:id=>1).albums
|
|
161
170
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
162
171
|
end
|
|
163
172
|
|
|
164
|
-
|
|
173
|
+
deprecated "should use a prepared statement if the associated dataset has conditions" do
|
|
165
174
|
@Album.dataset = @Album.dataset.where(:a=>2)
|
|
166
175
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
167
176
|
@Artist.load(:id=>1).albums
|
|
168
177
|
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE ((a = 2) AND (albums.artist_id = 1)) -- prepared"]
|
|
169
178
|
end
|
|
170
179
|
|
|
171
|
-
|
|
180
|
+
deprecated "should use a prepared statement if the :conditions association option" do
|
|
172
181
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :conditions=>{:a=>2}
|
|
173
182
|
@Artist.load(:id=>1).albums
|
|
174
183
|
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE ((a = 2) AND (albums.artist_id = 1)) -- prepared"]
|
|
175
184
|
end
|
|
176
185
|
|
|
177
|
-
|
|
186
|
+
deprecated "should not use a prepared statement if :conditions association option uses an identifier" do
|
|
178
187
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :conditions=>{Sequel.identifier('a')=>2}
|
|
179
188
|
@Artist.load(:id=>1).albums
|
|
180
189
|
@db.sqls.must_equal ["SELECT id, artist_id, id2, artist_id2 FROM albums WHERE ((a = 2) AND (albums.artist_id = 1)) -- prepared"]
|
|
181
190
|
end
|
|
182
191
|
|
|
183
|
-
|
|
192
|
+
deprecated "should run a regular query if :dataset option is used when defining the association" do
|
|
184
193
|
album = @Album
|
|
185
194
|
@Artist.one_to_many :albums, :class=>@Album, :dataset=>proc{album.filter(:artist_id=>id)}
|
|
186
195
|
@Artist.load(:id=>1).albums
|
|
187
196
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (artist_id = 1)"]
|
|
188
197
|
end
|
|
189
198
|
|
|
190
|
-
|
|
199
|
+
deprecated "should run a regular query if :cloning an association that doesn't used prepared statements" do
|
|
191
200
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id do |ds| ds end
|
|
192
201
|
@Artist.one_to_many :oalbums, :clone=>:albums
|
|
193
202
|
@Artist.load(:id=>1).oalbums
|
|
194
203
|
@db.sqls.must_equal ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
195
204
|
end
|
|
196
205
|
|
|
197
|
-
|
|
206
|
+
deprecated "should work correctly when using an instance specific association" do
|
|
198
207
|
tag = @Tag
|
|
199
208
|
@Artist.many_to_one :tag, :key=>nil, :read_only=>true, :dataset=>proc{tag.where(:id=>id).limit(1)}, :reciprocal=>nil, :reciprocal_type=>nil
|
|
200
209
|
@Artist.load(:id=>1).tag.must_be_nil
|