sequel 3.21.0 → 3.36.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 +855 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -7
- data/Rakefile +42 -24
- data/bin/sequel +26 -8
- data/doc/active_record.rdoc +1 -0
- data/doc/advanced_associations.rdoc +171 -11
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +85 -552
- data/doc/model_hooks.rdoc +78 -27
- data/doc/object_model.rdoc +541 -0
- data/doc/opening_databases.rdoc +97 -50
- data/doc/prepared_statements.rdoc +40 -14
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +30 -4
- 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/schema_modification.rdoc +572 -0
- data/doc/sharding.rdoc +95 -3
- data/doc/testing.rdoc +129 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +51 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +1 -57
- 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 +47 -0
- data/lib/sequel/adapters/jdbc/derby.rb +287 -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 +29 -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 +58 -48
- 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 +265 -94
- data/lib/sequel/adapters/mock.rb +361 -0
- data/lib/sequel/adapters/mysql.rb +118 -222
- data/lib/sequel/adapters/mysql2.rb +58 -57
- data/lib/sequel/adapters/odbc/mssql.rb +15 -7
- 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 +356 -107
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +342 -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 +335 -118
- data/lib/sequel/adapters/shared/mysql.rb +340 -76
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +243 -45
- data/lib/sequel/adapters/shared/postgres.rb +524 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +265 -89
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +9 -12
- data/lib/sequel/adapters/swift/postgres.rb +9 -74
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +8 -7
- data/lib/sequel/adapters/tinytds.rb +161 -21
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +38 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +118 -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 +150 -46
- data/lib/sequel/database/query.rb +215 -65
- data/lib/sequel/database/schema_generator.rb +64 -20
- data/lib/sequel/database/schema_methods.rb +212 -54
- data/lib/sequel/dataset/actions.rb +322 -85
- data/lib/sequel/dataset/features.rb +96 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +237 -44
- data/lib/sequel/dataset/sql.rb +698 -278
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
- data/lib/sequel/extensions/migration.rb +97 -11
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_inet.rb +89 -0
- data/lib/sequel/extensions/pg_json.rb +178 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query.rb +1 -1
- 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 +251 -37
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/server_block.rb +139 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1187 -393
- data/lib/sequel/model/base.rb +578 -170
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- 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/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -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 +123 -8
- 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 +12 -2
- data/lib/sequel/plugins/many_through_many.rb +79 -28
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +139 -63
- data/lib/sequel/plugins/optimistic_locking.rb +8 -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 +29 -15
- data/lib/sequel/plugins/schema.rb +7 -2
- 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 +10 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +526 -59
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +142 -40
- data/spec/adapters/mysql_spec.rb +380 -234
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +1050 -212
- data/spec/adapters/spec_helper.rb +8 -5
- data/spec/adapters/sqlite_spec.rb +139 -27
- data/spec/core/connection_pool_spec.rb +196 -93
- data/spec/core/database_spec.rb +879 -510
- data/spec/core/dataset_spec.rb +1415 -1086
- data/spec/core/expression_filters_spec.rb +554 -109
- data/spec/core/mock_adapter_spec.rb +449 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +482 -38
- data/spec/core/spec_helper.rb +6 -48
- 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/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/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +69 -92
- data/spec/extensions/identity_map_spec.rb +131 -22
- 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 -6
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +48 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- 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 +251 -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 +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_inet_spec.rb +44 -0
- data/spec/extensions/pg_json_spec.rb +101 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -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 +168 -0
- data/spec/extensions/query_spec.rb +6 -0
- 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 +429 -22
- data/spec/extensions/schema_spec.rb +25 -21
- 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 +85 -43
- 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 +22 -61
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -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 +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +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 +9 -3
- data/spec/integration/dataset_test.rb +605 -91
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +454 -143
- data/spec/integration/prepared_statement_test.rb +263 -128
- data/spec/integration/schema_test.rb +309 -43
- data/spec/integration/spec_helper.rb +40 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +18 -4
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +1067 -661
- data/spec/model/base_spec.rb +329 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +240 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +490 -232
- data/spec/model/spec_helper.rb +14 -71
- data/spec/model/validations_spec.rb +11 -0
- data/spec/rcov.opts +2 -0
- metadata +178 -80
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
|
3
3
|
describe "Sequel timezone support" do
|
|
4
|
-
def test_timezone
|
|
4
|
+
def test_timezone(timezone=Sequel.application_timezone)
|
|
5
|
+
tz = timezone
|
|
6
|
+
Sequel.datetime_class = Time
|
|
5
7
|
# Tests should cover both DST and non-DST times.
|
|
6
8
|
[Time.now, Time.local(2010,1,1,12), Time.local(2010,6,1,12)].each do |t|
|
|
7
9
|
@db[:t].insert(t)
|
|
8
10
|
t2 = @db[:t].single_value
|
|
9
|
-
t2 =
|
|
11
|
+
t2 = @db.to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
|
|
10
12
|
(t2 - t).should be_within(2).of(0)
|
|
11
|
-
t2.utc_offset.should == 0 if
|
|
12
|
-
t2.utc_offset.should == t.getlocal.utc_offset if
|
|
13
|
+
t2.utc_offset.should == 0 if timezone == :utc
|
|
14
|
+
t2.utc_offset.should == t.getlocal.utc_offset if timezone == :local
|
|
13
15
|
@db[:t].delete
|
|
14
16
|
end
|
|
15
17
|
|
|
@@ -19,10 +21,10 @@ describe "Sequel timezone support" do
|
|
|
19
21
|
[DateTime.now, DateTime.civil(2010,1,1,12,0,0,local_std_offset), DateTime.civil(2010,6,1,12,0,0,local_dst_offset)].each do |dt|
|
|
20
22
|
@db[:t].insert(dt)
|
|
21
23
|
dt2 = @db[:t].single_value
|
|
22
|
-
dt2 =
|
|
24
|
+
dt2 = @db.to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
|
|
23
25
|
(dt2 - dt).should be_within(0.00002).of(0)
|
|
24
|
-
dt2.offset.should == 0 if
|
|
25
|
-
dt2.offset.should == dt.offset if
|
|
26
|
+
dt2.offset.should == 0 if timezone == :utc
|
|
27
|
+
dt2.offset.should == dt.offset if timezone == :local
|
|
26
28
|
@db[:t].delete
|
|
27
29
|
end
|
|
28
30
|
end
|
|
@@ -32,30 +34,54 @@ describe "Sequel timezone support" do
|
|
|
32
34
|
@db.create_table!(:t){DateTime :t}
|
|
33
35
|
end
|
|
34
36
|
after do
|
|
35
|
-
@db.
|
|
37
|
+
@db.timezone = nil
|
|
36
38
|
Sequel.default_timezone = nil
|
|
37
39
|
Sequel.datetime_class = Time
|
|
40
|
+
@db.drop_table(:t)
|
|
38
41
|
end
|
|
39
42
|
|
|
40
|
-
cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do,
|
|
43
|
+
cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
|
|
41
44
|
Sequel.database_timezone = :utc
|
|
42
45
|
Sequel.application_timezone = :local
|
|
43
46
|
test_timezone
|
|
47
|
+
Sequel.database_timezone = nil
|
|
48
|
+
@db.timezone = :utc
|
|
49
|
+
test_timezone
|
|
44
50
|
end
|
|
45
51
|
|
|
46
|
-
cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do,
|
|
52
|
+
cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
|
|
47
53
|
Sequel.database_timezone = :local
|
|
48
54
|
Sequel.application_timezone = :utc
|
|
49
55
|
test_timezone
|
|
56
|
+
Sequel.database_timezone = nil
|
|
57
|
+
@db.timezone = :local
|
|
58
|
+
test_timezone
|
|
50
59
|
end
|
|
51
60
|
|
|
52
|
-
cspecify "should support using UTC for both database storage and for application", [:swift], [:do,
|
|
61
|
+
cspecify "should support using UTC for both database storage and for application", [:swift], [:do, :mysql], [:do, :postgres], [:oracle] do
|
|
53
62
|
Sequel.default_timezone = :utc
|
|
54
63
|
test_timezone
|
|
64
|
+
Sequel.database_timezone = :local
|
|
65
|
+
@db.timezone = :utc
|
|
66
|
+
test_timezone
|
|
55
67
|
end
|
|
56
68
|
|
|
57
|
-
cspecify "should support using local time for both database storage and for application", [:do,
|
|
69
|
+
cspecify "should support using local time for both database storage and for application", [:do, :mysql], [:do, :postgres], [:oracle], [:swift, :postgres], [:swift, :mysql] do
|
|
58
70
|
Sequel.default_timezone = :local
|
|
59
71
|
test_timezone
|
|
72
|
+
Sequel.database_timezone = :utc
|
|
73
|
+
@db.timezone = :local
|
|
74
|
+
test_timezone
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
specify "should allow overriding the database_timezone on a per-database basis" do
|
|
78
|
+
Sequel.database_timezone = :utc
|
|
79
|
+
@db.timezone = :local
|
|
80
|
+
t = Time.now
|
|
81
|
+
@db[:t].insert(t)
|
|
82
|
+
s = @db[:t].get(:t.cast(String))
|
|
83
|
+
if o = Date._parse(s)[:offset]
|
|
84
|
+
o.should == t.utc_offset
|
|
85
|
+
end
|
|
60
86
|
end
|
|
61
87
|
end
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
|
3
3
|
describe "Database transactions" do
|
|
4
|
-
before do
|
|
4
|
+
before(:all) do
|
|
5
5
|
@db = INTEGRATION_DB
|
|
6
|
-
@db.
|
|
7
|
-
@db.create_table(:items, :engine=>'InnoDB'){String :name; Integer :value}
|
|
6
|
+
@db.create_table!(:items, :engine=>'InnoDB'){String :name; Integer :value}
|
|
8
7
|
@d = @db[:items]
|
|
9
|
-
clear_sqls
|
|
10
8
|
end
|
|
11
|
-
|
|
12
|
-
@
|
|
9
|
+
before do
|
|
10
|
+
@d.delete
|
|
11
|
+
end
|
|
12
|
+
after(:all) do
|
|
13
|
+
@db.drop_table?(:items)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
specify "should support transactions" do
|
|
@@ -21,6 +22,13 @@ describe "Database transactions" do
|
|
|
21
22
|
@db.transaction{|conn| conn.should_not == nil}
|
|
22
23
|
end
|
|
23
24
|
|
|
25
|
+
specify "should have #in_transaction? work correctly" do
|
|
26
|
+
@db.in_transaction?.should be_false
|
|
27
|
+
c = nil
|
|
28
|
+
@db.transaction{c = @db.in_transaction?}
|
|
29
|
+
c.should be_true
|
|
30
|
+
end
|
|
31
|
+
|
|
24
32
|
specify "should correctly rollback transactions" do
|
|
25
33
|
proc do
|
|
26
34
|
@db.transaction do
|
|
@@ -29,12 +37,22 @@ describe "Database transactions" do
|
|
|
29
37
|
end
|
|
30
38
|
end.should raise_error(Interrupt)
|
|
31
39
|
|
|
40
|
+
@db.transaction do
|
|
41
|
+
@d << {:name => 'abc', :value => 1}
|
|
42
|
+
raise Sequel::Rollback
|
|
43
|
+
end.should be_nil
|
|
44
|
+
|
|
32
45
|
proc do
|
|
33
|
-
@db.transaction do
|
|
46
|
+
@db.transaction(:rollback=>:reraise) do
|
|
34
47
|
@d << {:name => 'abc', :value => 1}
|
|
35
48
|
raise Sequel::Rollback
|
|
36
49
|
end
|
|
37
|
-
end.
|
|
50
|
+
end.should raise_error(Sequel::Rollback)
|
|
51
|
+
|
|
52
|
+
@db.transaction(:rollback=>:always) do
|
|
53
|
+
@d << {:name => 'abc', :value => 1}
|
|
54
|
+
2
|
|
55
|
+
end.should be_nil
|
|
38
56
|
|
|
39
57
|
@d.count.should == 0
|
|
40
58
|
end
|
|
@@ -115,6 +133,16 @@ describe "Database transactions" do
|
|
|
115
133
|
end
|
|
116
134
|
|
|
117
135
|
if INTEGRATION_DB.supports_prepared_transactions?
|
|
136
|
+
specify "should allow saving and destroying of model objects" do
|
|
137
|
+
c = Class.new(Sequel::Model(@d))
|
|
138
|
+
c.set_primary_key :name
|
|
139
|
+
c.unrestrict_primary_key
|
|
140
|
+
c.use_after_commit_rollback = false
|
|
141
|
+
@db.transaction(:prepare=>'XYZ'){c.create(:name => '1'); c.create(:name => '2').destroy}
|
|
142
|
+
@db.commit_prepared_transaction('XYZ')
|
|
143
|
+
@d.select_order_map(:name).should == ['1']
|
|
144
|
+
end
|
|
145
|
+
|
|
118
146
|
specify "should commit prepared transactions using commit_prepared_transaction" do
|
|
119
147
|
@db.transaction(:prepare=>'XYZ'){@d << {:name => '1'}}
|
|
120
148
|
@db.commit_prepared_transaction('XYZ')
|
|
@@ -126,6 +154,14 @@ describe "Database transactions" do
|
|
|
126
154
|
@db.rollback_prepared_transaction('XYZ')
|
|
127
155
|
@d.select_order_map(:name).should == []
|
|
128
156
|
end
|
|
157
|
+
|
|
158
|
+
if INTEGRATION_DB.supports_savepoints_in_prepared_transactions?
|
|
159
|
+
specify "should support savepoints when using prepared transactions" do
|
|
160
|
+
@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@d << {:name => '1'}}}
|
|
161
|
+
@db.commit_prepared_transaction('XYZ')
|
|
162
|
+
@d.select_order_map(:name).should == ['1']
|
|
163
|
+
end
|
|
164
|
+
end
|
|
129
165
|
end
|
|
130
166
|
|
|
131
167
|
specify "should support all transaction isolation levels" do
|
|
@@ -134,4 +170,143 @@ describe "Database transactions" do
|
|
|
134
170
|
@d.count.should == i + 1
|
|
135
171
|
end
|
|
136
172
|
end
|
|
173
|
+
|
|
174
|
+
specify "should support after_commit outside transactions" do
|
|
175
|
+
c = nil
|
|
176
|
+
@db.after_commit{c = 1}
|
|
177
|
+
c.should == 1
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
specify "should support after_rollback outside transactions" do
|
|
181
|
+
c = nil
|
|
182
|
+
@db.after_rollback{c = 1}
|
|
183
|
+
c.should be_nil
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
specify "should support after_commit inside transactions" do
|
|
187
|
+
c = nil
|
|
188
|
+
@db.transaction{@db.after_commit{c = 1}; c.should be_nil}
|
|
189
|
+
c.should == 1
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
specify "should support after_rollback inside transactions" do
|
|
193
|
+
c = nil
|
|
194
|
+
@db.transaction{@db.after_rollback{c = 1}; c.should be_nil}
|
|
195
|
+
c.should be_nil
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
specify "should not call after_commit if the transaction rolls back" do
|
|
199
|
+
c = nil
|
|
200
|
+
@db.transaction{@db.after_commit{c = 1}; c.should be_nil; raise Sequel::Rollback}
|
|
201
|
+
c.should be_nil
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
specify "should call after_rollback if the transaction rolls back" do
|
|
205
|
+
c = nil
|
|
206
|
+
@db.transaction{@db.after_rollback{c = 1}; c.should be_nil; raise Sequel::Rollback}
|
|
207
|
+
c.should == 1
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
specify "should support multiple after_commit blocks inside transactions" do
|
|
211
|
+
c = []
|
|
212
|
+
@db.transaction{@db.after_commit{c << 1}; @db.after_commit{c << 2}; c.should == []}
|
|
213
|
+
c.should == [1, 2]
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
specify "should support multiple after_rollback blocks inside transactions" do
|
|
217
|
+
c = []
|
|
218
|
+
@db.transaction{@db.after_rollback{c << 1}; @db.after_rollback{c << 2}; c.should == []; raise Sequel::Rollback}
|
|
219
|
+
c.should == [1, 2]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
specify "should support after_commit inside nested transactions" do
|
|
223
|
+
c = nil
|
|
224
|
+
@db.transaction{@db.transaction{@db.after_commit{c = 1}}; c.should be_nil}
|
|
225
|
+
c.should == 1
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
specify "should support after_rollback inside nested transactions" do
|
|
229
|
+
c = nil
|
|
230
|
+
@db.transaction{@db.transaction{@db.after_rollback{c = 1}}; c.should be_nil; raise Sequel::Rollback}
|
|
231
|
+
c.should == 1
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
if INTEGRATION_DB.supports_savepoints?
|
|
235
|
+
specify "should support after_commit inside savepoints" do
|
|
236
|
+
c = nil
|
|
237
|
+
@db.transaction{@db.transaction(:savepoint=>true){@db.after_commit{c = 1}}; c.should be_nil}
|
|
238
|
+
c.should == 1
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
specify "should support after_rollback inside savepoints" do
|
|
242
|
+
c = nil
|
|
243
|
+
@db.transaction{@db.transaction(:savepoint=>true){@db.after_rollback{c = 1}}; c.should be_nil; raise Sequel::Rollback}
|
|
244
|
+
c.should == 1
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
if INTEGRATION_DB.supports_prepared_transactions?
|
|
249
|
+
specify "should raise an error if you attempt to use after_commit or after_rollback inside a prepared transaction" do
|
|
250
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{}}}.should raise_error(Sequel::Error)
|
|
251
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{}}}.should raise_error(Sequel::Error)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
if INTEGRATION_DB.supports_savepoints_in_prepared_transactions?
|
|
255
|
+
specify "should raise an error if you attempt to use after_commit or after rollback inside a savepoint in a prepared transaction" do
|
|
256
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{}}}}.should raise_error(Sequel::Error)
|
|
257
|
+
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{}}}}.should raise_error(Sequel::Error)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or (RUBY_ENGINE == 'rbx' && !Sequel.guarded?([:do, :sqlite], [:tinytds, :mssql]))) and RUBY_VERSION < '1.9'
|
|
264
|
+
describe "Database transactions and Thread#kill" do
|
|
265
|
+
before do
|
|
266
|
+
@db = INTEGRATION_DB
|
|
267
|
+
@db.create_table!(:items, :engine=>'InnoDB'){String :name; Integer :value}
|
|
268
|
+
@d = @db[:items]
|
|
269
|
+
end
|
|
270
|
+
after do
|
|
271
|
+
@db.drop_table?(:items)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
specify "should handle transactions inside threads" do
|
|
275
|
+
q = Queue.new
|
|
276
|
+
q1 = Queue.new
|
|
277
|
+
t = Thread.new do
|
|
278
|
+
@db.transaction do
|
|
279
|
+
@d << {:name => 'abc', :value => 1}
|
|
280
|
+
q1.push nil
|
|
281
|
+
q.pop
|
|
282
|
+
@d << {:name => 'def', :value => 2}
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
q1.pop
|
|
286
|
+
t.kill
|
|
287
|
+
@d.count.should == 0
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
if INTEGRATION_DB.supports_savepoints?
|
|
291
|
+
specify "should handle transactions with savepoints inside threads" do
|
|
292
|
+
q = Queue.new
|
|
293
|
+
q1 = Queue.new
|
|
294
|
+
t = Thread.new do
|
|
295
|
+
@db.transaction do
|
|
296
|
+
@d << {:name => 'abc', :value => 1}
|
|
297
|
+
@db.transaction(:savepoint=>true) do
|
|
298
|
+
@d << {:name => 'def', :value => 2}
|
|
299
|
+
q1.push nil
|
|
300
|
+
q.pop
|
|
301
|
+
@d << {:name => 'ghi', :value => 3}
|
|
302
|
+
end
|
|
303
|
+
@d << {:name => 'jkl', :value => 4}
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
q1.pop
|
|
307
|
+
t.kill
|
|
308
|
+
@d.count.should == 0
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
137
312
|
end
|
|
@@ -6,7 +6,7 @@ describe "Supported types" do
|
|
|
6
6
|
INTEGRATION_DB[:items]
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
specify "should support casting correctly" do
|
|
10
10
|
ds = create_items_table_with_column(:number, Integer)
|
|
11
11
|
ds.insert(:number => 1)
|
|
12
12
|
ds.select(:number.cast_string.as(:n)).map(:n).should == %w'1'
|
|
@@ -33,7 +33,7 @@ describe "Supported types" do
|
|
|
33
33
|
ds.all.should == [{:number=>2}]
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
cspecify "should support generic bignum type", [:swift, :sqlite] do
|
|
37
37
|
ds = create_items_table_with_column(:number, Bignum)
|
|
38
38
|
ds.insert(:number => 2**34)
|
|
39
39
|
ds.all.should == [{:number=>2**34}]
|
|
@@ -60,7 +60,7 @@ describe "Supported types" do
|
|
|
60
60
|
ds.all.should == [{:name=>'Test User'}]
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
cspecify "should support generic date type", [:do, :sqlite], [:jdbc, :sqlite], :mssql do
|
|
63
|
+
cspecify "should support generic date type", [:do, :sqlite], [:jdbc, :sqlite], :mssql, :oracle do
|
|
64
64
|
ds = create_items_table_with_column(:dat, Date)
|
|
65
65
|
d = Date.today
|
|
66
66
|
ds.insert(:dat => d)
|
|
@@ -68,6 +68,20 @@ describe "Supported types" do
|
|
|
68
68
|
ds.first[:dat].to_s.should == d.to_s
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
cspecify "should support generic time type", [:do], [:swift], [:odbc], [:jdbc, :mssql], [:jdbc, :sqlite], [:mysql2], [:tinytds], :oracle do
|
|
72
|
+
ds = create_items_table_with_column(:tim, Time, :only_time=>true)
|
|
73
|
+
t = Sequel::SQLTime.now
|
|
74
|
+
ds.insert(:tim => t)
|
|
75
|
+
v = ds.first[:tim]
|
|
76
|
+
ds.literal(v).should == ds.literal(t)
|
|
77
|
+
v.should be_a_kind_of(Sequel::SQLTime)
|
|
78
|
+
ds.delete
|
|
79
|
+
ds.insert(:tim => v)
|
|
80
|
+
v2 = ds.first[:tim]
|
|
81
|
+
ds.literal(v2).should == ds.literal(t)
|
|
82
|
+
v2.should be_a_kind_of(Sequel::SQLTime)
|
|
83
|
+
end
|
|
84
|
+
|
|
71
85
|
cspecify "should support generic datetime type", [:do, :sqlite], [:jdbc, :sqlite] do
|
|
72
86
|
ds = create_items_table_with_column(:tim, DateTime)
|
|
73
87
|
t = DateTime.now
|
|
@@ -86,7 +100,7 @@ describe "Supported types" do
|
|
|
86
100
|
ds.first[:name].should be_a_kind_of(::Sequel::SQL::Blob)
|
|
87
101
|
end
|
|
88
102
|
|
|
89
|
-
cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:odbc, :mssql] do
|
|
103
|
+
cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:jdbc, :db2], [:odbc, :mssql], :oracle do
|
|
90
104
|
ds = create_items_table_with_column(:number, TrueClass)
|
|
91
105
|
ds.insert(:number => true)
|
|
92
106
|
ds.all.should == [{:number=>true}]
|
|
@@ -2,15 +2,19 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe Sequel::Model::Associations::AssociationReflection, "#associated_class" do
|
|
4
4
|
before do
|
|
5
|
-
@c = Class.new(Sequel::Model)
|
|
5
|
+
@c = Class.new(Sequel::Model(:foo))
|
|
6
6
|
class ::ParParent < Sequel::Model; end
|
|
7
7
|
end
|
|
8
|
+
after do
|
|
9
|
+
Object.send(:remove_const, :ParParent)
|
|
10
|
+
end
|
|
8
11
|
|
|
9
12
|
it "should use the :class value if present" do
|
|
10
13
|
@c.many_to_one :c, :class=>ParParent
|
|
11
14
|
@c.association_reflection(:c).keys.should include(:class)
|
|
12
15
|
@c.association_reflection(:c).associated_class.should == ParParent
|
|
13
16
|
end
|
|
17
|
+
|
|
14
18
|
it "should figure out the class if the :class value is not present" do
|
|
15
19
|
@c.many_to_one :c, :class=>'ParParent'
|
|
16
20
|
@c.association_reflection(:c).keys.should_not include(:class)
|
|
@@ -20,15 +24,19 @@ end
|
|
|
20
24
|
|
|
21
25
|
describe Sequel::Model::Associations::AssociationReflection, "#primary_key" do
|
|
22
26
|
before do
|
|
23
|
-
@c = Class.new(Sequel::Model)
|
|
27
|
+
@c = Class.new(Sequel::Model(:foo))
|
|
24
28
|
class ::ParParent < Sequel::Model; end
|
|
25
29
|
end
|
|
30
|
+
after do
|
|
31
|
+
Object.send(:remove_const, :ParParent)
|
|
32
|
+
end
|
|
26
33
|
|
|
27
34
|
it "should use the :primary_key value if present" do
|
|
28
35
|
@c.many_to_one :c, :class=>ParParent, :primary_key=>:blah__blah
|
|
29
36
|
@c.association_reflection(:c).keys.should include(:primary_key)
|
|
30
37
|
@c.association_reflection(:c).primary_key.should == :blah__blah
|
|
31
38
|
end
|
|
39
|
+
|
|
32
40
|
it "should use the associated table's primary key if :primary_key is not present" do
|
|
33
41
|
@c.many_to_one :c, :class=>'ParParent'
|
|
34
42
|
@c.association_reflection(:c).keys.should_not include(:primary_key)
|
|
@@ -49,8 +57,8 @@ describe Sequel::Model::Associations::AssociationReflection, "#reciprocal" do
|
|
|
49
57
|
end
|
|
50
58
|
|
|
51
59
|
it "should use the :reciprocal value if present" do
|
|
52
|
-
@c = Class.new(Sequel::Model)
|
|
53
|
-
@d = Class.new(Sequel::Model)
|
|
60
|
+
@c = Class.new(Sequel::Model(:foo))
|
|
61
|
+
@d = Class.new(Sequel::Model(:foo))
|
|
54
62
|
@c.many_to_one :c, :class=>@d, :reciprocal=>:xx
|
|
55
63
|
@c.association_reflection(:c).keys.should include(:reciprocal)
|
|
56
64
|
@c.association_reflection(:c).reciprocal.should == :xx
|
|
@@ -111,9 +119,12 @@ end
|
|
|
111
119
|
|
|
112
120
|
describe Sequel::Model::Associations::AssociationReflection, "#select" do
|
|
113
121
|
before do
|
|
114
|
-
@c = Class.new(Sequel::Model)
|
|
122
|
+
@c = Class.new(Sequel::Model(:foo))
|
|
115
123
|
class ::ParParent < Sequel::Model; end
|
|
116
124
|
end
|
|
125
|
+
after do
|
|
126
|
+
Object.send(:remove_const, :ParParent)
|
|
127
|
+
end
|
|
117
128
|
|
|
118
129
|
it "should use the :select value if present" do
|
|
119
130
|
@c.many_to_one :c, :class=>ParParent, :select=>[:par_parents__id]
|
|
@@ -143,9 +154,12 @@ end
|
|
|
143
154
|
|
|
144
155
|
describe Sequel::Model::Associations::AssociationReflection, "#associated_object_keys" do
|
|
145
156
|
before do
|
|
146
|
-
@c = Class.new(Sequel::Model)
|
|
157
|
+
@c = Class.new(Sequel::Model(:foo))
|
|
147
158
|
class ::ParParent < Sequel::Model; end
|
|
148
159
|
end
|
|
160
|
+
after do
|
|
161
|
+
Object.send(:remove_const, :ParParent)
|
|
162
|
+
end
|
|
149
163
|
|
|
150
164
|
it "should use the primary keys for a many_to_one association" do
|
|
151
165
|
@c.many_to_one :c, :class=>ParParent
|
|
@@ -173,9 +187,36 @@ describe Sequel::Model::Associations::AssociationReflection, "#associated_object
|
|
|
173
187
|
end
|
|
174
188
|
end
|
|
175
189
|
|
|
190
|
+
describe Sequel::Model::Associations::AssociationReflection do
|
|
191
|
+
before do
|
|
192
|
+
@c = Class.new(Sequel::Model(:foo))
|
|
193
|
+
@c.meta_def(:name){"C"}
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "one_to_many #qualified_primary_key should be a qualified version of the primary key" do
|
|
197
|
+
@c.one_to_many :cs, :class=>@c
|
|
198
|
+
@c.dataset.literal(@c.association_reflection(:cs).qualified_primary_key).should == 'foo.id'
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "many_to_many #associated_key_column should be the left key" do
|
|
202
|
+
@c.many_to_many :cs, :class=>@c
|
|
203
|
+
@c.association_reflection(:cs).associated_key_column.should == :c_id
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it "many_to_many #qualified_right_key should be a qualified version of the primary key" do
|
|
207
|
+
@c.many_to_many :cs, :class=>@c, :right_key=>:c2_id
|
|
208
|
+
@c.dataset.literal(@c.association_reflection(:cs).qualified_right_key).should == 'cs_cs.c2_id'
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it "many_to_many #qualified_right_primary_key should be a qualified version of the primary key" do
|
|
212
|
+
@c.many_to_many :cs, :class=>@c
|
|
213
|
+
@c.dataset.literal(@c.association_reflection(:cs).qualified_right_primary_key).should == 'foo.id'
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
176
217
|
describe Sequel::Model::Associations::AssociationReflection, "#remove_before_destroy?" do
|
|
177
218
|
before do
|
|
178
|
-
@c = Class.new(Sequel::Model)
|
|
219
|
+
@c = Class.new(Sequel::Model(:foo))
|
|
179
220
|
end
|
|
180
221
|
|
|
181
222
|
it "should be true for many_to_one and many_to_many associations" do
|
|
@@ -184,6 +225,7 @@ describe Sequel::Model::Associations::AssociationReflection, "#remove_before_des
|
|
|
184
225
|
@c.many_to_many :cs, :class=>@c
|
|
185
226
|
@c.association_reflection(:cs).remove_before_destroy?.should be_true
|
|
186
227
|
end
|
|
228
|
+
|
|
187
229
|
it "should be false for one_to_one and one_to_many associations" do
|
|
188
230
|
@c.one_to_one :c, :class=>@c
|
|
189
231
|
@c.association_reflection(:c).remove_before_destroy?.should be_false
|
|
@@ -192,3 +234,155 @@ describe Sequel::Model::Associations::AssociationReflection, "#remove_before_des
|
|
|
192
234
|
end
|
|
193
235
|
end
|
|
194
236
|
|
|
237
|
+
describe Sequel::Model::Associations::AssociationReflection, "#eager_limit_strategy" do
|
|
238
|
+
before do
|
|
239
|
+
@c = Class.new(Sequel::Model(:a))
|
|
240
|
+
end
|
|
241
|
+
after do
|
|
242
|
+
Sequel::Model.default_eager_limit_strategy = nil
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it "should be nil by default for *_one associations" do
|
|
246
|
+
@c.many_to_one :c, :class=>@c
|
|
247
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
248
|
+
@c.one_to_one :c, :class=>@c
|
|
249
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it "should be :ruby by default for *_many associations" do
|
|
253
|
+
@c.one_to_many :cs, :class=>@c, :limit=>1
|
|
254
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
255
|
+
@c.many_to_many :cs, :class=>@c, :limit=>1
|
|
256
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it "should be nil for many_to_one associations" do
|
|
260
|
+
@c.many_to_one :c, :class=>@c, :eager_limit_strategy=>true
|
|
261
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
262
|
+
@c.many_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
|
|
263
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "should be a symbol for other associations if given a symbol" do
|
|
267
|
+
@c.one_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
|
|
268
|
+
@c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
|
|
269
|
+
@c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>:window_function, :limit=>1
|
|
270
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "should use :distinct_on for one_to_one associations if picking and the association dataset supports ordered distinct on" do
|
|
274
|
+
@c.dataset.meta_def(:supports_ordered_distinct_on?){true}
|
|
275
|
+
@c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
|
|
276
|
+
@c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "should use :window_function for associations if picking and the association dataset supports window functions" do
|
|
280
|
+
@c.dataset.meta_def(:supports_window_functions?){true}
|
|
281
|
+
@c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
|
|
282
|
+
@c.association_reflection(:c).eager_limit_strategy.should == :window_function
|
|
283
|
+
@c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
284
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
285
|
+
@c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
286
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "should use :ruby for *_many associations if picking and the association dataset doesn't window functions" do
|
|
290
|
+
@c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
291
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
292
|
+
@c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
|
|
293
|
+
@c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it "should respect Model.default_eager_limit_strategy to *_many associations" do
|
|
297
|
+
Sequel::Model.default_eager_limit_strategy = :window_function
|
|
298
|
+
Sequel::Model.default_eager_limit_strategy.should == :window_function
|
|
299
|
+
c = Class.new(Sequel::Model)
|
|
300
|
+
c.dataset = :a
|
|
301
|
+
c.default_eager_limit_strategy.should == :window_function
|
|
302
|
+
c.one_to_many :cs, :class=>c, :limit=>1
|
|
303
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
304
|
+
c.many_to_many :cs, :class=>c, :limit=>1
|
|
305
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
306
|
+
|
|
307
|
+
Sequel::Model.default_eager_limit_strategy = true
|
|
308
|
+
c = Class.new(Sequel::Model)
|
|
309
|
+
c.dataset = :a
|
|
310
|
+
c.one_to_many :cs, :class=>c, :limit=>1
|
|
311
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :ruby
|
|
312
|
+
c.dataset.meta_def(:supports_window_functions?){true}
|
|
313
|
+
c.many_to_many :cs, :class=>c, :limit=>1
|
|
314
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :window_function
|
|
315
|
+
|
|
316
|
+
c.default_eager_limit_strategy = :correlated_subquery
|
|
317
|
+
c.many_to_many :cs, :class=>c, :limit=>1
|
|
318
|
+
c.association_reflection(:cs).eager_limit_strategy.should == :correlated_subquery
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it "should ignore Model.default_eager_limit_strategy for one_to_one associations" do
|
|
322
|
+
@c.default_eager_limit_strategy = :correlated_subquery
|
|
323
|
+
@c.one_to_one :c, :class=>@c
|
|
324
|
+
@c.association_reflection(:c).eager_limit_strategy.should be_nil
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
describe Sequel::Model, " association reflection methods" do
|
|
329
|
+
before do
|
|
330
|
+
@c1 = Class.new(Sequel::Model(:nodes)) do
|
|
331
|
+
def self.name; 'Node'; end
|
|
332
|
+
def self.to_s; 'Node'; end
|
|
333
|
+
end
|
|
334
|
+
MODEL_DB.reset
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
it "#all_association_reflections should include all association reflection hashes" do
|
|
338
|
+
@c1.all_association_reflections.should == []
|
|
339
|
+
|
|
340
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
|
341
|
+
@c1.all_association_reflections.collect{|v| v[:name]}.should == [:parent]
|
|
342
|
+
@c1.all_association_reflections.collect{|v| v[:type]}.should == [:many_to_one]
|
|
343
|
+
@c1.all_association_reflections.collect{|v| v[:class]}.should == [@c1]
|
|
344
|
+
|
|
345
|
+
@c1.associate :one_to_many, :children, :class => @c1
|
|
346
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}
|
|
347
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:name]}.should == [:children, :parent]
|
|
348
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:type]}.should == [:one_to_many, :many_to_one]
|
|
349
|
+
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:class]}.should == [@c1, @c1]
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it "#association_reflection should return nil for nonexistent association" do
|
|
353
|
+
@c1.association_reflection(:blah).should == nil
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it "#association_reflection should return association reflection hash if association exists" do
|
|
357
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
|
358
|
+
@c1.association_reflection(:parent).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
|
|
359
|
+
@c1.association_reflection(:parent)[:name].should == :parent
|
|
360
|
+
@c1.association_reflection(:parent)[:type].should == :many_to_one
|
|
361
|
+
@c1.association_reflection(:parent)[:class].should == @c1
|
|
362
|
+
|
|
363
|
+
@c1.associate :one_to_many, :children, :class => @c1
|
|
364
|
+
@c1.association_reflection(:children).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
|
|
365
|
+
@c1.association_reflection(:children)[:name].should == :children
|
|
366
|
+
@c1.association_reflection(:children)[:type].should == :one_to_many
|
|
367
|
+
@c1.association_reflection(:children)[:class].should == @c1
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it "#associations should include all association names" do
|
|
371
|
+
@c1.associations.should == []
|
|
372
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
|
373
|
+
@c1.associations.should == [:parent]
|
|
374
|
+
@c1.associate :one_to_many, :children, :class => @c1
|
|
375
|
+
@c1.associations.sort_by{|x|x.to_s}.should == [:children, :parent]
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
it "association reflections should be copied upon subclasing" do
|
|
379
|
+
@c1.associate :many_to_one, :parent, :class => @c1
|
|
380
|
+
c = Class.new(@c1)
|
|
381
|
+
@c1.associations.should == [:parent]
|
|
382
|
+
c.associations.should == [:parent]
|
|
383
|
+
c.associate :many_to_one, :parent2, :class => @c1
|
|
384
|
+
@c1.associations.should == [:parent]
|
|
385
|
+
c.associations.sort_by{|x| x.to_s}.should == [:parent, :parent2]
|
|
386
|
+
c.instance_methods.map{|x| x.to_s}.should include('parent')
|
|
387
|
+
end
|
|
388
|
+
end
|