sequel 3.21.0 → 3.31.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 +485 -3
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +249 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- 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 +89 -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/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -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 +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- 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 +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +45 -0
- data/lib/sequel/adapters/jdbc/derby.rb +247 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +56 -29
- data/lib/sequel/adapters/jdbc/hsqldb.rb +170 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +81 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +335 -0
- data/lib/sequel/adapters/mysql.rb +82 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +351 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +321 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +231 -106
- data/lib/sequel/adapters/shared/mysql.rb +181 -63
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +231 -41
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +4 -7
- data/lib/sequel/adapters/shared/sqlite.rb +201 -57
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- 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 +104 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +231 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +48 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +665 -253
- 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 +1020 -337
- data/lib/sequel/model/base.rb +414 -132
- 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 +88 -44
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- 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 +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +111 -29
- data/spec/adapters/mysql_spec.rb +135 -123
- data/spec/adapters/oracle_spec.rb +49 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- 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 +21 -30
- data/spec/core/database_spec.rb +788 -512
- data/spec/core/dataset_spec.rb +1073 -1053
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -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_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +72 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +537 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +461 -65
- 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 +212 -122
- 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 +201 -7
- data/spec/model/associations_spec.rb +865 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +115 -73
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,197 @@ 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
|
-
|
|
713
|
-
before do
|
|
714
|
-
@db = Dummy3Database.new{Dummy3Database::DummyConnection.new(@db)}
|
|
715
|
-
end
|
|
716
|
-
|
|
574
|
+
shared_examples_for "Database#transaction" do
|
|
717
575
|
specify "should wrap the supplied block with BEGIN + COMMIT statements" do
|
|
718
576
|
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
719
|
-
@db.
|
|
577
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
720
578
|
end
|
|
721
579
|
|
|
722
580
|
specify "should support transaction isolation levels" do
|
|
@@ -724,7 +582,7 @@ describe "Database#transaction" do
|
|
|
724
582
|
[:uncommitted, :committed, :repeatable, :serializable].each do |l|
|
|
725
583
|
@db.transaction(:isolation=>l){@db.run "DROP TABLE #{l}"}
|
|
726
584
|
end
|
|
727
|
-
@db.
|
|
585
|
+
@db.sqls.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
728
586
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
729
587
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
730
588
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
@@ -736,7 +594,7 @@ describe "Database#transaction" do
|
|
|
736
594
|
@db.transaction_isolation_level = l
|
|
737
595
|
@db.transaction{@db.run "DROP TABLE #{l}"}
|
|
738
596
|
end
|
|
739
|
-
@db.
|
|
597
|
+
@db.sqls.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
740
598
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
741
599
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
742
600
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
@@ -751,12 +609,12 @@ describe "Database#transaction" do
|
|
|
751
609
|
end
|
|
752
610
|
end
|
|
753
611
|
@db.ret_commit
|
|
754
|
-
@db.
|
|
612
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
755
613
|
end
|
|
756
614
|
|
|
757
615
|
specify "should issue ROLLBACK if an exception is raised, and re-raise" do
|
|
758
616
|
@db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
|
|
759
|
-
@db.
|
|
617
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
760
618
|
|
|
761
619
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
762
620
|
end
|
|
@@ -768,7 +626,50 @@ describe "Database#transaction" do
|
|
|
768
626
|
@db.drop_table(:b)
|
|
769
627
|
end
|
|
770
628
|
|
|
771
|
-
@db.
|
|
629
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
specify "should have in_transaction? return true if inside a transaction" do
|
|
633
|
+
c = nil
|
|
634
|
+
@db.transaction{c = @db.in_transaction?}
|
|
635
|
+
c.should be_true
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
specify "should have in_transaction? handle sharding correctly" do
|
|
639
|
+
c = []
|
|
640
|
+
@db.transaction(:server=>:test){c << @db.in_transaction?}
|
|
641
|
+
@db.transaction(:server=>:test){c << @db.in_transaction?(:server=>:test)}
|
|
642
|
+
c.should == [false, true]
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
specify "should have in_transaction? return false if not in a transaction" do
|
|
646
|
+
@db.in_transaction?.should be_false
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
specify "should return nil if Sequel::Rollback is called in the transaction" do
|
|
650
|
+
@db.transaction{raise Sequel::Rollback}.should be_nil
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
specify "should reraise Sequel::Rollback errors when using :rollback=>:reraise option is given" do
|
|
654
|
+
proc {@db.transaction(:rollback=>:reraise){raise Sequel::Rollback}}.should raise_error(Sequel::Rollback)
|
|
655
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
656
|
+
proc {@db.transaction(:rollback=>:reraise){raise ArgumentError}}.should raise_error(ArgumentError)
|
|
657
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
658
|
+
@db.transaction(:rollback=>:reraise){1}.should == 1
|
|
659
|
+
@db.sqls.should == ['BEGIN', 'COMMIT']
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
specify "should always rollback if :rollback=>:always option is given" do
|
|
663
|
+
proc {@db.transaction(:rollback=>:always){raise ArgumentError}}.should raise_error(ArgumentError)
|
|
664
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
665
|
+
@db.transaction(:rollback=>:always){raise Sequel::Rollback}.should be_nil
|
|
666
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
667
|
+
@db.transaction(:rollback=>:always){1}.should be_nil
|
|
668
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
669
|
+
catch (:foo) do
|
|
670
|
+
@db.transaction(:rollback=>:always){throw :foo}
|
|
671
|
+
end
|
|
672
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
772
673
|
end
|
|
773
674
|
|
|
774
675
|
specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
|
|
@@ -780,47 +681,242 @@ describe "Database#transaction" do
|
|
|
780
681
|
end
|
|
781
682
|
|
|
782
683
|
specify "should be re-entrant" do
|
|
783
|
-
|
|
684
|
+
q, q1 = Queue.new, Queue.new
|
|
784
685
|
cc = nil
|
|
785
686
|
t = Thread.new do
|
|
786
687
|
@db.transaction {@db.transaction {@db.transaction {|c|
|
|
787
688
|
cc = c
|
|
788
|
-
|
|
689
|
+
q.pop
|
|
690
|
+
q1.push nil
|
|
691
|
+
q.pop
|
|
789
692
|
}}}
|
|
790
693
|
end
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
694
|
+
q.push nil
|
|
695
|
+
q1.pop
|
|
696
|
+
cc.should be_a_kind_of(Sequel::Mock::Connection)
|
|
697
|
+
tr = @db.instance_variable_get(:@transactions)
|
|
698
|
+
tr.keys.should == [cc]
|
|
699
|
+
q.push nil
|
|
795
700
|
t.join
|
|
796
|
-
|
|
701
|
+
tr.should be_empty
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
specify "should correctly handle nested transacation use with separate shards" do
|
|
705
|
+
@db.transaction do |c1|
|
|
706
|
+
@db.transaction(:server=>:test) do |c2|
|
|
707
|
+
c1.should_not == c2
|
|
708
|
+
@db.execute 'DROP TABLE test;'
|
|
709
|
+
end
|
|
710
|
+
end
|
|
711
|
+
@db.sqls.should == ['BEGIN', 'BEGIN -- test', 'DROP TABLE test;', 'COMMIT -- test', 'COMMIT']
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
if (!defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or RUBY_ENGINE == 'rbx') and RUBY_VERSION < '1.9'
|
|
715
|
+
specify "should handle Thread#kill for transactions inside threads" do
|
|
716
|
+
q = Queue.new
|
|
717
|
+
q1 = Queue.new
|
|
718
|
+
t = Thread.new do
|
|
719
|
+
@db.transaction do
|
|
720
|
+
@db.execute 'DROP TABLE test'
|
|
721
|
+
q1.push nil
|
|
722
|
+
q.pop
|
|
723
|
+
@db.execute 'DROP TABLE test2'
|
|
724
|
+
end
|
|
725
|
+
end
|
|
726
|
+
q1.pop
|
|
727
|
+
t.kill
|
|
728
|
+
t.join
|
|
729
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
730
|
+
end
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
specify "should raise an Error if after_commit or after_rollback is called without a block" do
|
|
734
|
+
proc{@db.after_commit}.should raise_error(Sequel::Error)
|
|
735
|
+
proc{@db.after_rollback}.should raise_error(Sequel::Error)
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
specify "should have after_commit and after_rollback respect :server option" do
|
|
739
|
+
@db.transaction(:server=>:test){@db.after_commit(:server=>:test){@db.execute('foo', :server=>:test)}}
|
|
740
|
+
@db.sqls.should == ['BEGIN -- test', 'COMMIT -- test', 'foo -- test']
|
|
741
|
+
@db.transaction(:server=>:test){@db.after_rollback(:server=>:test){@db.execute('foo', :server=>:test)}; raise Sequel::Rollback}
|
|
742
|
+
@db.sqls.should == ['BEGIN -- test', 'ROLLBACK -- test', 'foo -- test']
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
specify "should execute after_commit outside transactions" do
|
|
746
|
+
@db.after_commit{@db.execute('foo')}
|
|
747
|
+
@db.sqls.should == ['foo']
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
specify "should ignore after_rollback outside transactions" do
|
|
751
|
+
@db.after_rollback{@db.execute('foo')}
|
|
752
|
+
@db.sqls.should == []
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
specify "should support after_commit inside transactions" do
|
|
756
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}}
|
|
757
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo']
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
specify "should support after_rollback inside transactions" do
|
|
761
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}}
|
|
762
|
+
@db.sqls.should == ['BEGIN', 'COMMIT']
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
specify "should not call after_commit if the transaction rolls back" do
|
|
766
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}; raise Sequel::Rollback}
|
|
767
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
specify "should call after_rollback if the transaction rolls back" do
|
|
771
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}; raise Sequel::Rollback}
|
|
772
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo']
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
specify "should call multiple after_commit blocks in order if called inside transactions" do
|
|
776
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}; @db.after_commit{@db.execute('bar')}}
|
|
777
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo', 'bar']
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
specify "should call multiple after_rollback blocks in order if called inside transactions" do
|
|
781
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}; @db.after_rollback{@db.execute('bar')}; raise Sequel::Rollback}
|
|
782
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo', 'bar']
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
specify "should support after_commit inside nested transactions" do
|
|
786
|
+
@db.transaction{@db.transaction{@db.after_commit{@db.execute('foo')}}}
|
|
787
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo']
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
specify "should support after_rollback inside nested transactions" do
|
|
791
|
+
@db.transaction{@db.transaction{@db.after_rollback{@db.execute('foo')}}; raise Sequel::Rollback}
|
|
792
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo']
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
specify "should raise an error if you attempt to use after_commit inside a prepared transaction" do
|
|
796
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
797
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{@db.execute('foo')}}}.should raise_error(Sequel::Error)
|
|
798
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
specify "should raise an error if you attempt to use after_rollback inside a prepared transaction" do
|
|
802
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
803
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{@db.execute('foo')}}}.should raise_error(Sequel::Error)
|
|
804
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
797
805
|
end
|
|
798
806
|
end
|
|
799
807
|
|
|
800
|
-
describe "Database#transaction with
|
|
808
|
+
describe "Database#transaction with savepoint support" do
|
|
801
809
|
before do
|
|
802
|
-
@db =
|
|
810
|
+
@db = Sequel.mock(:servers=>{:test=>{}})
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
it_should_behave_like "Database#transaction"
|
|
814
|
+
|
|
815
|
+
specify "should support after_commit inside savepoints" do
|
|
803
816
|
@db.meta_def(:supports_savepoints?){true}
|
|
817
|
+
@db.transaction do
|
|
818
|
+
@db.after_commit{@db.execute('foo')}
|
|
819
|
+
@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('bar')}}
|
|
820
|
+
@db.after_commit{@db.execute('baz')}
|
|
821
|
+
end
|
|
822
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT', 'foo', 'bar', 'baz']
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
specify "should support after_rollback inside savepoints" do
|
|
826
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
827
|
+
@db.transaction do
|
|
828
|
+
@db.after_rollback{@db.execute('foo')}
|
|
829
|
+
@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('bar')}}
|
|
830
|
+
@db.after_rollback{@db.execute('baz')}
|
|
831
|
+
raise Sequel::Rollback
|
|
832
|
+
end
|
|
833
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'ROLLBACK', 'foo', 'bar', 'baz']
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
specify "should raise an error if you attempt to use after_commit inside a savepoint in a prepared transaction" do
|
|
837
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
838
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
839
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
|
840
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
specify "should raise an error if you attempt to use after_rollback inside a savepoint in a prepared transaction" do
|
|
844
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
845
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
846
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
|
847
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
848
|
+
end
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
describe "Database#transaction without savepoint support" do
|
|
852
|
+
before do
|
|
853
|
+
@db = Sequel.mock(:servers=>{:test=>{}})
|
|
854
|
+
@db.meta_def(:supports_savepoints?){false}
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
it_should_behave_like "Database#transaction"
|
|
858
|
+
end
|
|
859
|
+
|
|
860
|
+
describe "Sequel.transaction" do
|
|
861
|
+
before do
|
|
862
|
+
@sqls = []
|
|
863
|
+
@db1 = Sequel.mock(:append=>'1', :sqls=>@sqls)
|
|
864
|
+
@db2 = Sequel.mock(:append=>'2', :sqls=>@sqls)
|
|
865
|
+
@db3 = Sequel.mock(:append=>'3', :sqls=>@sqls)
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
specify "should run the block inside transacitons on all three databases" do
|
|
869
|
+
Sequel.transaction([@db1, @db2, @db3]){1}.should == 1
|
|
870
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
specify "should pass options to all the blocks" do
|
|
874
|
+
Sequel.transaction([@db1, @db2, @db3], :rollback=>:always){1}.should be_nil
|
|
875
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
specify "should handle Sequel::Rollback exceptions raised by the block to rollback on all databases" do
|
|
879
|
+
Sequel.transaction([@db1, @db2, @db3]){raise Sequel::Rollback}.should be_nil
|
|
880
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
specify "should handle nested transactions" do
|
|
884
|
+
Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3]){1}}.should == 1
|
|
885
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
886
|
+
end
|
|
887
|
+
|
|
888
|
+
specify "should handle savepoints" do
|
|
889
|
+
Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3], :savepoint=>true){1}}.should == 1
|
|
890
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3',
|
|
891
|
+
'SAVEPOINT autopoint_1 -- 1', 'SAVEPOINT autopoint_1 -- 2', 'SAVEPOINT autopoint_1 -- 3',
|
|
892
|
+
'RELEASE SAVEPOINT autopoint_1 -- 3', 'RELEASE SAVEPOINT autopoint_1 -- 2', 'RELEASE SAVEPOINT autopoint_1 -- 1',
|
|
893
|
+
'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
894
|
+
end
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
describe "Database#transaction with savepoints" do
|
|
898
|
+
before do
|
|
899
|
+
@db = Sequel.mock
|
|
804
900
|
end
|
|
805
901
|
|
|
806
902
|
specify "should wrap the supplied block with BEGIN + COMMIT statements" do
|
|
807
903
|
@db.transaction {@db.execute 'DROP TABLE test;'}
|
|
808
|
-
@db.
|
|
904
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
809
905
|
end
|
|
810
906
|
|
|
811
907
|
specify "should use savepoints if given the :savepoint option" do
|
|
812
908
|
@db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}}
|
|
813
|
-
@db.
|
|
909
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
|
814
910
|
end
|
|
815
911
|
|
|
816
912
|
specify "should not use a savepoints if no transaction is in progress" do
|
|
817
913
|
@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}
|
|
818
|
-
@db.
|
|
914
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
819
915
|
end
|
|
820
916
|
|
|
821
917
|
specify "should reuse the current transaction if no :savepoint option is given" do
|
|
822
918
|
@db.transaction{@db.transaction{@db.execute 'DROP TABLE test;'}}
|
|
823
|
-
@db.
|
|
919
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
824
920
|
end
|
|
825
921
|
|
|
826
922
|
specify "should handle returning inside of the block by committing" do
|
|
@@ -832,7 +928,7 @@ describe "Database#transaction with savepoints" do
|
|
|
832
928
|
end
|
|
833
929
|
end
|
|
834
930
|
@db.ret_commit
|
|
835
|
-
@db.
|
|
931
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
836
932
|
end
|
|
837
933
|
|
|
838
934
|
specify "should handle returning inside of a savepoint by committing" do
|
|
@@ -846,34 +942,34 @@ describe "Database#transaction with savepoints" do
|
|
|
846
942
|
end
|
|
847
943
|
end
|
|
848
944
|
@db.ret_commit
|
|
849
|
-
@db.
|
|
945
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
|
850
946
|
end
|
|
851
947
|
|
|
852
948
|
specify "should issue ROLLBACK if an exception is raised, and re-raise" do
|
|
853
949
|
@db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
|
|
854
|
-
@db.
|
|
950
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
855
951
|
|
|
856
952
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
857
953
|
end
|
|
858
954
|
|
|
859
955
|
specify "should issue ROLLBACK SAVEPOINT if an exception is raised inside a savepoint, and re-raise" do
|
|
860
956
|
@db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test'; raise RuntimeError}} rescue nil
|
|
861
|
-
@db.
|
|
957
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test', 'ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
862
958
|
|
|
863
959
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
864
960
|
end
|
|
865
961
|
|
|
866
|
-
specify "should issue ROLLBACK if Sequel::Rollback is
|
|
962
|
+
specify "should issue ROLLBACK if Sequel::Rollback is raised in the transaction" do
|
|
867
963
|
@db.transaction do
|
|
868
964
|
@db.drop_table(:a)
|
|
869
965
|
raise Sequel::Rollback
|
|
870
966
|
@db.drop_table(:b)
|
|
871
967
|
end
|
|
872
968
|
|
|
873
|
-
@db.
|
|
969
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
|
|
874
970
|
end
|
|
875
971
|
|
|
876
|
-
specify "should issue ROLLBACK SAVEPOINT if Sequel::Rollback is
|
|
972
|
+
specify "should issue ROLLBACK SAVEPOINT if Sequel::Rollback is raised in a savepoint" do
|
|
877
973
|
@db.transaction do
|
|
878
974
|
@db.transaction(:savepoint=>true) do
|
|
879
975
|
@db.drop_table(:a)
|
|
@@ -882,7 +978,7 @@ describe "Database#transaction with savepoints" do
|
|
|
882
978
|
@db.drop_table(:b)
|
|
883
979
|
end
|
|
884
980
|
|
|
885
|
-
@db.
|
|
981
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE a', 'ROLLBACK TO SAVEPOINT autopoint_1', 'DROP TABLE b', 'COMMIT']
|
|
886
982
|
end
|
|
887
983
|
|
|
888
984
|
specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
|
|
@@ -898,37 +994,28 @@ end
|
|
|
898
994
|
|
|
899
995
|
describe "A Database adapter with a scheme" do
|
|
900
996
|
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
|
|
997
|
+
@ccc = Class.new(Sequel::Database)
|
|
998
|
+
@ccc.send(:set_adapter_scheme, :ccc)
|
|
912
999
|
end
|
|
913
1000
|
|
|
914
1001
|
specify "should be registered in the ADAPTER_MAP" do
|
|
915
|
-
Sequel::ADAPTER_MAP[:ccc].should ==
|
|
1002
|
+
Sequel::ADAPTER_MAP[:ccc].should == @ccc
|
|
916
1003
|
end
|
|
917
1004
|
|
|
918
1005
|
specify "should give the database_type as the adapter scheme by default" do
|
|
919
|
-
|
|
1006
|
+
@ccc.new.database_type.should == :ccc
|
|
920
1007
|
end
|
|
921
1008
|
|
|
922
1009
|
specify "should be instantiated when its scheme is specified" do
|
|
923
1010
|
c = Sequel::Database.connect('ccc://localhost/db')
|
|
924
|
-
c.should be_a_kind_of(
|
|
1011
|
+
c.should be_a_kind_of(@ccc)
|
|
925
1012
|
c.opts[:host].should == 'localhost'
|
|
926
1013
|
c.opts[:database].should == 'db'
|
|
927
1014
|
end
|
|
928
1015
|
|
|
929
1016
|
specify "should be accessible through Sequel.connect" do
|
|
930
1017
|
c = Sequel.connect 'ccc://localhost/db'
|
|
931
|
-
c.should be_a_kind_of(
|
|
1018
|
+
c.should be_a_kind_of(@ccc)
|
|
932
1019
|
c.opts[:host].should == 'localhost'
|
|
933
1020
|
c.opts[:database].should == 'db'
|
|
934
1021
|
end
|
|
@@ -940,7 +1027,7 @@ describe "A Database adapter with a scheme" do
|
|
|
940
1027
|
returnValue = 'anything'
|
|
941
1028
|
|
|
942
1029
|
p = proc do |c|
|
|
943
|
-
c.should be_a_kind_of(
|
|
1030
|
+
c.should be_a_kind_of(@ccc)
|
|
944
1031
|
c.opts[:host].should == 'localhost'
|
|
945
1032
|
c.opts[:database].should == 'db'
|
|
946
1033
|
z = y
|
|
@@ -948,15 +1035,22 @@ describe "A Database adapter with a scheme" do
|
|
|
948
1035
|
x = c
|
|
949
1036
|
returnValue
|
|
950
1037
|
end
|
|
1038
|
+
|
|
1039
|
+
@ccc.class_eval do
|
|
1040
|
+
self::DISCONNECTS = []
|
|
1041
|
+
def disconnect
|
|
1042
|
+
self.class::DISCONNECTS << self
|
|
1043
|
+
end
|
|
1044
|
+
end
|
|
951
1045
|
Sequel::Database.connect('ccc://localhost/db', &p).should == returnValue
|
|
952
|
-
|
|
1046
|
+
@ccc::DISCONNECTS.should == [x]
|
|
953
1047
|
|
|
954
1048
|
Sequel.connect('ccc://localhost/db', &p).should == returnValue
|
|
955
|
-
|
|
1049
|
+
@ccc::DISCONNECTS.should == [y, x]
|
|
956
1050
|
|
|
957
1051
|
Sequel.send(:def_adapter_method, :ccc)
|
|
958
1052
|
Sequel.ccc('db', :host=>'localhost', &p).should == returnValue
|
|
959
|
-
|
|
1053
|
+
@ccc::DISCONNECTS.should == [z, y, x]
|
|
960
1054
|
end
|
|
961
1055
|
|
|
962
1056
|
specify "should be accessible through Sequel.<adapter>" do
|
|
@@ -967,31 +1061,31 @@ describe "A Database adapter with a scheme" do
|
|
|
967
1061
|
|
|
968
1062
|
c = Sequel.ccc('mydb')
|
|
969
1063
|
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
|
|
1064
|
+
c.should be_a_kind_of(@ccc)
|
|
1065
|
+
p.call.should == {:adapter=>:ccc, :database => 'mydb', :adapter_class=>@ccc}
|
|
972
1066
|
|
|
973
1067
|
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
|
|
1068
|
+
c.should be_a_kind_of(@ccc)
|
|
1069
|
+
p.call.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost', :adapter_class=>@ccc}
|
|
976
1070
|
|
|
977
1071
|
c = Sequel.ccc
|
|
978
|
-
c.should be_a_kind_of(
|
|
979
|
-
p.call.should == {:adapter=>:ccc, :adapter_class
|
|
1072
|
+
c.should be_a_kind_of(@ccc)
|
|
1073
|
+
p.call.should == {:adapter=>:ccc, :adapter_class=>@ccc}
|
|
980
1074
|
|
|
981
1075
|
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
|
|
1076
|
+
c.should be_a_kind_of(@ccc)
|
|
1077
|
+
p.call.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost', :adapter_class=>@ccc}
|
|
984
1078
|
end
|
|
985
1079
|
|
|
986
1080
|
specify "should be accessible through Sequel.connect with options" do
|
|
987
1081
|
c = Sequel.connect(:adapter => :ccc, :database => 'mydb')
|
|
988
|
-
c.should be_a_kind_of(
|
|
1082
|
+
c.should be_a_kind_of(@ccc)
|
|
989
1083
|
c.opts[:adapter].should == :ccc
|
|
990
1084
|
end
|
|
991
1085
|
|
|
992
1086
|
specify "should be accessible through Sequel.connect with URL parameters" do
|
|
993
1087
|
c = Sequel.connect 'ccc:///db?host=/tmp&user=test'
|
|
994
|
-
c.should be_a_kind_of(
|
|
1088
|
+
c.should be_a_kind_of(@ccc)
|
|
995
1089
|
c.opts[:host].should == '/tmp'
|
|
996
1090
|
c.opts[:database].should == 'db'
|
|
997
1091
|
c.opts[:user].should == 'test'
|
|
@@ -999,14 +1093,14 @@ describe "A Database adapter with a scheme" do
|
|
|
999
1093
|
|
|
1000
1094
|
specify "should have URL parameters take precedence over fixed URL parts" do
|
|
1001
1095
|
c = Sequel.connect 'ccc://localhost/db?host=a&database=b'
|
|
1002
|
-
c.should be_a_kind_of(
|
|
1096
|
+
c.should be_a_kind_of(@ccc)
|
|
1003
1097
|
c.opts[:host].should == 'a'
|
|
1004
1098
|
c.opts[:database].should == 'b'
|
|
1005
1099
|
end
|
|
1006
1100
|
|
|
1007
1101
|
specify "should have hash options take predence over URL parameters or parts" do
|
|
1008
1102
|
c = Sequel.connect 'ccc://localhost/db?host=/tmp', :host=>'a', :database=>'b', :user=>'c'
|
|
1009
|
-
c.should be_a_kind_of(
|
|
1103
|
+
c.should be_a_kind_of(@ccc)
|
|
1010
1104
|
c.opts[:host].should == 'a'
|
|
1011
1105
|
c.opts[:database].should == 'b'
|
|
1012
1106
|
c.opts[:user].should == 'c'
|
|
@@ -1014,7 +1108,7 @@ describe "A Database adapter with a scheme" do
|
|
|
1014
1108
|
|
|
1015
1109
|
specify "should unescape values of URL parameters and parts" do
|
|
1016
1110
|
c = Sequel.connect 'ccc:///d%5bb%5d?host=domain%5cinstance'
|
|
1017
|
-
c.should be_a_kind_of(
|
|
1111
|
+
c.should be_a_kind_of(@ccc)
|
|
1018
1112
|
c.opts[:database].should == 'd[b]'
|
|
1019
1113
|
c.opts[:host].should == 'domain\\instance'
|
|
1020
1114
|
end
|
|
@@ -1129,10 +1223,6 @@ describe "A single threaded database" do
|
|
|
1129
1223
|
end
|
|
1130
1224
|
|
|
1131
1225
|
describe "A database" do
|
|
1132
|
-
before do
|
|
1133
|
-
Sequel::Database.single_threaded = false
|
|
1134
|
-
end
|
|
1135
|
-
|
|
1136
1226
|
after do
|
|
1137
1227
|
Sequel::Database.single_threaded = false
|
|
1138
1228
|
end
|
|
@@ -1177,11 +1267,7 @@ end
|
|
|
1177
1267
|
|
|
1178
1268
|
describe "Database#fetch" do
|
|
1179
1269
|
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)}
|
|
1270
|
+
@db = Sequel.mock(:fetch=>proc{|sql| {:sql => sql}})
|
|
1185
1271
|
end
|
|
1186
1272
|
|
|
1187
1273
|
specify "should create a dataset and invoke its fetch_rows method with the given sql" do
|
|
@@ -1228,143 +1314,54 @@ end
|
|
|
1228
1314
|
|
|
1229
1315
|
describe "Database#[]" do
|
|
1230
1316
|
before do
|
|
1231
|
-
@db = Sequel
|
|
1317
|
+
@db = Sequel.mock
|
|
1232
1318
|
end
|
|
1233
1319
|
|
|
1234
1320
|
specify "should return a dataset when symbols are given" do
|
|
1235
1321
|
ds = @db[:items]
|
|
1236
|
-
ds.
|
|
1322
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
1237
1323
|
ds.opts[:from].should == [:items]
|
|
1238
1324
|
end
|
|
1239
1325
|
|
|
1240
1326
|
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
|
-
|
|
1327
|
+
@db.fetch = proc{|sql| {:sql=>sql}}
|
|
1246
1328
|
sql = nil
|
|
1247
1329
|
@db['select * from xyz where x = ? and y = ?', 15, 'abc'].each {|r| sql = r[:sql]}
|
|
1248
1330
|
sql.should == "select * from xyz where x = 15 and y = 'abc'"
|
|
1249
1331
|
end
|
|
1250
1332
|
end
|
|
1251
1333
|
|
|
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
1334
|
describe "Database#inspect" do
|
|
1321
|
-
before do
|
|
1322
|
-
@db = DummyDatabase.new
|
|
1323
|
-
|
|
1324
|
-
@db.meta_def(:uri) {'blah://blahblah/blah'}
|
|
1325
|
-
end
|
|
1326
|
-
|
|
1327
1335
|
specify "should include the class name and the connection url" do
|
|
1328
|
-
|
|
1336
|
+
Sequel.connect('mock://foo/bar').inspect.should == '#<Sequel::Mock::Database: "mock://foo/bar">'
|
|
1329
1337
|
end
|
|
1330
1338
|
end
|
|
1331
1339
|
|
|
1332
1340
|
describe "Database#get" do
|
|
1333
1341
|
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
|
|
1342
|
+
@db = Sequel.mock(:fetch=>{:a=>1})
|
|
1346
1343
|
end
|
|
1347
1344
|
|
|
1348
1345
|
specify "should use Dataset#get to get a single value" do
|
|
1349
|
-
@db.get(1).should ==
|
|
1350
|
-
@db.sqls.
|
|
1346
|
+
@db.get(1).should == 1
|
|
1347
|
+
@db.sqls.should == ['SELECT 1 LIMIT 1']
|
|
1351
1348
|
|
|
1352
1349
|
@db.get(:version.sql_function)
|
|
1353
|
-
@db.sqls.
|
|
1350
|
+
@db.sqls.should == ['SELECT version() LIMIT 1']
|
|
1354
1351
|
end
|
|
1355
1352
|
|
|
1356
1353
|
specify "should accept a block" do
|
|
1357
1354
|
@db.get{1}
|
|
1358
|
-
@db.sqls.
|
|
1355
|
+
@db.sqls.should == ['SELECT 1 LIMIT 1']
|
|
1359
1356
|
|
|
1360
1357
|
@db.get{version(1)}
|
|
1361
|
-
@db.sqls.
|
|
1358
|
+
@db.sqls.should == ['SELECT version(1) LIMIT 1']
|
|
1362
1359
|
end
|
|
1363
1360
|
end
|
|
1364
1361
|
|
|
1365
1362
|
describe "Database#call" do
|
|
1366
1363
|
specify "should call the prepared statement with the given name" do
|
|
1367
|
-
db =
|
|
1364
|
+
db = Sequel.mock(:fetch=>{:id => 1, :x => 1})
|
|
1368
1365
|
db[:items].prepare(:select, :select_all)
|
|
1369
1366
|
db.call(:select_all).should == [{:id => 1, :x => 1}]
|
|
1370
1367
|
db[:items].filter(:n=>:$n).prepare(:select, :select_n)
|
|
@@ -1376,146 +1373,129 @@ end
|
|
|
1376
1373
|
describe "Database#server_opts" do
|
|
1377
1374
|
specify "should return the general opts if no :servers option is used" do
|
|
1378
1375
|
opts = {:host=>1, :database=>2}
|
|
1379
|
-
|
|
1376
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 1
|
|
1380
1377
|
end
|
|
1381
1378
|
|
|
1382
1379
|
specify "should return the general opts if entry for the server is present in the :servers option" do
|
|
1383
1380
|
opts = {:host=>1, :database=>2, :servers=>{}}
|
|
1384
|
-
|
|
1381
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 1
|
|
1385
1382
|
end
|
|
1386
1383
|
|
|
1387
1384
|
specify "should return the general opts merged with the specific opts if given as a hash" do
|
|
1388
1385
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}}}
|
|
1389
|
-
|
|
1386
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 3
|
|
1390
1387
|
end
|
|
1391
1388
|
|
|
1392
1389
|
specify "should return the sgeneral opts merged with the specific opts if given as a proc" do
|
|
1393
1390
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>proc{|db| {:host=>4}}}}
|
|
1394
|
-
|
|
1391
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 4
|
|
1395
1392
|
end
|
|
1396
1393
|
|
|
1397
1394
|
specify "should raise an error if the specific opts is not a proc or hash" do
|
|
1398
1395
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>2}}
|
|
1399
|
-
proc{
|
|
1396
|
+
proc{Sequel::Database.new(opts).send(:server_opts, :server1)}.should raise_error(Sequel::Error)
|
|
1400
1397
|
end
|
|
1401
1398
|
end
|
|
1402
1399
|
|
|
1403
1400
|
describe "Database#add_servers" do
|
|
1404
1401
|
before do
|
|
1405
|
-
@db =
|
|
1406
|
-
def @db.connect(server)
|
|
1407
|
-
server_opts(server)
|
|
1408
|
-
end
|
|
1409
|
-
def @db.disconnect_connection(c)
|
|
1410
|
-
end
|
|
1402
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}})
|
|
1411
1403
|
end
|
|
1412
1404
|
|
|
1413
1405
|
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}
|
|
1406
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1407
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1408
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1417
1409
|
|
|
1418
1410
|
@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}
|
|
1411
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1412
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1413
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 6}
|
|
1422
1414
|
|
|
1423
1415
|
@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}
|
|
1416
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1417
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1418
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 6}
|
|
1427
1419
|
end
|
|
1428
1420
|
|
|
1429
1421
|
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}
|
|
1422
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1423
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1424
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1433
1425
|
|
|
1434
1426
|
@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}
|
|
1427
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1428
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1429
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1438
1430
|
|
|
1439
1431
|
@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}
|
|
1432
|
+
@db.synchronize{|c| c.opts[:host].should == 4}
|
|
1433
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 8}
|
|
1434
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 4}
|
|
1443
1435
|
end
|
|
1444
1436
|
end
|
|
1445
1437
|
|
|
1446
1438
|
describe "Database#remove_servers" do
|
|
1447
1439
|
before do
|
|
1448
|
-
@db =
|
|
1449
|
-
def @db.connect(server)
|
|
1450
|
-
server_opts(server)
|
|
1451
|
-
end
|
|
1452
|
-
def @db.disconnect_connection(c)
|
|
1453
|
-
end
|
|
1440
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
|
|
1454
1441
|
end
|
|
1455
1442
|
|
|
1456
1443
|
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}
|
|
1444
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1445
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1446
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 4}
|
|
1460
1447
|
|
|
1461
1448
|
@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}
|
|
1449
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1450
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 1}
|
|
1451
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1465
1452
|
end
|
|
1466
1453
|
|
|
1467
1454
|
specify "should accept arrays of symbols" do
|
|
1468
1455
|
@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}
|
|
1456
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1457
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 1}
|
|
1458
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1472
1459
|
end
|
|
1473
1460
|
|
|
1474
1461
|
specify "should allow removal while connections are still open" do
|
|
1475
1462
|
@db.synchronize do |c1|
|
|
1476
|
-
c1[:host].should == 1
|
|
1463
|
+
c1.opts[:host].should == 1
|
|
1477
1464
|
@db.synchronize(:server1) do |c2|
|
|
1478
|
-
c2[:host].should == 3
|
|
1465
|
+
c2.opts[:host].should == 3
|
|
1479
1466
|
@db.synchronize(:server2) do |c3|
|
|
1480
|
-
c3[:host].should == 4
|
|
1467
|
+
c3.opts[:host].should == 4
|
|
1481
1468
|
@db.remove_servers(:server1, :server2)
|
|
1482
1469
|
@db.synchronize(:server1) do |c4|
|
|
1483
1470
|
c4.should_not == c2
|
|
1484
1471
|
c4.should == c1
|
|
1485
|
-
c4[:host].should == 1
|
|
1472
|
+
c4.opts[:host].should == 1
|
|
1486
1473
|
@db.synchronize(:server2) do |c5|
|
|
1487
1474
|
c5.should_not == c3
|
|
1488
1475
|
c5.should == c1
|
|
1489
|
-
c5[:host].should == 1
|
|
1476
|
+
c5.opts[:host].should == 1
|
|
1490
1477
|
end
|
|
1491
1478
|
end
|
|
1492
|
-
c3[:host].should == 4
|
|
1479
|
+
c3.opts[:host].should == 4
|
|
1493
1480
|
end
|
|
1494
|
-
c2[:host].should == 3
|
|
1481
|
+
c2.opts[:host].should == 3
|
|
1495
1482
|
end
|
|
1496
|
-
c1[:host].should == 1
|
|
1483
|
+
c1.opts[:host].should == 1
|
|
1497
1484
|
end
|
|
1498
1485
|
end
|
|
1499
1486
|
end
|
|
1500
1487
|
|
|
1501
1488
|
describe "Database#each_server with do/jdbc adapter connection string without :adapter option" do
|
|
1502
|
-
|
|
1489
|
+
specify "should yield a separate database object for each server" do
|
|
1503
1490
|
klass = Class.new(Sequel::Database)
|
|
1504
|
-
klass.should_receive(:adapter_class).once.with(:jdbc).and_return(
|
|
1491
|
+
klass.should_receive(:adapter_class).once.with(:jdbc).and_return(Sequel::Mock::Database)
|
|
1505
1492
|
@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
1493
|
|
|
1513
|
-
specify "should yield a separate database object for each server" do
|
|
1514
1494
|
hosts = []
|
|
1515
1495
|
@db.each_server do |db|
|
|
1516
1496
|
db.should be_a_kind_of(Sequel::Database)
|
|
1517
1497
|
db.should_not == @db
|
|
1518
|
-
db.opts[:adapter_class].should ==
|
|
1498
|
+
db.opts[:adapter_class].should == Sequel::Mock::Database
|
|
1519
1499
|
db.opts[:database].should == 2
|
|
1520
1500
|
hosts << db.opts[:host]
|
|
1521
1501
|
end
|
|
@@ -1525,12 +1505,7 @@ end
|
|
|
1525
1505
|
|
|
1526
1506
|
describe "Database#each_server" do
|
|
1527
1507
|
before do
|
|
1528
|
-
@db = Sequel.
|
|
1529
|
-
def @db.connect(server)
|
|
1530
|
-
server_opts(server)
|
|
1531
|
-
end
|
|
1532
|
-
def @db.disconnect_connection(c)
|
|
1533
|
-
end
|
|
1508
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
|
|
1534
1509
|
end
|
|
1535
1510
|
|
|
1536
1511
|
specify "should yield a separate database object for each server" do
|
|
@@ -1561,21 +1536,25 @@ describe "Database#each_server" do
|
|
|
1561
1536
|
end
|
|
1562
1537
|
|
|
1563
1538
|
describe "Database#raise_error" do
|
|
1539
|
+
before do
|
|
1540
|
+
@db = Sequel.mock
|
|
1541
|
+
end
|
|
1542
|
+
|
|
1564
1543
|
specify "should reraise if the exception class is not in opts[:classes]" do
|
|
1565
1544
|
e = Class.new(StandardError)
|
|
1566
|
-
proc{
|
|
1545
|
+
proc{@db.send(:raise_error, e.new(''), :classes=>[])}.should raise_error(e)
|
|
1567
1546
|
end
|
|
1568
1547
|
|
|
1569
|
-
specify "should convert the exception to a DatabaseError if the exception class is
|
|
1570
|
-
proc{
|
|
1548
|
+
specify "should convert the exception to a DatabaseError if the exception class is in opts[:classes]" do
|
|
1549
|
+
proc{@db.send(:raise_error, Interrupt.new(''), :classes=>[Interrupt])}.should raise_error(Sequel::DatabaseError)
|
|
1571
1550
|
end
|
|
1572
1551
|
|
|
1573
1552
|
specify "should convert the exception to a DatabaseError if opts[:classes] if not present" do
|
|
1574
|
-
proc{
|
|
1553
|
+
proc{@db.send(:raise_error, Interrupt.new(''))}.should raise_error(Sequel::DatabaseError)
|
|
1575
1554
|
end
|
|
1576
1555
|
|
|
1577
1556
|
specify "should convert the exception to a DatabaseDisconnectError if opts[:disconnect] is true" do
|
|
1578
|
-
proc{
|
|
1557
|
+
proc{@db.send(:raise_error, Interrupt.new(''), :disconnect=>true)}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1579
1558
|
end
|
|
1580
1559
|
end
|
|
1581
1560
|
|
|
@@ -1594,6 +1573,303 @@ describe "Database#typecast_value" do
|
|
|
1594
1573
|
proc{@db.typecast_value(:datetime, 4)}.should raise_error(Sequel::InvalidValue)
|
|
1595
1574
|
end
|
|
1596
1575
|
|
|
1576
|
+
specify "should handle integers with leading 0 as base 10" do
|
|
1577
|
+
@db.typecast_value(:integer, "013").should == 13
|
|
1578
|
+
@db.typecast_value(:integer, "08").should == 8
|
|
1579
|
+
@db.typecast_value(:integer, "000013").should == 13
|
|
1580
|
+
@db.typecast_value(:integer, "000008").should == 8
|
|
1581
|
+
end
|
|
1582
|
+
|
|
1583
|
+
specify "should handle integers with leading 0x as base 16" do
|
|
1584
|
+
@db.typecast_value(:integer, "0x013").should == 19
|
|
1585
|
+
@db.typecast_value(:integer, "0x80").should == 128
|
|
1586
|
+
end
|
|
1587
|
+
|
|
1588
|
+
specify "should typecast blobs as as Sequel::SQL::Blob" do
|
|
1589
|
+
v = @db.typecast_value(:blob, "0x013")
|
|
1590
|
+
v.should be_a_kind_of(Sequel::SQL::Blob)
|
|
1591
|
+
v.should == Sequel::SQL::Blob.new("0x013")
|
|
1592
|
+
@db.typecast_value(:blob, v).object_id.should == v.object_id
|
|
1593
|
+
end
|
|
1594
|
+
|
|
1595
|
+
specify "should typecast boolean values to true, false, or nil" do
|
|
1596
|
+
@db.typecast_value(:boolean, false).should be_false
|
|
1597
|
+
@db.typecast_value(:boolean, 0).should be_false
|
|
1598
|
+
@db.typecast_value(:boolean, "0").should be_false
|
|
1599
|
+
@db.typecast_value(:boolean, 'f').should be_false
|
|
1600
|
+
@db.typecast_value(:boolean, 'false').should be_false
|
|
1601
|
+
@db.typecast_value(:boolean, true).should be_true
|
|
1602
|
+
@db.typecast_value(:boolean, 1).should be_true
|
|
1603
|
+
@db.typecast_value(:boolean, '1').should be_true
|
|
1604
|
+
@db.typecast_value(:boolean, 't').should be_true
|
|
1605
|
+
@db.typecast_value(:boolean, 'true').should be_true
|
|
1606
|
+
@db.typecast_value(:boolean, '').should be_nil
|
|
1607
|
+
end
|
|
1608
|
+
|
|
1609
|
+
specify "should typecast date values to Date" do
|
|
1610
|
+
@db.typecast_value(:date, Date.today).should == Date.today
|
|
1611
|
+
@db.typecast_value(:date, DateTime.now).should == Date.today
|
|
1612
|
+
@db.typecast_value(:date, Time.now).should == Date.today
|
|
1613
|
+
@db.typecast_value(:date, Date.today.to_s).should == Date.today
|
|
1614
|
+
@db.typecast_value(:date, :year=>Date.today.year, :month=>Date.today.month, :day=>Date.today.day).should == Date.today
|
|
1615
|
+
end
|
|
1616
|
+
|
|
1617
|
+
specify "should have Sequel.application_to_database_timestamp convert to Sequel.database_timezone" do
|
|
1618
|
+
begin
|
|
1619
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1620
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1621
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1622
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1623
|
+
Sequel.application_timezone = :utc
|
|
1624
|
+
Sequel.database_timezone = :local
|
|
1625
|
+
Sequel.application_to_database_timestamp(t).should == t4
|
|
1626
|
+
Sequel.application_timezone = :local
|
|
1627
|
+
Sequel.database_timezone = :utc
|
|
1628
|
+
Sequel.application_to_database_timestamp(t2).should == t3
|
|
1629
|
+
ensure
|
|
1630
|
+
Sequel.default_timezone = nil
|
|
1631
|
+
end
|
|
1632
|
+
end
|
|
1633
|
+
|
|
1634
|
+
specify "should have Database#to_application_timestamp convert values using the database's timezone" do
|
|
1635
|
+
begin
|
|
1636
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1637
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1638
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1639
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1640
|
+
Sequel.default_timezone = :utc
|
|
1641
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t
|
|
1642
|
+
Sequel.database_timezone = :local
|
|
1643
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t3
|
|
1644
|
+
Sequel.default_timezone = :local
|
|
1645
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t2
|
|
1646
|
+
Sequel.database_timezone = :utc
|
|
1647
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t4
|
|
1648
|
+
|
|
1649
|
+
Sequel.default_timezone = :utc
|
|
1650
|
+
@db.timezone = :local
|
|
1651
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t3
|
|
1652
|
+
Sequel.default_timezone = :local
|
|
1653
|
+
@db.timezone = :utc
|
|
1654
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t4
|
|
1655
|
+
ensure
|
|
1656
|
+
Sequel.default_timezone = nil
|
|
1657
|
+
end
|
|
1658
|
+
end
|
|
1659
|
+
|
|
1660
|
+
specify "should typecast datetime values to Sequel.datetime_class with correct timezone handling" do
|
|
1661
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1662
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1663
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1664
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1665
|
+
dt = DateTime.civil(2011, 1, 2, 3, 4, 5)
|
|
1666
|
+
r1 = defined?(Rational) ? Rational(t2.utc_offset, 86400) : t2.utc_offset/86400.0
|
|
1667
|
+
r2 = defined?(Rational) ? Rational((t - t2).to_i, 86400) : (t - t2).to_i/86400.0
|
|
1668
|
+
dt2 = DateTime.civil(2011, 1, 2, 3, 4, 5, r1)
|
|
1669
|
+
dt3 = DateTime.civil(2011, 1, 2, 3, 4, 5) - r2
|
|
1670
|
+
dt4 = DateTime.civil(2011, 1, 2, 3, 4, 5, r1) + r2
|
|
1671
|
+
|
|
1672
|
+
t.should == t4
|
|
1673
|
+
t2.should == t3
|
|
1674
|
+
dt.should == dt4
|
|
1675
|
+
dt2.should == dt3
|
|
1676
|
+
|
|
1677
|
+
check = proc do |i, o|
|
|
1678
|
+
v = @db.typecast_value(:datetime, i)
|
|
1679
|
+
v.should == o
|
|
1680
|
+
if o.is_a?(Time)
|
|
1681
|
+
v.utc_offset.should == o.utc_offset
|
|
1682
|
+
else
|
|
1683
|
+
v.offset.should == o.offset
|
|
1684
|
+
end
|
|
1685
|
+
end
|
|
1686
|
+
begin
|
|
1687
|
+
@db.typecast_value(:datetime, dt).should == t
|
|
1688
|
+
@db.typecast_value(:datetime, dt2).should == t2
|
|
1689
|
+
@db.typecast_value(:datetime, t).should == t
|
|
1690
|
+
@db.typecast_value(:datetime, t2).should == t2
|
|
1691
|
+
@db.typecast_value(:datetime, dt.to_s).should == t
|
|
1692
|
+
@db.typecast_value(:datetime, dt.strftime('%F %T')).should == t2
|
|
1693
|
+
@db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == Time.mktime(2011, 1, 2, 0, 0, 0)
|
|
1694
|
+
@db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec).should == t2
|
|
1695
|
+
|
|
1696
|
+
Sequel.datetime_class = DateTime
|
|
1697
|
+
@db.typecast_value(:datetime, dt).should == dt
|
|
1698
|
+
@db.typecast_value(:datetime, dt2).should == dt2
|
|
1699
|
+
@db.typecast_value(:datetime, t).should == dt
|
|
1700
|
+
@db.typecast_value(:datetime, t2).should == dt2
|
|
1701
|
+
@db.typecast_value(:datetime, dt.to_s).should == dt
|
|
1702
|
+
@db.typecast_value(:datetime, dt.strftime('%F %T')).should == dt
|
|
1703
|
+
@db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == DateTime.civil(2011, 1, 2, 0, 0, 0)
|
|
1704
|
+
@db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec).should == dt
|
|
1705
|
+
|
|
1706
|
+
Sequel.application_timezone = :utc
|
|
1707
|
+
Sequel.typecast_timezone = :local
|
|
1708
|
+
Sequel.datetime_class = Time
|
|
1709
|
+
check[dt, t]
|
|
1710
|
+
check[dt2, t3]
|
|
1711
|
+
check[t, t]
|
|
1712
|
+
check[t2, t3]
|
|
1713
|
+
check[dt.to_s, t]
|
|
1714
|
+
check[dt.strftime('%F %T'), t3]
|
|
1715
|
+
check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
|
|
1716
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t3]
|
|
1717
|
+
|
|
1718
|
+
Sequel.datetime_class = DateTime
|
|
1719
|
+
check[dt, dt]
|
|
1720
|
+
check[dt2, dt3]
|
|
1721
|
+
check[t, dt]
|
|
1722
|
+
check[t2, dt3]
|
|
1723
|
+
check[dt.to_s, dt]
|
|
1724
|
+
check[dt.strftime('%F %T'), dt3]
|
|
1725
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
|
|
1726
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt3]
|
|
1727
|
+
|
|
1728
|
+
Sequel.typecast_timezone = :utc
|
|
1729
|
+
Sequel.datetime_class = Time
|
|
1730
|
+
check[dt, t]
|
|
1731
|
+
check[dt2, t3]
|
|
1732
|
+
check[t, t]
|
|
1733
|
+
check[t2, t3]
|
|
1734
|
+
check[dt.to_s, t]
|
|
1735
|
+
check[dt.strftime('%F %T'), t]
|
|
1736
|
+
check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
|
|
1737
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t]
|
|
1738
|
+
|
|
1739
|
+
Sequel.datetime_class = DateTime
|
|
1740
|
+
check[dt, dt]
|
|
1741
|
+
check[dt2, dt3]
|
|
1742
|
+
check[t, dt]
|
|
1743
|
+
check[t2, dt3]
|
|
1744
|
+
check[dt.to_s, dt]
|
|
1745
|
+
check[dt.strftime('%F %T'), dt]
|
|
1746
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
|
|
1747
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt]
|
|
1748
|
+
|
|
1749
|
+
Sequel.application_timezone = :local
|
|
1750
|
+
Sequel.datetime_class = Time
|
|
1751
|
+
check[dt, t4]
|
|
1752
|
+
check[dt2, t2]
|
|
1753
|
+
check[t, t4]
|
|
1754
|
+
check[t2, t2]
|
|
1755
|
+
check[dt.to_s, t4]
|
|
1756
|
+
check[dt.strftime('%F %T'), t4]
|
|
1757
|
+
check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
|
|
1758
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t4]
|
|
1759
|
+
|
|
1760
|
+
Sequel.datetime_class = DateTime
|
|
1761
|
+
check[dt, dt4]
|
|
1762
|
+
check[dt2, dt2]
|
|
1763
|
+
check[t, dt4]
|
|
1764
|
+
check[t2, dt2]
|
|
1765
|
+
check[dt.to_s, dt4]
|
|
1766
|
+
check[dt.strftime('%F %T'), dt4]
|
|
1767
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
|
|
1768
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt4]
|
|
1769
|
+
|
|
1770
|
+
Sequel.typecast_timezone = :local
|
|
1771
|
+
Sequel.datetime_class = Time
|
|
1772
|
+
check[dt, t4]
|
|
1773
|
+
check[dt2, t2]
|
|
1774
|
+
check[t, t4]
|
|
1775
|
+
check[t2, t2]
|
|
1776
|
+
check[dt.to_s, t4]
|
|
1777
|
+
check[dt.strftime('%F %T'), t2]
|
|
1778
|
+
check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
|
|
1779
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, t2]
|
|
1780
|
+
|
|
1781
|
+
Sequel.datetime_class = DateTime
|
|
1782
|
+
check[dt, dt4]
|
|
1783
|
+
check[dt2, dt2]
|
|
1784
|
+
check[t, dt4]
|
|
1785
|
+
check[t2, dt2]
|
|
1786
|
+
check[dt.to_s, dt4]
|
|
1787
|
+
check[dt.strftime('%F %T'), dt2]
|
|
1788
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
|
|
1789
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec}, dt2]
|
|
1790
|
+
|
|
1791
|
+
ensure
|
|
1792
|
+
Sequel.default_timezone = nil
|
|
1793
|
+
Sequel.datetime_class = Time
|
|
1794
|
+
end
|
|
1795
|
+
end
|
|
1796
|
+
|
|
1797
|
+
specify "should handle arrays when typecasting timestamps" do
|
|
1798
|
+
begin
|
|
1799
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14]).should == Time.local(2011, 10, 11, 12, 13, 14)
|
|
1800
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14, 500000000]).should == Time.local(2011, 10, 11, 12, 13, 14, 500000)
|
|
1801
|
+
|
|
1802
|
+
Sequel.datetime_class = DateTime
|
|
1803
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14]).should == DateTime.civil(2011, 10, 11, 12, 13, 14)
|
|
1804
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14, 500000000]).should == DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5))
|
|
1805
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14, 500000000, (defined?(Rational) ? Rational(1, 2) : 0.5)]).should == DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5), (defined?(Rational) ? Rational(1, 2) : 0.5))
|
|
1806
|
+
ensure
|
|
1807
|
+
Sequel.datetime_class = Time
|
|
1808
|
+
end
|
|
1809
|
+
end
|
|
1810
|
+
|
|
1811
|
+
specify "should handle hashes when typecasting timestamps" do
|
|
1812
|
+
begin
|
|
1813
|
+
@db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14).should == Time.local(2011, 10, 11, 12, 13, 14)
|
|
1814
|
+
@db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :nanos=>500000000).should == Time.local(2011, 10, 11, 12, 13, 14, 500000)
|
|
1815
|
+
@db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14).should == Time.local(2011, 10, 11, 12, 13, 14)
|
|
1816
|
+
@db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'nanos'=>500000000).should == Time.local(2011, 10, 11, 12, 13, 14, 500000)
|
|
1817
|
+
|
|
1818
|
+
Sequel.datetime_class = DateTime
|
|
1819
|
+
@db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14).should == DateTime.civil(2011, 10, 11, 12, 13, 14)
|
|
1820
|
+
@db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :nanos=>500000000).should == DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5))
|
|
1821
|
+
@db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14).should == DateTime.civil(2011, 10, 11, 12, 13, 14)
|
|
1822
|
+
@db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'nanos'=>500000000).should == DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5))
|
|
1823
|
+
@db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :offset=>(defined?(Rational) ? Rational(1, 2) : 0.5)).should == DateTime.civil(2011, 10, 11, 12, 13, 14, (defined?(Rational) ? Rational(1, 2) : 0.5))
|
|
1824
|
+
@db.typecast_value(:datetime, :year=>2011, :month=>10, :day=>11, :hour=>12, :minute=>13, :second=>14, :nanos=>500000000, :offset=>(defined?(Rational) ? Rational(1, 2) : 0.5)).should == DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5), (defined?(Rational) ? Rational(1, 2) : 0.5))
|
|
1825
|
+
@db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'offset'=>(defined?(Rational) ? Rational(1, 2) : 0.5)).should == DateTime.civil(2011, 10, 11, 12, 13, 14, (defined?(Rational) ? Rational(1, 2) : 0.5))
|
|
1826
|
+
@db.typecast_value(:datetime, 'year'=>2011, 'month'=>10, 'day'=>11, 'hour'=>12, 'minute'=>13, 'second'=>14, 'nanos'=>500000000, 'offset'=>(defined?(Rational) ? Rational(1, 2) : 0.5)).should == DateTime.civil(2011, 10, 11, 12, 13, (defined?(Rational) ? Rational(29, 2) : 14.5), (defined?(Rational) ? Rational(1, 2) : 0.5))
|
|
1827
|
+
ensure
|
|
1828
|
+
Sequel.datetime_class = Time
|
|
1829
|
+
end
|
|
1830
|
+
end
|
|
1831
|
+
|
|
1832
|
+
specify "should typecast decimal values to BigDecimal" do
|
|
1833
|
+
[1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
|
|
1834
|
+
v = @db.typecast_value(:decimal, i)
|
|
1835
|
+
v.should be_a_kind_of(BigDecimal)
|
|
1836
|
+
v.should == BigDecimal.new('1.0')
|
|
1837
|
+
end
|
|
1838
|
+
end
|
|
1839
|
+
|
|
1840
|
+
specify "should typecast float values to Float" do
|
|
1841
|
+
[1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
|
|
1842
|
+
v = @db.typecast_value(:float, i)
|
|
1843
|
+
v.should be_a_kind_of(Float)
|
|
1844
|
+
v.should == 1.0
|
|
1845
|
+
end
|
|
1846
|
+
end
|
|
1847
|
+
|
|
1848
|
+
specify "should typecast string values to String" do
|
|
1849
|
+
[1.0, '1.0', '1.0'.to_sequel_blob].each do |i|
|
|
1850
|
+
v = @db.typecast_value(:string, i)
|
|
1851
|
+
v.should be_an_instance_of(String)
|
|
1852
|
+
v.should == "1.0"
|
|
1853
|
+
end
|
|
1854
|
+
end
|
|
1855
|
+
|
|
1856
|
+
specify "should typecast time values to SQLTime" do
|
|
1857
|
+
t = Time.now
|
|
1858
|
+
st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3)
|
|
1859
|
+
[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|
|
|
1860
|
+
v = @db.typecast_value(:time, i)
|
|
1861
|
+
v.should be_an_instance_of(Sequel::SQLTime)
|
|
1862
|
+
v.should == st
|
|
1863
|
+
end
|
|
1864
|
+
end
|
|
1865
|
+
|
|
1866
|
+
specify "should correctly handle time value conversion to SQLTime with fractional seconds" do
|
|
1867
|
+
t = Time.now
|
|
1868
|
+
st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3, 500000)
|
|
1869
|
+
t = Time.local(t.year, t.month, t.day, 1, 2, 3, 500000)
|
|
1870
|
+
@db.typecast_value(:time, t).should == st
|
|
1871
|
+
end
|
|
1872
|
+
|
|
1597
1873
|
specify "should have an underlying exception class available at wrapped_exception" do
|
|
1598
1874
|
begin
|
|
1599
1875
|
@db.typecast_value(:date, 'a')
|
|
@@ -1639,7 +1915,7 @@ describe "Database#blank_object?" do
|
|
|
1639
1915
|
end
|
|
1640
1916
|
|
|
1641
1917
|
describe "Database#schema_autoincrementing_primary_key?" do
|
|
1642
|
-
specify "should whether the parsed schema row indicates a primary key" do
|
|
1918
|
+
specify "should indicate whether the parsed schema row indicates a primary key" do
|
|
1643
1919
|
m = Sequel::Database.new.method(:schema_autoincrementing_primary_key?)
|
|
1644
1920
|
m.call(:primary_key=>true).should == true
|
|
1645
1921
|
m.call(:primary_key=>false).should == false
|
|
@@ -1695,7 +1971,7 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1695
1971
|
db = Sequel::Database.new
|
|
1696
1972
|
m = db.method(:column_schema_to_ruby_default)
|
|
1697
1973
|
p = lambda{|d,t| m.call(d,t)}
|
|
1698
|
-
p[nil, :integer].should
|
|
1974
|
+
p[nil, :integer].should be_nil
|
|
1699
1975
|
p['1', :integer].should == 1
|
|
1700
1976
|
p['-1', :integer].should == -1
|
|
1701
1977
|
p['1.0', :float].should == 1.0
|
|
@@ -1715,12 +1991,12 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1715
1991
|
p["'\\a''b'", :string].should == "\\a'b"
|
|
1716
1992
|
p["'NULL'", :string].should == "NULL"
|
|
1717
1993
|
p["'2009-10-29'", :date].should == Date.new(2009,10,29)
|
|
1718
|
-
p["CURRENT_TIMESTAMP", :date].should
|
|
1719
|
-
p["today()", :date].should
|
|
1994
|
+
p["CURRENT_TIMESTAMP", :date].should be_nil
|
|
1995
|
+
p["today()", :date].should be_nil
|
|
1720
1996
|
p["'2009-10-29T10:20:30-07:00'", :datetime].should == DateTime.parse('2009-10-29T10:20:30-07:00')
|
|
1721
1997
|
p["'2009-10-29 10:20:30'", :datetime].should == DateTime.parse('2009-10-29 10:20:30')
|
|
1722
1998
|
p["'10:20:30'", :time].should == Time.parse('10:20:30')
|
|
1723
|
-
p["NaN", :float].should
|
|
1999
|
+
p["NaN", :float].should be_nil
|
|
1724
2000
|
|
|
1725
2001
|
db.meta_def(:database_type){:postgres}
|
|
1726
2002
|
p["''::text", :string].should == ""
|
|
@@ -1744,8 +2020,8 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1744
2020
|
p["2009-10-29", :date].should == Date.new(2009,10,29)
|
|
1745
2021
|
p["2009-10-29 10:20:30", :datetime].should == DateTime.parse('2009-10-29 10:20:30')
|
|
1746
2022
|
p["10:20:30", :time].should == Time.parse('10:20:30')
|
|
1747
|
-
p["CURRENT_DATE", :date].should
|
|
1748
|
-
p["CURRENT_TIMESTAMP", :datetime].should
|
|
2023
|
+
p["CURRENT_DATE", :date].should be_nil
|
|
2024
|
+
p["CURRENT_TIMESTAMP", :datetime].should be_nil
|
|
1749
2025
|
p["a", :enum].should == "a"
|
|
1750
2026
|
|
|
1751
2027
|
db.meta_def(:database_type){:mssql}
|