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