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