sequel 3.46.0 → 3.47.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 +96 -0
- data/Rakefile +7 -1
- data/bin/sequel +6 -4
- data/doc/active_record.rdoc +1 -1
- data/doc/advanced_associations.rdoc +14 -35
- data/doc/association_basics.rdoc +66 -4
- data/doc/migration.rdoc +4 -0
- data/doc/opening_databases.rdoc +6 -0
- data/doc/postgresql.rdoc +302 -0
- data/doc/release_notes/3.47.0.txt +270 -0
- data/doc/security.rdoc +6 -0
- data/lib/sequel/adapters/ibmdb.rb +9 -9
- data/lib/sequel/adapters/jdbc.rb +22 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +7 -2
- data/lib/sequel/adapters/mock.rb +2 -0
- data/lib/sequel/adapters/postgres.rb +44 -13
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/mysql.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +94 -55
- data/lib/sequel/adapters/shared/sqlite.rb +3 -1
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/adapters/utils/pg_types.rb +1 -14
- data/lib/sequel/adapters/utils/split_alter_table.rb +3 -3
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +2 -2
- data/lib/sequel/database/features.rb +5 -0
- data/lib/sequel/database/misc.rb +47 -5
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/dataset/actions.rb +4 -2
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +8 -6
- data/lib/sequel/dataset/sql.rb +8 -6
- data/lib/sequel/extensions/constraint_validations.rb +5 -2
- data/lib/sequel/extensions/migration.rb +10 -8
- data/lib/sequel/extensions/pagination.rb +3 -0
- data/lib/sequel/extensions/pg_array.rb +85 -25
- data/lib/sequel/extensions/pg_hstore.rb +8 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +4 -1
- data/lib/sequel/extensions/pg_inet.rb +16 -13
- data/lib/sequel/extensions/pg_interval.rb +6 -2
- data/lib/sequel/extensions/pg_json.rb +18 -11
- data/lib/sequel/extensions/pg_range.rb +17 -2
- data/lib/sequel/extensions/pg_range_ops.rb +7 -5
- data/lib/sequel/extensions/pg_row.rb +29 -12
- data/lib/sequel/extensions/pretty_table.rb +3 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/schema_caching.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +3 -1
- data/lib/sequel/extensions/select_remove.rb +3 -0
- data/lib/sequel/model.rb +8 -2
- data/lib/sequel/model/associations.rb +39 -27
- data/lib/sequel/model/base.rb +99 -38
- data/lib/sequel/model/plugins.rb +25 -0
- data/lib/sequel/plugins/association_autoreloading.rb +27 -22
- data/lib/sequel/plugins/association_dependencies.rb +1 -7
- data/lib/sequel/plugins/auto_validations.rb +110 -0
- data/lib/sequel/plugins/boolean_readers.rb +1 -6
- data/lib/sequel/plugins/caching.rb +6 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +14 -7
- data/lib/sequel/plugins/constraint_validations.rb +2 -13
- data/lib/sequel/plugins/defaults_setter.rb +1 -6
- data/lib/sequel/plugins/dirty.rb +8 -0
- data/lib/sequel/plugins/error_splitter.rb +54 -0
- data/lib/sequel/plugins/force_encoding.rb +1 -5
- data/lib/sequel/plugins/hook_class_methods.rb +1 -6
- data/lib/sequel/plugins/input_transformer.rb +79 -0
- data/lib/sequel/plugins/instance_filters.rb +7 -1
- data/lib/sequel/plugins/instance_hooks.rb +7 -1
- data/lib/sequel/plugins/json_serializer.rb +5 -10
- data/lib/sequel/plugins/lazy_attributes.rb +20 -7
- data/lib/sequel/plugins/list.rb +1 -6
- data/lib/sequel/plugins/many_through_many.rb +1 -2
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +23 -39
- data/lib/sequel/plugins/optimistic_locking.rb +1 -5
- data/lib/sequel/plugins/pg_row.rb +4 -2
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -7
- data/lib/sequel/plugins/prepared_statements.rb +1 -5
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -11
- data/lib/sequel/plugins/rcte_tree.rb +2 -2
- data/lib/sequel/plugins/serialization.rb +11 -13
- data/lib/sequel/plugins/serialization_modification_detection.rb +13 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/static_cache.rb +67 -19
- data/lib/sequel/plugins/string_stripper.rb +7 -27
- data/lib/sequel/plugins/subclasses.rb +3 -5
- data/lib/sequel/plugins/tactical_eager_loading.rb +2 -2
- data/lib/sequel/plugins/timestamps.rb +2 -7
- data/lib/sequel/plugins/touch.rb +5 -8
- data/lib/sequel/plugins/tree.rb +1 -6
- data/lib/sequel/plugins/typecast_on_load.rb +1 -5
- data/lib/sequel/plugins/update_primary_key.rb +26 -14
- data/lib/sequel/plugins/validation_class_methods.rb +31 -16
- data/lib/sequel/plugins/validation_helpers.rb +50 -26
- data/lib/sequel/plugins/xml_serializer.rb +3 -6
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +131 -15
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/core/connection_pool_spec.rb +16 -17
- data/spec/core/database_spec.rb +111 -40
- data/spec/core/dataset_spec.rb +65 -74
- data/spec/core/expression_filters_spec.rb +6 -5
- data/spec/core/object_graph_spec.rb +0 -1
- data/spec/core/schema_spec.rb +23 -23
- data/spec/core/spec_helper.rb +5 -1
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/auto_validations_spec.rb +90 -0
- data/spec/extensions/caching_spec.rb +6 -0
- data/spec/extensions/class_table_inheritance_spec.rb +8 -1
- data/spec/extensions/composition_spec.rb +12 -5
- data/spec/extensions/constraint_validations_spec.rb +4 -4
- data/spec/extensions/core_refinements_spec.rb +29 -79
- data/spec/extensions/dirty_spec.rb +14 -0
- data/spec/extensions/error_splitter_spec.rb +18 -0
- data/spec/extensions/identity_map_spec.rb +0 -1
- data/spec/extensions/input_transformer_spec.rb +54 -0
- data/spec/extensions/instance_filters_spec.rb +6 -0
- data/spec/extensions/instance_hooks_spec.rb +12 -1
- data/spec/extensions/json_serializer_spec.rb +0 -1
- data/spec/extensions/lazy_attributes_spec.rb +64 -55
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +3 -4
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +53 -15
- data/spec/extensions/migration_spec.rb +16 -0
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/pg_array_spec.rb +48 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +10 -2
- data/spec/extensions/pg_hstore_spec.rb +5 -0
- data/spec/extensions/pg_inet_spec.rb +5 -0
- data/spec/extensions/pg_interval_spec.rb +7 -3
- data/spec/extensions/pg_json_spec.rb +6 -1
- data/spec/extensions/pg_range_ops_spec.rb +4 -1
- data/spec/extensions/pg_range_spec.rb +5 -0
- data/spec/extensions/pg_row_plugin_spec.rb +13 -0
- data/spec/extensions/pg_row_spec.rb +28 -19
- data/spec/extensions/pg_typecast_on_load_spec.rb +6 -1
- data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/serialization_modification_detection_spec.rb +8 -0
- data/spec/extensions/serialization_spec.rb +15 -1
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/static_cache_spec.rb +59 -9
- data/spec/extensions/tactical_eager_loading_spec.rb +19 -4
- data/spec/extensions/update_primary_key_spec.rb +17 -1
- data/spec/extensions/validation_class_methods_spec.rb +25 -0
- data/spec/extensions/validation_helpers_spec.rb +59 -3
- data/spec/integration/associations_test.rb +5 -5
- data/spec/integration/eager_loader_test.rb +32 -63
- data/spec/integration/model_test.rb +2 -2
- data/spec/integration/plugin_test.rb +88 -56
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +1 -1
- data/spec/integration/timezone_test.rb +0 -1
- data/spec/integration/transaction_test.rb +0 -1
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +106 -84
- data/spec/model/base_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +8 -8
- data/spec/model/model_spec.rb +27 -9
- data/spec/model/plugins_spec.rb +71 -0
- data/spec/model/record_spec.rb +99 -13
- metadata +12 -2
|
@@ -66,7 +66,7 @@ describe "constraint_validations extension" do
|
|
|
66
66
|
@db.sqls.should == ["DELETE FROM cv WHERE (table = 'foo')"]
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
it "should raise an error without deleting if attempting to drop validations
|
|
69
|
+
it "should raise an error without deleting if attempting to drop validations without table, column, or constraint" do
|
|
70
70
|
proc{@db.drop_constraint_validations_for({})}.should raise_error(Sequel::Error)
|
|
71
71
|
@db.sqls.should == []
|
|
72
72
|
end
|
|
@@ -97,7 +97,7 @@ describe "constraint_validations extension" do
|
|
|
97
97
|
@db.create_table(:foo){String :name; validate{presence :name, :allow_nil=>true}}
|
|
98
98
|
sqls = @db.sqls
|
|
99
99
|
parse_insert(sqls.slice!(1)).should == {:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t'}
|
|
100
|
-
sqls.should == ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK (trim(name) != ''))"]
|
|
100
|
+
sqls.should == ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NULL) OR (trim(name) != '')))"]
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
it "should handle :name option when adding validations" do
|
|
@@ -193,7 +193,7 @@ describe "constraint_validations extension" do
|
|
|
193
193
|
it "should support :format constraint validation" do
|
|
194
194
|
@db = Sequel.mock(:host=>'postgres')
|
|
195
195
|
@db.extension(:constraint_validations)
|
|
196
|
-
@db.create_table(:foo){String :name; validate{format
|
|
196
|
+
@db.create_table(:foo){String :name; validate{format(/^foo.*/, :name)}}
|
|
197
197
|
sqls = @db.sqls
|
|
198
198
|
parse_insert(sqls.slice!(1)).should == {:validation_type=>"format", :column=>"name", :table=>"foo", :argument=>'^foo.*'}
|
|
199
199
|
sqls.should == ["BEGIN", "COMMIT", "CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~ '^foo.*')))"]
|
|
@@ -202,7 +202,7 @@ describe "constraint_validations extension" do
|
|
|
202
202
|
it "should support :format constraint validation with case insensitive format" do
|
|
203
203
|
@db = Sequel.mock(:host=>'postgres')
|
|
204
204
|
@db.extension(:constraint_validations)
|
|
205
|
-
@db.create_table(:foo){String :name; validate{format
|
|
205
|
+
@db.create_table(:foo){String :name; validate{format(/^foo.*/i, :name)}}
|
|
206
206
|
sqls = @db.sqls
|
|
207
207
|
parse_insert(sqls.slice!(1)).should == {:validation_type=>"iformat", :column=>"name", :table=>"foo", :argument=>'^foo.*'}
|
|
208
208
|
sqls.should == ["BEGIN", "COMMIT", "CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~* '^foo.*')))"]
|
|
@@ -16,45 +16,6 @@ describe "Core refinements" do
|
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
if RUBY_VERSION < '1.9.0'
|
|
20
|
-
it "should not allow inequality operations on true, false, or nil" do
|
|
21
|
-
@d.lit(:x > 1).should == "(x > 1)"
|
|
22
|
-
@d.lit(:x < true).should == "(x < 't')"
|
|
23
|
-
@d.lit(:x >= false).should == "(x >= 'f')"
|
|
24
|
-
@d.lit(:x <= nil).should == "(x <= NULL)"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it "should not allow inequality operations on boolean complex expressions" do
|
|
28
|
-
@d.lit(:x > (:y > 5)).should == "(x > (y > 5))"
|
|
29
|
-
@d.lit(:x < (:y < 5)).should == "(x < (y < 5))"
|
|
30
|
-
@d.lit(:x >= (:y >= 5)).should == "(x >= (y >= 5))"
|
|
31
|
-
@d.lit(:x <= (:y <= 5)).should == "(x <= (y <= 5))"
|
|
32
|
-
@d.lit(:x > {:y => nil}).should == "(x > (y IS NULL))"
|
|
33
|
-
@d.lit(:x < ~{:y => nil}).should == "(x < (y IS NOT NULL))"
|
|
34
|
-
@d.lit(:x >= {:y => 5}).should == "(x >= (y = 5))"
|
|
35
|
-
@d.lit(:x <= ~{:y => 5}).should == "(x <= (y != 5))"
|
|
36
|
-
@d.lit(:x >= {:y => [1,2,3]}).should == "(x >= (y IN (1, 2, 3)))"
|
|
37
|
-
@d.lit(:x <= ~{:y => [1,2,3]}).should == "(x <= (y NOT IN (1, 2, 3)))"
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it "should support >, <, >=, and <= via Symbol#>,<,>=,<=" do
|
|
41
|
-
@d.l(:x > 100).should == '(x > 100)'
|
|
42
|
-
@d.l(:x < 100.01).should == '(x < 100.01)'
|
|
43
|
-
@d.l(:x >= 100000000000000000000000000000000000).should == '(x >= 100000000000000000000000000000000000)'
|
|
44
|
-
@d.l(:x <= 100).should == '(x <= 100)'
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "should support negation of >, <, >=, and <= via Symbol#~" do
|
|
48
|
-
@d.l(~(:x > 100)).should == '(x <= 100)'
|
|
49
|
-
@d.l(~(:x < 100.01)).should == '(x >= 100.01)'
|
|
50
|
-
@d.l(~(:x >= 100000000000000000000000000000000000)).should == '(x < 100000000000000000000000000000000000)'
|
|
51
|
-
@d.l(~(:x <= 100)).should == '(x > 100)'
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "should support double negation via ~" do
|
|
55
|
-
@d.l(~~(:x > 100)).should == '(x > 100)'
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
19
|
it "should support NOT via Symbol#~" do
|
|
59
20
|
@d.l(~:x).should == 'NOT x'
|
|
60
21
|
@d.l(~:x__y).should == 'NOT x.y'
|
|
@@ -221,7 +182,7 @@ end
|
|
|
221
182
|
|
|
222
183
|
describe "String#lit" do
|
|
223
184
|
before do
|
|
224
|
-
@ds =
|
|
185
|
+
@ds = Sequel::Database.new[:t]
|
|
225
186
|
end
|
|
226
187
|
|
|
227
188
|
specify "should return an LiteralString object" do
|
|
@@ -274,13 +235,13 @@ describe "#desc" do
|
|
|
274
235
|
end
|
|
275
236
|
|
|
276
237
|
specify "should format a DESC clause for a column ref" do
|
|
277
|
-
:test.desc
|
|
238
|
+
@ds.literal(:test.desc).should == 'test DESC'
|
|
278
239
|
|
|
279
|
-
:items__price.desc
|
|
240
|
+
@ds.literal(:items__price.desc).should == 'items.price DESC'
|
|
280
241
|
end
|
|
281
242
|
|
|
282
243
|
specify "should format a DESC clause for a function" do
|
|
283
|
-
:avg.sql_function(:test).desc
|
|
244
|
+
@ds.literal(:avg.sql_function(:test).desc).should == 'avg(test) DESC'
|
|
284
245
|
end
|
|
285
246
|
end
|
|
286
247
|
|
|
@@ -290,13 +251,13 @@ describe "#asc" do
|
|
|
290
251
|
end
|
|
291
252
|
|
|
292
253
|
specify "should format a ASC clause for a column ref" do
|
|
293
|
-
:test.asc
|
|
254
|
+
@ds.literal(:test.asc).should == 'test ASC'
|
|
294
255
|
|
|
295
|
-
:items__price.asc
|
|
256
|
+
@ds.literal(:items__price.asc).should == 'items.price ASC'
|
|
296
257
|
end
|
|
297
258
|
|
|
298
259
|
specify "should format a ASC clause for a function" do
|
|
299
|
-
:avg.sql_function(:test).asc
|
|
260
|
+
@ds.literal(:avg.sql_function(:test).asc).should == 'avg(test) ASC'
|
|
300
261
|
end
|
|
301
262
|
end
|
|
302
263
|
|
|
@@ -306,17 +267,17 @@ describe "#as" do
|
|
|
306
267
|
end
|
|
307
268
|
|
|
308
269
|
specify "should format a AS clause for a column ref" do
|
|
309
|
-
:test.as(:t)
|
|
270
|
+
@ds.literal(:test.as(:t)).should == 'test AS t'
|
|
310
271
|
|
|
311
|
-
:items__price.as(:p)
|
|
272
|
+
@ds.literal(:items__price.as(:p)).should == 'items.price AS p'
|
|
312
273
|
end
|
|
313
274
|
|
|
314
275
|
specify "should format a AS clause for a function" do
|
|
315
|
-
:avg.sql_function(:test).as(:avg)
|
|
276
|
+
@ds.literal(:avg.sql_function(:test).as(:avg)).should == 'avg(test) AS avg'
|
|
316
277
|
end
|
|
317
278
|
|
|
318
279
|
specify "should format a AS clause for a literal value" do
|
|
319
|
-
'abc'.as(:abc)
|
|
280
|
+
@ds.literal('abc'.as(:abc)).should == "'abc' AS abc"
|
|
320
281
|
end
|
|
321
282
|
end
|
|
322
283
|
|
|
@@ -364,34 +325,23 @@ describe "Blob" do
|
|
|
364
325
|
end
|
|
365
326
|
end
|
|
366
327
|
|
|
367
|
-
if RUBY_VERSION < '1.9.0'
|
|
368
|
-
describe "Symbol#[]" do
|
|
369
|
-
specify "should format an SQL Function" do
|
|
370
|
-
ds = Sequel::Dataset.new(nil)
|
|
371
|
-
ds.literal(:xyz[]).should == 'xyz()'
|
|
372
|
-
ds.literal(:xyz[1]).should == 'xyz(1)'
|
|
373
|
-
ds.literal(:xyz[1, 2, :abc[3]]).should == 'xyz(1, 2, abc(3))'
|
|
374
|
-
end
|
|
375
|
-
end
|
|
376
|
-
end
|
|
377
|
-
|
|
378
328
|
describe "Symbol#*" do
|
|
379
329
|
before do
|
|
380
330
|
@ds = Sequel::Dataset.new(nil)
|
|
381
331
|
end
|
|
382
332
|
|
|
383
333
|
specify "should format a qualified wildcard if no argument" do
|
|
384
|
-
:xyz
|
|
385
|
-
:abc
|
|
334
|
+
@ds.literal(:xyz.*).should == 'xyz.*'
|
|
335
|
+
@ds.literal(:abc.*).should == 'abc.*'
|
|
386
336
|
end
|
|
387
337
|
|
|
388
338
|
specify "should format a filter expression if an argument" do
|
|
389
|
-
:xyz.*(3)
|
|
390
|
-
:abc.*(5)
|
|
339
|
+
@ds.literal(:xyz.*(3)).should == '(xyz * 3)'
|
|
340
|
+
@ds.literal(:abc.*(5)).should == '(abc * 5)'
|
|
391
341
|
end
|
|
392
342
|
|
|
393
343
|
specify "should support qualified symbols if no argument" do
|
|
394
|
-
:xyz__abc
|
|
344
|
+
@ds.literal(:xyz__abc.*).should == 'xyz.abc.*'
|
|
395
345
|
end
|
|
396
346
|
end
|
|
397
347
|
|
|
@@ -445,12 +395,12 @@ describe "Symbol" do
|
|
|
445
395
|
end
|
|
446
396
|
|
|
447
397
|
specify "should support sql_function method" do
|
|
448
|
-
:COUNT.sql_function('1')
|
|
398
|
+
@ds.literal(:COUNT.sql_function('1')).should == "COUNT('1')"
|
|
449
399
|
@ds.select(:COUNT.sql_function('1')).sql.should == "SELECT COUNT('1')"
|
|
450
400
|
end
|
|
451
401
|
|
|
452
402
|
specify "should support cast method" do
|
|
453
|
-
:abc.cast(:integer)
|
|
403
|
+
@ds.literal(:abc.cast(:integer)).should == "CAST(abc AS integer)"
|
|
454
404
|
end
|
|
455
405
|
|
|
456
406
|
specify "should support sql array accesses via sql_subscript" do
|
|
@@ -463,19 +413,19 @@ describe "Symbol" do
|
|
|
463
413
|
specify "should support cast_numeric and cast_string" do
|
|
464
414
|
x = :abc.cast_numeric
|
|
465
415
|
x.should be_a_kind_of(Sequel::SQL::NumericExpression)
|
|
466
|
-
|
|
416
|
+
@ds.literal(x).should == "CAST(abc AS integer)"
|
|
467
417
|
|
|
468
418
|
x = :abc.cast_numeric(:real)
|
|
469
419
|
x.should be_a_kind_of(Sequel::SQL::NumericExpression)
|
|
470
|
-
|
|
420
|
+
@ds.literal(x).should == "CAST(abc AS real)"
|
|
471
421
|
|
|
472
422
|
x = :abc.cast_string
|
|
473
423
|
x.should be_a_kind_of(Sequel::SQL::StringExpression)
|
|
474
|
-
|
|
424
|
+
@ds.literal(x).should == "CAST(abc AS varchar(255))"
|
|
475
425
|
|
|
476
426
|
x = :abc.cast_string(:varchar)
|
|
477
427
|
x.should be_a_kind_of(Sequel::SQL::StringExpression)
|
|
478
|
-
|
|
428
|
+
@ds.literal(x).should == "CAST(abc AS varchar(255))"
|
|
479
429
|
end
|
|
480
430
|
|
|
481
431
|
specify "should allow database independent types when casting" do
|
|
@@ -485,16 +435,16 @@ describe "Symbol" do
|
|
|
485
435
|
return :bar if type == String
|
|
486
436
|
type
|
|
487
437
|
end
|
|
488
|
-
:abc.cast(String)
|
|
489
|
-
:abc.cast(String)
|
|
490
|
-
:abc.cast_string
|
|
491
|
-
:abc.cast_string(Integer)
|
|
492
|
-
:abc.cast_numeric
|
|
493
|
-
:abc.cast_numeric(String)
|
|
438
|
+
@ds.literal(:abc.cast(String)).should == "CAST(abc AS bar)"
|
|
439
|
+
@ds.literal(:abc.cast(String)).should == "CAST(abc AS bar)"
|
|
440
|
+
@ds.literal(:abc.cast_string).should == "CAST(abc AS bar)"
|
|
441
|
+
@ds.literal(:abc.cast_string(Integer)).should == "CAST(abc AS foo)"
|
|
442
|
+
@ds.literal(:abc.cast_numeric).should == "CAST(abc AS foo)"
|
|
443
|
+
@ds.literal(:abc.cast_numeric(String)).should == "CAST(abc AS bar)"
|
|
494
444
|
end
|
|
495
445
|
|
|
496
446
|
specify "should support SQL EXTRACT function via #extract " do
|
|
497
|
-
:abc.extract(:year)
|
|
447
|
+
@ds.literal(:abc.extract(:year)).should == "extract(year FROM abc)"
|
|
498
448
|
end
|
|
499
449
|
end
|
|
500
450
|
|
|
@@ -121,6 +121,12 @@ describe "Sequel::Plugins::Dirty" do
|
|
|
121
121
|
o.column_change(:initial).should == [v, 'a']
|
|
122
122
|
end
|
|
123
123
|
end
|
|
124
|
+
|
|
125
|
+
it "should work when freezing objects" do
|
|
126
|
+
@o.freeze
|
|
127
|
+
@o.initial_value(:initial).should == 'i'
|
|
128
|
+
proc{@o.initial = 'b'}.should raise_error
|
|
129
|
+
end
|
|
124
130
|
end
|
|
125
131
|
|
|
126
132
|
describe "with new instance" do
|
|
@@ -158,5 +164,13 @@ describe "Sequel::Plugins::Dirty" do
|
|
|
158
164
|
@o.save
|
|
159
165
|
@o.previous_changes.should == {:initial_changed=>['ic', 'ic2'], :missing_changed=>[nil, 'mc2']}
|
|
160
166
|
end
|
|
167
|
+
|
|
168
|
+
it "should work when freezing objects after saving" do
|
|
169
|
+
@o.initial = 'a'
|
|
170
|
+
@o.save
|
|
171
|
+
@o.freeze
|
|
172
|
+
@o.previous_changes[:initial].should == ['i', 'a']
|
|
173
|
+
proc{@o.initial = 'b'}.should raise_error
|
|
174
|
+
end
|
|
161
175
|
end
|
|
162
176
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::ErrorSplitter" do
|
|
4
|
+
before do
|
|
5
|
+
@c = Class.new(Sequel::Model)
|
|
6
|
+
@c.plugin :error_splitter
|
|
7
|
+
@m = @c.new
|
|
8
|
+
def @m.validate
|
|
9
|
+
errors.add([:a, :b], 'is bad')
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should split errors for multiple columns and assign them to each column" do
|
|
14
|
+
@m.valid?.should be_false
|
|
15
|
+
@m.errors.should == {:a=>['is bad'], :b=>['is bad']}
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
@@ -183,7 +183,6 @@ describe "Sequel::Plugins::IdentityMap" do
|
|
|
183
183
|
end
|
|
184
184
|
|
|
185
185
|
it "should not use the identity map as a lookup cache for a one_to_one association" do
|
|
186
|
-
c = @c2
|
|
187
186
|
@c2.one_to_one :artist, :class=>@c1, :key=>:artist_id
|
|
188
187
|
@c.with_identity_map do
|
|
189
188
|
MODEL_DB.sqls.length.should == 0
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::InputTransformer" do
|
|
4
|
+
before do
|
|
5
|
+
@c = Class.new(Sequel::Model)
|
|
6
|
+
@c.columns :name, :b
|
|
7
|
+
@c.plugin(:input_transformer, :reverser){|v| v.is_a?(String) ? v.reverse : v}
|
|
8
|
+
@o = @c.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should apply transformation to input" do
|
|
12
|
+
@o.name = ' name '
|
|
13
|
+
@o.name.should == ' eman '
|
|
14
|
+
@o.name = [1, 2, 3]
|
|
15
|
+
@o.name.should == [1, 2, 3]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should not apply any transformers by default" do
|
|
19
|
+
c = Class.new(Sequel::Model)
|
|
20
|
+
c.columns :name, :b
|
|
21
|
+
c.plugin :input_transformer
|
|
22
|
+
c.new(:name => ' name ').name.should == ' name '
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should allow skipping of columns using .skip_input_transformer" do
|
|
26
|
+
@c.skip_input_transformer :reverser, :name
|
|
27
|
+
v = ' name '
|
|
28
|
+
@o.name = v
|
|
29
|
+
@o.name.should equal(v)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should work correctly in subclasses" do
|
|
33
|
+
o = Class.new(@c).new
|
|
34
|
+
o.name = ' name '
|
|
35
|
+
o.name.should == ' eman '
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should raise an error if adding input filter without name" do
|
|
39
|
+
proc{@c.add_input_transformer(nil){}}.should raise_error(Sequel::Error)
|
|
40
|
+
proc{@c.plugin(:input_transformer){}}.should raise_error(Sequel::Error)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should raise an error if adding input filter without block" do
|
|
44
|
+
proc{@c.add_input_transformer(:foo)}.should raise_error(Sequel::Error)
|
|
45
|
+
proc{@c.plugin(:input_transformer, :foo)}.should raise_error(Sequel::Error)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should apply multiple input transformers in reverse order of their call" do
|
|
49
|
+
@c.add_input_transformer(:add_bar){|v| v << 'bar'}
|
|
50
|
+
@c.add_input_transformer(:add_foo){|v| v << 'foo'}
|
|
51
|
+
@o.name = ' name '
|
|
52
|
+
@o.name.should == 'raboof eman '
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -42,4 +42,10 @@ describe "instance_filters plugin" do
|
|
|
42
42
|
@p.update(:name=>'Bob')
|
|
43
43
|
MODEL_DB.sqls.should == ["UPDATE people SET name = 'Bob' WHERE (id = 1)"]
|
|
44
44
|
end
|
|
45
|
+
|
|
46
|
+
specify "shouldn't allow instance filters on frozen objects" do
|
|
47
|
+
@p.instance_filter(:name=>'Joe')
|
|
48
|
+
@p.freeze
|
|
49
|
+
proc{@p.instance_filter(:name=>'Jim')}.should raise_error
|
|
50
|
+
end
|
|
45
51
|
end
|
|
@@ -176,12 +176,23 @@ describe "InstanceHooks plugin" do
|
|
|
176
176
|
@x.save.should_not == nil
|
|
177
177
|
@r.should == [2, 1, 4, 3]
|
|
178
178
|
end
|
|
179
|
+
|
|
180
|
+
it "should not allow addition of instance hooks to frozen instances" do
|
|
181
|
+
@x.after_destroy_hook{r 1}
|
|
182
|
+
@x.before_destroy_hook{r 2}
|
|
183
|
+
@x.before_update_hook{r 3}
|
|
184
|
+
@x.before_save_hook{r 4}
|
|
185
|
+
@x.freeze
|
|
186
|
+
proc{@x.after_destroy_hook{r 1}}.should raise_error(Sequel::Error)
|
|
187
|
+
proc{@x.before_destroy_hook{r 2}}.should raise_error(Sequel::Error)
|
|
188
|
+
proc{@x.before_update_hook{r 3}}.should raise_error(Sequel::Error)
|
|
189
|
+
proc{@x.before_save_hook{r 4}}.should raise_error(Sequel::Error)
|
|
190
|
+
end
|
|
179
191
|
end
|
|
180
192
|
|
|
181
193
|
describe "InstanceHooks plugin with transactions" do
|
|
182
194
|
before do
|
|
183
195
|
@db = Sequel.mock(:numrows=>1)
|
|
184
|
-
pr = proc{|x| r(x)}
|
|
185
196
|
@c = Class.new(Sequel::Model(@db[:items])) do
|
|
186
197
|
attr_accessor :rb
|
|
187
198
|
def after_save
|
|
@@ -182,7 +182,6 @@ describe "Sequel::Plugins::JsonSerializer" do
|
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
it "should have dataset to_json method work with naked datasets" do
|
|
185
|
-
album = @album
|
|
186
185
|
ds = Album.dataset.naked
|
|
187
186
|
ds._fetch = {:id=>1, :name=>'RF', :artist_id=>2}
|
|
188
187
|
Sequel.parse_json(ds.to_json).should == [@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}]
|
|
@@ -68,17 +68,13 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
|
68
68
|
m.name.should == '1'
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
it "should
|
|
72
|
-
@c.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
m.name.should == '1'
|
|
76
|
-
m.values.should == {:id=>1, :name=>'1'}
|
|
77
|
-
@db.sqls.should == ['SELECT id FROM la LIMIT 1', 'SELECT name FROM la WHERE (id = 1) LIMIT 1']
|
|
78
|
-
end
|
|
71
|
+
it "should raise error if the model has no primary key" do
|
|
72
|
+
m = @c.first
|
|
73
|
+
@c.no_primary_key
|
|
74
|
+
proc{m.name}.should raise_error(Sequel::Error)
|
|
79
75
|
end
|
|
80
76
|
|
|
81
|
-
it "should lazily load the attribute for a single model object
|
|
77
|
+
it "should lazily load the attribute for a single model object" do
|
|
82
78
|
m = @c.first
|
|
83
79
|
m.values.should == {:id=>1}
|
|
84
80
|
m.name.should == '1'
|
|
@@ -86,34 +82,47 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
|
86
82
|
@db.sqls.should == ['SELECT id FROM la LIMIT 1', 'SELECT name FROM la WHERE (id = 1) LIMIT 1']
|
|
87
83
|
end
|
|
88
84
|
|
|
85
|
+
it "should lazily load the attribute for a frozen model object" do
|
|
86
|
+
m = @c.first
|
|
87
|
+
m.freeze
|
|
88
|
+
m.name.should == '1'
|
|
89
|
+
@db.sqls.should == ['SELECT id FROM la LIMIT 1', 'SELECT name FROM la WHERE (id = 1) LIMIT 1']
|
|
90
|
+
m.name.should == '1'
|
|
91
|
+
@db.sqls.should == ['SELECT name FROM la WHERE (id = 1) LIMIT 1']
|
|
92
|
+
end
|
|
93
|
+
|
|
89
94
|
it "should not lazily load the attribute for a single model object if the value already exists" do
|
|
90
|
-
@c.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
@db.sqls.should == ['SELECT id FROM la LIMIT 1']
|
|
97
|
-
end
|
|
95
|
+
m = @c.first
|
|
96
|
+
m.values.should == {:id=>1}
|
|
97
|
+
m[:name] = '1'
|
|
98
|
+
m.name.should == '1'
|
|
99
|
+
m.values.should == {:id=>1, :name=>'1'}
|
|
100
|
+
@db.sqls.should == ['SELECT id FROM la LIMIT 1']
|
|
98
101
|
end
|
|
99
102
|
|
|
100
103
|
it "should not lazily load the attribute for a single model object if it is a new record" do
|
|
101
|
-
@c.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
@db.sqls.should == []
|
|
106
|
-
end
|
|
104
|
+
m = @c.new
|
|
105
|
+
m.values.should == {}
|
|
106
|
+
m.name.should == nil
|
|
107
|
+
@db.sqls.should == []
|
|
107
108
|
end
|
|
108
109
|
|
|
109
110
|
it "should eagerly load the attribute for all model objects reteived with it" do
|
|
110
|
-
@c.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
ms = @c.all
|
|
112
|
+
ms.map{|m| m.values}.should == [{:id=>1}, {:id=>2}]
|
|
113
|
+
ms.map{|m| m.name}.should == %w'1 2'
|
|
114
|
+
ms.map{|m| m.values}.should == [{:id=>1, :name=>'1'}, {:id=>2, :name=>'2'}]
|
|
115
|
+
sqls = @db.sqls
|
|
116
|
+
['SELECT id, name FROM la WHERE (id IN (1, 2))',
|
|
117
|
+
'SELECT id, name FROM la WHERE (id IN (2, 1))'].should include(sqls.pop)
|
|
118
|
+
sqls.should == ['SELECT id FROM la']
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "should not eagerly load the attribute if model instance is frozen, and deal with other frozen instances if not frozen" do
|
|
122
|
+
ms = @c.all
|
|
123
|
+
ms.first.freeze
|
|
124
|
+
ms.map{|m| m.name}.should == %w'1 2'
|
|
125
|
+
@db.sqls.should == ['SELECT id FROM la', 'SELECT name FROM la WHERE (id = 1) LIMIT 1', 'SELECT id, name FROM la WHERE (id IN (2))']
|
|
117
126
|
end
|
|
118
127
|
|
|
119
128
|
it "should add the accessors to a module included in the class, so they can be easily overridden" do
|
|
@@ -122,35 +131,35 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
|
122
131
|
"#{super}-blah"
|
|
123
132
|
end
|
|
124
133
|
end
|
|
125
|
-
@c.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
ms = @c.all
|
|
135
|
+
ms.map{|m| m.values}.should == [{:id=>1}, {:id=>2}]
|
|
136
|
+
ms.map{|m| m.name}.should == %w'1-blah 2-blah'
|
|
137
|
+
ms.map{|m| m.values}.should == [{:id=>1, :name=>'1'}, {:id=>2, :name=>'2'}]
|
|
138
|
+
sqls = @db.sqls
|
|
139
|
+
['SELECT id, name FROM la WHERE (id IN (1, 2))',
|
|
140
|
+
'SELECT id, name FROM la WHERE (id IN (2, 1))'].should include(sqls.pop)
|
|
141
|
+
sqls.should == ['SELECT id FROM la']
|
|
132
142
|
end
|
|
133
143
|
|
|
134
144
|
it "should work with the serialization plugin" do
|
|
135
145
|
@c.plugin :serialization, :yaml, :name
|
|
136
146
|
@c.instance_dataset._fetch = @ds._fetch = [[{:id=>1}, {:id=>2}], [{:id=>1, :name=>"--- 3\n"}, {:id=>2, :name=>"--- 6\n"}], [{:id=>1}], [{:name=>"--- 3\n"}]]
|
|
137
|
-
@
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
end
|
|
147
|
+
ms = @ds.all
|
|
148
|
+
ms.map{|m| m.values}.should == [{:id=>1}, {:id=>2}]
|
|
149
|
+
ms.map{|m| m.name}.should == [3,6]
|
|
150
|
+
ms.map{|m| m.values}.should == [{:id=>1, :name=>"--- 3\n"}, {:id=>2, :name=>"--- 6\n"}]
|
|
151
|
+
ms.map{|m| m.deserialized_values}.should == [{:name=>3}, {:name=>6}]
|
|
152
|
+
ms.map{|m| m.name}.should == [3,6]
|
|
153
|
+
sqls = @db.sqls
|
|
154
|
+
['SELECT id, name FROM la WHERE (id IN (1, 2))',
|
|
155
|
+
'SELECT id, name FROM la WHERE (id IN (2, 1))'].should include(sqls.pop)
|
|
156
|
+
sqls.should == ['SELECT id FROM la']
|
|
157
|
+
m = @ds.first
|
|
158
|
+
m.values.should == {:id=>1}
|
|
159
|
+
m.name.should == 3
|
|
160
|
+
m.values.should == {:id=>1, :name=>"--- 3\n"}
|
|
161
|
+
m.deserialized_values.should == {:name=>3}
|
|
162
|
+
m.name.should == 3
|
|
163
|
+
@db.sqls.should == ["SELECT id FROM la LIMIT 1", "SELECT name FROM la WHERE (id = 1) LIMIT 1"]
|
|
155
164
|
end
|
|
156
165
|
end
|