sequel 3.21.0 → 3.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +413 -3
- data/README.rdoc +20 -6
- data/Rakefile +23 -16
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +86 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +115 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +15 -7
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- 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/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +5 -31
- data/lib/sequel/adapters/jdbc/db2.rb +44 -0
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +26 -17
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +107 -38
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +78 -182
- data/lib/sequel/adapters/mysql2.rb +24 -23
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +349 -51
- data/lib/sequel/adapters/postgres.rb +169 -21
- data/lib/sequel/adapters/shared/access.rb +21 -6
- data/lib/sequel/adapters/shared/db2.rb +288 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +108 -65
- data/lib/sequel/adapters/shared/mysql.rb +56 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -34
- data/lib/sequel/adapters/shared/postgres.rb +107 -58
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +168 -41
- data/lib/sequel/adapters/sqlite.rb +27 -18
- data/lib/sequel/adapters/swift/mysql.rb +9 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +152 -17
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +100 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +194 -57
- data/lib/sequel/dataset/features.rb +81 -8
- data/lib/sequel/dataset/graph.rb +8 -7
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +32 -15
- data/lib/sequel/dataset/query.rb +223 -42
- data/lib/sequel/dataset/sql.rb +58 -61
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +997 -331
- data/lib/sequel/model/base.rb +386 -129
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -25
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +44 -35
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +65 -29
- data/spec/adapters/mysql_spec.rb +122 -123
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +213 -61
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +729 -508
- data/spec/core/dataset_spec.rb +980 -1044
- data/spec/core/expression_filters_spec.rb +159 -42
- 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 +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +4 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +522 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +375 -62
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +200 -120
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +174 -7
- data/spec/model/associations_spec.rb +849 -661
- data/spec/model/base_spec.rb +255 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +640 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +207 -167
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +321 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +95 -38
data/spec/core/database_spec.rb
CHANGED
|
@@ -74,46 +74,46 @@ describe "A new Database" do
|
|
|
74
74
|
Sequel.identifier_input_method = nil
|
|
75
75
|
Sequel::Database.identifier_input_method.should == ""
|
|
76
76
|
db = Sequel::Database.new(:identifier_input_method=>nil)
|
|
77
|
-
db.identifier_input_method.should
|
|
77
|
+
db.identifier_input_method.should be_nil
|
|
78
78
|
db.identifier_input_method = :downcase
|
|
79
79
|
db.identifier_input_method.should == :downcase
|
|
80
80
|
db = Sequel::Database.new(:identifier_input_method=>:upcase)
|
|
81
81
|
db.identifier_input_method.should == :upcase
|
|
82
82
|
db.identifier_input_method = nil
|
|
83
|
-
db.identifier_input_method.should
|
|
83
|
+
db.identifier_input_method.should be_nil
|
|
84
84
|
Sequel.identifier_input_method = :downcase
|
|
85
85
|
Sequel::Database.identifier_input_method.should == :downcase
|
|
86
86
|
db = Sequel::Database.new(:identifier_input_method=>nil)
|
|
87
|
-
db.identifier_input_method.should
|
|
87
|
+
db.identifier_input_method.should be_nil
|
|
88
88
|
db.identifier_input_method = :upcase
|
|
89
89
|
db.identifier_input_method.should == :upcase
|
|
90
90
|
db = Sequel::Database.new(:identifier_input_method=>:upcase)
|
|
91
91
|
db.identifier_input_method.should == :upcase
|
|
92
92
|
db.identifier_input_method = nil
|
|
93
|
-
db.identifier_input_method.should
|
|
93
|
+
db.identifier_input_method.should be_nil
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
specify "should respect the :identifier_output_method option" do
|
|
97
97
|
Sequel.identifier_output_method = nil
|
|
98
98
|
Sequel::Database.identifier_output_method.should == ""
|
|
99
99
|
db = Sequel::Database.new(:identifier_output_method=>nil)
|
|
100
|
-
db.identifier_output_method.should
|
|
100
|
+
db.identifier_output_method.should be_nil
|
|
101
101
|
db.identifier_output_method = :downcase
|
|
102
102
|
db.identifier_output_method.should == :downcase
|
|
103
103
|
db = Sequel::Database.new(:identifier_output_method=>:upcase)
|
|
104
104
|
db.identifier_output_method.should == :upcase
|
|
105
105
|
db.identifier_output_method = nil
|
|
106
|
-
db.identifier_output_method.should
|
|
106
|
+
db.identifier_output_method.should be_nil
|
|
107
107
|
Sequel.identifier_output_method = :downcase
|
|
108
108
|
Sequel::Database.identifier_output_method.should == :downcase
|
|
109
109
|
db = Sequel::Database.new(:identifier_output_method=>nil)
|
|
110
|
-
db.identifier_output_method.should
|
|
110
|
+
db.identifier_output_method.should be_nil
|
|
111
111
|
db.identifier_output_method = :upcase
|
|
112
112
|
db.identifier_output_method.should == :upcase
|
|
113
113
|
db = Sequel::Database.new(:identifier_output_method=>:upcase)
|
|
114
114
|
db.identifier_output_method.should == :upcase
|
|
115
115
|
db.identifier_output_method = nil
|
|
116
|
-
db.identifier_output_method.should
|
|
116
|
+
db.identifier_output_method.should be_nil
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
specify "should use the default Sequel.quote_identifiers value" do
|
|
@@ -384,339 +384,201 @@ describe "Database#dataset" do
|
|
|
384
384
|
end
|
|
385
385
|
end
|
|
386
386
|
|
|
387
|
-
describe "Database#
|
|
388
|
-
specify "should raise Sequel::NotImplemented" do
|
|
389
|
-
proc {Sequel::Database.new.execute('blah blah')}.should raise_error(Sequel::NotImplemented)
|
|
390
|
-
proc {Sequel::Database.new << 'blah blah'}.should raise_error(Sequel::NotImplemented)
|
|
391
|
-
end
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
describe "Database#tables" do
|
|
395
|
-
specify "should raise Sequel::NotImplemented" do
|
|
396
|
-
proc {Sequel::Database.new.tables}.should raise_error(Sequel::NotImplemented)
|
|
397
|
-
end
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
describe "Database#indexes" do
|
|
401
|
-
specify "should raise Sequel::NotImplemented" do
|
|
402
|
-
proc {Sequel::Database.new.indexes(:table)}.should raise_error(Sequel::NotImplemented)
|
|
403
|
-
end
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
describe "Database#<< and run" do
|
|
387
|
+
describe "Database#dataset_class" do
|
|
407
388
|
before do
|
|
408
|
-
|
|
409
|
-
@
|
|
410
|
-
define_method(:execute_ddl){|sql, *opts| sqls.clear; sqls << sql; sqls.concat(opts)}
|
|
411
|
-
end
|
|
412
|
-
@db = @c.new({})
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
specify "should pass the supplied sql to #execute_ddl" do
|
|
416
|
-
(@db << "DELETE FROM items")
|
|
417
|
-
@sqls.should == ["DELETE FROM items", {}]
|
|
418
|
-
@db.run("DELETE FROM items2")
|
|
419
|
-
@sqls.should == ["DELETE FROM items2", {}]
|
|
420
|
-
end
|
|
421
|
-
|
|
422
|
-
specify "should return nil" do
|
|
423
|
-
(@db << "DELETE FROM items").should == nil
|
|
424
|
-
@db.run("DELETE FROM items").should == nil
|
|
389
|
+
@db = Sequel::Database.new
|
|
390
|
+
@dsc = Class.new(Sequel::Dataset)
|
|
425
391
|
end
|
|
426
392
|
|
|
427
|
-
specify "should
|
|
428
|
-
@db.
|
|
429
|
-
@
|
|
393
|
+
specify "should have setter set the class to use to create datasets" do
|
|
394
|
+
@db.dataset_class = @dsc
|
|
395
|
+
ds = @db.dataset
|
|
396
|
+
ds.should be_a_kind_of(@dsc)
|
|
397
|
+
ds.opts.should == {}
|
|
398
|
+
ds.db.should be(@db)
|
|
430
399
|
end
|
|
431
|
-
end
|
|
432
400
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
@db =
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
specify "should wrap the supplied block in pool.hold" do
|
|
439
|
-
stop = false
|
|
440
|
-
c1, c2 = nil
|
|
441
|
-
t1 = Thread.new {@db.synchronize {|c| c1 = c; while !stop;sleep 0.1;end}}
|
|
442
|
-
while !c1;end
|
|
443
|
-
c1.should == 12345
|
|
444
|
-
t2 = Thread.new {@db.synchronize {|c| c2 = c}}
|
|
445
|
-
sleep 0.2
|
|
446
|
-
@db.pool.available_connections.should be_empty
|
|
447
|
-
c2.should be_nil
|
|
448
|
-
stop = true
|
|
449
|
-
t1.join
|
|
450
|
-
sleep 0.1
|
|
451
|
-
c2.should == 12345
|
|
452
|
-
t2.join
|
|
401
|
+
specify "should have getter return the class to use to create datasets" do
|
|
402
|
+
@db.dataset_class.should == Sequel::Dataset
|
|
403
|
+
@db.dataset_class = @dsc
|
|
404
|
+
@db.dataset_class.should == @dsc
|
|
453
405
|
end
|
|
454
406
|
end
|
|
455
|
-
|
|
456
|
-
describe "Database#
|
|
407
|
+
|
|
408
|
+
describe "Database#extend_datasets" do
|
|
457
409
|
before do
|
|
458
|
-
@db = Sequel::Database.new
|
|
410
|
+
@db = Sequel::Database.new
|
|
411
|
+
@m = Module.new{def foo() [3] end}
|
|
412
|
+
@m2 = Module.new{def foo() [4] + super end}
|
|
413
|
+
@db.extend_datasets(@m)
|
|
459
414
|
end
|
|
460
415
|
|
|
461
|
-
specify "should
|
|
462
|
-
@db.
|
|
463
|
-
@test.should_not be_nil
|
|
416
|
+
specify "should change the dataset class to a subclass the first time it is called" do
|
|
417
|
+
@db.dataset_class.superclass.should == Sequel::Dataset
|
|
464
418
|
end
|
|
465
|
-
|
|
466
|
-
specify "should
|
|
467
|
-
@db.
|
|
419
|
+
|
|
420
|
+
specify "should not create a subclass of the dataset class if called more than once" do
|
|
421
|
+
@db.extend_datasets(@m2)
|
|
422
|
+
@db.dataset_class.superclass.should == Sequel::Dataset
|
|
468
423
|
end
|
|
469
424
|
|
|
470
|
-
specify "should
|
|
471
|
-
|
|
425
|
+
specify "should make the dataset class include the module" do
|
|
426
|
+
@db.dataset_class.ancestors.should include(@m)
|
|
427
|
+
@db.dataset_class.ancestors.should_not include(@m2)
|
|
428
|
+
@db.extend_datasets(@m2)
|
|
429
|
+
@db.dataset_class.ancestors.should include(@m)
|
|
430
|
+
@db.dataset_class.ancestors.should include(@m2)
|
|
472
431
|
end
|
|
473
|
-
end
|
|
474
432
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
433
|
+
specify "should have datasets respond to the module's methods" do
|
|
434
|
+
@db.dataset.foo.should == [3]
|
|
435
|
+
@db.extend_datasets(@m2)
|
|
436
|
+
@db.dataset.foo.should == [4, 3]
|
|
479
437
|
end
|
|
480
|
-
end
|
|
481
438
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
@sqls ||= []
|
|
487
|
-
@sqls << sql
|
|
439
|
+
specify "should take a block and create a module from it to use" do
|
|
440
|
+
@db.dataset.foo.should == [3]
|
|
441
|
+
@db.extend_datasets{def foo() [5] + super end}
|
|
442
|
+
@db.dataset.foo.should == [5, 3]
|
|
488
443
|
end
|
|
489
|
-
|
|
490
|
-
def transaction; yield; end
|
|
491
444
|
|
|
492
|
-
|
|
493
|
-
|
|
445
|
+
specify "should raise an error if both a module and a block are provided" do
|
|
446
|
+
proc{@db.extend_datasets(@m2){def foo() [5] + super end}}.should raise_error(Sequel::Error)
|
|
494
447
|
end
|
|
495
|
-
end
|
|
496
448
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
@db
|
|
449
|
+
specify "should be able to override methods defined in the original Dataset class" do
|
|
450
|
+
@db.extend_datasets(Module.new{def select(*a, &block) super.order(*a, &block) end})
|
|
451
|
+
@db[:t].select(:a, :b).sql.should == 'SELECT a, b FROM t ORDER BY a, b'
|
|
500
452
|
end
|
|
501
|
-
|
|
502
|
-
specify "should
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
@db.sqls.should == [
|
|
509
|
-
'CREATE TABLE test (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
|
|
510
|
-
'CREATE UNIQUE INDEX test_name_index ON test (name)'
|
|
511
|
-
]
|
|
453
|
+
|
|
454
|
+
specify "should reapply settings if dataset_class is chagned" do
|
|
455
|
+
c = Class.new(Sequel::Dataset)
|
|
456
|
+
@db.dataset_class = c
|
|
457
|
+
@db.dataset_class.superclass.should == c
|
|
458
|
+
@db.dataset_class.ancestors.should include(@m)
|
|
459
|
+
@db.dataset.foo.should == [3]
|
|
512
460
|
end
|
|
461
|
+
end
|
|
513
462
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
column :name, :text
|
|
518
|
-
index :name, :unique => true
|
|
519
|
-
end
|
|
520
|
-
|
|
521
|
-
@db.sqls.should == [
|
|
522
|
-
'CREATE TEMPORARY TABLE test_tmp (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
|
|
523
|
-
'CREATE UNIQUE INDEX test_tmp_name_index ON test_tmp (name)'
|
|
524
|
-
]
|
|
463
|
+
describe "Database#execute" do
|
|
464
|
+
specify "should raise Sequel::NotImplemented" do
|
|
465
|
+
proc {Sequel::Database.new.execute('blah blah')}.should raise_error(Sequel::NotImplemented)
|
|
525
466
|
end
|
|
526
467
|
end
|
|
527
468
|
|
|
528
|
-
describe "Database#
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
end
|
|
532
|
-
|
|
533
|
-
specify "should construct proper SQL" do
|
|
534
|
-
@db.alter_table :xyz do
|
|
535
|
-
add_column :aaa, :text, :null => false, :unique => true
|
|
536
|
-
drop_column :bbb
|
|
537
|
-
rename_column :ccc, :ddd
|
|
538
|
-
set_column_type :eee, :integer
|
|
539
|
-
set_column_default :hhh, 'abcd'
|
|
540
|
-
|
|
541
|
-
add_index :fff, :unique => true
|
|
542
|
-
drop_index :ggg
|
|
543
|
-
end
|
|
544
|
-
|
|
545
|
-
@db.sqls.should == [
|
|
546
|
-
'ALTER TABLE xyz ADD COLUMN aaa text NOT NULL UNIQUE',
|
|
547
|
-
'ALTER TABLE xyz DROP COLUMN bbb',
|
|
548
|
-
'ALTER TABLE xyz RENAME COLUMN ccc TO ddd',
|
|
549
|
-
'ALTER TABLE xyz ALTER COLUMN eee TYPE integer',
|
|
550
|
-
"ALTER TABLE xyz ALTER COLUMN hhh SET DEFAULT 'abcd'",
|
|
551
|
-
|
|
552
|
-
'CREATE UNIQUE INDEX xyz_fff_index ON xyz (fff)',
|
|
553
|
-
'DROP INDEX xyz_ggg_index'
|
|
554
|
-
]
|
|
469
|
+
describe "Database#tables" do
|
|
470
|
+
specify "should raise Sequel::NotImplemented" do
|
|
471
|
+
proc {Sequel::Database.new.tables}.should raise_error(Sequel::NotImplemented)
|
|
555
472
|
end
|
|
556
473
|
end
|
|
557
474
|
|
|
558
|
-
describe "Database#
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
end
|
|
562
|
-
|
|
563
|
-
specify "should construct proper SQL" do
|
|
564
|
-
@db.add_column :test, :name, :text, :unique => true
|
|
565
|
-
@db.sqls.should == [
|
|
566
|
-
'ALTER TABLE test ADD COLUMN name text UNIQUE'
|
|
567
|
-
]
|
|
475
|
+
describe "Database#views" do
|
|
476
|
+
specify "should raise Sequel::NotImplemented" do
|
|
477
|
+
proc {Sequel::Database.new.views}.should raise_error(Sequel::NotImplemented)
|
|
568
478
|
end
|
|
569
479
|
end
|
|
570
480
|
|
|
571
|
-
describe "Database#
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
end
|
|
575
|
-
|
|
576
|
-
specify "should construct proper SQL" do
|
|
577
|
-
@db.drop_column :test, :name
|
|
578
|
-
@db.sqls.should == [
|
|
579
|
-
'ALTER TABLE test DROP COLUMN name'
|
|
580
|
-
]
|
|
481
|
+
describe "Database#indexes" do
|
|
482
|
+
specify "should raise Sequel::NotImplemented" do
|
|
483
|
+
proc {Sequel::Database.new.indexes(:table)}.should raise_error(Sequel::NotImplemented)
|
|
581
484
|
end
|
|
582
485
|
end
|
|
583
486
|
|
|
584
|
-
describe "Database#
|
|
487
|
+
describe "Database#run" do
|
|
585
488
|
before do
|
|
586
|
-
@db =
|
|
489
|
+
@db = Sequel.mock(:servers=>{:s1=>{}})
|
|
587
490
|
end
|
|
588
491
|
|
|
589
|
-
specify "should
|
|
590
|
-
@db.
|
|
591
|
-
@db.sqls.should == [
|
|
592
|
-
'ALTER TABLE test RENAME COLUMN abc TO def'
|
|
593
|
-
]
|
|
594
|
-
end
|
|
595
|
-
end
|
|
596
|
-
|
|
597
|
-
describe "Database#set_column_type" do
|
|
598
|
-
before do
|
|
599
|
-
@db = DummyDatabase.new
|
|
492
|
+
specify "should execute the code on the database" do
|
|
493
|
+
@db.run("DELETE FROM items")
|
|
494
|
+
@db.sqls.should == ["DELETE FROM items"]
|
|
600
495
|
end
|
|
601
496
|
|
|
602
|
-
specify "should
|
|
603
|
-
@db.
|
|
604
|
-
@db.sqls.should == [
|
|
605
|
-
'ALTER TABLE test ALTER COLUMN name TYPE integer'
|
|
606
|
-
]
|
|
607
|
-
end
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
describe "Database#set_column_default" do
|
|
611
|
-
before do
|
|
612
|
-
@db = DummyDatabase.new
|
|
497
|
+
specify "should return nil" do
|
|
498
|
+
@db.run("DELETE FROM items").should be_nil
|
|
613
499
|
end
|
|
614
500
|
|
|
615
|
-
specify "should
|
|
616
|
-
@db.
|
|
617
|
-
@db.sqls.should == [
|
|
618
|
-
"ALTER TABLE test ALTER COLUMN name SET DEFAULT 'zyx'"
|
|
619
|
-
]
|
|
501
|
+
specify "should accept options passed to execute_ddl" do
|
|
502
|
+
@db.run("DELETE FROM items", :server=>:s1)
|
|
503
|
+
@db.sqls.should == ["DELETE FROM items -- s1"]
|
|
620
504
|
end
|
|
621
505
|
end
|
|
622
506
|
|
|
623
|
-
describe "Database
|
|
507
|
+
describe "Database#<<" do
|
|
624
508
|
before do
|
|
625
|
-
@db =
|
|
509
|
+
@db = Sequel.mock
|
|
626
510
|
end
|
|
627
|
-
|
|
628
|
-
specify "should
|
|
629
|
-
@db
|
|
630
|
-
@db.sqls.should == [
|
|
631
|
-
'CREATE UNIQUE INDEX test_name_index ON test (name)'
|
|
632
|
-
]
|
|
511
|
+
|
|
512
|
+
specify "should execute the code on the database" do
|
|
513
|
+
@db << "DELETE FROM items"
|
|
514
|
+
@db.sqls.should == ["DELETE FROM items"]
|
|
633
515
|
end
|
|
634
516
|
|
|
635
|
-
specify "should
|
|
636
|
-
@db
|
|
637
|
-
@db.sqls.should == [
|
|
638
|
-
'CREATE INDEX test_one_two_index ON test (one, two)'
|
|
639
|
-
]
|
|
517
|
+
specify "should be chainable" do
|
|
518
|
+
@db << "DELETE FROM items" << "DELETE FROM items2"
|
|
519
|
+
@db.sqls.should == ["DELETE FROM items", "DELETE FROM items2"]
|
|
640
520
|
end
|
|
641
521
|
end
|
|
642
522
|
|
|
643
|
-
describe "Database#
|
|
523
|
+
describe "Database#synchronize" do
|
|
644
524
|
before do
|
|
645
|
-
@db =
|
|
525
|
+
@db = Sequel::Database.new(:max_connections => 1){12345}
|
|
646
526
|
end
|
|
647
527
|
|
|
648
|
-
specify "should
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
528
|
+
specify "should wrap the supplied block in pool.hold" do
|
|
529
|
+
q, q1, q2, q3 = Queue.new, Queue.new, Queue.new, Queue.new
|
|
530
|
+
c1, c2 = nil
|
|
531
|
+
t1 = Thread.new{@db.synchronize{|c| c1 = c; q.push nil; q1.pop}; q.push nil}
|
|
532
|
+
q.pop
|
|
533
|
+
c1.should == 12345
|
|
534
|
+
t2 = Thread.new{@db.synchronize{|c| c2 = c; q2.push nil}}
|
|
535
|
+
@db.pool.available_connections.should be_empty
|
|
536
|
+
c2.should be_nil
|
|
537
|
+
q1.push nil
|
|
538
|
+
q.pop
|
|
539
|
+
q2.pop
|
|
540
|
+
c2.should == 12345
|
|
541
|
+
t1.join
|
|
542
|
+
t2.join
|
|
653
543
|
end
|
|
654
|
-
|
|
655
|
-
end
|
|
656
|
-
|
|
657
|
-
class Dummy2Database < Sequel::Database
|
|
658
|
-
attr_reader :sql
|
|
659
|
-
def execute(sql); @sql = sql; end
|
|
660
|
-
def transaction; yield; end
|
|
661
544
|
end
|
|
662
545
|
|
|
663
|
-
describe "Database#
|
|
546
|
+
describe "Database#test_connection" do
|
|
664
547
|
before do
|
|
665
|
-
@db =
|
|
548
|
+
@db = Sequel::Database.new{@test = rand(100)}
|
|
666
549
|
end
|
|
667
550
|
|
|
668
|
-
specify "should
|
|
669
|
-
@db.
|
|
670
|
-
@
|
|
551
|
+
specify "should attempt to get a connection" do
|
|
552
|
+
@db.test_connection
|
|
553
|
+
@test.should_not be_nil
|
|
671
554
|
end
|
|
672
555
|
|
|
673
|
-
specify "should
|
|
674
|
-
@db.
|
|
675
|
-
@db.sqls.should == [
|
|
676
|
-
'DROP TABLE a',
|
|
677
|
-
'DROP TABLE bb',
|
|
678
|
-
'DROP TABLE ccc'
|
|
679
|
-
]
|
|
556
|
+
specify "should return true if successful" do
|
|
557
|
+
@db.test_connection.should be_true
|
|
680
558
|
end
|
|
681
|
-
end
|
|
682
559
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
@db = DummyDatabase.new
|
|
686
|
-
end
|
|
687
|
-
|
|
688
|
-
specify "should construct proper SQL" do
|
|
689
|
-
@db.rename_table :abc, :xyz
|
|
690
|
-
@db.sqls.should == ['ALTER TABLE abc RENAME TO xyz']
|
|
560
|
+
specify "should raise an error if the attempting to connect raises an error" do
|
|
561
|
+
proc{Sequel::Database.new{raise Sequel::Error, 'blah'}.test_connection}.should raise_error(Sequel::Error)
|
|
691
562
|
end
|
|
692
563
|
end
|
|
693
564
|
|
|
694
565
|
describe "Database#table_exists?" do
|
|
695
566
|
specify "should try to select the first record from the table's dataset" do
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
end
|
|
701
|
-
|
|
702
|
-
class Dummy3Database < Sequel::Database
|
|
703
|
-
attr_reader :sql, :transactions
|
|
704
|
-
def execute(sql, opts={}); @sql ||= []; @sql << sql; end
|
|
705
|
-
|
|
706
|
-
class DummyConnection
|
|
707
|
-
def initialize(db); @db = db; end
|
|
708
|
-
def execute(sql); @db.execute(sql); end
|
|
567
|
+
db = Sequel.mock(:fetch=>[Sequel::Error, [], [{:a=>1}]])
|
|
568
|
+
db.table_exists?(:a).should be_false
|
|
569
|
+
db.table_exists?(:b).should be_true
|
|
570
|
+
db.table_exists?(:c).should be_true
|
|
709
571
|
end
|
|
710
572
|
end
|
|
711
573
|
|
|
712
574
|
describe "Database#transaction" do
|
|
713
575
|
before do
|
|
714
|
-
@db =
|
|
576
|
+
@db = Sequel.mock(:servers=>{:test=>{}})
|
|
715
577
|
end
|
|
716
578
|
|
|
717
579
|
specify "should wrap the supplied block with BEGIN + COMMIT statements" do
|
|
718
580
|
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
719
|
-
@db.
|
|
581
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
720
582
|
end
|
|
721
583
|
|
|
722
584
|
specify "should support transaction isolation levels" do
|
|
@@ -724,7 +586,7 @@ describe "Database#transaction" do
|
|
|
724
586
|
[:uncommitted, :committed, :repeatable, :serializable].each do |l|
|
|
725
587
|
@db.transaction(:isolation=>l){@db.run "DROP TABLE #{l}"}
|
|
726
588
|
end
|
|
727
|
-
@db.
|
|
589
|
+
@db.sqls.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
728
590
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
729
591
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
730
592
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
@@ -736,7 +598,7 @@ describe "Database#transaction" do
|
|
|
736
598
|
@db.transaction_isolation_level = l
|
|
737
599
|
@db.transaction{@db.run "DROP TABLE #{l}"}
|
|
738
600
|
end
|
|
739
|
-
@db.
|
|
601
|
+
@db.sqls.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
740
602
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
741
603
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
742
604
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
@@ -751,12 +613,12 @@ describe "Database#transaction" do
|
|
|
751
613
|
end
|
|
752
614
|
end
|
|
753
615
|
@db.ret_commit
|
|
754
|
-
@db.
|
|
616
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
755
617
|
end
|
|
756
618
|
|
|
757
619
|
specify "should issue ROLLBACK if an exception is raised, and re-raise" do
|
|
758
620
|
@db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
|
|
759
|
-
@db.
|
|
621
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
760
622
|
|
|
761
623
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
762
624
|
end
|
|
@@ -768,7 +630,50 @@ describe "Database#transaction" do
|
|
|
768
630
|
@db.drop_table(:b)
|
|
769
631
|
end
|
|
770
632
|
|
|
771
|
-
@db.
|
|
633
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
specify "should have in_transaction? return true if inside a transaction" do
|
|
637
|
+
c = nil
|
|
638
|
+
@db.transaction{c = @db.in_transaction?}
|
|
639
|
+
c.should be_true
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
specify "should have in_transaction? handle sharding correctly" do
|
|
643
|
+
c = []
|
|
644
|
+
@db.transaction(:server=>:test){c << @db.in_transaction?}
|
|
645
|
+
@db.transaction(:server=>:test){c << @db.in_transaction?(:server=>:test)}
|
|
646
|
+
c.should == [false, true]
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
specify "should have in_transaction? return false if not in a transaction" do
|
|
650
|
+
@db.in_transaction?.should be_false
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
specify "should return nil if Sequel::Rollback is called in the transaction" do
|
|
654
|
+
@db.transaction{raise Sequel::Rollback}.should be_nil
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
specify "should reraise Sequel::Rollback errors when using :rollback=>:reraise option is given" do
|
|
658
|
+
proc {@db.transaction(:rollback=>:reraise){raise Sequel::Rollback}}.should raise_error(Sequel::Rollback)
|
|
659
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
660
|
+
proc {@db.transaction(:rollback=>:reraise){raise ArgumentError}}.should raise_error(ArgumentError)
|
|
661
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
662
|
+
@db.transaction(:rollback=>:reraise){1}.should == 1
|
|
663
|
+
@db.sqls.should == ['BEGIN', 'COMMIT']
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
specify "should always rollback if :rollback=>:always option is given" do
|
|
667
|
+
proc {@db.transaction(:rollback=>:always){raise ArgumentError}}.should raise_error(ArgumentError)
|
|
668
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
669
|
+
@db.transaction(:rollback=>:always){raise Sequel::Rollback}.should be_nil
|
|
670
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
671
|
+
@db.transaction(:rollback=>:always){1}.should be_nil
|
|
672
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
673
|
+
catch (:foo) do
|
|
674
|
+
@db.transaction(:rollback=>:always){throw :foo}
|
|
675
|
+
end
|
|
676
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
772
677
|
end
|
|
773
678
|
|
|
774
679
|
specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
|
|
@@ -780,47 +685,218 @@ describe "Database#transaction" do
|
|
|
780
685
|
end
|
|
781
686
|
|
|
782
687
|
specify "should be re-entrant" do
|
|
783
|
-
|
|
688
|
+
q, q1 = Queue.new, Queue.new
|
|
784
689
|
cc = nil
|
|
785
690
|
t = Thread.new do
|
|
786
691
|
@db.transaction {@db.transaction {@db.transaction {|c|
|
|
787
692
|
cc = c
|
|
788
|
-
|
|
693
|
+
q.pop
|
|
694
|
+
q1.push nil
|
|
695
|
+
q.pop
|
|
789
696
|
}}}
|
|
790
697
|
end
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
698
|
+
q.push nil
|
|
699
|
+
q1.pop
|
|
700
|
+
cc.should be_a_kind_of(Sequel::Mock::Connection)
|
|
701
|
+
tr = @db.instance_variable_get(:@transactions)
|
|
702
|
+
tr.should == {cc=>{:savepoint_level=>1}}
|
|
703
|
+
q.push nil
|
|
795
704
|
t.join
|
|
796
|
-
|
|
705
|
+
tr.should be_empty
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
specify "should correctly handle nested transacation use with separate shards" do
|
|
709
|
+
@db.transaction do |c1|
|
|
710
|
+
@db.transaction(:server=>:test) do |c2|
|
|
711
|
+
c1.should_not == c2
|
|
712
|
+
@db.execute 'DROP TABLE test;'
|
|
713
|
+
end
|
|
714
|
+
end
|
|
715
|
+
@db.sqls.should == ['BEGIN', 'BEGIN -- test', 'DROP TABLE test;', 'COMMIT -- test', 'COMMIT']
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
if (!defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or RUBY_ENGINE == 'rbx') and RUBY_VERSION < '1.9'
|
|
719
|
+
specify "should handle Thread#kill for transactions inside threads" do
|
|
720
|
+
q = Queue.new
|
|
721
|
+
q1 = Queue.new
|
|
722
|
+
t = Thread.new do
|
|
723
|
+
@db.transaction do
|
|
724
|
+
@db.execute 'DROP TABLE test'
|
|
725
|
+
q1.push nil
|
|
726
|
+
q.pop
|
|
727
|
+
@db.execute 'DROP TABLE test2'
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
q1.pop
|
|
731
|
+
t.kill
|
|
732
|
+
t.join
|
|
733
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
specify "should raise an Error if after_commit or after_rollback is called without a block" do
|
|
738
|
+
proc{@db.after_commit}.should raise_error(Sequel::Error)
|
|
739
|
+
proc{@db.after_rollback}.should raise_error(Sequel::Error)
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
specify "should execute after_commit outside transactions" do
|
|
743
|
+
@db.after_commit{@db.execute('foo')}
|
|
744
|
+
@db.sqls.should == ['foo']
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
specify "should ignore after_rollback outside transactions" do
|
|
748
|
+
@db.after_rollback{@db.execute('foo')}
|
|
749
|
+
@db.sqls.should == []
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
specify "should support after_commit inside transactions" do
|
|
753
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}}
|
|
754
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo']
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
specify "should support after_rollback inside transactions" do
|
|
758
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}}
|
|
759
|
+
@db.sqls.should == ['BEGIN', 'COMMIT']
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
specify "should not call after_commit if the transaction rolls back" do
|
|
763
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}; raise Sequel::Rollback}
|
|
764
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
specify "should call after_rollback if the transaction rolls back" do
|
|
768
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}; raise Sequel::Rollback}
|
|
769
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo']
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
specify "should call multiple after_commit blocks in order if called inside transactions" do
|
|
773
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}; @db.after_commit{@db.execute('bar')}}
|
|
774
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo', 'bar']
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
specify "should call multiple after_rollback blocks in order if called inside transactions" do
|
|
778
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}; @db.after_rollback{@db.execute('bar')}; raise Sequel::Rollback}
|
|
779
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo', 'bar']
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
specify "should support after_commit inside nested transactions" do
|
|
783
|
+
@db.transaction{@db.transaction{@db.after_commit{@db.execute('foo')}}}
|
|
784
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo']
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
specify "should support after_rollback inside nested transactions" do
|
|
788
|
+
@db.transaction{@db.transaction{@db.after_rollback{@db.execute('foo')}}; raise Sequel::Rollback}
|
|
789
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo']
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
specify "should support after_commit inside savepoints" do
|
|
793
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
794
|
+
@db.transaction do
|
|
795
|
+
@db.after_commit{@db.execute('foo')}
|
|
796
|
+
@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('bar')}}
|
|
797
|
+
@db.after_commit{@db.execute('baz')}
|
|
798
|
+
end
|
|
799
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT', 'foo', 'bar', 'baz']
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
specify "should support after_rollback inside savepoints" do
|
|
803
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
804
|
+
@db.transaction do
|
|
805
|
+
@db.after_rollback{@db.execute('foo')}
|
|
806
|
+
@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('bar')}}
|
|
807
|
+
@db.after_rollback{@db.execute('baz')}
|
|
808
|
+
raise Sequel::Rollback
|
|
809
|
+
end
|
|
810
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'ROLLBACK', 'foo', 'bar', 'baz']
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
specify "should raise an error if you attempt to use after_commit inside a prepared transaction" do
|
|
814
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
815
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{@db.execute('foo')}}}.should raise_error(Sequel::Error)
|
|
816
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
specify "should raise an error if you attempt to use after_rollback inside a prepared transaction" do
|
|
820
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
821
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{@db.execute('foo')}}}.should raise_error(Sequel::Error)
|
|
822
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
specify "should raise an error if you attempt to use after_commit inside a savepoint in a prepared transaction" do
|
|
826
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
827
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
828
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
|
829
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
830
|
+
end
|
|
831
|
+
|
|
832
|
+
specify "should raise an error if you attempt to use after_rollback inside a savepoint in a prepared transaction" do
|
|
833
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
834
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
835
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
|
836
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
797
837
|
end
|
|
798
838
|
end
|
|
799
839
|
|
|
840
|
+
describe "Sequel.transaction" do
|
|
841
|
+
before do
|
|
842
|
+
@sqls = []
|
|
843
|
+
@db1 = Sequel.mock(:append=>'1', :sqls=>@sqls)
|
|
844
|
+
@db2 = Sequel.mock(:append=>'2', :sqls=>@sqls)
|
|
845
|
+
@db3 = Sequel.mock(:append=>'3', :sqls=>@sqls)
|
|
846
|
+
end
|
|
847
|
+
|
|
848
|
+
specify "should run the block inside transacitons on all three databases" do
|
|
849
|
+
Sequel.transaction([@db1, @db2, @db3]){1}.should == 1
|
|
850
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
specify "should pass options to all the blocks" do
|
|
854
|
+
Sequel.transaction([@db1, @db2, @db3], :rollback=>:always){1}.should be_nil
|
|
855
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
specify "should handle Sequel::Rollback exceptions raised by the block to rollback on all databases" do
|
|
859
|
+
Sequel.transaction([@db1, @db2, @db3]){raise Sequel::Rollback}.should be_nil
|
|
860
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
specify "should handle nested transactions" do
|
|
864
|
+
Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3]){1}}.should == 1
|
|
865
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
specify "should handle savepoints" do
|
|
869
|
+
Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3], :savepoint=>true){1}}.should == 1
|
|
870
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3',
|
|
871
|
+
'SAVEPOINT autopoint_1 -- 1', 'SAVEPOINT autopoint_1 -- 2', 'SAVEPOINT autopoint_1 -- 3',
|
|
872
|
+
'RELEASE SAVEPOINT autopoint_1 -- 3', 'RELEASE SAVEPOINT autopoint_1 -- 2', 'RELEASE SAVEPOINT autopoint_1 -- 1',
|
|
873
|
+
'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
874
|
+
end
|
|
875
|
+
end
|
|
876
|
+
|
|
800
877
|
describe "Database#transaction with savepoints" do
|
|
801
878
|
before do
|
|
802
|
-
@db =
|
|
803
|
-
@db.meta_def(:supports_savepoints?){true}
|
|
879
|
+
@db = Sequel.mock
|
|
804
880
|
end
|
|
805
881
|
|
|
806
882
|
specify "should wrap the supplied block with BEGIN + COMMIT statements" do
|
|
807
883
|
@db.transaction {@db.execute 'DROP TABLE test;'}
|
|
808
|
-
@db.
|
|
884
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
809
885
|
end
|
|
810
886
|
|
|
811
887
|
specify "should use savepoints if given the :savepoint option" do
|
|
812
888
|
@db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}}
|
|
813
|
-
@db.
|
|
889
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
|
814
890
|
end
|
|
815
891
|
|
|
816
892
|
specify "should not use a savepoints if no transaction is in progress" do
|
|
817
893
|
@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}
|
|
818
|
-
@db.
|
|
894
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
819
895
|
end
|
|
820
896
|
|
|
821
897
|
specify "should reuse the current transaction if no :savepoint option is given" do
|
|
822
898
|
@db.transaction{@db.transaction{@db.execute 'DROP TABLE test;'}}
|
|
823
|
-
@db.
|
|
899
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
824
900
|
end
|
|
825
901
|
|
|
826
902
|
specify "should handle returning inside of the block by committing" do
|
|
@@ -832,7 +908,7 @@ describe "Database#transaction with savepoints" do
|
|
|
832
908
|
end
|
|
833
909
|
end
|
|
834
910
|
@db.ret_commit
|
|
835
|
-
@db.
|
|
911
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
836
912
|
end
|
|
837
913
|
|
|
838
914
|
specify "should handle returning inside of a savepoint by committing" do
|
|
@@ -846,34 +922,34 @@ describe "Database#transaction with savepoints" do
|
|
|
846
922
|
end
|
|
847
923
|
end
|
|
848
924
|
@db.ret_commit
|
|
849
|
-
@db.
|
|
925
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
|
850
926
|
end
|
|
851
927
|
|
|
852
928
|
specify "should issue ROLLBACK if an exception is raised, and re-raise" do
|
|
853
929
|
@db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
|
|
854
|
-
@db.
|
|
930
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
855
931
|
|
|
856
932
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
857
933
|
end
|
|
858
934
|
|
|
859
935
|
specify "should issue ROLLBACK SAVEPOINT if an exception is raised inside a savepoint, and re-raise" do
|
|
860
936
|
@db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test'; raise RuntimeError}} rescue nil
|
|
861
|
-
@db.
|
|
937
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test', 'ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
862
938
|
|
|
863
939
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
864
940
|
end
|
|
865
941
|
|
|
866
|
-
specify "should issue ROLLBACK if Sequel::Rollback is
|
|
942
|
+
specify "should issue ROLLBACK if Sequel::Rollback is raised in the transaction" do
|
|
867
943
|
@db.transaction do
|
|
868
944
|
@db.drop_table(:a)
|
|
869
945
|
raise Sequel::Rollback
|
|
870
946
|
@db.drop_table(:b)
|
|
871
947
|
end
|
|
872
948
|
|
|
873
|
-
@db.
|
|
949
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
|
|
874
950
|
end
|
|
875
951
|
|
|
876
|
-
specify "should issue ROLLBACK SAVEPOINT if Sequel::Rollback is
|
|
952
|
+
specify "should issue ROLLBACK SAVEPOINT if Sequel::Rollback is raised in a savepoint" do
|
|
877
953
|
@db.transaction do
|
|
878
954
|
@db.transaction(:savepoint=>true) do
|
|
879
955
|
@db.drop_table(:a)
|
|
@@ -882,7 +958,7 @@ describe "Database#transaction with savepoints" do
|
|
|
882
958
|
@db.drop_table(:b)
|
|
883
959
|
end
|
|
884
960
|
|
|
885
|
-
@db.
|
|
961
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE a', 'ROLLBACK TO SAVEPOINT autopoint_1', 'DROP TABLE b', 'COMMIT']
|
|
886
962
|
end
|
|
887
963
|
|
|
888
964
|
specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
|
|
@@ -898,37 +974,28 @@ end
|
|
|
898
974
|
|
|
899
975
|
describe "A Database adapter with a scheme" do
|
|
900
976
|
before do
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
DISCONNECTS.clear
|
|
904
|
-
else
|
|
905
|
-
DISCONNECTS = []
|
|
906
|
-
end
|
|
907
|
-
set_adapter_scheme :ccc
|
|
908
|
-
def disconnect
|
|
909
|
-
DISCONNECTS << self
|
|
910
|
-
end
|
|
911
|
-
end
|
|
977
|
+
@ccc = Class.new(Sequel::Database)
|
|
978
|
+
@ccc.send(:set_adapter_scheme, :ccc)
|
|
912
979
|
end
|
|
913
980
|
|
|
914
981
|
specify "should be registered in the ADAPTER_MAP" do
|
|
915
|
-
Sequel::ADAPTER_MAP[:ccc].should ==
|
|
982
|
+
Sequel::ADAPTER_MAP[:ccc].should == @ccc
|
|
916
983
|
end
|
|
917
984
|
|
|
918
985
|
specify "should give the database_type as the adapter scheme by default" do
|
|
919
|
-
|
|
986
|
+
@ccc.new.database_type.should == :ccc
|
|
920
987
|
end
|
|
921
988
|
|
|
922
989
|
specify "should be instantiated when its scheme is specified" do
|
|
923
990
|
c = Sequel::Database.connect('ccc://localhost/db')
|
|
924
|
-
c.should be_a_kind_of(
|
|
991
|
+
c.should be_a_kind_of(@ccc)
|
|
925
992
|
c.opts[:host].should == 'localhost'
|
|
926
993
|
c.opts[:database].should == 'db'
|
|
927
994
|
end
|
|
928
995
|
|
|
929
996
|
specify "should be accessible through Sequel.connect" do
|
|
930
997
|
c = Sequel.connect 'ccc://localhost/db'
|
|
931
|
-
c.should be_a_kind_of(
|
|
998
|
+
c.should be_a_kind_of(@ccc)
|
|
932
999
|
c.opts[:host].should == 'localhost'
|
|
933
1000
|
c.opts[:database].should == 'db'
|
|
934
1001
|
end
|
|
@@ -940,7 +1007,7 @@ describe "A Database adapter with a scheme" do
|
|
|
940
1007
|
returnValue = 'anything'
|
|
941
1008
|
|
|
942
1009
|
p = proc do |c|
|
|
943
|
-
c.should be_a_kind_of(
|
|
1010
|
+
c.should be_a_kind_of(@ccc)
|
|
944
1011
|
c.opts[:host].should == 'localhost'
|
|
945
1012
|
c.opts[:database].should == 'db'
|
|
946
1013
|
z = y
|
|
@@ -948,15 +1015,22 @@ describe "A Database adapter with a scheme" do
|
|
|
948
1015
|
x = c
|
|
949
1016
|
returnValue
|
|
950
1017
|
end
|
|
1018
|
+
|
|
1019
|
+
@ccc.class_eval do
|
|
1020
|
+
self::DISCONNECTS = []
|
|
1021
|
+
def disconnect
|
|
1022
|
+
self.class::DISCONNECTS << self
|
|
1023
|
+
end
|
|
1024
|
+
end
|
|
951
1025
|
Sequel::Database.connect('ccc://localhost/db', &p).should == returnValue
|
|
952
|
-
|
|
1026
|
+
@ccc::DISCONNECTS.should == [x]
|
|
953
1027
|
|
|
954
1028
|
Sequel.connect('ccc://localhost/db', &p).should == returnValue
|
|
955
|
-
|
|
1029
|
+
@ccc::DISCONNECTS.should == [y, x]
|
|
956
1030
|
|
|
957
1031
|
Sequel.send(:def_adapter_method, :ccc)
|
|
958
1032
|
Sequel.ccc('db', :host=>'localhost', &p).should == returnValue
|
|
959
|
-
|
|
1033
|
+
@ccc::DISCONNECTS.should == [z, y, x]
|
|
960
1034
|
end
|
|
961
1035
|
|
|
962
1036
|
specify "should be accessible through Sequel.<adapter>" do
|
|
@@ -967,31 +1041,31 @@ describe "A Database adapter with a scheme" do
|
|
|
967
1041
|
|
|
968
1042
|
c = Sequel.ccc('mydb')
|
|
969
1043
|
p = proc{c.opts.delete_if{|k,v| k == :disconnection_proc || k == :single_threaded}}
|
|
970
|
-
c.should be_a_kind_of(
|
|
971
|
-
p.call.should == {:adapter=>:ccc, :database => 'mydb', :adapter_class
|
|
1044
|
+
c.should be_a_kind_of(@ccc)
|
|
1045
|
+
p.call.should == {:adapter=>:ccc, :database => 'mydb', :adapter_class=>@ccc}
|
|
972
1046
|
|
|
973
1047
|
c = Sequel.ccc('mydb', :host => 'localhost')
|
|
974
|
-
c.should be_a_kind_of(
|
|
975
|
-
p.call.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost', :adapter_class
|
|
1048
|
+
c.should be_a_kind_of(@ccc)
|
|
1049
|
+
p.call.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost', :adapter_class=>@ccc}
|
|
976
1050
|
|
|
977
1051
|
c = Sequel.ccc
|
|
978
|
-
c.should be_a_kind_of(
|
|
979
|
-
p.call.should == {:adapter=>:ccc, :adapter_class
|
|
1052
|
+
c.should be_a_kind_of(@ccc)
|
|
1053
|
+
p.call.should == {:adapter=>:ccc, :adapter_class=>@ccc}
|
|
980
1054
|
|
|
981
1055
|
c = Sequel.ccc(:database => 'mydb', :host => 'localhost')
|
|
982
|
-
c.should be_a_kind_of(
|
|
983
|
-
p.call.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost', :adapter_class
|
|
1056
|
+
c.should be_a_kind_of(@ccc)
|
|
1057
|
+
p.call.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost', :adapter_class=>@ccc}
|
|
984
1058
|
end
|
|
985
1059
|
|
|
986
1060
|
specify "should be accessible through Sequel.connect with options" do
|
|
987
1061
|
c = Sequel.connect(:adapter => :ccc, :database => 'mydb')
|
|
988
|
-
c.should be_a_kind_of(
|
|
1062
|
+
c.should be_a_kind_of(@ccc)
|
|
989
1063
|
c.opts[:adapter].should == :ccc
|
|
990
1064
|
end
|
|
991
1065
|
|
|
992
1066
|
specify "should be accessible through Sequel.connect with URL parameters" do
|
|
993
1067
|
c = Sequel.connect 'ccc:///db?host=/tmp&user=test'
|
|
994
|
-
c.should be_a_kind_of(
|
|
1068
|
+
c.should be_a_kind_of(@ccc)
|
|
995
1069
|
c.opts[:host].should == '/tmp'
|
|
996
1070
|
c.opts[:database].should == 'db'
|
|
997
1071
|
c.opts[:user].should == 'test'
|
|
@@ -999,14 +1073,14 @@ describe "A Database adapter with a scheme" do
|
|
|
999
1073
|
|
|
1000
1074
|
specify "should have URL parameters take precedence over fixed URL parts" do
|
|
1001
1075
|
c = Sequel.connect 'ccc://localhost/db?host=a&database=b'
|
|
1002
|
-
c.should be_a_kind_of(
|
|
1076
|
+
c.should be_a_kind_of(@ccc)
|
|
1003
1077
|
c.opts[:host].should == 'a'
|
|
1004
1078
|
c.opts[:database].should == 'b'
|
|
1005
1079
|
end
|
|
1006
1080
|
|
|
1007
1081
|
specify "should have hash options take predence over URL parameters or parts" do
|
|
1008
1082
|
c = Sequel.connect 'ccc://localhost/db?host=/tmp', :host=>'a', :database=>'b', :user=>'c'
|
|
1009
|
-
c.should be_a_kind_of(
|
|
1083
|
+
c.should be_a_kind_of(@ccc)
|
|
1010
1084
|
c.opts[:host].should == 'a'
|
|
1011
1085
|
c.opts[:database].should == 'b'
|
|
1012
1086
|
c.opts[:user].should == 'c'
|
|
@@ -1014,7 +1088,7 @@ describe "A Database adapter with a scheme" do
|
|
|
1014
1088
|
|
|
1015
1089
|
specify "should unescape values of URL parameters and parts" do
|
|
1016
1090
|
c = Sequel.connect 'ccc:///d%5bb%5d?host=domain%5cinstance'
|
|
1017
|
-
c.should be_a_kind_of(
|
|
1091
|
+
c.should be_a_kind_of(@ccc)
|
|
1018
1092
|
c.opts[:database].should == 'd[b]'
|
|
1019
1093
|
c.opts[:host].should == 'domain\\instance'
|
|
1020
1094
|
end
|
|
@@ -1129,10 +1203,6 @@ describe "A single threaded database" do
|
|
|
1129
1203
|
end
|
|
1130
1204
|
|
|
1131
1205
|
describe "A database" do
|
|
1132
|
-
before do
|
|
1133
|
-
Sequel::Database.single_threaded = false
|
|
1134
|
-
end
|
|
1135
|
-
|
|
1136
1206
|
after do
|
|
1137
1207
|
Sequel::Database.single_threaded = false
|
|
1138
1208
|
end
|
|
@@ -1177,11 +1247,7 @@ end
|
|
|
1177
1247
|
|
|
1178
1248
|
describe "Database#fetch" do
|
|
1179
1249
|
before do
|
|
1180
|
-
@db = Sequel
|
|
1181
|
-
c = Class.new(Sequel::Dataset) do
|
|
1182
|
-
def fetch_rows(sql); yield({:sql => sql}); end
|
|
1183
|
-
end
|
|
1184
|
-
@db.meta_def(:dataset) {c.new(self)}
|
|
1250
|
+
@db = Sequel.mock(:fetch=>proc{|sql| {:sql => sql}})
|
|
1185
1251
|
end
|
|
1186
1252
|
|
|
1187
1253
|
specify "should create a dataset and invoke its fetch_rows method with the given sql" do
|
|
@@ -1228,143 +1294,54 @@ end
|
|
|
1228
1294
|
|
|
1229
1295
|
describe "Database#[]" do
|
|
1230
1296
|
before do
|
|
1231
|
-
@db = Sequel
|
|
1297
|
+
@db = Sequel.mock
|
|
1232
1298
|
end
|
|
1233
1299
|
|
|
1234
1300
|
specify "should return a dataset when symbols are given" do
|
|
1235
1301
|
ds = @db[:items]
|
|
1236
|
-
ds.
|
|
1302
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
1237
1303
|
ds.opts[:from].should == [:items]
|
|
1238
1304
|
end
|
|
1239
1305
|
|
|
1240
1306
|
specify "should return a dataset when a string is given" do
|
|
1241
|
-
|
|
1242
|
-
def fetch_rows(sql); yield({:sql => sql}); end
|
|
1243
|
-
end
|
|
1244
|
-
@db.meta_def(:dataset) {c.new(self)}
|
|
1245
|
-
|
|
1307
|
+
@db.fetch = proc{|sql| {:sql=>sql}}
|
|
1246
1308
|
sql = nil
|
|
1247
1309
|
@db['select * from xyz where x = ? and y = ?', 15, 'abc'].each {|r| sql = r[:sql]}
|
|
1248
1310
|
sql.should == "select * from xyz where x = 15 and y = 'abc'"
|
|
1249
1311
|
end
|
|
1250
1312
|
end
|
|
1251
1313
|
|
|
1252
|
-
describe "Database#create_view" do
|
|
1253
|
-
before do
|
|
1254
|
-
@db = DummyDatabase.new
|
|
1255
|
-
end
|
|
1256
|
-
|
|
1257
|
-
specify "should construct proper SQL with raw SQL" do
|
|
1258
|
-
@db.create_view :test, "SELECT * FROM xyz"
|
|
1259
|
-
@db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
|
|
1260
|
-
@db.sqls.clear
|
|
1261
|
-
@db.create_view :test.identifier, "SELECT * FROM xyz"
|
|
1262
|
-
@db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
|
|
1263
|
-
end
|
|
1264
|
-
|
|
1265
|
-
specify "should construct proper SQL with dataset" do
|
|
1266
|
-
@db.create_view :test, @db[:items].select(:a, :b).order(:c)
|
|
1267
|
-
@db.sqls.should == ['CREATE VIEW test AS SELECT a, b FROM items ORDER BY c']
|
|
1268
|
-
@db.sqls.clear
|
|
1269
|
-
@db.create_view :test.qualify(:sch), @db[:items].select(:a, :b).order(:c)
|
|
1270
|
-
@db.sqls.should == ['CREATE VIEW sch.test AS SELECT a, b FROM items ORDER BY c']
|
|
1271
|
-
end
|
|
1272
|
-
end
|
|
1273
|
-
|
|
1274
|
-
describe "Database#create_or_replace_view" do
|
|
1275
|
-
before do
|
|
1276
|
-
@db = DummyDatabase.new
|
|
1277
|
-
end
|
|
1278
|
-
|
|
1279
|
-
specify "should construct proper SQL with raw SQL" do
|
|
1280
|
-
@db.create_or_replace_view :test, "SELECT * FROM xyz"
|
|
1281
|
-
@db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT * FROM xyz']
|
|
1282
|
-
@db.sqls.clear
|
|
1283
|
-
@db.create_or_replace_view :sch__test, "SELECT * FROM xyz"
|
|
1284
|
-
@db.sqls.should == ['CREATE OR REPLACE VIEW sch.test AS SELECT * FROM xyz']
|
|
1285
|
-
end
|
|
1286
|
-
|
|
1287
|
-
specify "should construct proper SQL with dataset" do
|
|
1288
|
-
@db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
|
|
1289
|
-
@db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
|
|
1290
|
-
@db.sqls.clear
|
|
1291
|
-
@db.create_or_replace_view :test.identifier, @db[:items].select(:a, :b).order(:c)
|
|
1292
|
-
@db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
|
|
1293
|
-
end
|
|
1294
|
-
end
|
|
1295
|
-
|
|
1296
|
-
describe "Database#drop_view" do
|
|
1297
|
-
before do
|
|
1298
|
-
@db = DummyDatabase.new
|
|
1299
|
-
end
|
|
1300
|
-
|
|
1301
|
-
specify "should construct proper SQL" do
|
|
1302
|
-
@db.drop_view :test
|
|
1303
|
-
@db.drop_view :test.identifier
|
|
1304
|
-
@db.drop_view :sch__test
|
|
1305
|
-
@db.drop_view :test.qualify(:sch)
|
|
1306
|
-
@db.sqls.should == ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test', 'DROP VIEW sch.test']
|
|
1307
|
-
end
|
|
1308
|
-
end
|
|
1309
|
-
|
|
1310
|
-
describe "Database#alter_table_sql" do
|
|
1311
|
-
before do
|
|
1312
|
-
@db = DummyDatabase.new
|
|
1313
|
-
end
|
|
1314
|
-
|
|
1315
|
-
specify "should raise error for an invalid op" do
|
|
1316
|
-
proc {@db.send(:alter_table_sql, :mau, :op => :blah)}.should raise_error(Sequel::Error)
|
|
1317
|
-
end
|
|
1318
|
-
end
|
|
1319
|
-
|
|
1320
1314
|
describe "Database#inspect" do
|
|
1321
|
-
before do
|
|
1322
|
-
@db = DummyDatabase.new
|
|
1323
|
-
|
|
1324
|
-
@db.meta_def(:uri) {'blah://blahblah/blah'}
|
|
1325
|
-
end
|
|
1326
|
-
|
|
1327
1315
|
specify "should include the class name and the connection url" do
|
|
1328
|
-
|
|
1316
|
+
Sequel.connect('mock://foo/bar').inspect.should == '#<Sequel::Mock::Database: "mock://foo/bar">'
|
|
1329
1317
|
end
|
|
1330
1318
|
end
|
|
1331
1319
|
|
|
1332
1320
|
describe "Database#get" do
|
|
1333
1321
|
before do
|
|
1334
|
-
@
|
|
1335
|
-
def dataset
|
|
1336
|
-
ds = super
|
|
1337
|
-
def ds.get(*args, &block)
|
|
1338
|
-
@db.execute select(*args, &block).sql
|
|
1339
|
-
args
|
|
1340
|
-
end
|
|
1341
|
-
ds
|
|
1342
|
-
end
|
|
1343
|
-
end
|
|
1344
|
-
|
|
1345
|
-
@db = @c.new
|
|
1322
|
+
@db = Sequel.mock(:fetch=>{:a=>1})
|
|
1346
1323
|
end
|
|
1347
1324
|
|
|
1348
1325
|
specify "should use Dataset#get to get a single value" do
|
|
1349
|
-
@db.get(1).should ==
|
|
1350
|
-
@db.sqls.
|
|
1326
|
+
@db.get(1).should == 1
|
|
1327
|
+
@db.sqls.should == ['SELECT 1 LIMIT 1']
|
|
1351
1328
|
|
|
1352
1329
|
@db.get(:version.sql_function)
|
|
1353
|
-
@db.sqls.
|
|
1330
|
+
@db.sqls.should == ['SELECT version() LIMIT 1']
|
|
1354
1331
|
end
|
|
1355
1332
|
|
|
1356
1333
|
specify "should accept a block" do
|
|
1357
1334
|
@db.get{1}
|
|
1358
|
-
@db.sqls.
|
|
1335
|
+
@db.sqls.should == ['SELECT 1 LIMIT 1']
|
|
1359
1336
|
|
|
1360
1337
|
@db.get{version(1)}
|
|
1361
|
-
@db.sqls.
|
|
1338
|
+
@db.sqls.should == ['SELECT version(1) LIMIT 1']
|
|
1362
1339
|
end
|
|
1363
1340
|
end
|
|
1364
1341
|
|
|
1365
1342
|
describe "Database#call" do
|
|
1366
1343
|
specify "should call the prepared statement with the given name" do
|
|
1367
|
-
db =
|
|
1344
|
+
db = Sequel.mock(:fetch=>{:id => 1, :x => 1})
|
|
1368
1345
|
db[:items].prepare(:select, :select_all)
|
|
1369
1346
|
db.call(:select_all).should == [{:id => 1, :x => 1}]
|
|
1370
1347
|
db[:items].filter(:n=>:$n).prepare(:select, :select_n)
|
|
@@ -1376,146 +1353,129 @@ end
|
|
|
1376
1353
|
describe "Database#server_opts" do
|
|
1377
1354
|
specify "should return the general opts if no :servers option is used" do
|
|
1378
1355
|
opts = {:host=>1, :database=>2}
|
|
1379
|
-
|
|
1356
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 1
|
|
1380
1357
|
end
|
|
1381
1358
|
|
|
1382
1359
|
specify "should return the general opts if entry for the server is present in the :servers option" do
|
|
1383
1360
|
opts = {:host=>1, :database=>2, :servers=>{}}
|
|
1384
|
-
|
|
1361
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 1
|
|
1385
1362
|
end
|
|
1386
1363
|
|
|
1387
1364
|
specify "should return the general opts merged with the specific opts if given as a hash" do
|
|
1388
1365
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}}}
|
|
1389
|
-
|
|
1366
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 3
|
|
1390
1367
|
end
|
|
1391
1368
|
|
|
1392
1369
|
specify "should return the sgeneral opts merged with the specific opts if given as a proc" do
|
|
1393
1370
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>proc{|db| {:host=>4}}}}
|
|
1394
|
-
|
|
1371
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 4
|
|
1395
1372
|
end
|
|
1396
1373
|
|
|
1397
1374
|
specify "should raise an error if the specific opts is not a proc or hash" do
|
|
1398
1375
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>2}}
|
|
1399
|
-
proc{
|
|
1376
|
+
proc{Sequel::Database.new(opts).send(:server_opts, :server1)}.should raise_error(Sequel::Error)
|
|
1400
1377
|
end
|
|
1401
1378
|
end
|
|
1402
1379
|
|
|
1403
1380
|
describe "Database#add_servers" do
|
|
1404
1381
|
before do
|
|
1405
|
-
@db =
|
|
1406
|
-
def @db.connect(server)
|
|
1407
|
-
server_opts(server)
|
|
1408
|
-
end
|
|
1409
|
-
def @db.disconnect_connection(c)
|
|
1410
|
-
end
|
|
1382
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}})
|
|
1411
1383
|
end
|
|
1412
1384
|
|
|
1413
1385
|
specify "should add new servers to the connection pool" do
|
|
1414
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1415
|
-
@db.synchronize(:server1){|c| c[:host].should == 3}
|
|
1416
|
-
@db.synchronize(:server2){|c| c[:host].should == 1}
|
|
1386
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1387
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1388
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1417
1389
|
|
|
1418
1390
|
@db.add_servers(:server2=>{:host=>6})
|
|
1419
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1420
|
-
@db.synchronize(:server1){|c| c[:host].should == 3}
|
|
1421
|
-
@db.synchronize(:server2){|c| c[:host].should == 6}
|
|
1391
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1392
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1393
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 6}
|
|
1422
1394
|
|
|
1423
1395
|
@db.disconnect
|
|
1424
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1425
|
-
@db.synchronize(:server1){|c| c[:host].should == 3}
|
|
1426
|
-
@db.synchronize(:server2){|c| c[:host].should == 6}
|
|
1396
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1397
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1398
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 6}
|
|
1427
1399
|
end
|
|
1428
1400
|
|
|
1429
1401
|
specify "should replace options for future connections to existing servers" do
|
|
1430
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1431
|
-
@db.synchronize(:server1){|c| c[:host].should == 3}
|
|
1432
|
-
@db.synchronize(:server2){|c| c[:host].should == 1}
|
|
1402
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1403
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1404
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1433
1405
|
|
|
1434
1406
|
@db.add_servers(:default=>proc{{:host=>4}}, :server1=>{:host=>8})
|
|
1435
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1436
|
-
@db.synchronize(:server1){|c| c[:host].should == 3}
|
|
1437
|
-
@db.synchronize(:server2){|c| c[:host].should == 1}
|
|
1407
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1408
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1409
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1438
1410
|
|
|
1439
1411
|
@db.disconnect
|
|
1440
|
-
@db.synchronize{|c| c[:host].should == 4}
|
|
1441
|
-
@db.synchronize(:server1){|c| c[:host].should == 8}
|
|
1442
|
-
@db.synchronize(:server2){|c| c[:host].should == 4}
|
|
1412
|
+
@db.synchronize{|c| c.opts[:host].should == 4}
|
|
1413
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 8}
|
|
1414
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 4}
|
|
1443
1415
|
end
|
|
1444
1416
|
end
|
|
1445
1417
|
|
|
1446
1418
|
describe "Database#remove_servers" do
|
|
1447
1419
|
before do
|
|
1448
|
-
@db =
|
|
1449
|
-
def @db.connect(server)
|
|
1450
|
-
server_opts(server)
|
|
1451
|
-
end
|
|
1452
|
-
def @db.disconnect_connection(c)
|
|
1453
|
-
end
|
|
1420
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
|
|
1454
1421
|
end
|
|
1455
1422
|
|
|
1456
1423
|
specify "should remove servers from the connection pool" do
|
|
1457
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1458
|
-
@db.synchronize(:server1){|c| c[:host].should == 3}
|
|
1459
|
-
@db.synchronize(:server2){|c| c[:host].should == 4}
|
|
1424
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1425
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1426
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 4}
|
|
1460
1427
|
|
|
1461
1428
|
@db.remove_servers(:server1, :server2)
|
|
1462
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1463
|
-
@db.synchronize(:server1){|c| c[:host].should == 1}
|
|
1464
|
-
@db.synchronize(:server2){|c| c[:host].should == 1}
|
|
1429
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1430
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 1}
|
|
1431
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1465
1432
|
end
|
|
1466
1433
|
|
|
1467
1434
|
specify "should accept arrays of symbols" do
|
|
1468
1435
|
@db.remove_servers([:server1, :server2])
|
|
1469
|
-
@db.synchronize{|c| c[:host].should == 1}
|
|
1470
|
-
@db.synchronize(:server1){|c| c[:host].should == 1}
|
|
1471
|
-
@db.synchronize(:server2){|c| c[:host].should == 1}
|
|
1436
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1437
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 1}
|
|
1438
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1472
1439
|
end
|
|
1473
1440
|
|
|
1474
1441
|
specify "should allow removal while connections are still open" do
|
|
1475
1442
|
@db.synchronize do |c1|
|
|
1476
|
-
c1[:host].should == 1
|
|
1443
|
+
c1.opts[:host].should == 1
|
|
1477
1444
|
@db.synchronize(:server1) do |c2|
|
|
1478
|
-
c2[:host].should == 3
|
|
1445
|
+
c2.opts[:host].should == 3
|
|
1479
1446
|
@db.synchronize(:server2) do |c3|
|
|
1480
|
-
c3[:host].should == 4
|
|
1447
|
+
c3.opts[:host].should == 4
|
|
1481
1448
|
@db.remove_servers(:server1, :server2)
|
|
1482
1449
|
@db.synchronize(:server1) do |c4|
|
|
1483
1450
|
c4.should_not == c2
|
|
1484
1451
|
c4.should == c1
|
|
1485
|
-
c4[:host].should == 1
|
|
1452
|
+
c4.opts[:host].should == 1
|
|
1486
1453
|
@db.synchronize(:server2) do |c5|
|
|
1487
1454
|
c5.should_not == c3
|
|
1488
1455
|
c5.should == c1
|
|
1489
|
-
c5[:host].should == 1
|
|
1456
|
+
c5.opts[:host].should == 1
|
|
1490
1457
|
end
|
|
1491
1458
|
end
|
|
1492
|
-
c3[:host].should == 4
|
|
1459
|
+
c3.opts[:host].should == 4
|
|
1493
1460
|
end
|
|
1494
|
-
c2[:host].should == 3
|
|
1461
|
+
c2.opts[:host].should == 3
|
|
1495
1462
|
end
|
|
1496
|
-
c1[:host].should == 1
|
|
1463
|
+
c1.opts[:host].should == 1
|
|
1497
1464
|
end
|
|
1498
1465
|
end
|
|
1499
1466
|
end
|
|
1500
1467
|
|
|
1501
1468
|
describe "Database#each_server with do/jdbc adapter connection string without :adapter option" do
|
|
1502
|
-
|
|
1469
|
+
specify "should yield a separate database object for each server" do
|
|
1503
1470
|
klass = Class.new(Sequel::Database)
|
|
1504
|
-
klass.should_receive(:adapter_class).once.with(:jdbc).and_return(
|
|
1471
|
+
klass.should_receive(:adapter_class).once.with(:jdbc).and_return(Sequel::Mock::Database)
|
|
1505
1472
|
@db = klass.connect('jdbc:blah:', :host=>1, :database=>2, :servers=>{:server1=>{:host=>3}})
|
|
1506
|
-
def @db.connect(server)
|
|
1507
|
-
server_opts(server)
|
|
1508
|
-
end
|
|
1509
|
-
def @db.disconnect_connection(c)
|
|
1510
|
-
end
|
|
1511
|
-
end
|
|
1512
1473
|
|
|
1513
|
-
specify "should yield a separate database object for each server" do
|
|
1514
1474
|
hosts = []
|
|
1515
1475
|
@db.each_server do |db|
|
|
1516
1476
|
db.should be_a_kind_of(Sequel::Database)
|
|
1517
1477
|
db.should_not == @db
|
|
1518
|
-
db.opts[:adapter_class].should ==
|
|
1478
|
+
db.opts[:adapter_class].should == Sequel::Mock::Database
|
|
1519
1479
|
db.opts[:database].should == 2
|
|
1520
1480
|
hosts << db.opts[:host]
|
|
1521
1481
|
end
|
|
@@ -1525,12 +1485,7 @@ end
|
|
|
1525
1485
|
|
|
1526
1486
|
describe "Database#each_server" do
|
|
1527
1487
|
before do
|
|
1528
|
-
@db = Sequel.
|
|
1529
|
-
def @db.connect(server)
|
|
1530
|
-
server_opts(server)
|
|
1531
|
-
end
|
|
1532
|
-
def @db.disconnect_connection(c)
|
|
1533
|
-
end
|
|
1488
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
|
|
1534
1489
|
end
|
|
1535
1490
|
|
|
1536
1491
|
specify "should yield a separate database object for each server" do
|
|
@@ -1561,21 +1516,25 @@ describe "Database#each_server" do
|
|
|
1561
1516
|
end
|
|
1562
1517
|
|
|
1563
1518
|
describe "Database#raise_error" do
|
|
1519
|
+
before do
|
|
1520
|
+
@db = Sequel.mock
|
|
1521
|
+
end
|
|
1522
|
+
|
|
1564
1523
|
specify "should reraise if the exception class is not in opts[:classes]" do
|
|
1565
1524
|
e = Class.new(StandardError)
|
|
1566
|
-
proc{
|
|
1525
|
+
proc{@db.send(:raise_error, e.new(''), :classes=>[])}.should raise_error(e)
|
|
1567
1526
|
end
|
|
1568
1527
|
|
|
1569
|
-
specify "should convert the exception to a DatabaseError if the exception class is
|
|
1570
|
-
proc{
|
|
1528
|
+
specify "should convert the exception to a DatabaseError if the exception class is in opts[:classes]" do
|
|
1529
|
+
proc{@db.send(:raise_error, Interrupt.new(''), :classes=>[Interrupt])}.should raise_error(Sequel::DatabaseError)
|
|
1571
1530
|
end
|
|
1572
1531
|
|
|
1573
1532
|
specify "should convert the exception to a DatabaseError if opts[:classes] if not present" do
|
|
1574
|
-
proc{
|
|
1533
|
+
proc{@db.send(:raise_error, Interrupt.new(''))}.should raise_error(Sequel::DatabaseError)
|
|
1575
1534
|
end
|
|
1576
1535
|
|
|
1577
1536
|
specify "should convert the exception to a DatabaseDisconnectError if opts[:disconnect] is true" do
|
|
1578
|
-
proc{
|
|
1537
|
+
proc{@db.send(:raise_error, Interrupt.new(''), :disconnect=>true)}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1579
1538
|
end
|
|
1580
1539
|
end
|
|
1581
1540
|
|
|
@@ -1594,6 +1553,268 @@ describe "Database#typecast_value" do
|
|
|
1594
1553
|
proc{@db.typecast_value(:datetime, 4)}.should raise_error(Sequel::InvalidValue)
|
|
1595
1554
|
end
|
|
1596
1555
|
|
|
1556
|
+
specify "should handle integers with leading 0 as base 10" do
|
|
1557
|
+
@db.typecast_value(:integer, "013").should == 13
|
|
1558
|
+
@db.typecast_value(:integer, "08").should == 8
|
|
1559
|
+
@db.typecast_value(:integer, "000013").should == 13
|
|
1560
|
+
@db.typecast_value(:integer, "000008").should == 8
|
|
1561
|
+
end
|
|
1562
|
+
|
|
1563
|
+
specify "should handle integers with leading 0x as base 16" do
|
|
1564
|
+
@db.typecast_value(:integer, "0x013").should == 19
|
|
1565
|
+
@db.typecast_value(:integer, "0x80").should == 128
|
|
1566
|
+
end
|
|
1567
|
+
|
|
1568
|
+
specify "should typecast blobs as as Sequel::SQL::Blob" do
|
|
1569
|
+
v = @db.typecast_value(:blob, "0x013")
|
|
1570
|
+
v.should be_a_kind_of(Sequel::SQL::Blob)
|
|
1571
|
+
v.should == Sequel::SQL::Blob.new("0x013")
|
|
1572
|
+
@db.typecast_value(:blob, v).object_id.should == v.object_id
|
|
1573
|
+
end
|
|
1574
|
+
|
|
1575
|
+
specify "should typecast boolean values to true, false, or nil" do
|
|
1576
|
+
@db.typecast_value(:boolean, false).should be_false
|
|
1577
|
+
@db.typecast_value(:boolean, 0).should be_false
|
|
1578
|
+
@db.typecast_value(:boolean, "0").should be_false
|
|
1579
|
+
@db.typecast_value(:boolean, 'f').should be_false
|
|
1580
|
+
@db.typecast_value(:boolean, 'false').should be_false
|
|
1581
|
+
@db.typecast_value(:boolean, true).should be_true
|
|
1582
|
+
@db.typecast_value(:boolean, 1).should be_true
|
|
1583
|
+
@db.typecast_value(:boolean, '1').should be_true
|
|
1584
|
+
@db.typecast_value(:boolean, 't').should be_true
|
|
1585
|
+
@db.typecast_value(:boolean, 'true').should be_true
|
|
1586
|
+
@db.typecast_value(:boolean, '').should be_nil
|
|
1587
|
+
end
|
|
1588
|
+
|
|
1589
|
+
specify "should typecast date values to Date" do
|
|
1590
|
+
@db.typecast_value(:date, Date.today).should == Date.today
|
|
1591
|
+
@db.typecast_value(:date, DateTime.now).should == Date.today
|
|
1592
|
+
@db.typecast_value(:date, Time.now).should == Date.today
|
|
1593
|
+
@db.typecast_value(:date, Date.today.to_s).should == Date.today
|
|
1594
|
+
@db.typecast_value(:date, :year=>Date.today.year, :month=>Date.today.month, :day=>Date.today.day).should == Date.today
|
|
1595
|
+
end
|
|
1596
|
+
|
|
1597
|
+
specify "should have Sequel.application_to_database_timestamp convert to Sequel.database_timezone" do
|
|
1598
|
+
begin
|
|
1599
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1600
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1601
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1602
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1603
|
+
Sequel.application_timezone = :utc
|
|
1604
|
+
Sequel.database_timezone = :local
|
|
1605
|
+
Sequel.application_to_database_timestamp(t).should == t4
|
|
1606
|
+
Sequel.application_timezone = :local
|
|
1607
|
+
Sequel.database_timezone = :utc
|
|
1608
|
+
Sequel.application_to_database_timestamp(t2).should == t3
|
|
1609
|
+
ensure
|
|
1610
|
+
Sequel.default_timezone = nil
|
|
1611
|
+
end
|
|
1612
|
+
end
|
|
1613
|
+
|
|
1614
|
+
specify "should have Database#to_application_timestamp convert values using the database's timezone" do
|
|
1615
|
+
begin
|
|
1616
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1617
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1618
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1619
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1620
|
+
Sequel.default_timezone = :utc
|
|
1621
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t
|
|
1622
|
+
Sequel.database_timezone = :local
|
|
1623
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t3
|
|
1624
|
+
Sequel.default_timezone = :local
|
|
1625
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t2
|
|
1626
|
+
Sequel.database_timezone = :utc
|
|
1627
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t4
|
|
1628
|
+
|
|
1629
|
+
Sequel.default_timezone = :utc
|
|
1630
|
+
@db.timezone = :local
|
|
1631
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t3
|
|
1632
|
+
Sequel.default_timezone = :local
|
|
1633
|
+
@db.timezone = :utc
|
|
1634
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t4
|
|
1635
|
+
ensure
|
|
1636
|
+
Sequel.default_timezone = nil
|
|
1637
|
+
end
|
|
1638
|
+
end
|
|
1639
|
+
|
|
1640
|
+
specify "should typecast datetime values to Sequel.datetime_class with correct timezone handling" do
|
|
1641
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1642
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1643
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1644
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1645
|
+
dt = DateTime.civil(2011, 1, 2, 3, 4, 5)
|
|
1646
|
+
r1 = defined?(Rational) ? Rational(t2.utc_offset, 86400) : t2.utc_offset/86400.0
|
|
1647
|
+
r2 = defined?(Rational) ? Rational((t - t2).to_i, 86400) : (t - t2).to_i/86400.0
|
|
1648
|
+
dt2 = DateTime.civil(2011, 1, 2, 3, 4, 5, r1)
|
|
1649
|
+
dt3 = DateTime.civil(2011, 1, 2, 3, 4, 5) - r2
|
|
1650
|
+
dt4 = DateTime.civil(2011, 1, 2, 3, 4, 5, r1) + r2
|
|
1651
|
+
|
|
1652
|
+
t.should == t4
|
|
1653
|
+
t2.should == t3
|
|
1654
|
+
dt.should == dt4
|
|
1655
|
+
dt2.should == dt3
|
|
1656
|
+
|
|
1657
|
+
check = proc do |i, o|
|
|
1658
|
+
v = @db.typecast_value(:datetime, i)
|
|
1659
|
+
v.should == o
|
|
1660
|
+
if o.is_a?(Time)
|
|
1661
|
+
v.utc_offset.should == o.utc_offset
|
|
1662
|
+
else
|
|
1663
|
+
v.offset.should == o.offset
|
|
1664
|
+
end
|
|
1665
|
+
end
|
|
1666
|
+
begin
|
|
1667
|
+
@db.typecast_value(:datetime, dt).should == t
|
|
1668
|
+
@db.typecast_value(:datetime, dt2).should == t2
|
|
1669
|
+
@db.typecast_value(:datetime, t).should == t
|
|
1670
|
+
@db.typecast_value(:datetime, t2).should == t2
|
|
1671
|
+
@db.typecast_value(:datetime, dt.to_s).should == t
|
|
1672
|
+
@db.typecast_value(:datetime, dt.strftime('%F %T')).should == t2
|
|
1673
|
+
@db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == Time.mktime(2011, 1, 2, 0, 0, 0)
|
|
1674
|
+
@db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec).should == t2
|
|
1675
|
+
|
|
1676
|
+
Sequel.datetime_class = DateTime
|
|
1677
|
+
@db.typecast_value(:datetime, dt).should == dt
|
|
1678
|
+
@db.typecast_value(:datetime, dt2).should == dt2
|
|
1679
|
+
@db.typecast_value(:datetime, t).should == dt
|
|
1680
|
+
@db.typecast_value(:datetime, t2).should == dt2
|
|
1681
|
+
@db.typecast_value(:datetime, dt.to_s).should == dt
|
|
1682
|
+
@db.typecast_value(:datetime, dt.strftime('%F %T')).should == dt
|
|
1683
|
+
@db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == DateTime.civil(2011, 1, 2, 0, 0, 0)
|
|
1684
|
+
@db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec).should == dt
|
|
1685
|
+
|
|
1686
|
+
Sequel.application_timezone = :utc
|
|
1687
|
+
Sequel.typecast_timezone = :local
|
|
1688
|
+
Sequel.datetime_class = Time
|
|
1689
|
+
check[dt, t]
|
|
1690
|
+
check[dt2, t3]
|
|
1691
|
+
check[t, t]
|
|
1692
|
+
check[t2, t3]
|
|
1693
|
+
check[dt.to_s, t]
|
|
1694
|
+
check[dt.strftime('%F %T'), t3]
|
|
1695
|
+
check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
|
|
1696
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t3]
|
|
1697
|
+
|
|
1698
|
+
Sequel.datetime_class = DateTime
|
|
1699
|
+
check[dt, dt]
|
|
1700
|
+
check[dt2, dt3]
|
|
1701
|
+
check[t, dt]
|
|
1702
|
+
check[t2, dt3]
|
|
1703
|
+
check[dt.to_s, dt]
|
|
1704
|
+
check[dt.strftime('%F %T'), dt3]
|
|
1705
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
|
|
1706
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt3]
|
|
1707
|
+
|
|
1708
|
+
Sequel.typecast_timezone = :utc
|
|
1709
|
+
Sequel.datetime_class = Time
|
|
1710
|
+
check[dt, t]
|
|
1711
|
+
check[dt2, t3]
|
|
1712
|
+
check[t, t]
|
|
1713
|
+
check[t2, t3]
|
|
1714
|
+
check[dt.to_s, t]
|
|
1715
|
+
check[dt.strftime('%F %T'), t]
|
|
1716
|
+
check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
|
|
1717
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t]
|
|
1718
|
+
|
|
1719
|
+
Sequel.datetime_class = DateTime
|
|
1720
|
+
check[dt, dt]
|
|
1721
|
+
check[dt2, dt3]
|
|
1722
|
+
check[t, dt]
|
|
1723
|
+
check[t2, dt3]
|
|
1724
|
+
check[dt.to_s, dt]
|
|
1725
|
+
check[dt.strftime('%F %T'), dt]
|
|
1726
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
|
|
1727
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt]
|
|
1728
|
+
|
|
1729
|
+
Sequel.application_timezone = :local
|
|
1730
|
+
Sequel.datetime_class = Time
|
|
1731
|
+
check[dt, t4]
|
|
1732
|
+
check[dt2, t2]
|
|
1733
|
+
check[t, t4]
|
|
1734
|
+
check[t2, t2]
|
|
1735
|
+
check[dt.to_s, t4]
|
|
1736
|
+
check[dt.strftime('%F %T'), t4]
|
|
1737
|
+
check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
|
|
1738
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t4]
|
|
1739
|
+
|
|
1740
|
+
Sequel.datetime_class = DateTime
|
|
1741
|
+
check[dt, dt4]
|
|
1742
|
+
check[dt2, dt2]
|
|
1743
|
+
check[t, dt4]
|
|
1744
|
+
check[t2, dt2]
|
|
1745
|
+
check[dt.to_s, dt4]
|
|
1746
|
+
check[dt.strftime('%F %T'), dt4]
|
|
1747
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
|
|
1748
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt4]
|
|
1749
|
+
|
|
1750
|
+
Sequel.typecast_timezone = :local
|
|
1751
|
+
Sequel.datetime_class = Time
|
|
1752
|
+
check[dt, t4]
|
|
1753
|
+
check[dt2, t2]
|
|
1754
|
+
check[t, t4]
|
|
1755
|
+
check[t2, t2]
|
|
1756
|
+
check[dt.to_s, t4]
|
|
1757
|
+
check[dt.strftime('%F %T'), t2]
|
|
1758
|
+
check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
|
|
1759
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t2]
|
|
1760
|
+
|
|
1761
|
+
Sequel.datetime_class = DateTime
|
|
1762
|
+
check[dt, dt4]
|
|
1763
|
+
check[dt2, dt2]
|
|
1764
|
+
check[t, dt4]
|
|
1765
|
+
check[t2, dt2]
|
|
1766
|
+
check[dt.to_s, dt4]
|
|
1767
|
+
check[dt.strftime('%F %T'), dt2]
|
|
1768
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
|
|
1769
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt2]
|
|
1770
|
+
|
|
1771
|
+
ensure
|
|
1772
|
+
Sequel.default_timezone = nil
|
|
1773
|
+
Sequel.datetime_class = Time
|
|
1774
|
+
end
|
|
1775
|
+
end
|
|
1776
|
+
|
|
1777
|
+
specify "should typecast decimal values to BigDecimal" do
|
|
1778
|
+
[1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
|
|
1779
|
+
v = @db.typecast_value(:decimal, i)
|
|
1780
|
+
v.should be_a_kind_of(BigDecimal)
|
|
1781
|
+
v.should == BigDecimal.new('1.0')
|
|
1782
|
+
end
|
|
1783
|
+
end
|
|
1784
|
+
|
|
1785
|
+
specify "should typecast float values to Float" do
|
|
1786
|
+
[1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
|
|
1787
|
+
v = @db.typecast_value(:float, i)
|
|
1788
|
+
v.should be_a_kind_of(Float)
|
|
1789
|
+
v.should == 1.0
|
|
1790
|
+
end
|
|
1791
|
+
end
|
|
1792
|
+
|
|
1793
|
+
specify "should typecast string values to String" do
|
|
1794
|
+
[1.0, '1.0', '1.0'.to_sequel_blob].each do |i|
|
|
1795
|
+
v = @db.typecast_value(:string, i)
|
|
1796
|
+
v.should be_an_instance_of(String)
|
|
1797
|
+
v.should == "1.0"
|
|
1798
|
+
end
|
|
1799
|
+
end
|
|
1800
|
+
|
|
1801
|
+
specify "should typecast time values to SQLTime" do
|
|
1802
|
+
t = Time.now
|
|
1803
|
+
st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3)
|
|
1804
|
+
[st, Time.utc(t.year, t.month, t.day, 1, 2, 3), Time.local(t.year, t.month, t.day, 1, 2, 3), '01:02:03', {:hour=>1, :minute=>2, :second=>3}].each do |i|
|
|
1805
|
+
v = @db.typecast_value(:time, i)
|
|
1806
|
+
v.should be_an_instance_of(Sequel::SQLTime)
|
|
1807
|
+
v.should == st
|
|
1808
|
+
end
|
|
1809
|
+
end
|
|
1810
|
+
|
|
1811
|
+
specify "should correctly handle time value conversion to SQLTime with fractional seconds" do
|
|
1812
|
+
t = Time.now
|
|
1813
|
+
st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3, 500000)
|
|
1814
|
+
t = Time.local(t.year, t.month, t.day, 1, 2, 3, 500000)
|
|
1815
|
+
@db.typecast_value(:time, t).should == st
|
|
1816
|
+
end
|
|
1817
|
+
|
|
1597
1818
|
specify "should have an underlying exception class available at wrapped_exception" do
|
|
1598
1819
|
begin
|
|
1599
1820
|
@db.typecast_value(:date, 'a')
|
|
@@ -1639,7 +1860,7 @@ describe "Database#blank_object?" do
|
|
|
1639
1860
|
end
|
|
1640
1861
|
|
|
1641
1862
|
describe "Database#schema_autoincrementing_primary_key?" do
|
|
1642
|
-
specify "should whether the parsed schema row indicates a primary key" do
|
|
1863
|
+
specify "should indicate whether the parsed schema row indicates a primary key" do
|
|
1643
1864
|
m = Sequel::Database.new.method(:schema_autoincrementing_primary_key?)
|
|
1644
1865
|
m.call(:primary_key=>true).should == true
|
|
1645
1866
|
m.call(:primary_key=>false).should == false
|
|
@@ -1695,7 +1916,7 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1695
1916
|
db = Sequel::Database.new
|
|
1696
1917
|
m = db.method(:column_schema_to_ruby_default)
|
|
1697
1918
|
p = lambda{|d,t| m.call(d,t)}
|
|
1698
|
-
p[nil, :integer].should
|
|
1919
|
+
p[nil, :integer].should be_nil
|
|
1699
1920
|
p['1', :integer].should == 1
|
|
1700
1921
|
p['-1', :integer].should == -1
|
|
1701
1922
|
p['1.0', :float].should == 1.0
|
|
@@ -1715,12 +1936,12 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1715
1936
|
p["'\\a''b'", :string].should == "\\a'b"
|
|
1716
1937
|
p["'NULL'", :string].should == "NULL"
|
|
1717
1938
|
p["'2009-10-29'", :date].should == Date.new(2009,10,29)
|
|
1718
|
-
p["CURRENT_TIMESTAMP", :date].should
|
|
1719
|
-
p["today()", :date].should
|
|
1939
|
+
p["CURRENT_TIMESTAMP", :date].should be_nil
|
|
1940
|
+
p["today()", :date].should be_nil
|
|
1720
1941
|
p["'2009-10-29T10:20:30-07:00'", :datetime].should == DateTime.parse('2009-10-29T10:20:30-07:00')
|
|
1721
1942
|
p["'2009-10-29 10:20:30'", :datetime].should == DateTime.parse('2009-10-29 10:20:30')
|
|
1722
1943
|
p["'10:20:30'", :time].should == Time.parse('10:20:30')
|
|
1723
|
-
p["NaN", :float].should
|
|
1944
|
+
p["NaN", :float].should be_nil
|
|
1724
1945
|
|
|
1725
1946
|
db.meta_def(:database_type){:postgres}
|
|
1726
1947
|
p["''::text", :string].should == ""
|
|
@@ -1744,8 +1965,8 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1744
1965
|
p["2009-10-29", :date].should == Date.new(2009,10,29)
|
|
1745
1966
|
p["2009-10-29 10:20:30", :datetime].should == DateTime.parse('2009-10-29 10:20:30')
|
|
1746
1967
|
p["10:20:30", :time].should == Time.parse('10:20:30')
|
|
1747
|
-
p["CURRENT_DATE", :date].should
|
|
1748
|
-
p["CURRENT_TIMESTAMP", :datetime].should
|
|
1968
|
+
p["CURRENT_DATE", :date].should be_nil
|
|
1969
|
+
p["CURRENT_TIMESTAMP", :datetime].should be_nil
|
|
1749
1970
|
p["a", :enum].should == "a"
|
|
1750
1971
|
|
|
1751
1972
|
db.meta_def(:database_type){:mssql}
|