sequel 3.21.0 → 3.41.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 +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +576 -0
- data/doc/opening_databases.rdoc +121 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- 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/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +539 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +334 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +137 -16
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +77 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +168 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -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 +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- 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 +57 -12
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +227 -33
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- 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/connection_validator_spec.rb +118 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +324 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +200 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +340 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- 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 +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +65 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -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 +8 -11
- data/spec/extensions/touch_spec.rb +53 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +223 -81
- data/spec/core/core_sql_spec.rb +0 -451
data/spec/core/database_spec.rb
CHANGED
|
@@ -37,7 +37,8 @@ describe "A new Database" do
|
|
|
37
37
|
|
|
38
38
|
specify "should pass the supplied block to the connection pool" do
|
|
39
39
|
cc = nil
|
|
40
|
-
d = Sequel::Database.new
|
|
40
|
+
d = Sequel::Database.new
|
|
41
|
+
d.meta_def(:connect){|c| 1234}
|
|
41
42
|
d.synchronize {|c| cc = c}
|
|
42
43
|
cc.should == 1234
|
|
43
44
|
end
|
|
@@ -74,46 +75,46 @@ describe "A new Database" do
|
|
|
74
75
|
Sequel.identifier_input_method = nil
|
|
75
76
|
Sequel::Database.identifier_input_method.should == ""
|
|
76
77
|
db = Sequel::Database.new(:identifier_input_method=>nil)
|
|
77
|
-
db.identifier_input_method.should
|
|
78
|
+
db.identifier_input_method.should be_nil
|
|
78
79
|
db.identifier_input_method = :downcase
|
|
79
80
|
db.identifier_input_method.should == :downcase
|
|
80
81
|
db = Sequel::Database.new(:identifier_input_method=>:upcase)
|
|
81
82
|
db.identifier_input_method.should == :upcase
|
|
82
83
|
db.identifier_input_method = nil
|
|
83
|
-
db.identifier_input_method.should
|
|
84
|
+
db.identifier_input_method.should be_nil
|
|
84
85
|
Sequel.identifier_input_method = :downcase
|
|
85
86
|
Sequel::Database.identifier_input_method.should == :downcase
|
|
86
87
|
db = Sequel::Database.new(:identifier_input_method=>nil)
|
|
87
|
-
db.identifier_input_method.should
|
|
88
|
+
db.identifier_input_method.should be_nil
|
|
88
89
|
db.identifier_input_method = :upcase
|
|
89
90
|
db.identifier_input_method.should == :upcase
|
|
90
91
|
db = Sequel::Database.new(:identifier_input_method=>:upcase)
|
|
91
92
|
db.identifier_input_method.should == :upcase
|
|
92
93
|
db.identifier_input_method = nil
|
|
93
|
-
db.identifier_input_method.should
|
|
94
|
+
db.identifier_input_method.should be_nil
|
|
94
95
|
end
|
|
95
96
|
|
|
96
97
|
specify "should respect the :identifier_output_method option" do
|
|
97
98
|
Sequel.identifier_output_method = nil
|
|
98
99
|
Sequel::Database.identifier_output_method.should == ""
|
|
99
100
|
db = Sequel::Database.new(:identifier_output_method=>nil)
|
|
100
|
-
db.identifier_output_method.should
|
|
101
|
+
db.identifier_output_method.should be_nil
|
|
101
102
|
db.identifier_output_method = :downcase
|
|
102
103
|
db.identifier_output_method.should == :downcase
|
|
103
104
|
db = Sequel::Database.new(:identifier_output_method=>:upcase)
|
|
104
105
|
db.identifier_output_method.should == :upcase
|
|
105
106
|
db.identifier_output_method = nil
|
|
106
|
-
db.identifier_output_method.should
|
|
107
|
+
db.identifier_output_method.should be_nil
|
|
107
108
|
Sequel.identifier_output_method = :downcase
|
|
108
109
|
Sequel::Database.identifier_output_method.should == :downcase
|
|
109
110
|
db = Sequel::Database.new(:identifier_output_method=>nil)
|
|
110
|
-
db.identifier_output_method.should
|
|
111
|
+
db.identifier_output_method.should be_nil
|
|
111
112
|
db.identifier_output_method = :upcase
|
|
112
113
|
db.identifier_output_method.should == :upcase
|
|
113
114
|
db = Sequel::Database.new(:identifier_output_method=>:upcase)
|
|
114
115
|
db.identifier_output_method.should == :upcase
|
|
115
116
|
db.identifier_output_method = nil
|
|
116
|
-
db.identifier_output_method.should
|
|
117
|
+
db.identifier_output_method.should be_nil
|
|
117
118
|
end
|
|
118
119
|
|
|
119
120
|
specify "should use the default Sequel.quote_identifiers value" do
|
|
@@ -193,8 +194,7 @@ describe "A new Database" do
|
|
|
193
194
|
end
|
|
194
195
|
|
|
195
196
|
specify "should populate :adapter option when using connection string" do
|
|
196
|
-
Sequel
|
|
197
|
-
Sequel.connect('do:test://host/db_name').opts[:adapter] == :do
|
|
197
|
+
Sequel.connect('mock:/').opts[:adapter].should == "mock"
|
|
198
198
|
end
|
|
199
199
|
end
|
|
200
200
|
|
|
@@ -325,6 +325,10 @@ describe "Database#uri" do
|
|
|
325
325
|
@db.uri.should == 'mau://user:pass@localhost:9876/maumau'
|
|
326
326
|
end
|
|
327
327
|
|
|
328
|
+
specify "should return nil if a connection uri was not used" do
|
|
329
|
+
Sequel.mock.uri.should be_nil
|
|
330
|
+
end
|
|
331
|
+
|
|
328
332
|
specify "should be aliased as #url" do
|
|
329
333
|
@db.url.should == 'mau://user:pass@localhost:9876/maumau'
|
|
330
334
|
end
|
|
@@ -366,7 +370,7 @@ describe "Database#dataset" do
|
|
|
366
370
|
end
|
|
367
371
|
|
|
368
372
|
specify "should provide a filtered #from dataset if a block is given" do
|
|
369
|
-
d = @db.from(:mau)
|
|
373
|
+
d = @db.from(:mau){x.sql_number > 100}
|
|
370
374
|
d.should be_a_kind_of(Sequel::Dataset)
|
|
371
375
|
d.sql.should == 'SELECT * FROM mau WHERE (x > 100)'
|
|
372
376
|
end
|
|
@@ -384,339 +388,214 @@ describe "Database#dataset" do
|
|
|
384
388
|
end
|
|
385
389
|
end
|
|
386
390
|
|
|
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
|
|
391
|
+
describe "Database#dataset_class" do
|
|
407
392
|
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", {}]
|
|
393
|
+
@db = Sequel::Database.new
|
|
394
|
+
@dsc = Class.new(Sequel::Dataset)
|
|
420
395
|
end
|
|
421
396
|
|
|
422
|
-
specify "should
|
|
423
|
-
|
|
424
|
-
@db.
|
|
397
|
+
specify "should have setter set the class to use to create datasets" do
|
|
398
|
+
@db.dataset_class = @dsc
|
|
399
|
+
ds = @db.dataset
|
|
400
|
+
ds.should be_a_kind_of(@dsc)
|
|
401
|
+
ds.opts.should == {}
|
|
402
|
+
ds.db.should be(@db)
|
|
425
403
|
end
|
|
426
|
-
|
|
427
|
-
specify "should
|
|
428
|
-
@db.
|
|
429
|
-
@
|
|
404
|
+
|
|
405
|
+
specify "should have getter return the class to use to create datasets" do
|
|
406
|
+
@db.dataset_class.should == Sequel::Dataset
|
|
407
|
+
@db.dataset_class = @dsc
|
|
408
|
+
@db.dataset_class.should == @dsc
|
|
430
409
|
end
|
|
431
410
|
end
|
|
432
|
-
|
|
433
|
-
describe "Database#
|
|
411
|
+
|
|
412
|
+
describe "Database#extend_datasets" do
|
|
434
413
|
before do
|
|
435
|
-
@db = Sequel::Database.new
|
|
414
|
+
@db = Sequel::Database.new
|
|
415
|
+
@m = Module.new{def foo() [3] end}
|
|
416
|
+
@m2 = Module.new{def foo() [4] + super end}
|
|
417
|
+
@db.extend_datasets(@m)
|
|
436
418
|
end
|
|
437
419
|
|
|
438
|
-
specify "should
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
|
420
|
+
specify "should clear a cached dataset" do
|
|
421
|
+
@db = Sequel::Database.new
|
|
422
|
+
@db.literal(1).should == '1'
|
|
423
|
+
@db.extend_datasets{def literal(v) '2' end}
|
|
424
|
+
@db.literal(1).should == '2'
|
|
453
425
|
end
|
|
454
|
-
end
|
|
455
426
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
@db = Sequel::Database.new{@test = rand(100)}
|
|
427
|
+
specify "should change the dataset class to a subclass the first time it is called" do
|
|
428
|
+
@db.dataset_class.superclass.should == Sequel::Dataset
|
|
459
429
|
end
|
|
460
|
-
|
|
461
|
-
specify "should
|
|
462
|
-
@db.
|
|
463
|
-
@
|
|
464
|
-
end
|
|
465
|
-
|
|
466
|
-
specify "should return true if successful" do
|
|
467
|
-
@db.test_connection.should be_true
|
|
430
|
+
|
|
431
|
+
specify "should not create a subclass of the dataset class if called more than once" do
|
|
432
|
+
@db.extend_datasets(@m2)
|
|
433
|
+
@db.dataset_class.superclass.should == Sequel::Dataset
|
|
468
434
|
end
|
|
469
435
|
|
|
470
|
-
specify "should
|
|
471
|
-
|
|
436
|
+
specify "should make the dataset class include the module" do
|
|
437
|
+
@db.dataset_class.ancestors.should include(@m)
|
|
438
|
+
@db.dataset_class.ancestors.should_not include(@m2)
|
|
439
|
+
@db.extend_datasets(@m2)
|
|
440
|
+
@db.dataset_class.ancestors.should include(@m)
|
|
441
|
+
@db.dataset_class.ancestors.should include(@m2)
|
|
472
442
|
end
|
|
473
|
-
end
|
|
474
443
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
444
|
+
specify "should have datasets respond to the module's methods" do
|
|
445
|
+
@db.dataset.foo.should == [3]
|
|
446
|
+
@db.extend_datasets(@m2)
|
|
447
|
+
@db.dataset.foo.should == [4, 3]
|
|
479
448
|
end
|
|
480
|
-
end
|
|
481
449
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
@sqls ||= []
|
|
487
|
-
@sqls << sql
|
|
450
|
+
specify "should take a block and create a module from it to use" do
|
|
451
|
+
@db.dataset.foo.should == [3]
|
|
452
|
+
@db.extend_datasets{def foo() [5] + super end}
|
|
453
|
+
@db.dataset.foo.should == [5, 3]
|
|
488
454
|
end
|
|
489
|
-
|
|
490
|
-
def transaction; yield; end
|
|
491
455
|
|
|
492
|
-
|
|
493
|
-
|
|
456
|
+
specify "should raise an error if both a module and a block are provided" do
|
|
457
|
+
proc{@db.extend_datasets(@m2){def foo() [5] + super end}}.should raise_error(Sequel::Error)
|
|
494
458
|
end
|
|
495
|
-
end
|
|
496
459
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
@db
|
|
460
|
+
specify "should be able to override methods defined in the original Dataset class" do
|
|
461
|
+
@db.extend_datasets(Module.new{def select(*a, &block) super.order(*a, &block) end})
|
|
462
|
+
@db[:t].select(:a, :b).sql.should == 'SELECT a, b FROM t ORDER BY a, b'
|
|
500
463
|
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
|
-
]
|
|
464
|
+
|
|
465
|
+
specify "should reapply settings if dataset_class is chagned" do
|
|
466
|
+
c = Class.new(Sequel::Dataset)
|
|
467
|
+
@db.dataset_class = c
|
|
468
|
+
@db.dataset_class.superclass.should == c
|
|
469
|
+
@db.dataset_class.ancestors.should include(@m)
|
|
470
|
+
@db.dataset.foo.should == [3]
|
|
512
471
|
end
|
|
472
|
+
end
|
|
513
473
|
|
|
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
|
-
]
|
|
474
|
+
describe "Database#execute" do
|
|
475
|
+
specify "should raise Sequel::NotImplemented" do
|
|
476
|
+
proc {Sequel::Database.new.execute('blah blah')}.should raise_error(Sequel::NotImplemented)
|
|
525
477
|
end
|
|
526
478
|
end
|
|
527
479
|
|
|
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
|
-
]
|
|
480
|
+
describe "Database#tables" do
|
|
481
|
+
specify "should raise Sequel::NotImplemented" do
|
|
482
|
+
proc {Sequel::Database.new.tables}.should raise_error(Sequel::NotImplemented)
|
|
555
483
|
end
|
|
556
484
|
end
|
|
557
485
|
|
|
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
|
-
]
|
|
486
|
+
describe "Database#views" do
|
|
487
|
+
specify "should raise Sequel::NotImplemented" do
|
|
488
|
+
proc {Sequel::Database.new.views}.should raise_error(Sequel::NotImplemented)
|
|
568
489
|
end
|
|
569
490
|
end
|
|
570
491
|
|
|
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
|
-
]
|
|
492
|
+
describe "Database#indexes" do
|
|
493
|
+
specify "should raise Sequel::NotImplemented" do
|
|
494
|
+
proc {Sequel::Database.new.indexes(:table)}.should raise_error(Sequel::NotImplemented)
|
|
581
495
|
end
|
|
582
496
|
end
|
|
583
497
|
|
|
584
|
-
describe "Database#
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
end
|
|
588
|
-
|
|
589
|
-
specify "should construct proper SQL" do
|
|
590
|
-
@db.rename_column :test, :abc, :def
|
|
591
|
-
@db.sqls.should == [
|
|
592
|
-
'ALTER TABLE test RENAME COLUMN abc TO def'
|
|
593
|
-
]
|
|
498
|
+
describe "Database#foreign_key_list" do
|
|
499
|
+
specify "should raise Sequel::NotImplemented" do
|
|
500
|
+
proc {Sequel::Database.new.foreign_key_list(:table)}.should raise_error(Sequel::NotImplemented)
|
|
594
501
|
end
|
|
595
502
|
end
|
|
596
503
|
|
|
597
|
-
describe "Database#
|
|
504
|
+
describe "Database#run" do
|
|
598
505
|
before do
|
|
599
|
-
@db =
|
|
506
|
+
@db = Sequel.mock(:servers=>{:s1=>{}})
|
|
600
507
|
end
|
|
601
508
|
|
|
602
|
-
specify "should
|
|
603
|
-
@db.
|
|
604
|
-
@db.sqls.should == [
|
|
605
|
-
'ALTER TABLE test ALTER COLUMN name TYPE integer'
|
|
606
|
-
]
|
|
509
|
+
specify "should execute the code on the database" do
|
|
510
|
+
@db.run("DELETE FROM items")
|
|
511
|
+
@db.sqls.should == ["DELETE FROM items"]
|
|
607
512
|
end
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
before do
|
|
612
|
-
@db = DummyDatabase.new
|
|
513
|
+
|
|
514
|
+
specify "should return nil" do
|
|
515
|
+
@db.run("DELETE FROM items").should be_nil
|
|
613
516
|
end
|
|
614
517
|
|
|
615
|
-
specify "should
|
|
616
|
-
@db.
|
|
617
|
-
@db.sqls.should == [
|
|
618
|
-
"ALTER TABLE test ALTER COLUMN name SET DEFAULT 'zyx'"
|
|
619
|
-
]
|
|
518
|
+
specify "should accept options passed to execute_ddl" do
|
|
519
|
+
@db.run("DELETE FROM items", :server=>:s1)
|
|
520
|
+
@db.sqls.should == ["DELETE FROM items -- s1"]
|
|
620
521
|
end
|
|
621
522
|
end
|
|
622
523
|
|
|
623
|
-
describe "Database
|
|
524
|
+
describe "Database#<<" do
|
|
624
525
|
before do
|
|
625
|
-
@db =
|
|
526
|
+
@db = Sequel.mock
|
|
626
527
|
end
|
|
627
|
-
|
|
628
|
-
specify "should
|
|
629
|
-
@db
|
|
630
|
-
@db.sqls.should == [
|
|
631
|
-
'CREATE UNIQUE INDEX test_name_index ON test (name)'
|
|
632
|
-
]
|
|
528
|
+
|
|
529
|
+
specify "should execute the code on the database" do
|
|
530
|
+
@db << "DELETE FROM items"
|
|
531
|
+
@db.sqls.should == ["DELETE FROM items"]
|
|
633
532
|
end
|
|
634
533
|
|
|
635
|
-
specify "should
|
|
636
|
-
@db
|
|
637
|
-
@db.sqls.should == [
|
|
638
|
-
'CREATE INDEX test_one_two_index ON test (one, two)'
|
|
639
|
-
]
|
|
534
|
+
specify "should be chainable" do
|
|
535
|
+
@db << "DELETE FROM items" << "DELETE FROM items2"
|
|
536
|
+
@db.sqls.should == ["DELETE FROM items", "DELETE FROM items2"]
|
|
640
537
|
end
|
|
641
538
|
end
|
|
642
539
|
|
|
643
|
-
describe "Database#
|
|
540
|
+
describe "Database#synchronize" do
|
|
644
541
|
before do
|
|
645
|
-
@db =
|
|
542
|
+
@db = Sequel::Database.new(:max_connections => 1)
|
|
543
|
+
@db.meta_def(:connect){|c| 12345}
|
|
646
544
|
end
|
|
647
545
|
|
|
648
|
-
specify "should
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
546
|
+
specify "should wrap the supplied block in pool.hold" do
|
|
547
|
+
q, q1, q2, q3 = Queue.new, Queue.new, Queue.new, Queue.new
|
|
548
|
+
c1, c2 = nil
|
|
549
|
+
t1 = Thread.new{@db.synchronize{|c| c1 = c; q.push nil; q1.pop}; q.push nil}
|
|
550
|
+
q.pop
|
|
551
|
+
c1.should == 12345
|
|
552
|
+
t2 = Thread.new{@db.synchronize{|c| c2 = c; q2.push nil}}
|
|
553
|
+
@db.pool.available_connections.should be_empty
|
|
554
|
+
c2.should be_nil
|
|
555
|
+
q1.push nil
|
|
556
|
+
q.pop
|
|
557
|
+
q2.pop
|
|
558
|
+
c2.should == 12345
|
|
559
|
+
t1.join
|
|
560
|
+
t2.join
|
|
653
561
|
end
|
|
654
|
-
|
|
655
562
|
end
|
|
656
563
|
|
|
657
|
-
|
|
658
|
-
attr_reader :sql
|
|
659
|
-
def execute(sql); @sql = sql; end
|
|
660
|
-
def transaction; yield; end
|
|
661
|
-
end
|
|
662
|
-
|
|
663
|
-
describe "Database#drop_table" do
|
|
564
|
+
describe "Database#test_connection" do
|
|
664
565
|
before do
|
|
665
|
-
@db =
|
|
566
|
+
@db = Sequel::Database.new
|
|
567
|
+
pr = proc{@test = rand(100)}
|
|
568
|
+
@db.meta_def(:connect){|c| pr.call}
|
|
666
569
|
end
|
|
667
570
|
|
|
668
|
-
specify "should
|
|
669
|
-
@db.
|
|
670
|
-
@
|
|
571
|
+
specify "should attempt to get a connection" do
|
|
572
|
+
@db.test_connection
|
|
573
|
+
@test.should_not be_nil
|
|
671
574
|
end
|
|
672
575
|
|
|
673
|
-
specify "should
|
|
674
|
-
@db.
|
|
675
|
-
@db.sqls.should == [
|
|
676
|
-
'DROP TABLE a',
|
|
677
|
-
'DROP TABLE bb',
|
|
678
|
-
'DROP TABLE ccc'
|
|
679
|
-
]
|
|
576
|
+
specify "should return true if successful" do
|
|
577
|
+
@db.test_connection.should be_true
|
|
680
578
|
end
|
|
681
|
-
end
|
|
682
579
|
|
|
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']
|
|
580
|
+
specify "should raise an error if the attempting to connect raises an error" do
|
|
581
|
+
proc{Sequel::Database.new{raise Sequel::Error, 'blah'}.test_connection}.should raise_error(Sequel::Error)
|
|
691
582
|
end
|
|
692
583
|
end
|
|
693
584
|
|
|
694
585
|
describe "Database#table_exists?" do
|
|
695
586
|
specify "should try to select the first record from the table's dataset" do
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
587
|
+
db = Sequel.mock(:fetch=>[Sequel::Error, [], [{:a=>1}]])
|
|
588
|
+
db.table_exists?(:a).should be_false
|
|
589
|
+
db.sqls.should == ["SELECT NULL FROM a LIMIT 1"]
|
|
590
|
+
db.table_exists?(:b).should be_true
|
|
591
|
+
db.table_exists?(:c).should be_true
|
|
699
592
|
end
|
|
700
593
|
end
|
|
701
594
|
|
|
702
|
-
|
|
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
|
|
709
|
-
end
|
|
710
|
-
end
|
|
711
|
-
|
|
712
|
-
describe "Database#transaction" do
|
|
713
|
-
before do
|
|
714
|
-
@db = Dummy3Database.new{Dummy3Database::DummyConnection.new(@db)}
|
|
715
|
-
end
|
|
716
|
-
|
|
595
|
+
shared_examples_for "Database#transaction" do
|
|
717
596
|
specify "should wrap the supplied block with BEGIN + COMMIT statements" do
|
|
718
597
|
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
719
|
-
@db.
|
|
598
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
720
599
|
end
|
|
721
600
|
|
|
722
601
|
specify "should support transaction isolation levels" do
|
|
@@ -724,7 +603,7 @@ describe "Database#transaction" do
|
|
|
724
603
|
[:uncommitted, :committed, :repeatable, :serializable].each do |l|
|
|
725
604
|
@db.transaction(:isolation=>l){@db.run "DROP TABLE #{l}"}
|
|
726
605
|
end
|
|
727
|
-
@db.
|
|
606
|
+
@db.sqls.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
728
607
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
729
608
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
730
609
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
@@ -736,12 +615,24 @@ describe "Database#transaction" do
|
|
|
736
615
|
@db.transaction_isolation_level = l
|
|
737
616
|
@db.transaction{@db.run "DROP TABLE #{l}"}
|
|
738
617
|
end
|
|
739
|
-
@db.
|
|
618
|
+
@db.sqls.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
740
619
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
741
620
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
742
621
|
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
743
622
|
end
|
|
744
623
|
|
|
624
|
+
specify "should support :disconnect=>:retry option for automatically retrying on disconnect" do
|
|
625
|
+
a = []
|
|
626
|
+
@db.transaction(:disconnect=>:retry){a << 1; raise Sequel::DatabaseDisconnectError if a.length < 2}
|
|
627
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'BEGIN', 'COMMIT']
|
|
628
|
+
a.should == [1, 1]
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
specify "should raise an error if attempting to use :disconnect=>:retry inside another transaction" do
|
|
632
|
+
proc{@db.transaction{@db.transaction(:disconnect=>:retry){}}}.should raise_error(Sequel::Error)
|
|
633
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
634
|
+
end
|
|
635
|
+
|
|
745
636
|
specify "should handle returning inside of the block by committing" do
|
|
746
637
|
def @db.ret_commit
|
|
747
638
|
transaction do
|
|
@@ -751,16 +642,55 @@ describe "Database#transaction" do
|
|
|
751
642
|
end
|
|
752
643
|
end
|
|
753
644
|
@db.ret_commit
|
|
754
|
-
@db.
|
|
645
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
755
646
|
end
|
|
756
647
|
|
|
757
648
|
specify "should issue ROLLBACK if an exception is raised, and re-raise" do
|
|
758
649
|
@db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
|
|
759
|
-
@db.
|
|
650
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
760
651
|
|
|
761
652
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
762
653
|
end
|
|
763
654
|
|
|
655
|
+
specify "should handle errors when sending BEGIN" do
|
|
656
|
+
ec = Class.new(StandardError)
|
|
657
|
+
@db.meta_def(:database_error_classes){[ec]}
|
|
658
|
+
@db.meta_def(:log_connection_execute){|c, sql| sql =~ /BEGIN/ ? raise(ec, 'bad') : super(c, sql)}
|
|
659
|
+
begin
|
|
660
|
+
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
661
|
+
rescue Sequel::DatabaseError => e
|
|
662
|
+
end
|
|
663
|
+
e.should_not be_nil
|
|
664
|
+
e.wrapped_exception.should be_a_kind_of(ec)
|
|
665
|
+
@db.sqls.should == ['ROLLBACK']
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
specify "should handle errors when sending COMMIT" do
|
|
669
|
+
ec = Class.new(StandardError)
|
|
670
|
+
@db.meta_def(:database_error_classes){[ec]}
|
|
671
|
+
@db.meta_def(:log_connection_execute){|c, sql| sql =~ /COMMIT/ ? raise(ec, 'bad') : super(c, sql)}
|
|
672
|
+
begin
|
|
673
|
+
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
674
|
+
rescue Sequel::DatabaseError => e
|
|
675
|
+
end
|
|
676
|
+
e.should_not be_nil
|
|
677
|
+
e.wrapped_exception.should be_a_kind_of(ec)
|
|
678
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;']
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
specify "should handle errors when sending ROLLBACK" do
|
|
682
|
+
ec = Class.new(StandardError)
|
|
683
|
+
@db.meta_def(:database_error_classes){[ec]}
|
|
684
|
+
@db.meta_def(:log_connection_execute){|c, sql| sql =~ /ROLLBACK/ ? raise(ec, 'bad') : super(c, sql)}
|
|
685
|
+
begin
|
|
686
|
+
@db.transaction{raise ArgumentError, 'asdf'}
|
|
687
|
+
rescue Sequel::DatabaseError => e
|
|
688
|
+
end
|
|
689
|
+
e.should_not be_nil
|
|
690
|
+
e.wrapped_exception.should be_a_kind_of(ec)
|
|
691
|
+
@db.sqls.should == ['BEGIN']
|
|
692
|
+
end
|
|
693
|
+
|
|
764
694
|
specify "should issue ROLLBACK if Sequel::Rollback is called in the transaction" do
|
|
765
695
|
@db.transaction do
|
|
766
696
|
@db.drop_table(:a)
|
|
@@ -768,7 +698,50 @@ describe "Database#transaction" do
|
|
|
768
698
|
@db.drop_table(:b)
|
|
769
699
|
end
|
|
770
700
|
|
|
771
|
-
@db.
|
|
701
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
specify "should have in_transaction? return true if inside a transaction" do
|
|
705
|
+
c = nil
|
|
706
|
+
@db.transaction{c = @db.in_transaction?}
|
|
707
|
+
c.should be_true
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
specify "should have in_transaction? handle sharding correctly" do
|
|
711
|
+
c = []
|
|
712
|
+
@db.transaction(:server=>:test){c << @db.in_transaction?}
|
|
713
|
+
@db.transaction(:server=>:test){c << @db.in_transaction?(:server=>:test)}
|
|
714
|
+
c.should == [false, true]
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
specify "should have in_transaction? return false if not in a transaction" do
|
|
718
|
+
@db.in_transaction?.should be_false
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
specify "should return nil if Sequel::Rollback is called in the transaction" do
|
|
722
|
+
@db.transaction{raise Sequel::Rollback}.should be_nil
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
specify "should reraise Sequel::Rollback errors when using :rollback=>:reraise option is given" do
|
|
726
|
+
proc {@db.transaction(:rollback=>:reraise){raise Sequel::Rollback}}.should raise_error(Sequel::Rollback)
|
|
727
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
728
|
+
proc {@db.transaction(:rollback=>:reraise){raise ArgumentError}}.should raise_error(ArgumentError)
|
|
729
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
730
|
+
@db.transaction(:rollback=>:reraise){1}.should == 1
|
|
731
|
+
@db.sqls.should == ['BEGIN', 'COMMIT']
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
specify "should always rollback if :rollback=>:always option is given" do
|
|
735
|
+
proc {@db.transaction(:rollback=>:always){raise ArgumentError}}.should raise_error(ArgumentError)
|
|
736
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
737
|
+
@db.transaction(:rollback=>:always){raise Sequel::Rollback}.should be_nil
|
|
738
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
739
|
+
@db.transaction(:rollback=>:always){1}.should be_nil
|
|
740
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
741
|
+
catch (:foo) do
|
|
742
|
+
@db.transaction(:rollback=>:always){throw :foo}
|
|
743
|
+
end
|
|
744
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
772
745
|
end
|
|
773
746
|
|
|
774
747
|
specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
|
|
@@ -780,47 +753,242 @@ describe "Database#transaction" do
|
|
|
780
753
|
end
|
|
781
754
|
|
|
782
755
|
specify "should be re-entrant" do
|
|
783
|
-
|
|
756
|
+
q, q1 = Queue.new, Queue.new
|
|
784
757
|
cc = nil
|
|
785
758
|
t = Thread.new do
|
|
786
759
|
@db.transaction {@db.transaction {@db.transaction {|c|
|
|
787
760
|
cc = c
|
|
788
|
-
|
|
761
|
+
q.pop
|
|
762
|
+
q1.push nil
|
|
763
|
+
q.pop
|
|
789
764
|
}}}
|
|
790
765
|
end
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
766
|
+
q.push nil
|
|
767
|
+
q1.pop
|
|
768
|
+
cc.should be_a_kind_of(Sequel::Mock::Connection)
|
|
769
|
+
tr = @db.instance_variable_get(:@transactions)
|
|
770
|
+
tr.keys.should == [cc]
|
|
771
|
+
q.push nil
|
|
795
772
|
t.join
|
|
796
|
-
|
|
773
|
+
tr.should be_empty
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
specify "should correctly handle nested transacation use with separate shards" do
|
|
777
|
+
@db.transaction do |c1|
|
|
778
|
+
@db.transaction(:server=>:test) do |c2|
|
|
779
|
+
c1.should_not == c2
|
|
780
|
+
@db.execute 'DROP TABLE test;'
|
|
781
|
+
end
|
|
782
|
+
end
|
|
783
|
+
@db.sqls.should == ['BEGIN', 'BEGIN -- test', 'DROP TABLE test;', 'COMMIT -- test', 'COMMIT']
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
if (!defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or RUBY_ENGINE == 'rbx') and RUBY_VERSION < '1.9'
|
|
787
|
+
specify "should handle Thread#kill for transactions inside threads" do
|
|
788
|
+
q = Queue.new
|
|
789
|
+
q1 = Queue.new
|
|
790
|
+
t = Thread.new do
|
|
791
|
+
@db.transaction do
|
|
792
|
+
@db.execute 'DROP TABLE test'
|
|
793
|
+
q1.push nil
|
|
794
|
+
q.pop
|
|
795
|
+
@db.execute 'DROP TABLE test2'
|
|
796
|
+
end
|
|
797
|
+
end
|
|
798
|
+
q1.pop
|
|
799
|
+
t.kill
|
|
800
|
+
t.join
|
|
801
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
802
|
+
end
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
specify "should raise an Error if after_commit or after_rollback is called without a block" do
|
|
806
|
+
proc{@db.after_commit}.should raise_error(Sequel::Error)
|
|
807
|
+
proc{@db.after_rollback}.should raise_error(Sequel::Error)
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
specify "should have after_commit and after_rollback respect :server option" do
|
|
811
|
+
@db.transaction(:server=>:test){@db.after_commit(:server=>:test){@db.execute('foo', :server=>:test)}}
|
|
812
|
+
@db.sqls.should == ['BEGIN -- test', 'COMMIT -- test', 'foo -- test']
|
|
813
|
+
@db.transaction(:server=>:test){@db.after_rollback(:server=>:test){@db.execute('foo', :server=>:test)}; raise Sequel::Rollback}
|
|
814
|
+
@db.sqls.should == ['BEGIN -- test', 'ROLLBACK -- test', 'foo -- test']
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
specify "should execute after_commit outside transactions" do
|
|
818
|
+
@db.after_commit{@db.execute('foo')}
|
|
819
|
+
@db.sqls.should == ['foo']
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
specify "should ignore after_rollback outside transactions" do
|
|
823
|
+
@db.after_rollback{@db.execute('foo')}
|
|
824
|
+
@db.sqls.should == []
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
specify "should support after_commit inside transactions" do
|
|
828
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}}
|
|
829
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo']
|
|
830
|
+
end
|
|
831
|
+
|
|
832
|
+
specify "should support after_rollback inside transactions" do
|
|
833
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}}
|
|
834
|
+
@db.sqls.should == ['BEGIN', 'COMMIT']
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
specify "should not call after_commit if the transaction rolls back" do
|
|
838
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}; raise Sequel::Rollback}
|
|
839
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
specify "should call after_rollback if the transaction rolls back" do
|
|
843
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}; raise Sequel::Rollback}
|
|
844
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo']
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
specify "should call multiple after_commit blocks in order if called inside transactions" do
|
|
848
|
+
@db.transaction{@db.after_commit{@db.execute('foo')}; @db.after_commit{@db.execute('bar')}}
|
|
849
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo', 'bar']
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
specify "should call multiple after_rollback blocks in order if called inside transactions" do
|
|
853
|
+
@db.transaction{@db.after_rollback{@db.execute('foo')}; @db.after_rollback{@db.execute('bar')}; raise Sequel::Rollback}
|
|
854
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo', 'bar']
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
specify "should support after_commit inside nested transactions" do
|
|
858
|
+
@db.transaction{@db.transaction{@db.after_commit{@db.execute('foo')}}}
|
|
859
|
+
@db.sqls.should == ['BEGIN', 'COMMIT', 'foo']
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
specify "should support after_rollback inside nested transactions" do
|
|
863
|
+
@db.transaction{@db.transaction{@db.after_rollback{@db.execute('foo')}}; raise Sequel::Rollback}
|
|
864
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK', 'foo']
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
specify "should raise an error if you attempt to use after_commit inside a prepared transaction" do
|
|
868
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
869
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{@db.execute('foo')}}}.should raise_error(Sequel::Error)
|
|
870
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
specify "should raise an error if you attempt to use after_rollback inside a prepared transaction" do
|
|
874
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
875
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{@db.execute('foo')}}}.should raise_error(Sequel::Error)
|
|
876
|
+
@db.sqls.should == ['BEGIN', 'ROLLBACK']
|
|
797
877
|
end
|
|
798
878
|
end
|
|
799
879
|
|
|
800
|
-
describe "Database#transaction with
|
|
880
|
+
describe "Database#transaction with savepoint support" do
|
|
801
881
|
before do
|
|
802
|
-
@db =
|
|
882
|
+
@db = Sequel.mock(:servers=>{:test=>{}})
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
it_should_behave_like "Database#transaction"
|
|
886
|
+
|
|
887
|
+
specify "should support after_commit inside savepoints" do
|
|
803
888
|
@db.meta_def(:supports_savepoints?){true}
|
|
889
|
+
@db.transaction do
|
|
890
|
+
@db.after_commit{@db.execute('foo')}
|
|
891
|
+
@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('bar')}}
|
|
892
|
+
@db.after_commit{@db.execute('baz')}
|
|
893
|
+
end
|
|
894
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT', 'foo', 'bar', 'baz']
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
specify "should support after_rollback inside savepoints" do
|
|
898
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
899
|
+
@db.transaction do
|
|
900
|
+
@db.after_rollback{@db.execute('foo')}
|
|
901
|
+
@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('bar')}}
|
|
902
|
+
@db.after_rollback{@db.execute('baz')}
|
|
903
|
+
raise Sequel::Rollback
|
|
904
|
+
end
|
|
905
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'ROLLBACK', 'foo', 'bar', 'baz']
|
|
906
|
+
end
|
|
907
|
+
|
|
908
|
+
specify "should raise an error if you attempt to use after_commit inside a savepoint in a prepared transaction" do
|
|
909
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
910
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
911
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
|
912
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
913
|
+
end
|
|
914
|
+
|
|
915
|
+
specify "should raise an error if you attempt to use after_rollback inside a savepoint in a prepared transaction" do
|
|
916
|
+
@db.meta_def(:supports_savepoints?){true}
|
|
917
|
+
@db.meta_def(:supports_prepared_transactions?){true}
|
|
918
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
|
919
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
920
|
+
end
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
describe "Database#transaction without savepoint support" do
|
|
924
|
+
before do
|
|
925
|
+
@db = Sequel.mock(:servers=>{:test=>{}})
|
|
926
|
+
@db.meta_def(:supports_savepoints?){false}
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
it_should_behave_like "Database#transaction"
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
describe "Sequel.transaction" do
|
|
933
|
+
before do
|
|
934
|
+
@sqls = []
|
|
935
|
+
@db1 = Sequel.mock(:append=>'1', :sqls=>@sqls)
|
|
936
|
+
@db2 = Sequel.mock(:append=>'2', :sqls=>@sqls)
|
|
937
|
+
@db3 = Sequel.mock(:append=>'3', :sqls=>@sqls)
|
|
938
|
+
end
|
|
939
|
+
|
|
940
|
+
specify "should run the block inside transacitons on all three databases" do
|
|
941
|
+
Sequel.transaction([@db1, @db2, @db3]){1}.should == 1
|
|
942
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
specify "should pass options to all the blocks" do
|
|
946
|
+
Sequel.transaction([@db1, @db2, @db3], :rollback=>:always){1}.should be_nil
|
|
947
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
|
|
948
|
+
end
|
|
949
|
+
|
|
950
|
+
specify "should handle Sequel::Rollback exceptions raised by the block to rollback on all databases" do
|
|
951
|
+
Sequel.transaction([@db1, @db2, @db3]){raise Sequel::Rollback}.should be_nil
|
|
952
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'ROLLBACK -- 3', 'ROLLBACK -- 2', 'ROLLBACK -- 1']
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
specify "should handle nested transactions" do
|
|
956
|
+
Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3]){1}}.should == 1
|
|
957
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3', 'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
958
|
+
end
|
|
959
|
+
|
|
960
|
+
specify "should handle savepoints" do
|
|
961
|
+
Sequel.transaction([@db1, @db2, @db3]){Sequel.transaction([@db1, @db2, @db3], :savepoint=>true){1}}.should == 1
|
|
962
|
+
@sqls.should == ['BEGIN -- 1', 'BEGIN -- 2', 'BEGIN -- 3',
|
|
963
|
+
'SAVEPOINT autopoint_1 -- 1', 'SAVEPOINT autopoint_1 -- 2', 'SAVEPOINT autopoint_1 -- 3',
|
|
964
|
+
'RELEASE SAVEPOINT autopoint_1 -- 3', 'RELEASE SAVEPOINT autopoint_1 -- 2', 'RELEASE SAVEPOINT autopoint_1 -- 1',
|
|
965
|
+
'COMMIT -- 3', 'COMMIT -- 2', 'COMMIT -- 1']
|
|
966
|
+
end
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
describe "Database#transaction with savepoints" do
|
|
970
|
+
before do
|
|
971
|
+
@db = Sequel.mock
|
|
804
972
|
end
|
|
805
973
|
|
|
806
974
|
specify "should wrap the supplied block with BEGIN + COMMIT statements" do
|
|
807
975
|
@db.transaction {@db.execute 'DROP TABLE test;'}
|
|
808
|
-
@db.
|
|
976
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
809
977
|
end
|
|
810
978
|
|
|
811
979
|
specify "should use savepoints if given the :savepoint option" do
|
|
812
980
|
@db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}}
|
|
813
|
-
@db.
|
|
981
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
|
814
982
|
end
|
|
815
983
|
|
|
816
984
|
specify "should not use a savepoints if no transaction is in progress" do
|
|
817
985
|
@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}
|
|
818
|
-
@db.
|
|
986
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
819
987
|
end
|
|
820
988
|
|
|
821
989
|
specify "should reuse the current transaction if no :savepoint option is given" do
|
|
822
990
|
@db.transaction{@db.transaction{@db.execute 'DROP TABLE test;'}}
|
|
823
|
-
@db.
|
|
991
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
824
992
|
end
|
|
825
993
|
|
|
826
994
|
specify "should handle returning inside of the block by committing" do
|
|
@@ -832,7 +1000,7 @@ describe "Database#transaction with savepoints" do
|
|
|
832
1000
|
end
|
|
833
1001
|
end
|
|
834
1002
|
@db.ret_commit
|
|
835
|
-
@db.
|
|
1003
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
836
1004
|
end
|
|
837
1005
|
|
|
838
1006
|
specify "should handle returning inside of a savepoint by committing" do
|
|
@@ -846,34 +1014,34 @@ describe "Database#transaction with savepoints" do
|
|
|
846
1014
|
end
|
|
847
1015
|
end
|
|
848
1016
|
@db.ret_commit
|
|
849
|
-
@db.
|
|
1017
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
|
850
1018
|
end
|
|
851
1019
|
|
|
852
1020
|
specify "should issue ROLLBACK if an exception is raised, and re-raise" do
|
|
853
1021
|
@db.transaction {@db.execute 'DROP TABLE test'; raise RuntimeError} rescue nil
|
|
854
|
-
@db.
|
|
1022
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test', 'ROLLBACK']
|
|
855
1023
|
|
|
856
1024
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
857
1025
|
end
|
|
858
1026
|
|
|
859
1027
|
specify "should issue ROLLBACK SAVEPOINT if an exception is raised inside a savepoint, and re-raise" do
|
|
860
1028
|
@db.transaction{@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test'; raise RuntimeError}} rescue nil
|
|
861
|
-
@db.
|
|
1029
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test', 'ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
|
862
1030
|
|
|
863
1031
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
864
1032
|
end
|
|
865
1033
|
|
|
866
|
-
specify "should issue ROLLBACK if Sequel::Rollback is
|
|
1034
|
+
specify "should issue ROLLBACK if Sequel::Rollback is raised in the transaction" do
|
|
867
1035
|
@db.transaction do
|
|
868
1036
|
@db.drop_table(:a)
|
|
869
1037
|
raise Sequel::Rollback
|
|
870
1038
|
@db.drop_table(:b)
|
|
871
1039
|
end
|
|
872
1040
|
|
|
873
|
-
@db.
|
|
1041
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE a', 'ROLLBACK']
|
|
874
1042
|
end
|
|
875
1043
|
|
|
876
|
-
specify "should issue ROLLBACK SAVEPOINT if Sequel::Rollback is
|
|
1044
|
+
specify "should issue ROLLBACK SAVEPOINT if Sequel::Rollback is raised in a savepoint" do
|
|
877
1045
|
@db.transaction do
|
|
878
1046
|
@db.transaction(:savepoint=>true) do
|
|
879
1047
|
@db.drop_table(:a)
|
|
@@ -882,7 +1050,7 @@ describe "Database#transaction with savepoints" do
|
|
|
882
1050
|
@db.drop_table(:b)
|
|
883
1051
|
end
|
|
884
1052
|
|
|
885
|
-
@db.
|
|
1053
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE a', 'ROLLBACK TO SAVEPOINT autopoint_1', 'DROP TABLE b', 'COMMIT']
|
|
886
1054
|
end
|
|
887
1055
|
|
|
888
1056
|
specify "should raise database errors when commiting a transaction as Sequel::DatabaseError" do
|
|
@@ -898,37 +1066,28 @@ end
|
|
|
898
1066
|
|
|
899
1067
|
describe "A Database adapter with a scheme" do
|
|
900
1068
|
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
|
|
1069
|
+
@ccc = Class.new(Sequel::Database)
|
|
1070
|
+
@ccc.send(:set_adapter_scheme, :ccc)
|
|
912
1071
|
end
|
|
913
1072
|
|
|
914
1073
|
specify "should be registered in the ADAPTER_MAP" do
|
|
915
|
-
Sequel::ADAPTER_MAP[:ccc].should ==
|
|
1074
|
+
Sequel::ADAPTER_MAP[:ccc].should == @ccc
|
|
916
1075
|
end
|
|
917
1076
|
|
|
918
1077
|
specify "should give the database_type as the adapter scheme by default" do
|
|
919
|
-
|
|
1078
|
+
@ccc.new.database_type.should == :ccc
|
|
920
1079
|
end
|
|
921
1080
|
|
|
922
1081
|
specify "should be instantiated when its scheme is specified" do
|
|
923
1082
|
c = Sequel::Database.connect('ccc://localhost/db')
|
|
924
|
-
c.should be_a_kind_of(
|
|
1083
|
+
c.should be_a_kind_of(@ccc)
|
|
925
1084
|
c.opts[:host].should == 'localhost'
|
|
926
1085
|
c.opts[:database].should == 'db'
|
|
927
1086
|
end
|
|
928
1087
|
|
|
929
1088
|
specify "should be accessible through Sequel.connect" do
|
|
930
1089
|
c = Sequel.connect 'ccc://localhost/db'
|
|
931
|
-
c.should be_a_kind_of(
|
|
1090
|
+
c.should be_a_kind_of(@ccc)
|
|
932
1091
|
c.opts[:host].should == 'localhost'
|
|
933
1092
|
c.opts[:database].should == 'db'
|
|
934
1093
|
end
|
|
@@ -940,7 +1099,7 @@ describe "A Database adapter with a scheme" do
|
|
|
940
1099
|
returnValue = 'anything'
|
|
941
1100
|
|
|
942
1101
|
p = proc do |c|
|
|
943
|
-
c.should be_a_kind_of(
|
|
1102
|
+
c.should be_a_kind_of(@ccc)
|
|
944
1103
|
c.opts[:host].should == 'localhost'
|
|
945
1104
|
c.opts[:database].should == 'db'
|
|
946
1105
|
z = y
|
|
@@ -948,15 +1107,22 @@ describe "A Database adapter with a scheme" do
|
|
|
948
1107
|
x = c
|
|
949
1108
|
returnValue
|
|
950
1109
|
end
|
|
1110
|
+
|
|
1111
|
+
@ccc.class_eval do
|
|
1112
|
+
self::DISCONNECTS = []
|
|
1113
|
+
def disconnect
|
|
1114
|
+
self.class::DISCONNECTS << self
|
|
1115
|
+
end
|
|
1116
|
+
end
|
|
951
1117
|
Sequel::Database.connect('ccc://localhost/db', &p).should == returnValue
|
|
952
|
-
|
|
1118
|
+
@ccc::DISCONNECTS.should == [x]
|
|
953
1119
|
|
|
954
1120
|
Sequel.connect('ccc://localhost/db', &p).should == returnValue
|
|
955
|
-
|
|
1121
|
+
@ccc::DISCONNECTS.should == [y, x]
|
|
956
1122
|
|
|
957
1123
|
Sequel.send(:def_adapter_method, :ccc)
|
|
958
1124
|
Sequel.ccc('db', :host=>'localhost', &p).should == returnValue
|
|
959
|
-
|
|
1125
|
+
@ccc::DISCONNECTS.should == [z, y, x]
|
|
960
1126
|
end
|
|
961
1127
|
|
|
962
1128
|
specify "should be accessible through Sequel.<adapter>" do
|
|
@@ -966,32 +1132,31 @@ describe "A Database adapter with a scheme" do
|
|
|
966
1132
|
proc {Sequel.ccc('abc', 'def')}.should raise_error(Sequel::Error)
|
|
967
1133
|
|
|
968
1134
|
c = Sequel.ccc('mydb')
|
|
969
|
-
|
|
970
|
-
c.should
|
|
971
|
-
p.call.should == {:adapter=>:ccc, :database => 'mydb', :adapter_class=>CCC}
|
|
1135
|
+
c.should be_a_kind_of(@ccc)
|
|
1136
|
+
c.opts.values_at(:adapter, :database, :adapter_class).should == [:ccc, 'mydb', @ccc]
|
|
972
1137
|
|
|
973
1138
|
c = Sequel.ccc('mydb', :host => 'localhost')
|
|
974
|
-
c.should be_a_kind_of(
|
|
975
|
-
|
|
1139
|
+
c.should be_a_kind_of(@ccc)
|
|
1140
|
+
c.opts.values_at(:adapter, :database, :host, :adapter_class).should == [:ccc, 'mydb', 'localhost', @ccc]
|
|
976
1141
|
|
|
977
1142
|
c = Sequel.ccc
|
|
978
|
-
c.should be_a_kind_of(
|
|
979
|
-
|
|
1143
|
+
c.should be_a_kind_of(@ccc)
|
|
1144
|
+
c.opts.values_at(:adapter, :adapter_class).should == [:ccc, @ccc]
|
|
980
1145
|
|
|
981
1146
|
c = Sequel.ccc(:database => 'mydb', :host => 'localhost')
|
|
982
|
-
c.should be_a_kind_of(
|
|
983
|
-
|
|
1147
|
+
c.should be_a_kind_of(@ccc)
|
|
1148
|
+
c.opts.values_at(:adapter, :database, :host, :adapter_class).should == [:ccc, 'mydb', 'localhost', @ccc]
|
|
984
1149
|
end
|
|
985
1150
|
|
|
986
1151
|
specify "should be accessible through Sequel.connect with options" do
|
|
987
1152
|
c = Sequel.connect(:adapter => :ccc, :database => 'mydb')
|
|
988
|
-
c.should be_a_kind_of(
|
|
1153
|
+
c.should be_a_kind_of(@ccc)
|
|
989
1154
|
c.opts[:adapter].should == :ccc
|
|
990
1155
|
end
|
|
991
1156
|
|
|
992
1157
|
specify "should be accessible through Sequel.connect with URL parameters" do
|
|
993
1158
|
c = Sequel.connect 'ccc:///db?host=/tmp&user=test'
|
|
994
|
-
c.should be_a_kind_of(
|
|
1159
|
+
c.should be_a_kind_of(@ccc)
|
|
995
1160
|
c.opts[:host].should == '/tmp'
|
|
996
1161
|
c.opts[:database].should == 'db'
|
|
997
1162
|
c.opts[:user].should == 'test'
|
|
@@ -999,14 +1164,14 @@ describe "A Database adapter with a scheme" do
|
|
|
999
1164
|
|
|
1000
1165
|
specify "should have URL parameters take precedence over fixed URL parts" do
|
|
1001
1166
|
c = Sequel.connect 'ccc://localhost/db?host=a&database=b'
|
|
1002
|
-
c.should be_a_kind_of(
|
|
1167
|
+
c.should be_a_kind_of(@ccc)
|
|
1003
1168
|
c.opts[:host].should == 'a'
|
|
1004
1169
|
c.opts[:database].should == 'b'
|
|
1005
1170
|
end
|
|
1006
1171
|
|
|
1007
1172
|
specify "should have hash options take predence over URL parameters or parts" do
|
|
1008
1173
|
c = Sequel.connect 'ccc://localhost/db?host=/tmp', :host=>'a', :database=>'b', :user=>'c'
|
|
1009
|
-
c.should be_a_kind_of(
|
|
1174
|
+
c.should be_a_kind_of(@ccc)
|
|
1010
1175
|
c.opts[:host].should == 'a'
|
|
1011
1176
|
c.opts[:database].should == 'b'
|
|
1012
1177
|
c.opts[:user].should == 'c'
|
|
@@ -1014,7 +1179,7 @@ describe "A Database adapter with a scheme" do
|
|
|
1014
1179
|
|
|
1015
1180
|
specify "should unescape values of URL parameters and parts" do
|
|
1016
1181
|
c = Sequel.connect 'ccc:///d%5bb%5d?host=domain%5cinstance'
|
|
1017
|
-
c.should be_a_kind_of(
|
|
1182
|
+
c.should be_a_kind_of(@ccc)
|
|
1018
1183
|
c.opts[:database].should == 'd[b]'
|
|
1019
1184
|
c.opts[:host].should == 'domain\\instance'
|
|
1020
1185
|
end
|
|
@@ -1097,7 +1262,8 @@ end
|
|
|
1097
1262
|
describe "A single threaded database" do
|
|
1098
1263
|
before do
|
|
1099
1264
|
conn = 1234567
|
|
1100
|
-
@db = Sequel::Database.new(:single_threaded => true)
|
|
1265
|
+
@db = Sequel::Database.new(:single_threaded => true)
|
|
1266
|
+
@db.meta_def(:connect) do |c|
|
|
1101
1267
|
conn += 1
|
|
1102
1268
|
end
|
|
1103
1269
|
end
|
|
@@ -1129,10 +1295,6 @@ describe "A single threaded database" do
|
|
|
1129
1295
|
end
|
|
1130
1296
|
|
|
1131
1297
|
describe "A database" do
|
|
1132
|
-
before do
|
|
1133
|
-
Sequel::Database.single_threaded = false
|
|
1134
|
-
end
|
|
1135
|
-
|
|
1136
1298
|
after do
|
|
1137
1299
|
Sequel::Database.single_threaded = false
|
|
1138
1300
|
end
|
|
@@ -1177,11 +1339,7 @@ end
|
|
|
1177
1339
|
|
|
1178
1340
|
describe "Database#fetch" do
|
|
1179
1341
|
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)}
|
|
1342
|
+
@db = Sequel.mock(:fetch=>proc{|sql| {:sql => sql}})
|
|
1185
1343
|
end
|
|
1186
1344
|
|
|
1187
1345
|
specify "should create a dataset and invoke its fetch_rows method with the given sql" do
|
|
@@ -1219,7 +1377,7 @@ describe "Database#fetch" do
|
|
|
1219
1377
|
ds.select_sql.should == 'select * from xyz'
|
|
1220
1378
|
ds.sql.should == 'select * from xyz'
|
|
1221
1379
|
|
|
1222
|
-
ds.filter!
|
|
1380
|
+
ds.filter!{price.sql_number < 100}
|
|
1223
1381
|
ds.select_sql.should == 'select * from xyz'
|
|
1224
1382
|
ds.sql.should == 'select * from xyz'
|
|
1225
1383
|
end
|
|
@@ -1228,143 +1386,62 @@ end
|
|
|
1228
1386
|
|
|
1229
1387
|
describe "Database#[]" do
|
|
1230
1388
|
before do
|
|
1231
|
-
@db = Sequel
|
|
1389
|
+
@db = Sequel.mock
|
|
1232
1390
|
end
|
|
1233
1391
|
|
|
1234
1392
|
specify "should return a dataset when symbols are given" do
|
|
1235
1393
|
ds = @db[:items]
|
|
1236
|
-
ds.
|
|
1394
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
1237
1395
|
ds.opts[:from].should == [:items]
|
|
1238
1396
|
end
|
|
1239
1397
|
|
|
1240
1398
|
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
|
-
|
|
1399
|
+
@db.fetch = proc{|sql| {:sql=>sql}}
|
|
1246
1400
|
sql = nil
|
|
1247
1401
|
@db['select * from xyz where x = ? and y = ?', 15, 'abc'].each {|r| sql = r[:sql]}
|
|
1248
1402
|
sql.should == "select * from xyz where x = 15 and y = 'abc'"
|
|
1249
1403
|
end
|
|
1250
1404
|
end
|
|
1251
1405
|
|
|
1252
|
-
describe "Database#
|
|
1253
|
-
|
|
1254
|
-
|
|
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']
|
|
1406
|
+
describe "Database#inspect" do
|
|
1407
|
+
specify "should include the class name and the connection url" do
|
|
1408
|
+
Sequel.connect('mock://foo/bar').inspect.should == '#<Sequel::Mock::Database: "mock://foo/bar">'
|
|
1307
1409
|
end
|
|
1308
|
-
end
|
|
1309
1410
|
|
|
1310
|
-
|
|
1311
|
-
|
|
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)
|
|
1411
|
+
specify "should include the class name and the connection options if an options hash was given" do
|
|
1412
|
+
Sequel.connect(:adapter=>:mock).inspect.should =~ /#<Sequel::Mock::Database: \{:adapter=>:mock\}>/
|
|
1317
1413
|
end
|
|
1318
|
-
end
|
|
1319
1414
|
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
@db = DummyDatabase.new
|
|
1323
|
-
|
|
1324
|
-
@db.meta_def(:uri) {'blah://blahblah/blah'}
|
|
1325
|
-
end
|
|
1326
|
-
|
|
1327
|
-
specify "should include the class name and the connection url" do
|
|
1328
|
-
@db.inspect.should == '#<DummyDatabase: "blah://blahblah/blah">'
|
|
1415
|
+
specify "should include the class name, uri, and connection options if uri and options hash was given" do
|
|
1416
|
+
Sequel.connect('mock://foo', :database=>'bar').inspect.should =~ /#<Sequel::Mock::Database: "mock:\/\/foo" \{:database=>"bar"\}>/
|
|
1329
1417
|
end
|
|
1330
1418
|
end
|
|
1331
1419
|
|
|
1332
1420
|
describe "Database#get" do
|
|
1333
1421
|
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
|
|
1422
|
+
@db = Sequel.mock(:fetch=>{:a=>1})
|
|
1346
1423
|
end
|
|
1347
1424
|
|
|
1348
1425
|
specify "should use Dataset#get to get a single value" do
|
|
1349
|
-
@db.get(1).should ==
|
|
1350
|
-
@db.sqls.
|
|
1426
|
+
@db.get(1).should == 1
|
|
1427
|
+
@db.sqls.should == ['SELECT 1 LIMIT 1']
|
|
1351
1428
|
|
|
1352
|
-
@db.get(:version
|
|
1353
|
-
@db.sqls.
|
|
1429
|
+
@db.get(Sequel.function(:version))
|
|
1430
|
+
@db.sqls.should == ['SELECT version() LIMIT 1']
|
|
1354
1431
|
end
|
|
1355
1432
|
|
|
1356
1433
|
specify "should accept a block" do
|
|
1357
1434
|
@db.get{1}
|
|
1358
|
-
@db.sqls.
|
|
1435
|
+
@db.sqls.should == ['SELECT 1 LIMIT 1']
|
|
1359
1436
|
|
|
1360
1437
|
@db.get{version(1)}
|
|
1361
|
-
@db.sqls.
|
|
1438
|
+
@db.sqls.should == ['SELECT version(1) LIMIT 1']
|
|
1362
1439
|
end
|
|
1363
1440
|
end
|
|
1364
1441
|
|
|
1365
1442
|
describe "Database#call" do
|
|
1366
1443
|
specify "should call the prepared statement with the given name" do
|
|
1367
|
-
db =
|
|
1444
|
+
db = Sequel.mock(:fetch=>{:id => 1, :x => 1})
|
|
1368
1445
|
db[:items].prepare(:select, :select_all)
|
|
1369
1446
|
db.call(:select_all).should == [{:id => 1, :x => 1}]
|
|
1370
1447
|
db[:items].filter(:n=>:$n).prepare(:select, :select_n)
|
|
@@ -1376,146 +1453,134 @@ end
|
|
|
1376
1453
|
describe "Database#server_opts" do
|
|
1377
1454
|
specify "should return the general opts if no :servers option is used" do
|
|
1378
1455
|
opts = {:host=>1, :database=>2}
|
|
1379
|
-
|
|
1456
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 1
|
|
1380
1457
|
end
|
|
1381
1458
|
|
|
1382
1459
|
specify "should return the general opts if entry for the server is present in the :servers option" do
|
|
1383
1460
|
opts = {:host=>1, :database=>2, :servers=>{}}
|
|
1384
|
-
|
|
1461
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 1
|
|
1385
1462
|
end
|
|
1386
1463
|
|
|
1387
1464
|
specify "should return the general opts merged with the specific opts if given as a hash" do
|
|
1388
1465
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}}}
|
|
1389
|
-
|
|
1466
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 3
|
|
1390
1467
|
end
|
|
1391
1468
|
|
|
1392
1469
|
specify "should return the sgeneral opts merged with the specific opts if given as a proc" do
|
|
1393
1470
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>proc{|db| {:host=>4}}}}
|
|
1394
|
-
|
|
1471
|
+
Sequel::Database.new(opts).send(:server_opts, :server1)[:host].should == 4
|
|
1395
1472
|
end
|
|
1396
1473
|
|
|
1397
1474
|
specify "should raise an error if the specific opts is not a proc or hash" do
|
|
1398
1475
|
opts = {:host=>1, :database=>2, :servers=>{:server1=>2}}
|
|
1399
|
-
proc{
|
|
1476
|
+
proc{Sequel::Database.new(opts).send(:server_opts, :server1)}.should raise_error(Sequel::Error)
|
|
1477
|
+
end
|
|
1478
|
+
|
|
1479
|
+
specify "should return the general opts merged with given opts if given opts is a Hash" do
|
|
1480
|
+
opts = {:host=>1, :database=>2}
|
|
1481
|
+
Sequel::Database.new(opts).send(:server_opts, :host=>2)[:host].should == 2
|
|
1400
1482
|
end
|
|
1401
1483
|
end
|
|
1402
1484
|
|
|
1403
1485
|
describe "Database#add_servers" do
|
|
1404
1486
|
before do
|
|
1405
|
-
@db =
|
|
1406
|
-
def @db.connect(server)
|
|
1407
|
-
server_opts(server)
|
|
1408
|
-
end
|
|
1409
|
-
def @db.disconnect_connection(c)
|
|
1410
|
-
end
|
|
1487
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}})
|
|
1411
1488
|
end
|
|
1412
1489
|
|
|
1413
1490
|
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}
|
|
1491
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1492
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1493
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1417
1494
|
|
|
1418
1495
|
@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}
|
|
1496
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1497
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1498
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 6}
|
|
1422
1499
|
|
|
1423
1500
|
@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}
|
|
1501
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1502
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1503
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 6}
|
|
1427
1504
|
end
|
|
1428
1505
|
|
|
1429
1506
|
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}
|
|
1507
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1508
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1509
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1433
1510
|
|
|
1434
1511
|
@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}
|
|
1512
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1513
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1514
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1438
1515
|
|
|
1439
1516
|
@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}
|
|
1517
|
+
@db.synchronize{|c| c.opts[:host].should == 4}
|
|
1518
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 8}
|
|
1519
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 4}
|
|
1443
1520
|
end
|
|
1444
1521
|
end
|
|
1445
1522
|
|
|
1446
1523
|
describe "Database#remove_servers" do
|
|
1447
1524
|
before do
|
|
1448
|
-
@db =
|
|
1449
|
-
def @db.connect(server)
|
|
1450
|
-
server_opts(server)
|
|
1451
|
-
end
|
|
1452
|
-
def @db.disconnect_connection(c)
|
|
1453
|
-
end
|
|
1525
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
|
|
1454
1526
|
end
|
|
1455
1527
|
|
|
1456
1528
|
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}
|
|
1529
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1530
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 3}
|
|
1531
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 4}
|
|
1460
1532
|
|
|
1461
1533
|
@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}
|
|
1534
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1535
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 1}
|
|
1536
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1465
1537
|
end
|
|
1466
1538
|
|
|
1467
1539
|
specify "should accept arrays of symbols" do
|
|
1468
1540
|
@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}
|
|
1541
|
+
@db.synchronize{|c| c.opts[:host].should == 1}
|
|
1542
|
+
@db.synchronize(:server1){|c| c.opts[:host].should == 1}
|
|
1543
|
+
@db.synchronize(:server2){|c| c.opts[:host].should == 1}
|
|
1472
1544
|
end
|
|
1473
1545
|
|
|
1474
1546
|
specify "should allow removal while connections are still open" do
|
|
1475
1547
|
@db.synchronize do |c1|
|
|
1476
|
-
c1[:host].should == 1
|
|
1548
|
+
c1.opts[:host].should == 1
|
|
1477
1549
|
@db.synchronize(:server1) do |c2|
|
|
1478
|
-
c2[:host].should == 3
|
|
1550
|
+
c2.opts[:host].should == 3
|
|
1479
1551
|
@db.synchronize(:server2) do |c3|
|
|
1480
|
-
c3[:host].should == 4
|
|
1552
|
+
c3.opts[:host].should == 4
|
|
1481
1553
|
@db.remove_servers(:server1, :server2)
|
|
1482
1554
|
@db.synchronize(:server1) do |c4|
|
|
1483
1555
|
c4.should_not == c2
|
|
1484
1556
|
c4.should == c1
|
|
1485
|
-
c4[:host].should == 1
|
|
1557
|
+
c4.opts[:host].should == 1
|
|
1486
1558
|
@db.synchronize(:server2) do |c5|
|
|
1487
1559
|
c5.should_not == c3
|
|
1488
1560
|
c5.should == c1
|
|
1489
|
-
c5[:host].should == 1
|
|
1561
|
+
c5.opts[:host].should == 1
|
|
1490
1562
|
end
|
|
1491
1563
|
end
|
|
1492
|
-
c3[:host].should == 4
|
|
1564
|
+
c3.opts[:host].should == 4
|
|
1493
1565
|
end
|
|
1494
|
-
c2[:host].should == 3
|
|
1566
|
+
c2.opts[:host].should == 3
|
|
1495
1567
|
end
|
|
1496
|
-
c1[:host].should == 1
|
|
1568
|
+
c1.opts[:host].should == 1
|
|
1497
1569
|
end
|
|
1498
1570
|
end
|
|
1499
1571
|
end
|
|
1500
1572
|
|
|
1501
1573
|
describe "Database#each_server with do/jdbc adapter connection string without :adapter option" do
|
|
1502
|
-
|
|
1574
|
+
specify "should yield a separate database object for each server" do
|
|
1503
1575
|
klass = Class.new(Sequel::Database)
|
|
1504
|
-
klass.should_receive(:adapter_class).once.with(:jdbc).and_return(
|
|
1576
|
+
klass.should_receive(:adapter_class).once.with(:jdbc).and_return(Sequel::Mock::Database)
|
|
1505
1577
|
@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
1578
|
|
|
1513
|
-
specify "should yield a separate database object for each server" do
|
|
1514
1579
|
hosts = []
|
|
1515
1580
|
@db.each_server do |db|
|
|
1516
1581
|
db.should be_a_kind_of(Sequel::Database)
|
|
1517
1582
|
db.should_not == @db
|
|
1518
|
-
db.opts[:adapter_class].should ==
|
|
1583
|
+
db.opts[:adapter_class].should == Sequel::Mock::Database
|
|
1519
1584
|
db.opts[:database].should == 2
|
|
1520
1585
|
hosts << db.opts[:host]
|
|
1521
1586
|
end
|
|
@@ -1525,12 +1590,7 @@ end
|
|
|
1525
1590
|
|
|
1526
1591
|
describe "Database#each_server" do
|
|
1527
1592
|
before do
|
|
1528
|
-
@db = Sequel.
|
|
1529
|
-
def @db.connect(server)
|
|
1530
|
-
server_opts(server)
|
|
1531
|
-
end
|
|
1532
|
-
def @db.disconnect_connection(c)
|
|
1533
|
-
end
|
|
1593
|
+
@db = Sequel.mock(:host=>1, :database=>2, :servers=>{:server1=>{:host=>3}, :server2=>{:host=>4}})
|
|
1534
1594
|
end
|
|
1535
1595
|
|
|
1536
1596
|
specify "should yield a separate database object for each server" do
|
|
@@ -1561,21 +1621,25 @@ describe "Database#each_server" do
|
|
|
1561
1621
|
end
|
|
1562
1622
|
|
|
1563
1623
|
describe "Database#raise_error" do
|
|
1624
|
+
before do
|
|
1625
|
+
@db = Sequel.mock
|
|
1626
|
+
end
|
|
1627
|
+
|
|
1564
1628
|
specify "should reraise if the exception class is not in opts[:classes]" do
|
|
1565
1629
|
e = Class.new(StandardError)
|
|
1566
|
-
proc{
|
|
1630
|
+
proc{@db.send(:raise_error, e.new(''), :classes=>[])}.should raise_error(e)
|
|
1567
1631
|
end
|
|
1568
1632
|
|
|
1569
|
-
specify "should convert the exception to a DatabaseError if the exception class is
|
|
1570
|
-
proc{
|
|
1633
|
+
specify "should convert the exception to a DatabaseError if the exception class is in opts[:classes]" do
|
|
1634
|
+
proc{@db.send(:raise_error, Interrupt.new(''), :classes=>[Interrupt])}.should raise_error(Sequel::DatabaseError)
|
|
1571
1635
|
end
|
|
1572
1636
|
|
|
1573
1637
|
specify "should convert the exception to a DatabaseError if opts[:classes] if not present" do
|
|
1574
|
-
proc{
|
|
1638
|
+
proc{@db.send(:raise_error, Interrupt.new(''))}.should raise_error(Sequel::DatabaseError)
|
|
1575
1639
|
end
|
|
1576
1640
|
|
|
1577
1641
|
specify "should convert the exception to a DatabaseDisconnectError if opts[:disconnect] is true" do
|
|
1578
|
-
proc{
|
|
1642
|
+
proc{@db.send(:raise_error, Interrupt.new(''), :disconnect=>true)}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
1579
1643
|
end
|
|
1580
1644
|
end
|
|
1581
1645
|
|
|
@@ -1594,6 +1658,305 @@ describe "Database#typecast_value" do
|
|
|
1594
1658
|
proc{@db.typecast_value(:datetime, 4)}.should raise_error(Sequel::InvalidValue)
|
|
1595
1659
|
end
|
|
1596
1660
|
|
|
1661
|
+
specify "should handle integers with leading 0 as base 10" do
|
|
1662
|
+
@db.typecast_value(:integer, "013").should == 13
|
|
1663
|
+
@db.typecast_value(:integer, "08").should == 8
|
|
1664
|
+
@db.typecast_value(:integer, "000013").should == 13
|
|
1665
|
+
@db.typecast_value(:integer, "000008").should == 8
|
|
1666
|
+
end
|
|
1667
|
+
|
|
1668
|
+
specify "should handle integers with leading 0x as base 16" do
|
|
1669
|
+
@db.typecast_value(:integer, "0x013").should == 19
|
|
1670
|
+
@db.typecast_value(:integer, "0x80").should == 128
|
|
1671
|
+
end
|
|
1672
|
+
|
|
1673
|
+
specify "should typecast blobs as as Sequel::SQL::Blob" do
|
|
1674
|
+
v = @db.typecast_value(:blob, "0x013")
|
|
1675
|
+
v.should be_a_kind_of(Sequel::SQL::Blob)
|
|
1676
|
+
v.should == Sequel::SQL::Blob.new("0x013")
|
|
1677
|
+
@db.typecast_value(:blob, v).object_id.should == v.object_id
|
|
1678
|
+
end
|
|
1679
|
+
|
|
1680
|
+
specify "should typecast boolean values to true, false, or nil" do
|
|
1681
|
+
@db.typecast_value(:boolean, false).should be_false
|
|
1682
|
+
@db.typecast_value(:boolean, 0).should be_false
|
|
1683
|
+
@db.typecast_value(:boolean, "0").should be_false
|
|
1684
|
+
@db.typecast_value(:boolean, 'f').should be_false
|
|
1685
|
+
@db.typecast_value(:boolean, 'false').should be_false
|
|
1686
|
+
@db.typecast_value(:boolean, true).should be_true
|
|
1687
|
+
@db.typecast_value(:boolean, 1).should be_true
|
|
1688
|
+
@db.typecast_value(:boolean, '1').should be_true
|
|
1689
|
+
@db.typecast_value(:boolean, 't').should be_true
|
|
1690
|
+
@db.typecast_value(:boolean, 'true').should be_true
|
|
1691
|
+
@db.typecast_value(:boolean, '').should be_nil
|
|
1692
|
+
end
|
|
1693
|
+
|
|
1694
|
+
specify "should typecast date values to Date" do
|
|
1695
|
+
@db.typecast_value(:date, Date.today).should == Date.today
|
|
1696
|
+
@db.typecast_value(:date, DateTime.now).should == Date.today
|
|
1697
|
+
@db.typecast_value(:date, Time.now).should == Date.today
|
|
1698
|
+
@db.typecast_value(:date, Date.today.to_s).should == Date.today
|
|
1699
|
+
@db.typecast_value(:date, :year=>Date.today.year, :month=>Date.today.month, :day=>Date.today.day).should == Date.today
|
|
1700
|
+
end
|
|
1701
|
+
|
|
1702
|
+
specify "should have Sequel.application_to_database_timestamp convert to Sequel.database_timezone" do
|
|
1703
|
+
begin
|
|
1704
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1705
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1706
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1707
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1708
|
+
Sequel.application_timezone = :utc
|
|
1709
|
+
Sequel.database_timezone = :local
|
|
1710
|
+
Sequel.application_to_database_timestamp(t).should == t4
|
|
1711
|
+
Sequel.application_timezone = :local
|
|
1712
|
+
Sequel.database_timezone = :utc
|
|
1713
|
+
Sequel.application_to_database_timestamp(t2).should == t3
|
|
1714
|
+
ensure
|
|
1715
|
+
Sequel.default_timezone = nil
|
|
1716
|
+
end
|
|
1717
|
+
end
|
|
1718
|
+
|
|
1719
|
+
specify "should have Database#to_application_timestamp convert values using the database's timezone" do
|
|
1720
|
+
begin
|
|
1721
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5) # UTC Time
|
|
1722
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5) # Local Time
|
|
1723
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5) - (t - t2) # Local Time in UTC Time
|
|
1724
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5) + (t - t2) # UTC Time in Local Time
|
|
1725
|
+
Sequel.default_timezone = :utc
|
|
1726
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t
|
|
1727
|
+
Sequel.database_timezone = :local
|
|
1728
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t3
|
|
1729
|
+
Sequel.default_timezone = :local
|
|
1730
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t2
|
|
1731
|
+
Sequel.database_timezone = :utc
|
|
1732
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t4
|
|
1733
|
+
|
|
1734
|
+
Sequel.default_timezone = :utc
|
|
1735
|
+
@db.timezone = :local
|
|
1736
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t3
|
|
1737
|
+
Sequel.default_timezone = :local
|
|
1738
|
+
@db.timezone = :utc
|
|
1739
|
+
@db.to_application_timestamp('2011-01-02 03:04:05').should == t4
|
|
1740
|
+
ensure
|
|
1741
|
+
Sequel.default_timezone = nil
|
|
1742
|
+
end
|
|
1743
|
+
end
|
|
1744
|
+
|
|
1745
|
+
specify "should typecast datetime values to Sequel.datetime_class with correct timezone handling" do
|
|
1746
|
+
t = Time.utc(2011, 1, 2, 3, 4, 5, 500000) # UTC Time
|
|
1747
|
+
t2 = Time.mktime(2011, 1, 2, 3, 4, 5, 500000) # Local Time
|
|
1748
|
+
t3 = Time.utc(2011, 1, 2, 3, 4, 5, 500000) - (t - t2) # Local Time in UTC Time
|
|
1749
|
+
t4 = Time.mktime(2011, 1, 2, 3, 4, 5, 500000) + (t - t2) # UTC Time in Local Time
|
|
1750
|
+
secs = defined?(Rational) ? Rational(11, 2) : 5.5
|
|
1751
|
+
r1 = defined?(Rational) ? Rational(t2.utc_offset, 86400) : t2.utc_offset/86400.0
|
|
1752
|
+
r2 = defined?(Rational) ? Rational((t - t2).to_i, 86400) : (t - t2).to_i/86400.0
|
|
1753
|
+
dt = DateTime.civil(2011, 1, 2, 3, 4, secs)
|
|
1754
|
+
dt2 = DateTime.civil(2011, 1, 2, 3, 4, secs, r1)
|
|
1755
|
+
dt3 = DateTime.civil(2011, 1, 2, 3, 4, secs) - r2
|
|
1756
|
+
dt4 = DateTime.civil(2011, 1, 2, 3, 4, secs, r1) + r2
|
|
1757
|
+
|
|
1758
|
+
t.should == t4
|
|
1759
|
+
t2.should == t3
|
|
1760
|
+
dt.should == dt4
|
|
1761
|
+
dt2.should == dt3
|
|
1762
|
+
|
|
1763
|
+
check = proc do |i, o|
|
|
1764
|
+
v = @db.typecast_value(:datetime, i)
|
|
1765
|
+
v.should == o
|
|
1766
|
+
if o.is_a?(Time)
|
|
1767
|
+
v.utc_offset.should == o.utc_offset
|
|
1768
|
+
else
|
|
1769
|
+
v.offset.should == o.offset
|
|
1770
|
+
end
|
|
1771
|
+
end
|
|
1772
|
+
@db.extend_datasets(Module.new{def supports_timestamp_timezones?; true; end})
|
|
1773
|
+
begin
|
|
1774
|
+
@db.typecast_value(:datetime, dt).should == t
|
|
1775
|
+
@db.typecast_value(:datetime, dt2).should == t2
|
|
1776
|
+
@db.typecast_value(:datetime, t).should == t
|
|
1777
|
+
@db.typecast_value(:datetime, t2).should == t2
|
|
1778
|
+
@db.typecast_value(:datetime, @db.literal(dt)[1...-1]).should == t
|
|
1779
|
+
@db.typecast_value(:datetime, dt.strftime('%F %T.%N')).should == t2
|
|
1780
|
+
@db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == Time.mktime(2011, 1, 2, 0, 0, 0)
|
|
1781
|
+
@db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000).should == t2
|
|
1782
|
+
|
|
1783
|
+
Sequel.datetime_class = DateTime
|
|
1784
|
+
@db.typecast_value(:datetime, dt).should == dt
|
|
1785
|
+
@db.typecast_value(:datetime, dt2).should == dt2
|
|
1786
|
+
@db.typecast_value(:datetime, t).should == dt
|
|
1787
|
+
@db.typecast_value(:datetime, t2).should == dt2
|
|
1788
|
+
@db.typecast_value(:datetime, @db.literal(dt)[1...-1]).should == dt
|
|
1789
|
+
@db.typecast_value(:datetime, dt.strftime('%F %T.%N')).should == dt
|
|
1790
|
+
@db.typecast_value(:datetime, Date.civil(2011, 1, 2)).should == DateTime.civil(2011, 1, 2, 0, 0, 0)
|
|
1791
|
+
@db.typecast_value(:datetime, :year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000).should == dt
|
|
1792
|
+
|
|
1793
|
+
Sequel.application_timezone = :utc
|
|
1794
|
+
Sequel.typecast_timezone = :local
|
|
1795
|
+
Sequel.datetime_class = Time
|
|
1796
|
+
check[dt, t]
|
|
1797
|
+
check[dt2, t3]
|
|
1798
|
+
check[t, t]
|
|
1799
|
+
check[t2, t3]
|
|
1800
|
+
check[@db.literal(dt)[1...-1], t]
|
|
1801
|
+
check[dt.strftime('%F %T.%N'), t3]
|
|
1802
|
+
check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
|
|
1803
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t3]
|
|
1804
|
+
|
|
1805
|
+
Sequel.datetime_class = DateTime
|
|
1806
|
+
check[dt, dt]
|
|
1807
|
+
check[dt2, dt3]
|
|
1808
|
+
check[t, dt]
|
|
1809
|
+
check[t2, dt3]
|
|
1810
|
+
check[@db.literal(dt)[1...-1], dt]
|
|
1811
|
+
check[dt.strftime('%F %T.%N'), dt3]
|
|
1812
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
|
|
1813
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt3]
|
|
1814
|
+
|
|
1815
|
+
Sequel.typecast_timezone = :utc
|
|
1816
|
+
Sequel.datetime_class = Time
|
|
1817
|
+
check[dt, t]
|
|
1818
|
+
check[dt2, t3]
|
|
1819
|
+
check[t, t]
|
|
1820
|
+
check[t2, t3]
|
|
1821
|
+
check[@db.literal(dt)[1...-1], t]
|
|
1822
|
+
check[dt.strftime('%F %T.%N'), t]
|
|
1823
|
+
check[Date.civil(2011, 1, 2), Time.utc(2011, 1, 2, 0, 0, 0)]
|
|
1824
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t]
|
|
1825
|
+
|
|
1826
|
+
Sequel.datetime_class = DateTime
|
|
1827
|
+
check[dt, dt]
|
|
1828
|
+
check[dt2, dt3]
|
|
1829
|
+
check[t, dt]
|
|
1830
|
+
check[t2, dt3]
|
|
1831
|
+
check[@db.literal(dt)[1...-1], dt]
|
|
1832
|
+
check[dt.strftime('%F %T.%N'), dt]
|
|
1833
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0)]
|
|
1834
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt]
|
|
1835
|
+
|
|
1836
|
+
Sequel.application_timezone = :local
|
|
1837
|
+
Sequel.datetime_class = Time
|
|
1838
|
+
check[dt, t4]
|
|
1839
|
+
check[dt2, t2]
|
|
1840
|
+
check[t, t4]
|
|
1841
|
+
check[t2, t2]
|
|
1842
|
+
check[@db.literal(dt)[1...-1], t4]
|
|
1843
|
+
check[dt.strftime('%F %T.%N'), t4]
|
|
1844
|
+
check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
|
|
1845
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t4]
|
|
1846
|
+
|
|
1847
|
+
Sequel.datetime_class = DateTime
|
|
1848
|
+
check[dt, dt4]
|
|
1849
|
+
check[dt2, dt2]
|
|
1850
|
+
check[t, dt4]
|
|
1851
|
+
check[t2, dt2]
|
|
1852
|
+
check[@db.literal(dt)[1...-1], dt4]
|
|
1853
|
+
check[dt.strftime('%F %T.%N'), dt4]
|
|
1854
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
|
|
1855
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt4]
|
|
1856
|
+
|
|
1857
|
+
Sequel.typecast_timezone = :local
|
|
1858
|
+
Sequel.datetime_class = Time
|
|
1859
|
+
check[dt, t4]
|
|
1860
|
+
check[dt2, t2]
|
|
1861
|
+
check[t, t4]
|
|
1862
|
+
check[t2, t2]
|
|
1863
|
+
check[@db.literal(dt)[1...-1], t4]
|
|
1864
|
+
check[dt.strftime('%F %T.%N'), t2]
|
|
1865
|
+
check[Date.civil(2011, 1, 2), Time.local(2011, 1, 2, 0, 0, 0)]
|
|
1866
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, t2]
|
|
1867
|
+
|
|
1868
|
+
Sequel.datetime_class = DateTime
|
|
1869
|
+
check[dt, dt4]
|
|
1870
|
+
check[dt2, dt2]
|
|
1871
|
+
check[t, dt4]
|
|
1872
|
+
check[t2, dt2]
|
|
1873
|
+
check[@db.literal(dt)[1...-1], dt4]
|
|
1874
|
+
check[dt.strftime('%F %T.%N'), dt2]
|
|
1875
|
+
check[Date.civil(2011, 1, 2), DateTime.civil(2011, 1, 2, 0, 0, 0, r1)]
|
|
1876
|
+
check[{:year=>dt.year, :month=>dt.month, :day=>dt.day, :hour=>dt.hour, :minute=>dt.min, :second=>dt.sec, :nanos=>500000000}, dt2]
|
|
1877
|
+
|
|
1878
|
+
ensure
|
|
1879
|
+
Sequel.default_timezone = nil
|
|
1880
|
+
Sequel.datetime_class = Time
|
|
1881
|
+
end
|
|
1882
|
+
end
|
|
1883
|
+
|
|
1884
|
+
specify "should handle arrays when typecasting timestamps" do
|
|
1885
|
+
begin
|
|
1886
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14]).should == Time.local(2011, 10, 11, 12, 13, 14)
|
|
1887
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14, 500000000]).should == Time.local(2011, 10, 11, 12, 13, 14, 500000)
|
|
1888
|
+
|
|
1889
|
+
Sequel.datetime_class = DateTime
|
|
1890
|
+
@db.typecast_value(:datetime, [2011, 10, 11, 12, 13, 14]).should == DateTime.civil(2011, 10, 11, 12, 13, 14)
|
|
1891
|
+
@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))
|
|
1892
|
+
@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))
|
|
1893
|
+
ensure
|
|
1894
|
+
Sequel.datetime_class = Time
|
|
1895
|
+
end
|
|
1896
|
+
end
|
|
1897
|
+
|
|
1898
|
+
specify "should handle hashes when typecasting timestamps" do
|
|
1899
|
+
begin
|
|
1900
|
+
@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)
|
|
1901
|
+
@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)
|
|
1902
|
+
@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)
|
|
1903
|
+
@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)
|
|
1904
|
+
|
|
1905
|
+
Sequel.datetime_class = DateTime
|
|
1906
|
+
@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)
|
|
1907
|
+
@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))
|
|
1908
|
+
@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)
|
|
1909
|
+
@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))
|
|
1910
|
+
@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))
|
|
1911
|
+
@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))
|
|
1912
|
+
@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))
|
|
1913
|
+
@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))
|
|
1914
|
+
ensure
|
|
1915
|
+
Sequel.datetime_class = Time
|
|
1916
|
+
end
|
|
1917
|
+
end
|
|
1918
|
+
|
|
1919
|
+
specify "should typecast decimal values to BigDecimal" do
|
|
1920
|
+
[1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
|
|
1921
|
+
v = @db.typecast_value(:decimal, i)
|
|
1922
|
+
v.should be_a_kind_of(BigDecimal)
|
|
1923
|
+
v.should == BigDecimal.new('1.0')
|
|
1924
|
+
end
|
|
1925
|
+
end
|
|
1926
|
+
|
|
1927
|
+
specify "should typecast float values to Float" do
|
|
1928
|
+
[1.0, 1, '1.0', BigDecimal('1.0')].each do |i|
|
|
1929
|
+
v = @db.typecast_value(:float, i)
|
|
1930
|
+
v.should be_a_kind_of(Float)
|
|
1931
|
+
v.should == 1.0
|
|
1932
|
+
end
|
|
1933
|
+
end
|
|
1934
|
+
|
|
1935
|
+
specify "should typecast string values to String" do
|
|
1936
|
+
[1.0, '1.0', Sequel.blob('1.0')].each do |i|
|
|
1937
|
+
v = @db.typecast_value(:string, i)
|
|
1938
|
+
v.should be_an_instance_of(String)
|
|
1939
|
+
v.should == "1.0"
|
|
1940
|
+
end
|
|
1941
|
+
end
|
|
1942
|
+
|
|
1943
|
+
specify "should typecast time values to SQLTime" do
|
|
1944
|
+
t = Time.now
|
|
1945
|
+
st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3)
|
|
1946
|
+
[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|
|
|
1947
|
+
v = @db.typecast_value(:time, i)
|
|
1948
|
+
v.should be_an_instance_of(Sequel::SQLTime)
|
|
1949
|
+
v.should == st
|
|
1950
|
+
end
|
|
1951
|
+
end
|
|
1952
|
+
|
|
1953
|
+
specify "should correctly handle time value conversion to SQLTime with fractional seconds" do
|
|
1954
|
+
t = Time.now
|
|
1955
|
+
st = Sequel::SQLTime.local(t.year, t.month, t.day, 1, 2, 3, 500000)
|
|
1956
|
+
t = Time.local(t.year, t.month, t.day, 1, 2, 3, 500000)
|
|
1957
|
+
@db.typecast_value(:time, t).should == st
|
|
1958
|
+
end
|
|
1959
|
+
|
|
1597
1960
|
specify "should have an underlying exception class available at wrapped_exception" do
|
|
1598
1961
|
begin
|
|
1599
1962
|
@db.typecast_value(:date, 'a')
|
|
@@ -1639,10 +2002,23 @@ describe "Database#blank_object?" do
|
|
|
1639
2002
|
end
|
|
1640
2003
|
|
|
1641
2004
|
describe "Database#schema_autoincrementing_primary_key?" do
|
|
1642
|
-
specify "should whether the parsed schema row indicates a primary key" do
|
|
2005
|
+
specify "should indicate whether the parsed schema row indicates a primary key" do
|
|
1643
2006
|
m = Sequel::Database.new.method(:schema_autoincrementing_primary_key?)
|
|
1644
|
-
m.call(:primary_key=>true).should == true
|
|
1645
|
-
m.call(:primary_key=>
|
|
2007
|
+
m.call(:primary_key=>true, :db_type=>'integer').should == true
|
|
2008
|
+
m.call(:primary_key=>true, :db_type=>'varchar(255)').should == false
|
|
2009
|
+
m.call(:primary_key=>false, :db_type=>'integer').should == false
|
|
2010
|
+
end
|
|
2011
|
+
end
|
|
2012
|
+
|
|
2013
|
+
describe "Database#supports_transactional_ddl?" do
|
|
2014
|
+
specify "should be false by default" do
|
|
2015
|
+
Sequel::Database.new.supports_transactional_ddl?.should == false
|
|
2016
|
+
end
|
|
2017
|
+
end
|
|
2018
|
+
|
|
2019
|
+
describe "Database#global_index_namespace?" do
|
|
2020
|
+
specify "should be true by default" do
|
|
2021
|
+
Sequel::Database.new.global_index_namespace?.should == true
|
|
1646
2022
|
end
|
|
1647
2023
|
end
|
|
1648
2024
|
|
|
@@ -1652,6 +2028,19 @@ describe "Database#supports_savepoints?" do
|
|
|
1652
2028
|
end
|
|
1653
2029
|
end
|
|
1654
2030
|
|
|
2031
|
+
describe "Database#supports_savepoints_in_prepared_transactions?" do
|
|
2032
|
+
specify "should be false by default" do
|
|
2033
|
+
Sequel::Database.new.supports_savepoints_in_prepared_transactions?.should == false
|
|
2034
|
+
end
|
|
2035
|
+
|
|
2036
|
+
specify "should be true if both savepoints and prepared transactions are supported" do
|
|
2037
|
+
db = Sequel::Database.new
|
|
2038
|
+
db.meta_def(:supports_savepoints?){true}
|
|
2039
|
+
db.meta_def(:supports_prepared_transactions?){true}
|
|
2040
|
+
db.supports_savepoints_in_prepared_transactions?.should == true
|
|
2041
|
+
end
|
|
2042
|
+
end
|
|
2043
|
+
|
|
1655
2044
|
describe "Database#supports_prepared_transactions?" do
|
|
1656
2045
|
specify "should be false by default" do
|
|
1657
2046
|
Sequel::Database.new.supports_prepared_transactions?.should == false
|
|
@@ -1693,15 +2082,18 @@ end
|
|
|
1693
2082
|
describe "Database#column_schema_to_ruby_default" do
|
|
1694
2083
|
specify "should handle converting many default formats" do
|
|
1695
2084
|
db = Sequel::Database.new
|
|
1696
|
-
|
|
1697
|
-
p
|
|
1698
|
-
p[
|
|
2085
|
+
p = lambda{|d,t| db.send(:column_schema_to_ruby_default, d, t)}
|
|
2086
|
+
p[nil, :integer].should be_nil
|
|
2087
|
+
p[1, :integer].should == 1
|
|
1699
2088
|
p['1', :integer].should == 1
|
|
1700
2089
|
p['-1', :integer].should == -1
|
|
2090
|
+
p[1.0, :float].should == 1.0
|
|
1701
2091
|
p['1.0', :float].should == 1.0
|
|
1702
2092
|
p['-1.0', :float].should == -1.0
|
|
1703
2093
|
p['1.0', :decimal].should == BigDecimal.new('1.0')
|
|
1704
2094
|
p['-1.0', :decimal].should == BigDecimal.new('-1.0')
|
|
2095
|
+
p[true, :boolean].should == true
|
|
2096
|
+
p[false, :boolean].should == false
|
|
1705
2097
|
p['1', :boolean].should == true
|
|
1706
2098
|
p['0', :boolean].should == false
|
|
1707
2099
|
p['true', :boolean].should == true
|
|
@@ -1709,33 +2101,40 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1709
2101
|
p["'t'", :boolean].should == true
|
|
1710
2102
|
p["'f'", :boolean].should == false
|
|
1711
2103
|
p["'a'", :string].should == 'a'
|
|
1712
|
-
p["'a'", :blob].should == 'a'
|
|
2104
|
+
p["'a'", :blob].should == Sequel.blob('a')
|
|
1713
2105
|
p["'a'", :blob].should be_a_kind_of(Sequel::SQL::Blob)
|
|
1714
2106
|
p["''", :string].should == ''
|
|
1715
2107
|
p["'\\a''b'", :string].should == "\\a'b"
|
|
1716
2108
|
p["'NULL'", :string].should == "NULL"
|
|
2109
|
+
p[Date.today, :date].should == Date.today
|
|
1717
2110
|
p["'2009-10-29'", :date].should == Date.new(2009,10,29)
|
|
1718
|
-
p["CURRENT_TIMESTAMP", :date].should ==
|
|
1719
|
-
p["
|
|
2111
|
+
p["CURRENT_TIMESTAMP", :date].should == Sequel::CURRENT_DATE
|
|
2112
|
+
p["CURRENT_DATE", :date].should == Sequel::CURRENT_DATE
|
|
2113
|
+
p["now()", :date].should == Sequel::CURRENT_DATE
|
|
2114
|
+
p["getdate()", :date].should == Sequel::CURRENT_DATE
|
|
2115
|
+
p["CURRENT_TIMESTAMP", :datetime].should == Sequel::CURRENT_TIMESTAMP
|
|
2116
|
+
p["CURRENT_DATE", :datetime].should == Sequel::CURRENT_TIMESTAMP
|
|
2117
|
+
p["now()", :datetime].should == Sequel::CURRENT_TIMESTAMP
|
|
2118
|
+
p["getdate()", :datetime].should == Sequel::CURRENT_TIMESTAMP
|
|
1720
2119
|
p["'2009-10-29T10:20:30-07:00'", :datetime].should == DateTime.parse('2009-10-29T10:20:30-07:00')
|
|
1721
2120
|
p["'2009-10-29 10:20:30'", :datetime].should == DateTime.parse('2009-10-29 10:20:30')
|
|
1722
2121
|
p["'10:20:30'", :time].should == Time.parse('10:20:30')
|
|
1723
|
-
p["NaN", :float].should
|
|
2122
|
+
p["NaN", :float].should be_nil
|
|
1724
2123
|
|
|
1725
|
-
db.
|
|
2124
|
+
db = Sequel.mock(:host=>'postgres')
|
|
1726
2125
|
p["''::text", :string].should == ""
|
|
1727
2126
|
p["'\\a''b'::character varying", :string].should == "\\a'b"
|
|
1728
2127
|
p["'a'::bpchar", :string].should == "a"
|
|
1729
2128
|
p["(-1)", :integer].should == -1
|
|
1730
2129
|
p["(-1.0)", :float].should == -1.0
|
|
1731
2130
|
p['(-1.0)', :decimal].should == BigDecimal.new('-1.0')
|
|
1732
|
-
p["'a'::bytea", :blob].should == 'a'
|
|
2131
|
+
p["'a'::bytea", :blob].should == Sequel.blob('a')
|
|
1733
2132
|
p["'a'::bytea", :blob].should be_a_kind_of(Sequel::SQL::Blob)
|
|
1734
2133
|
p["'2009-10-29'::date", :date].should == Date.new(2009,10,29)
|
|
1735
2134
|
p["'2009-10-29 10:20:30.241343'::timestamp without time zone", :datetime].should == DateTime.parse('2009-10-29 10:20:30.241343')
|
|
1736
2135
|
p["'10:20:30'::time without time zone", :time].should == Time.parse('10:20:30')
|
|
1737
2136
|
|
|
1738
|
-
db.
|
|
2137
|
+
db = Sequel.mock(:host=>'mysql')
|
|
1739
2138
|
p["\\a'b", :string].should == "\\a'b"
|
|
1740
2139
|
p["a", :string].should == "a"
|
|
1741
2140
|
p["NULL", :string].should == "NULL"
|
|
@@ -1744,14 +2143,71 @@ describe "Database#column_schema_to_ruby_default" do
|
|
|
1744
2143
|
p["2009-10-29", :date].should == Date.new(2009,10,29)
|
|
1745
2144
|
p["2009-10-29 10:20:30", :datetime].should == DateTime.parse('2009-10-29 10:20:30')
|
|
1746
2145
|
p["10:20:30", :time].should == Time.parse('10:20:30')
|
|
1747
|
-
p["CURRENT_DATE", :date].should == nil
|
|
1748
|
-
p["CURRENT_TIMESTAMP", :datetime].should == nil
|
|
1749
2146
|
p["a", :enum].should == "a"
|
|
2147
|
+
p["a,b", :set].should == "a,b"
|
|
1750
2148
|
|
|
1751
|
-
db.
|
|
2149
|
+
db = Sequel.mock(:host=>'mssql')
|
|
1752
2150
|
p["(N'a')", :string].should == "a"
|
|
1753
2151
|
p["((-12))", :integer].should == -12
|
|
1754
2152
|
p["((12.1))", :float].should == 12.1
|
|
1755
2153
|
p["((-12.1))", :decimal].should == BigDecimal.new('-12.1')
|
|
1756
2154
|
end
|
|
1757
2155
|
end
|
|
2156
|
+
|
|
2157
|
+
describe "Database extensions" do
|
|
2158
|
+
before(:all) do
|
|
2159
|
+
class << Sequel
|
|
2160
|
+
alias _extension extension
|
|
2161
|
+
def extension(*)
|
|
2162
|
+
end
|
|
2163
|
+
end
|
|
2164
|
+
end
|
|
2165
|
+
after(:all) do
|
|
2166
|
+
class << Sequel
|
|
2167
|
+
alias extension _extension
|
|
2168
|
+
end
|
|
2169
|
+
end
|
|
2170
|
+
before do
|
|
2171
|
+
@db = Sequel.mock
|
|
2172
|
+
end
|
|
2173
|
+
|
|
2174
|
+
specify "should be able to register an extension with a module Database#extension extend the module" do
|
|
2175
|
+
Sequel::Database.register_extension(:foo, Module.new{def a; 1; end})
|
|
2176
|
+
@db.extension(:foo).a.should == 1
|
|
2177
|
+
end
|
|
2178
|
+
|
|
2179
|
+
specify "should be able to register an extension with a block and Database#extension call the block" do
|
|
2180
|
+
@db.quote_identifiers = false
|
|
2181
|
+
Sequel::Database.register_extension(:foo){|db| db.quote_identifiers = true}
|
|
2182
|
+
@db.extension(:foo).quote_identifiers?.should be_true
|
|
2183
|
+
end
|
|
2184
|
+
|
|
2185
|
+
specify "should be able to register an extension with a callable and Database#extension call the callable" do
|
|
2186
|
+
@db.quote_identifiers = false
|
|
2187
|
+
Sequel::Database.register_extension(:foo, proc{|db| db.quote_identifiers = true})
|
|
2188
|
+
@db.extension(:foo).quote_identifiers?.should be_true
|
|
2189
|
+
end
|
|
2190
|
+
|
|
2191
|
+
specify "should be able to load multiple extensions in the same call" do
|
|
2192
|
+
@db.quote_identifiers = false
|
|
2193
|
+
@db.identifier_input_method = :downcase
|
|
2194
|
+
Sequel::Database.register_extension(:foo, proc{|db| db.quote_identifiers = true})
|
|
2195
|
+
Sequel::Database.register_extension(:bar, proc{|db| db.identifier_input_method = nil})
|
|
2196
|
+
@db.extension(:foo, :bar)
|
|
2197
|
+
@db.quote_identifiers?.should be_true
|
|
2198
|
+
@db.identifier_input_method.should be_nil
|
|
2199
|
+
end
|
|
2200
|
+
|
|
2201
|
+
specify "should return the receiver" do
|
|
2202
|
+
Sequel::Database.register_extension(:foo, Module.new{def a; 1; end})
|
|
2203
|
+
@db.extension(:foo).should equal(@db)
|
|
2204
|
+
end
|
|
2205
|
+
|
|
2206
|
+
specify "should raise an Error if registering with both a module and a block" do
|
|
2207
|
+
proc{Sequel::Database.register_extension(:foo, Module.new){}}.should raise_error(Sequel::Error)
|
|
2208
|
+
end
|
|
2209
|
+
|
|
2210
|
+
specify "should raise an Error if attempting to load an incompatible extension" do
|
|
2211
|
+
proc{@db.extension(:foo2)}.should raise_error(Sequel::Error)
|
|
2212
|
+
end
|
|
2213
|
+
end
|