sequel 4.22.0 → 4.23.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.
- checksums.yaml +4 -4
- data/CHANGELOG +22 -0
- data/README.rdoc +6 -0
- data/Rakefile +59 -81
- data/doc/migration.rdoc +2 -0
- data/doc/release_notes/4.23.0.txt +65 -0
- data/doc/sharding.rdoc +16 -14
- data/doc/testing.rdoc +61 -77
- data/lib/sequel/adapters/jdbc.rb +1 -0
- data/lib/sequel/adapters/mock.rb +0 -1
- data/lib/sequel/adapters/postgres.rb +1 -0
- data/lib/sequel/adapters/postgresql.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +3 -3
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +9 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/transactions.rb +2 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +12 -12
- data/lib/sequel/extensions/date_arithmetic.rb +0 -4
- data/lib/sequel/extensions/pagination.rb +14 -2
- data/lib/sequel/extensions/pg_enum.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/delay_add_association.rb +50 -0
- data/lib/sequel/plugins/list.rb +2 -2
- data/lib/sequel/plugins/nested_attributes.rb +8 -28
- data/lib/sequel/plugins/update_refresh.rb +50 -0
- data/lib/sequel/plugins/validate_associated.rb +55 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +29 -29
- data/spec/adapters/firebird_spec.rb +97 -103
- data/spec/adapters/informix_spec.rb +25 -25
- data/spec/adapters/mssql_spec.rb +156 -172
- data/spec/adapters/mysql_spec.rb +334 -359
- data/spec/adapters/oracle_spec.rb +67 -69
- data/spec/adapters/postgres_spec.rb +1298 -1249
- data/spec/adapters/spec_helper.rb +2 -35
- data/spec/adapters/sqlanywhere_spec.rb +39 -39
- data/spec/adapters/sqlite_spec.rb +203 -200
- data/spec/bin_spec.rb +57 -59
- data/spec/core/connection_pool_spec.rb +402 -401
- data/spec/core/database_spec.rb +953 -944
- data/spec/core/dataset_spec.rb +2178 -2168
- data/spec/core/deprecated_spec.rb +19 -19
- data/spec/core/expression_filters_spec.rb +415 -415
- data/spec/core/mock_adapter_spec.rb +212 -212
- data/spec/core/object_graph_spec.rb +73 -73
- data/spec/core/placeholder_literalizer_spec.rb +71 -71
- data/spec/core/schema_generator_spec.rb +44 -44
- data/spec/core/schema_spec.rb +470 -472
- data/spec/core/spec_helper.rb +5 -20
- data/spec/core/version_spec.rb +2 -2
- data/spec/core_extensions_spec.rb +320 -320
- data/spec/extensions/accessed_columns_spec.rb +12 -12
- data/spec/extensions/active_model_spec.rb +3 -3
- data/spec/extensions/after_initialize_spec.rb +2 -2
- data/spec/extensions/arbitrary_servers_spec.rb +23 -23
- data/spec/extensions/association_dependencies_spec.rb +34 -34
- data/spec/extensions/association_pks_spec.rb +98 -98
- data/spec/extensions/association_proxies_spec.rb +33 -33
- data/spec/extensions/auto_validations_spec.rb +46 -46
- data/spec/extensions/blacklist_security_spec.rb +19 -18
- data/spec/extensions/blank_spec.rb +36 -36
- data/spec/extensions/boolean_readers_spec.rb +36 -36
- data/spec/extensions/caching_spec.rb +82 -82
- data/spec/extensions/class_table_inheritance_spec.rb +72 -72
- data/spec/extensions/column_conflicts_spec.rb +19 -14
- data/spec/extensions/column_select_spec.rb +19 -19
- data/spec/extensions/columns_introspection_spec.rb +43 -43
- data/spec/extensions/composition_spec.rb +64 -64
- data/spec/extensions/connection_validator_spec.rb +92 -90
- data/spec/extensions/constraint_validations_plugin_spec.rb +92 -92
- data/spec/extensions/constraint_validations_spec.rb +80 -80
- data/spec/extensions/core_refinements_spec.rb +220 -220
- data/spec/extensions/csv_serializer_spec.rb +44 -44
- data/spec/extensions/current_datetime_timestamp_spec.rb +8 -8
- data/spec/extensions/dataset_associations_spec.rb +65 -65
- data/spec/extensions/dataset_source_alias_spec.rb +16 -16
- data/spec/extensions/date_arithmetic_spec.rb +51 -58
- data/spec/extensions/defaults_setter_spec.rb +19 -19
- data/spec/extensions/delay_add_association_spec.rb +52 -0
- data/spec/extensions/dirty_spec.rb +51 -51
- data/spec/extensions/eager_each_spec.rb +8 -8
- data/spec/extensions/empty_array_ignore_nulls_spec.rb +10 -10
- data/spec/extensions/error_splitter_spec.rb +2 -2
- data/spec/extensions/error_sql_spec.rb +4 -4
- data/spec/extensions/eval_inspect_spec.rb +3 -3
- data/spec/extensions/filter_having_spec.rb +8 -8
- data/spec/extensions/force_encoding_spec.rb +30 -30
- data/spec/extensions/from_block_spec.rb +7 -7
- data/spec/extensions/graph_each_spec.rb +19 -19
- data/spec/extensions/hash_aliases_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +100 -100
- data/spec/extensions/inflector_spec.rb +54 -54
- data/spec/extensions/input_transformer_spec.rb +10 -10
- data/spec/extensions/insert_returning_select_spec.rb +8 -8
- data/spec/extensions/instance_filters_spec.rb +26 -26
- data/spec/extensions/instance_hooks_spec.rb +85 -85
- data/spec/extensions/json_serializer_spec.rb +68 -68
- data/spec/extensions/lazy_attributes_spec.rb +49 -49
- data/spec/extensions/list_spec.rb +77 -75
- data/spec/extensions/looser_typecasting_spec.rb +16 -16
- data/spec/extensions/many_through_many_spec.rb +627 -627
- data/spec/extensions/meta_def_spec.rb +7 -7
- data/spec/extensions/migration_spec.rb +217 -217
- data/spec/extensions/modification_detection_spec.rb +20 -20
- data/spec/extensions/mssql_optimistic_locking_spec.rb +21 -21
- data/spec/extensions/named_timezones_spec.rb +18 -18
- data/spec/extensions/nested_attributes_spec.rb +107 -107
- data/spec/extensions/null_dataset_spec.rb +24 -24
- data/spec/extensions/optimistic_locking_spec.rb +21 -21
- data/spec/extensions/pagination_spec.rb +52 -52
- data/spec/extensions/pg_array_associations_spec.rb +273 -273
- data/spec/extensions/pg_array_ops_spec.rb +52 -52
- data/spec/extensions/pg_array_spec.rb +152 -152
- data/spec/extensions/pg_enum_spec.rb +13 -13
- data/spec/extensions/pg_hstore_ops_spec.rb +63 -63
- data/spec/extensions/pg_hstore_spec.rb +84 -84
- data/spec/extensions/pg_inet_spec.rb +15 -15
- data/spec/extensions/pg_interval_spec.rb +29 -29
- data/spec/extensions/pg_json_ops_spec.rb +86 -84
- data/spec/extensions/pg_json_spec.rb +104 -104
- data/spec/extensions/pg_loose_count_spec.rb +6 -6
- data/spec/extensions/pg_range_ops_spec.rb +24 -24
- data/spec/extensions/pg_range_spec.rb +143 -143
- data/spec/extensions/pg_row_ops_spec.rb +14 -14
- data/spec/extensions/pg_row_plugin_spec.rb +12 -12
- data/spec/extensions/pg_row_spec.rb +118 -118
- data/spec/extensions/pg_static_cache_updater_spec.rb +28 -28
- data/spec/extensions/pg_typecast_on_load_spec.rb +21 -21
- data/spec/extensions/prepared_statements_associations_spec.rb +42 -42
- data/spec/extensions/prepared_statements_safe_spec.rb +18 -18
- data/spec/extensions/prepared_statements_spec.rb +28 -28
- data/spec/extensions/prepared_statements_with_pk_spec.rb +11 -11
- data/spec/extensions/pretty_table_spec.rb +16 -16
- data/spec/extensions/query_literals_spec.rb +37 -37
- data/spec/extensions/query_spec.rb +32 -32
- data/spec/extensions/rcte_tree_spec.rb +141 -141
- data/spec/extensions/round_timestamps_spec.rb +21 -21
- data/spec/extensions/schema_caching_spec.rb +8 -8
- data/spec/extensions/schema_dumper_spec.rb +78 -78
- data/spec/extensions/schema_spec.rb +31 -27
- data/spec/extensions/scissors_spec.rb +3 -3
- data/spec/extensions/select_remove_spec.rb +14 -14
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +28 -28
- data/spec/extensions/serialization_modification_detection_spec.rb +33 -33
- data/spec/extensions/serialization_spec.rb +79 -78
- data/spec/extensions/server_block_spec.rb +17 -17
- data/spec/extensions/set_overrides_spec.rb +30 -30
- data/spec/extensions/sharding_spec.rb +65 -65
- data/spec/extensions/shared_caching_spec.rb +29 -29
- data/spec/extensions/single_table_inheritance_spec.rb +79 -79
- data/spec/extensions/skip_create_refresh_spec.rb +3 -3
- data/spec/extensions/spec_helper.rb +4 -29
- data/spec/extensions/split_array_nil_spec.rb +9 -9
- data/spec/extensions/split_values_spec.rb +7 -7
- data/spec/extensions/sql_expr_spec.rb +32 -32
- data/spec/extensions/static_cache_spec.rb +123 -123
- data/spec/extensions/string_date_time_spec.rb +34 -34
- data/spec/extensions/string_stripper_spec.rb +15 -15
- data/spec/extensions/subclasses_spec.rb +31 -31
- data/spec/extensions/table_select_spec.rb +15 -15
- data/spec/extensions/tactical_eager_loading_spec.rb +23 -23
- data/spec/extensions/thread_local_timezones_spec.rb +13 -13
- data/spec/extensions/timestamps_spec.rb +40 -40
- data/spec/extensions/to_dot_spec.rb +34 -34
- data/spec/extensions/touch_spec.rb +52 -52
- data/spec/extensions/tree_spec.rb +72 -72
- data/spec/extensions/typecast_on_load_spec.rb +25 -25
- data/spec/extensions/unlimited_update_spec.rb +2 -2
- data/spec/extensions/update_or_create_spec.rb +36 -36
- data/spec/extensions/update_primary_key_spec.rb +35 -35
- data/spec/extensions/update_refresh_spec.rb +41 -0
- data/spec/extensions/validate_associated_spec.rb +52 -0
- data/spec/extensions/validation_class_methods_spec.rb +314 -317
- data/spec/extensions/validation_helpers_spec.rb +195 -195
- data/spec/extensions/xml_serializer_spec.rb +48 -48
- data/spec/guards_helper.rb +55 -0
- data/spec/integration/associations_test.rb +1089 -1088
- data/spec/integration/database_test.rb +29 -29
- data/spec/integration/dataset_test.rb +661 -661
- data/spec/integration/eager_loader_test.rb +147 -147
- data/spec/integration/migrator_test.rb +122 -122
- data/spec/integration/model_test.rb +70 -70
- data/spec/integration/plugin_test.rb +682 -640
- data/spec/integration/prepared_statement_test.rb +172 -172
- data/spec/integration/schema_test.rb +245 -245
- data/spec/integration/spec_helper.rb +1 -64
- data/spec/integration/timezone_test.rb +17 -17
- data/spec/integration/transaction_test.rb +87 -87
- data/spec/integration/type_test.rb +33 -33
- data/spec/model/association_reflection_spec.rb +130 -121
- data/spec/model/associations_spec.rb +1112 -1113
- data/spec/model/base_spec.rb +197 -196
- data/spec/model/class_dataset_methods_spec.rb +118 -118
- data/spec/model/dataset_methods_spec.rb +49 -49
- data/spec/model/eager_loading_spec.rb +705 -702
- data/spec/model/hooks_spec.rb +169 -168
- data/spec/model/inflector_spec.rb +5 -5
- data/spec/model/model_spec.rb +287 -297
- data/spec/model/plugins_spec.rb +47 -47
- data/spec/model/record_spec.rb +534 -535
- data/spec/model/spec_helper.rb +3 -21
- data/spec/model/validations_spec.rb +72 -70
- data/spec/spec_config.rb +8 -0
- metadata +41 -9
- data/lib/sequel/adapters/fdbsql.rb +0 -286
- data/lib/sequel/adapters/jdbc/fdbsql.rb +0 -66
- data/lib/sequel/adapters/openbase.rb +0 -54
- data/lib/sequel/adapters/shared/fdbsql.rb +0 -550
- data/spec/adapters/fdbsql_spec.rb +0 -429
- data/spec/rspec_helper.rb +0 -22
|
@@ -8,78 +8,78 @@ describe "null_dataset extension" do
|
|
|
8
8
|
@pr = proc{|*a| @i += 1}
|
|
9
9
|
end
|
|
10
10
|
after do
|
|
11
|
-
@db.sqls.
|
|
11
|
+
@db.sqls.must_equal [] unless @skip_check
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it "should make each be a noop" do
|
|
15
|
-
@ds.each(&@pr).
|
|
16
|
-
@i.
|
|
15
|
+
@ds.each(&@pr).must_be_same_as(@ds)
|
|
16
|
+
@i.must_equal 0
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it "should make fetch_rows be a noop" do
|
|
20
|
-
@ds.fetch_rows("SELECT 1", &@pr).
|
|
21
|
-
@i.
|
|
20
|
+
@ds.fetch_rows("SELECT 1", &@pr).must_equal nil
|
|
21
|
+
@i.must_equal 0
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
it "should make insert be a noop" do
|
|
25
|
-
@ds.insert(1).
|
|
25
|
+
@ds.insert(1).must_equal nil
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
it "should make update be a noop" do
|
|
29
|
-
@ds.update(:a=>1).
|
|
29
|
+
@ds.update(:a=>1).must_equal 0
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "should make delete be a noop" do
|
|
33
|
-
@ds.delete.
|
|
33
|
+
@ds.delete.must_equal 0
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
it "should make truncate be a noop" do
|
|
37
|
-
@ds.truncate.
|
|
37
|
+
@ds.truncate.must_equal nil
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
it "should make execute_* be a noop" do
|
|
41
|
-
@ds.send(:execute_ddl,'FOO').
|
|
42
|
-
@ds.send(:execute_insert,'FOO').
|
|
43
|
-
@ds.send(:execute_dui,'FOO').
|
|
44
|
-
@ds.send(:execute,'FOO').
|
|
41
|
+
@ds.send(:execute_ddl,'FOO').must_equal nil
|
|
42
|
+
@ds.send(:execute_insert,'FOO').must_equal nil
|
|
43
|
+
@ds.send(:execute_dui,'FOO').must_equal nil
|
|
44
|
+
@ds.send(:execute,'FOO').must_equal nil
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
it "should have working columns" do
|
|
48
48
|
@skip_check = true
|
|
49
|
-
@ds.columns.
|
|
50
|
-
@db.sqls.
|
|
49
|
+
@ds.columns.must_equal [:id]
|
|
50
|
+
@db.sqls.must_equal ['SELECT * FROM table LIMIT 1']
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
it "should have count return 0" do
|
|
54
|
-
@ds.count.
|
|
54
|
+
@ds.count.must_equal 0
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
it "should have empty return true" do
|
|
58
|
-
@ds.empty?.
|
|
58
|
+
@ds.empty?.must_equal true
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it "should make import a noop" do
|
|
62
|
-
@ds.import([:id], [[1], [2], [3]]).
|
|
62
|
+
@ds.import([:id], [[1], [2], [3]]).must_equal nil
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
it "should have nullify method returned modified receiver" do
|
|
66
66
|
@skip_check = true
|
|
67
67
|
ds = @db[:table]
|
|
68
|
-
ds.nullify.
|
|
68
|
+
ds.nullify.wont_be_same_as(ds)
|
|
69
69
|
ds.each(&@pr)
|
|
70
|
-
@db.sqls.
|
|
71
|
-
@i.
|
|
70
|
+
@db.sqls.must_equal ['SELECT * FROM table']
|
|
71
|
+
@i.must_equal 1
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
it "should have nullify! method modify receiver" do
|
|
75
75
|
ds = @db[:table]
|
|
76
|
-
ds.nullify!.
|
|
76
|
+
ds.nullify!.must_be_same_as(ds)
|
|
77
77
|
ds.each(&@pr)
|
|
78
|
-
@i.
|
|
78
|
+
@i.must_equal 0
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
it "should work with method chaining" do
|
|
82
82
|
@ds.where(:a=>1).select(:b).each(&@pr)
|
|
83
|
-
@i.
|
|
83
|
+
@i.must_equal 0
|
|
84
84
|
end
|
|
85
85
|
end
|
|
@@ -47,55 +47,55 @@ describe "optimistic_locking plugin" do
|
|
|
47
47
|
@c.plugin :optimistic_locking
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
it "should raise an error when updating a stale record" do
|
|
51
51
|
p1 = @c[1]
|
|
52
52
|
p2 = @c[1]
|
|
53
53
|
p1.update(:name=>'Jim')
|
|
54
|
-
proc{p2.update(:name=>'Bob')}.
|
|
54
|
+
proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
it "should raise an error when destroying a stale record" do
|
|
58
58
|
p1 = @c[1]
|
|
59
59
|
p2 = @c[1]
|
|
60
60
|
p1.update(:name=>'Jim')
|
|
61
|
-
proc{p2.destroy}.
|
|
61
|
+
proc{p2.destroy}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
it "should not raise an error when updating the same record twice" do
|
|
65
65
|
p1 = @c[1]
|
|
66
66
|
p1.update(:name=>'Jim')
|
|
67
|
-
|
|
67
|
+
p1.update(:name=>'Bob')
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
it "should allow changing the lock column via model.lock_column=" do
|
|
71
71
|
@lv.replace('lv')
|
|
72
72
|
@c.columns :id, :name, :lv
|
|
73
73
|
@c.lock_column = :lv
|
|
74
74
|
p1 = @c[1]
|
|
75
75
|
p2 = @c[1]
|
|
76
76
|
p1.update(:name=>'Jim')
|
|
77
|
-
proc{p2.update(:name=>'Bob')}.
|
|
77
|
+
proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
it "should allow changing the lock column via plugin option" do
|
|
81
81
|
@lv.replace('lv')
|
|
82
82
|
@c.columns :id, :name, :lv
|
|
83
83
|
@c.plugin :optimistic_locking, :lock_column=>:lv
|
|
84
84
|
p1 = @c[1]
|
|
85
85
|
p2 = @c[1]
|
|
86
86
|
p1.update(:name=>'Jim')
|
|
87
|
-
proc{p2.destroy}.
|
|
87
|
+
proc{p2.destroy}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
it "should work when subclassing" do
|
|
91
91
|
c = Class.new(@c)
|
|
92
92
|
p1 = c[1]
|
|
93
93
|
p2 = c[1]
|
|
94
94
|
p1.update(:name=>'Jim')
|
|
95
|
-
proc{p2.update(:name=>'Bob')}.
|
|
95
|
+
proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
it "should work correctly if attempting to refresh and save again after a failed save" do
|
|
99
99
|
p1 = @c[1]
|
|
100
100
|
p2 = @c[1]
|
|
101
101
|
p1.update(:name=>'Jim')
|
|
@@ -104,25 +104,25 @@ describe "optimistic_locking plugin" do
|
|
|
104
104
|
rescue Sequel::Plugins::OptimisticLocking::Error
|
|
105
105
|
p2.refresh
|
|
106
106
|
@c.db.sqls
|
|
107
|
-
|
|
107
|
+
p2.update(:name=>'Bob')
|
|
108
108
|
end
|
|
109
|
-
@c.db.sqls.first.
|
|
109
|
+
@c.db.sqls.first.must_match(/UPDATE people SET (name = 'Bob', lock_version = 4|lock_version = 4, name = 'Bob') WHERE \(\(id = 1\) AND \(lock_version = 3\)\)/)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
it "should increment the lock column when #modified! even if no columns are changed" do
|
|
113
113
|
p1 = @c[1]
|
|
114
114
|
p1.modified!
|
|
115
115
|
lv = p1.lock_version
|
|
116
116
|
p1.save_changes
|
|
117
|
-
p1.lock_version.
|
|
117
|
+
p1.lock_version.must_equal lv + 1
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
@c.instance_dataset.meta_def(:update) { raise
|
|
120
|
+
it "should not increment the lock column when the update fails" do
|
|
121
|
+
@c.instance_dataset.meta_def(:update) {|_| raise }
|
|
122
122
|
p1 = @c[1]
|
|
123
123
|
p1.modified!
|
|
124
124
|
lv = p1.lock_version
|
|
125
|
-
proc{p1.save_changes}.
|
|
126
|
-
p1.lock_version.
|
|
125
|
+
proc{p1.save_changes}.must_raise(RuntimeError)
|
|
126
|
+
p1.lock_version.must_equal lv
|
|
127
127
|
end
|
|
128
128
|
end
|
|
@@ -8,80 +8,80 @@ describe "A paginated dataset" do
|
|
|
8
8
|
@paginated = @d.paginate(1, 20)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
proc{@d.limit(10).paginate(1,10)}.
|
|
13
|
-
proc{@paginated.paginate(2,20)}.
|
|
14
|
-
proc{@d.limit(10).each_page(10){|ds|}}.
|
|
15
|
-
proc{@d.limit(10).each_page(10)}.
|
|
11
|
+
it "should raise an error if the dataset already has a limit" do
|
|
12
|
+
proc{@d.limit(10).paginate(1,10)}.must_raise(Sequel::Error)
|
|
13
|
+
proc{@paginated.paginate(2,20)}.must_raise(Sequel::Error)
|
|
14
|
+
proc{@d.limit(10).each_page(10){|ds|}}.must_raise(Sequel::Error)
|
|
15
|
+
proc{@d.limit(10).each_page(10)}.must_raise(Sequel::Error)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
@paginated.opts[:limit].
|
|
20
|
-
@paginated.opts[:offset].
|
|
18
|
+
it "should set the limit and offset options correctly" do
|
|
19
|
+
@paginated.opts[:limit].must_equal 20
|
|
20
|
+
@paginated.opts[:offset].must_equal 0
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
@paginated.page_count.
|
|
25
|
-
@d.paginate(1, 50).page_count.
|
|
23
|
+
it "should set the page count correctly" do
|
|
24
|
+
@paginated.page_count.must_equal 8
|
|
25
|
+
@d.paginate(1, 50).page_count.must_equal 4
|
|
26
26
|
|
|
27
27
|
@d.meta_def(:count) {0}
|
|
28
|
-
@d.paginate(1, 50).page_count.
|
|
28
|
+
@d.paginate(1, 50).page_count.must_equal 1
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
@paginated.current_page.
|
|
33
|
-
@d.paginate(3, 50).current_page.
|
|
31
|
+
it "should set the current page number correctly" do
|
|
32
|
+
@paginated.current_page.must_equal 1
|
|
33
|
+
@d.paginate(3, 50).current_page.must_equal 3
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
@paginated.next_page.
|
|
38
|
-
@d.paginate(4, 50).next_page.
|
|
36
|
+
it "should return the next page number or nil if we're on the last" do
|
|
37
|
+
@paginated.next_page.must_equal 2
|
|
38
|
+
@d.paginate(4, 50).next_page.must_equal nil
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
@paginated.prev_page.
|
|
43
|
-
@d.paginate(4, 50).prev_page.
|
|
41
|
+
it "should return the previous page number or nil if we're on the first" do
|
|
42
|
+
@paginated.prev_page.must_equal nil
|
|
43
|
+
@d.paginate(4, 50).prev_page.must_equal 3
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
@paginated.page_range.
|
|
48
|
-
@d.paginate(4, 50).page_range.
|
|
46
|
+
it "should return the page range" do
|
|
47
|
+
@paginated.page_range.must_equal(1..8)
|
|
48
|
+
@d.paginate(4, 50).page_range.must_equal(1..4)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
@paginated.current_page_record_range.
|
|
53
|
-
@d.paginate(4, 50).current_page_record_range.
|
|
54
|
-
@d.paginate(5, 50).current_page_record_range.
|
|
51
|
+
it "should return the record range for the current page" do
|
|
52
|
+
@paginated.current_page_record_range.must_equal(1..20)
|
|
53
|
+
@d.paginate(4, 50).current_page_record_range.must_equal(151..153)
|
|
54
|
+
@d.paginate(5, 50).current_page_record_range.must_equal(0..0)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
@paginated.current_page_record_count.
|
|
59
|
-
@d.paginate(3, 50).current_page_record_count.
|
|
60
|
-
@d.paginate(4, 50).current_page_record_count.
|
|
61
|
-
@d.paginate(5, 50).current_page_record_count.
|
|
57
|
+
it "should return the record count for the current page" do
|
|
58
|
+
@paginated.current_page_record_count.must_equal 20
|
|
59
|
+
@d.paginate(3, 50).current_page_record_count.must_equal 50
|
|
60
|
+
@d.paginate(4, 50).current_page_record_count.must_equal 3
|
|
61
|
+
@d.paginate(5, 50).current_page_record_count.must_equal 0
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
@paginated.last_page?.
|
|
66
|
-
@d.paginate(2, 20).last_page?.
|
|
67
|
-
@d.paginate(5, 30).last_page?.
|
|
68
|
-
@d.paginate(6, 30).last_page?.
|
|
64
|
+
it "should know if current page is last page" do
|
|
65
|
+
@paginated.last_page?.must_equal false
|
|
66
|
+
@d.paginate(2, 20).last_page?.must_equal false
|
|
67
|
+
@d.paginate(5, 30).last_page?.must_equal false
|
|
68
|
+
@d.paginate(6, 30).last_page?.must_equal true
|
|
69
69
|
|
|
70
70
|
@d.meta_def(:count) {0}
|
|
71
|
-
@d.paginate(1, 30).last_page?.
|
|
72
|
-
@d.paginate(2, 30).last_page?.
|
|
71
|
+
@d.paginate(1, 30).last_page?.must_equal true
|
|
72
|
+
@d.paginate(2, 30).last_page?.must_equal false
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
@paginated.first_page?.
|
|
77
|
-
@d.paginate(1, 20).first_page?.
|
|
78
|
-
@d.paginate(2, 20).first_page?.
|
|
75
|
+
it "should know if current page is first page" do
|
|
76
|
+
@paginated.first_page?.must_equal true
|
|
77
|
+
@d.paginate(1, 20).first_page?.must_equal true
|
|
78
|
+
@d.paginate(2, 20).first_page?.must_equal false
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
it "should work with fixed sql" do
|
|
82
82
|
ds = @d.clone(:sql => 'select * from blah')
|
|
83
83
|
ds.meta_def(:count) {150}
|
|
84
|
-
ds.paginate(2, 50).sql.
|
|
84
|
+
ds.paginate(2, 50).sql.must_equal 'SELECT * FROM (select * from blah) AS t1 LIMIT 50 OFFSET 50'
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
@@ -91,14 +91,14 @@ describe "Dataset#each_page" do
|
|
|
91
91
|
@d.meta_def(:count) {153}
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
proc{@d.limit(10).each_page(10){}}.
|
|
94
|
+
it "should raise an error if the dataset already has a limit" do
|
|
95
|
+
proc{@d.limit(10).each_page(10){}}.must_raise(Sequel::Error)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
it "should iterate over each page in the resultset as a paginated dataset" do
|
|
99
99
|
a = []
|
|
100
100
|
@d.each_page(50) {|p| a << p}
|
|
101
|
-
a.map {|p| p.sql}.
|
|
101
|
+
a.map {|p| p.sql}.must_equal [
|
|
102
102
|
'SELECT * FROM items LIMIT 50 OFFSET 0',
|
|
103
103
|
'SELECT * FROM items LIMIT 50 OFFSET 50',
|
|
104
104
|
'SELECT * FROM items LIMIT 50 OFFSET 100',
|
|
@@ -106,9 +106,9 @@ describe "Dataset#each_page" do
|
|
|
106
106
|
]
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
it "should return an enumerator if no block is given" do
|
|
110
110
|
enum = @d.each_page(50)
|
|
111
|
-
enum.map {|p| p.sql}.
|
|
111
|
+
enum.map {|p| p.sql}.must_equal [
|
|
112
112
|
'SELECT * FROM items LIMIT 50 OFFSET 0',
|
|
113
113
|
'SELECT * FROM items LIMIT 50 OFFSET 50',
|
|
114
114
|
'SELECT * FROM items LIMIT 50 OFFSET 100',
|
|
@@ -41,100 +41,100 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
41
41
|
@c2.many_to_pg_array :artists, :clone=>:artists, :eager_loader=>pr
|
|
42
42
|
@c1.eager(:tags).all
|
|
43
43
|
@c2.eager(:artists).all
|
|
44
|
-
khs.
|
|
44
|
+
khs.must_equal [[{}, nil], [{:id=>{2=>[Tag.load(:id=>2)]}}, {2=>[Tag.load(:id=>2)]}]]
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
it "should not issue queries if the object cannot have associated objects" do
|
|
48
|
-
@n1.tags.
|
|
49
|
-
@c1.load(:tag_ids=>[]).tags.
|
|
50
|
-
@n2.artists.
|
|
51
|
-
@db.sqls.
|
|
48
|
+
@n1.tags.must_equal []
|
|
49
|
+
@c1.load(:tag_ids=>[]).tags.must_equal []
|
|
50
|
+
@n2.artists.must_equal []
|
|
51
|
+
@db.sqls.must_equal []
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
it "should use correct SQL when loading associations lazily" do
|
|
55
|
-
@o1.tags.
|
|
56
|
-
@o2.artists.
|
|
57
|
-
@db.sqls.
|
|
55
|
+
@o1.tags.must_equal [@o2]
|
|
56
|
+
@o2.artists.must_equal [@o1]
|
|
57
|
+
@db.sqls.must_equal ["SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))", "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[])"]
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
it "should accept :primary_key option for primary keys to use in current and associated table" do
|
|
61
61
|
@c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel./(:id, 3)
|
|
62
62
|
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3
|
|
63
|
-
@o1.tags_dataset.sql.
|
|
64
|
-
@o2.artists_dataset.sql.
|
|
63
|
+
@o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE ((tags.id / 3) IN (1, 2, 3))"
|
|
64
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[6]::integer[])"
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
it "should allowing filtering by associations" do
|
|
68
|
-
@c1.filter(:tags=>@o2).sql.
|
|
69
|
-
@c2.filter(:artists=>@o1).sql.
|
|
68
|
+
@c1.filter(:tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[])"
|
|
69
|
+
@c2.filter(:artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))"
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
it "should allowing filtering by associations with :conditions" do
|
|
73
|
-
@c1.filter(:a_tags=>@o2).sql.
|
|
74
|
-
@c2.filter(:a_artists=>@o1).sql.
|
|
73
|
+
@c1.filter(:a_tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id = 2)))), 'f')"
|
|
74
|
+
@c2.filter(:a_artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id = 1))))"
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
it "should allowing excluding by associations" do
|
|
78
|
-
@c1.exclude(:tags=>@o2).sql.
|
|
79
|
-
@c2.exclude(:artists=>@o1).sql.
|
|
78
|
+
@c1.exclude(:tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE (NOT (artists.tag_ids @> ARRAY[2]::integer[]) OR (artists.tag_ids IS NULL))"
|
|
79
|
+
@c2.exclude(:artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (1, 2, 3)) OR (tags.id IS NULL))"
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
it "should allowing excluding by associations with :conditions" do
|
|
83
|
-
@c1.exclude(:a_tags=>@o2).sql.
|
|
84
|
-
@c2.exclude(:a_artists=>@o1).sql.
|
|
83
|
+
@c1.exclude(:a_tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id = 2)))), 'f') OR (artists.tag_ids IS NULL))"
|
|
84
|
+
@c2.exclude(:a_artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id = 1)))) OR (tags.id IS NULL))"
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
it "should allowing filtering by multiple associations" do
|
|
88
|
-
@c1.filter(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.
|
|
89
|
-
@c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.
|
|
88
|
+
@c1.filter(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[1,2]::integer[])"
|
|
89
|
+
@c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (3, 4, 5))"
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
it "should allowing filtering by multiple associations with :conditions" do
|
|
93
|
-
@c1.filter(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.
|
|
94
|
-
@c2.filter(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.
|
|
93
|
+
@c1.filter(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (1, 2))))), 'f')"
|
|
94
|
+
@c2.filter(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (7, 8)))))"
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
it "should allowing excluding by multiple associations" do
|
|
98
|
-
@c1.exclude(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.
|
|
99
|
-
@c2.exclude(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.
|
|
98
|
+
@c1.exclude(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (NOT (artists.tag_ids && ARRAY[1,2]::integer[]) OR (artists.tag_ids IS NULL))"
|
|
99
|
+
@c2.exclude(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (3, 4, 5)) OR (tags.id IS NULL))"
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
it "should allowing excluding by multiple associations with :conditions" do
|
|
103
|
-
@c1.exclude(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.
|
|
104
|
-
@c2.exclude(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.
|
|
103
|
+
@c1.exclude(:a_tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (1, 2))))), 'f') OR (artists.tag_ids IS NULL))"
|
|
104
|
+
@c2.exclude(:a_artists=>[@c1.load(:id=>7, :tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:id=>8, :tag_ids=>Sequel.pg_array([4, 5]))]).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (7, 8))))) OR (tags.id IS NULL))"
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
it "should allowing filtering/excluding associations with NULL or empty values" do
|
|
108
|
-
@c1.filter(:tags=>@c2.new).sql.
|
|
109
|
-
@c1.exclude(:tags=>@c2.new).sql.
|
|
110
|
-
@c2.filter(:artists=>@c1.new).sql.
|
|
111
|
-
@c2.exclude(:artists=>@c1.new).sql.
|
|
108
|
+
@c1.filter(:tags=>@c2.new).sql.must_equal 'SELECT * FROM artists WHERE \'f\''
|
|
109
|
+
@c1.exclude(:tags=>@c2.new).sql.must_equal 'SELECT * FROM artists WHERE \'t\''
|
|
110
|
+
@c2.filter(:artists=>@c1.new).sql.must_equal 'SELECT * FROM tags WHERE \'f\''
|
|
111
|
+
@c2.exclude(:artists=>@c1.new).sql.must_equal 'SELECT * FROM tags WHERE \'t\''
|
|
112
112
|
|
|
113
|
-
@c2.filter(:artists=>@c1.load(:tag_ids=>[])).sql.
|
|
114
|
-
@c2.exclude(:artists=>@c1.load(:tag_ids=>[])).sql.
|
|
113
|
+
@c2.filter(:artists=>@c1.load(:tag_ids=>[])).sql.must_equal 'SELECT * FROM tags WHERE \'f\''
|
|
114
|
+
@c2.exclude(:artists=>@c1.load(:tag_ids=>[])).sql.must_equal 'SELECT * FROM tags WHERE \'t\''
|
|
115
115
|
|
|
116
|
-
@c1.filter(:tags=>[@c2.new, @c2.load(:id=>2)]).sql.
|
|
117
|
-
@c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.new]).sql.
|
|
116
|
+
@c1.filter(:tags=>[@c2.new, @c2.load(:id=>2)]).sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"
|
|
117
|
+
@c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.new]).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (3, 4))"
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
it "should allowing filtering by association datasets" do
|
|
121
|
-
@c1.filter(:tags=>@c2.where(:id=>1)).sql.
|
|
122
|
-
@c2.filter(:artists=>@c1.where(:id=>1)).sql.
|
|
121
|
+
@c1.filter(:tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), 'f')"
|
|
122
|
+
@c2.filter(:artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1)))"
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
it "should allowing filtering by association datasets with :conditions" do
|
|
126
|
-
@c1.filter(:a_tags=>@c2.where(:id=>1)).sql.
|
|
127
|
-
@c2.filter(:a_artists=>@c1.where(:id=>1)).sql.
|
|
126
|
+
@c1.filter(:a_tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (id = 1)))))), 'f')"
|
|
127
|
+
@c2.filter(:a_artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (id = 1))))))"
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
it "should allowing excluding by association datasets" do
|
|
131
|
-
@c1.exclude(:tags=>@c2.where(:id=>1)).sql.
|
|
132
|
-
@c2.exclude(:artists=>@c1.where(:id=>1)).sql.
|
|
131
|
+
@c1.exclude(:tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), 'f') OR (artists.tag_ids IS NULL))"
|
|
132
|
+
@c2.exclude(:artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1))) OR (tags.id IS NULL))"
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
it "should allowing excluding by association datasets with :conditions" do
|
|
136
|
-
@c1.exclude(:a_tags=>@c2.where(:id=>1)).sql.
|
|
137
|
-
@c2.exclude(:a_artists=>@c1.where(:id=>1)).sql.
|
|
136
|
+
@c1.exclude(:a_tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE (NOT coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE ((name = 'A') AND (tags.id IS NOT NULL) AND (tags.id IN (SELECT tags.id FROM tags WHERE (id = 1)))))), 'f') OR (artists.tag_ids IS NULL))"
|
|
137
|
+
@c2.exclude(:a_artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE ((name = 'A') AND (artists.tag_ids IS NOT NULL) AND (artists.id IN (SELECT artists.id FROM artists WHERE (id = 1)))))) OR (tags.id IS NULL))"
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
it "filter by associations should respect key options" do
|
|
@@ -142,82 +142,82 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
142
142
|
@c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
|
|
143
143
|
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
|
|
144
144
|
|
|
145
|
-
@c1.filter(:tags=>@o2).sql.
|
|
146
|
-
@c2.filter(:artists=>@o1).sql.
|
|
147
|
-
@c1.filter(:tags=>@c2.where(:id=>1)).sql.
|
|
148
|
-
@c2.filter(:artists=>@c1.where(:id=>1)).sql.
|
|
145
|
+
@c1.filter(:tags=>@o2).sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids[1:2] @> ARRAY[6]::integer[])"
|
|
146
|
+
@c2.filter(:artists=>@o1).sql.must_equal "SELECT * FROM tags WHERE ((tags.id * 3) IN (3, 6, 9))"
|
|
147
|
+
@c1.filter(:tags=>@c2.where(:id=>1)).sql.must_equal "SELECT * FROM artists WHERE coalesce((artists.tag_ids[1:2] && (SELECT array_agg((tags.id * 3)) FROM tags WHERE (id = 1))), 'f')"
|
|
148
|
+
@c2.filter(:artists=>@c1.where(:id=>1)).sql.must_equal "SELECT * FROM tags WHERE ((tags.id * 3) IN (SELECT unnest(artists.tag_ids[1:2]) FROM artists WHERE (id = 1)))"
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
it "should raise an error if associated model does not have a primary key, and :primary_key is not specified" do
|
|
152
152
|
@c1.no_primary_key
|
|
153
153
|
@c2.no_primary_key
|
|
154
154
|
@c1.pg_array_to_many :tags, :clone=>:tags
|
|
155
|
-
proc{@o1.tags}.
|
|
156
|
-
proc{@c2.many_to_pg_array :artists, :clone=>:artists}.
|
|
157
|
-
@db.sqls.
|
|
155
|
+
proc{@o1.tags}.must_raise(Sequel::Error)
|
|
156
|
+
proc{@c2.many_to_pg_array :artists, :clone=>:artists}.must_raise(Sequel::Error)
|
|
157
|
+
@db.sqls.must_equal []
|
|
158
158
|
end
|
|
159
159
|
|
|
160
160
|
it "should support a :key option" do
|
|
161
161
|
@c1.pg_array_to_many :tags, :clone=>:tags, :key=>:tag2_ids
|
|
162
162
|
@c2.many_to_pg_array :artists, :clone=>:artists, :key=>:tag2_ids
|
|
163
163
|
@c1.class_eval{def tag2_ids; tag_ids.map{|x| x * 2} end}
|
|
164
|
-
@o1.tags_dataset.sql.
|
|
165
|
-
@o2.artists_dataset.sql.
|
|
164
|
+
@o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (2, 4, 6))"
|
|
165
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag2_ids @> ARRAY[2]::integer[])"
|
|
166
166
|
end
|
|
167
167
|
|
|
168
168
|
it "should support a :key_column option" do
|
|
169
169
|
@c2.many_to_pg_array :artists, :clone=>:artists, :key_column=>Sequel.pg_array(:tag_ids)[1..2], :key=>:tag2_ids
|
|
170
|
-
@o2.artists_dataset.sql.
|
|
170
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids[1:2] @> ARRAY[2]::integer[])"
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
it "should support a :primary_key option" do
|
|
174
174
|
@c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>:id2
|
|
175
175
|
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id2
|
|
176
|
-
@o1.tags_dataset.sql.
|
|
176
|
+
@o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id2 IN (1, 2, 3))"
|
|
177
177
|
@c2.class_eval{def id2; id*2 end}
|
|
178
|
-
@o2.artists_dataset.sql.
|
|
178
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[4]::integer[])"
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
it "should support a :conditions option" do
|
|
182
182
|
@c1.pg_array_to_many :tags, :clone=>:tags, :conditions=>{:a=>1}
|
|
183
183
|
@c2.many_to_pg_array :artists, :clone=>:artists, :conditions=>{:a=>1}
|
|
184
|
-
@o1.tags_dataset.sql.
|
|
185
|
-
@o2.artists_dataset.sql.
|
|
184
|
+
@o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE ((a = 1) AND (tags.id IN (1, 2, 3)))"
|
|
185
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE ((a = 1) AND (artists.tag_ids @> ARRAY[2]::integer[]))"
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
it "should support an :order option" do
|
|
189
189
|
@c1.pg_array_to_many :tags, :clone=>:tags, :order=>[:a, :b]
|
|
190
190
|
@c2.many_to_pg_array :artists, :clone=>:artists, :order=>[:a, :b]
|
|
191
|
-
@o1.tags_dataset.sql.
|
|
192
|
-
@o2.artists_dataset.sql.
|
|
191
|
+
@o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3)) ORDER BY a, b"
|
|
192
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[]) ORDER BY a, b"
|
|
193
193
|
end
|
|
194
194
|
|
|
195
195
|
it "should support a select option" do
|
|
196
196
|
@c1.pg_array_to_many :tags, :clone=>:tags, :select=>[:a, :b]
|
|
197
197
|
@c2.many_to_pg_array :artists, :clone=>:artists, :select=>[:a, :b]
|
|
198
|
-
@c1.load(:tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.
|
|
199
|
-
@c2.load(:id=>1).artists_dataset.sql.
|
|
198
|
+
@c1.load(:tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.must_equal "SELECT a, b FROM tags WHERE (tags.id IN (1, 2, 3))"
|
|
199
|
+
@c2.load(:id=>1).artists_dataset.sql.must_equal "SELECT a, b FROM artists WHERE (artists.tag_ids @> ARRAY[1]::integer[])"
|
|
200
200
|
end
|
|
201
201
|
|
|
202
202
|
it "should accept a block" do
|
|
203
203
|
@c1.pg_array_to_many :tags, :clone=>:tags do |ds| ds.filter(:yyy=>@yyy) end
|
|
204
204
|
@c2.many_to_pg_array :artists, :clone=>:artists do |ds| ds.filter(:a=>1) end
|
|
205
|
-
@c1.new(:yyy=>6, :tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.
|
|
206
|
-
@o2.artists_dataset.sql.
|
|
205
|
+
@c1.new(:yyy=>6, :tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.must_equal "SELECT * FROM tags WHERE ((tags.id IN (1, 2, 3)) AND (yyy = 6))"
|
|
206
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE ((artists.tag_ids @> ARRAY[2]::integer[]) AND (a = 1))"
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
it "should support a :dataset option that is used instead of the default" do
|
|
210
210
|
@c1.pg_array_to_many :tags, :clone=>:tags, :dataset=>proc{Tag.where(:id=>tag_ids.map{|x| x*2})}
|
|
211
211
|
@c2.many_to_pg_array :artists, :clone=>:artists, :dataset=>proc{Artist.where(Sequel.pg_array(Sequel.pg_array(:tag_ids)[1..2]).contains([id]))}
|
|
212
|
-
@o1.tags_dataset.sql.
|
|
213
|
-
@o2.artists_dataset.sql.
|
|
212
|
+
@o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (id IN (2, 4, 6))"
|
|
213
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (tag_ids[1:2] @> ARRAY[2])"
|
|
214
214
|
end
|
|
215
215
|
|
|
216
216
|
it "should support a :limit option" do
|
|
217
217
|
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[2, 3]
|
|
218
218
|
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[3, 2]
|
|
219
|
-
@o1.tags_dataset.sql.
|
|
220
|
-
@o2.artists_dataset.sql.
|
|
219
|
+
@o1.tags_dataset.sql.must_equal "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3)) LIMIT 2 OFFSET 3"
|
|
220
|
+
@o2.artists_dataset.sql.must_equal "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[]) LIMIT 3 OFFSET 2"
|
|
221
221
|
end
|
|
222
222
|
|
|
223
223
|
it "should support a :uniq option that removes duplicates from the association" do
|
|
@@ -225,39 +225,39 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
225
225
|
@c2.many_to_pg_array :artists, :clone=>:artists, :uniq=>true
|
|
226
226
|
@c1.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
|
227
227
|
@c2.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
|
228
|
-
@o1.tags.
|
|
229
|
-
@o2.artists.
|
|
228
|
+
@o1.tags.must_equal [@c2.load(:id=>20), @c2.load(:id=>30)]
|
|
229
|
+
@o2.artists.must_equal [@c1.load(:id=>20), @c1.load(:id=>30)]
|
|
230
230
|
end
|
|
231
231
|
|
|
232
232
|
it "reflection associated_object_keys should return correct values" do
|
|
233
|
-
@c1.association_reflection(:tags).associated_object_keys.
|
|
234
|
-
@c2.association_reflection(:artists).associated_object_keys.
|
|
233
|
+
@c1.association_reflection(:tags).associated_object_keys.must_equal [:id]
|
|
234
|
+
@c2.association_reflection(:artists).associated_object_keys.must_equal [:tag_ids]
|
|
235
235
|
end
|
|
236
236
|
|
|
237
237
|
it "reflection remove_before_destroy? should return correct values" do
|
|
238
|
-
@c1.association_reflection(:tags).remove_before_destroy?.
|
|
239
|
-
@c2.association_reflection(:artists).remove_before_destroy?.
|
|
238
|
+
@c1.association_reflection(:tags).remove_before_destroy?.must_equal true
|
|
239
|
+
@c2.association_reflection(:artists).remove_before_destroy?.must_equal false
|
|
240
240
|
end
|
|
241
241
|
|
|
242
242
|
it "reflection reciprocal should be correct" do
|
|
243
|
-
@c1.association_reflection(:tags).reciprocal.
|
|
244
|
-
@c2.association_reflection(:artists).reciprocal.
|
|
243
|
+
@c1.association_reflection(:tags).reciprocal.must_equal :artists
|
|
244
|
+
@c2.association_reflection(:artists).reciprocal.must_equal :tags
|
|
245
245
|
end
|
|
246
246
|
|
|
247
247
|
it "should eagerly load correctly" do
|
|
248
248
|
a = @c1.eager(:tags).all
|
|
249
|
-
a.
|
|
249
|
+
a.must_equal [@o1]
|
|
250
250
|
sqls = @db.sqls
|
|
251
|
-
sqls.pop.
|
|
252
|
-
sqls.
|
|
253
|
-
a.first.tags.
|
|
254
|
-
@db.sqls.
|
|
251
|
+
sqls.pop.must_match(/SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
252
|
+
sqls.must_equal ["SELECT * FROM artists"]
|
|
253
|
+
a.first.tags.must_equal [@o2]
|
|
254
|
+
@db.sqls.must_equal []
|
|
255
255
|
|
|
256
256
|
a = @c2.eager(:artists).all
|
|
257
|
-
a.
|
|
258
|
-
@db.sqls.
|
|
259
|
-
a.first.artists.
|
|
260
|
-
@db.sqls.
|
|
257
|
+
a.must_equal [@o2]
|
|
258
|
+
@db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
|
|
259
|
+
a.first.artists.must_equal [@o1]
|
|
260
|
+
@db.sqls.must_equal []
|
|
261
261
|
end
|
|
262
262
|
|
|
263
263
|
it "should support using custom key options when eager loading associations" do
|
|
@@ -266,46 +266,46 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
266
266
|
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
|
|
267
267
|
|
|
268
268
|
a = @c1.eager(:tags).all
|
|
269
|
-
a.
|
|
269
|
+
a.must_equal [@o1]
|
|
270
270
|
sqls = @db.sqls
|
|
271
|
-
sqls.pop.
|
|
272
|
-
sqls.
|
|
273
|
-
a.first.tags.
|
|
274
|
-
@db.sqls.
|
|
271
|
+
sqls.pop.must_match(/SELECT \* FROM tags WHERE \(\(tags\.id \* 3\) IN \([369], [369], [369]\)\)/)
|
|
272
|
+
sqls.must_equal ["SELECT * FROM artists"]
|
|
273
|
+
a.first.tags.must_equal [@o2]
|
|
274
|
+
@db.sqls.must_equal []
|
|
275
275
|
|
|
276
276
|
a = @c2.eager(:artists).all
|
|
277
|
-
a.
|
|
278
|
-
@db.sqls.
|
|
279
|
-
a.first.artists.
|
|
280
|
-
@db.sqls.
|
|
277
|
+
a.must_equal [@o2]
|
|
278
|
+
@db.sqls.must_equal ["SELECT * FROM tags", "SELECT * FROM artists WHERE (artists.tag_ids[1:2] && ARRAY[6]::integer[])"]
|
|
279
|
+
a.first.artists.must_equal [@o1]
|
|
280
|
+
@db.sqls.must_equal []
|
|
281
281
|
end
|
|
282
282
|
|
|
283
283
|
it "should allow cascading of eager loading for associations of associated models" do
|
|
284
284
|
a = @c1.eager(:tags=>:artists).all
|
|
285
|
-
a.
|
|
285
|
+
a.must_equal [@o1]
|
|
286
286
|
sqls = @db.sqls
|
|
287
|
-
sqls.slice!(1).
|
|
288
|
-
sqls.
|
|
289
|
-
a.first.tags.
|
|
290
|
-
a.first.tags.first.artists.
|
|
291
|
-
@db.sqls.
|
|
287
|
+
sqls.slice!(1).must_match(/SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
288
|
+
sqls.must_equal ['SELECT * FROM artists', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
|
|
289
|
+
a.first.tags.must_equal [@o2]
|
|
290
|
+
a.first.tags.first.artists.must_equal [@o1]
|
|
291
|
+
@db.sqls.must_equal []
|
|
292
292
|
end
|
|
293
293
|
|
|
294
294
|
it "should respect :eager when lazily loading an association" do
|
|
295
295
|
@c1.pg_array_to_many :tags2, :clone=>:tags, :eager=>:artists, :key=>:tag_ids
|
|
296
296
|
@c2.many_to_pg_array :artists2, :clone=>:artists, :eager=>:tags
|
|
297
297
|
|
|
298
|
-
@o1.tags2.
|
|
299
|
-
@db.sqls.
|
|
300
|
-
@o1.tags2.first.artists.
|
|
301
|
-
@db.sqls.
|
|
298
|
+
@o1.tags2.must_equal [@o2]
|
|
299
|
+
@db.sqls.must_equal ["SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))", "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
|
|
300
|
+
@o1.tags2.first.artists.must_equal [@o1]
|
|
301
|
+
@db.sqls.must_equal []
|
|
302
302
|
|
|
303
|
-
@o2.artists2.
|
|
303
|
+
@o2.artists2.must_equal [@o1]
|
|
304
304
|
sqls = @db.sqls
|
|
305
|
-
sqls.pop.
|
|
306
|
-
sqls.
|
|
307
|
-
@o2.artists2.first.tags.
|
|
308
|
-
@db.sqls.
|
|
305
|
+
sqls.pop.must_match(/SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
306
|
+
sqls.must_equal ["SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]::integer[])"]
|
|
307
|
+
@o2.artists2.first.tags.must_equal [@o2]
|
|
308
|
+
@db.sqls.must_equal []
|
|
309
309
|
end
|
|
310
310
|
|
|
311
311
|
it "should cascade eagerly loading when the :eager_graph association option is used" do
|
|
@@ -315,37 +315,37 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
315
315
|
@c2.dataset._fetch = {:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
316
316
|
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
317
317
|
|
|
318
|
-
@o1.tags2.
|
|
319
|
-
@db.sqls.first.
|
|
320
|
-
@o1.tags2.first.artists.
|
|
321
|
-
@db.sqls.
|
|
318
|
+
@o1.tags2.must_equal [@o2]
|
|
319
|
+
@db.sqls.first.must_match(/SELECT tags\.id, artists\.id AS artists_id, artists\.tag_ids FROM tags LEFT OUTER JOIN artists ON \(artists.tag_ids @> ARRAY\[tags.id\]\) WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
320
|
+
@o1.tags2.first.artists.must_equal [@o1]
|
|
321
|
+
@db.sqls.must_equal []
|
|
322
322
|
|
|
323
|
-
@o2.artists2.
|
|
324
|
-
@db.sqls.
|
|
325
|
-
@o2.artists2.first.tags.
|
|
326
|
-
@db.sqls.
|
|
323
|
+
@o2.artists2.must_equal [@o1]
|
|
324
|
+
@db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id]) WHERE (artists.tag_ids @> ARRAY[2]::integer[])"]
|
|
325
|
+
@o2.artists2.first.tags.must_equal [@o2]
|
|
326
|
+
@db.sqls.must_equal []
|
|
327
327
|
|
|
328
328
|
@c2.dataset._fetch = {:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
329
329
|
@c1.dataset._fetch = {:id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
330
330
|
|
|
331
331
|
a = @c1.eager(:tags2).all
|
|
332
332
|
sqls = @db.sqls
|
|
333
|
-
sqls.pop.
|
|
334
|
-
sqls.
|
|
335
|
-
a.
|
|
336
|
-
a.first.tags2.
|
|
337
|
-
a.first.tags2.first.artists.
|
|
338
|
-
@db.sqls.
|
|
333
|
+
sqls.pop.must_match(/SELECT tags\.id, artists\.id AS artists_id, artists\.tag_ids FROM tags LEFT OUTER JOIN artists ON \(artists.tag_ids @> ARRAY\[tags.id\]\) WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
334
|
+
sqls.must_equal ["SELECT * FROM artists"]
|
|
335
|
+
a.must_equal [@o1]
|
|
336
|
+
a.first.tags2.must_equal [@o2]
|
|
337
|
+
a.first.tags2.first.artists.must_equal [@o1]
|
|
338
|
+
@db.sqls.must_equal []
|
|
339
339
|
|
|
340
340
|
@c2.dataset._fetch = {:id=>2}
|
|
341
341
|
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
342
342
|
|
|
343
343
|
a = @c2.eager(:artists2).all
|
|
344
|
-
@db.sqls.
|
|
345
|
-
a.
|
|
346
|
-
a.first.artists2.
|
|
347
|
-
a.first.artists2.first.tags.
|
|
348
|
-
@db.sqls.
|
|
344
|
+
@db.sqls.must_equal ["SELECT * FROM tags", "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id]) WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
|
|
345
|
+
a.must_equal [@o2]
|
|
346
|
+
a.first.artists2.must_equal [@o1]
|
|
347
|
+
a.first.artists2.first.tags.must_equal [@o2]
|
|
348
|
+
@db.sqls.must_equal []
|
|
349
349
|
end
|
|
350
350
|
|
|
351
351
|
it "should respect the :limit option when eager loading" do
|
|
@@ -353,64 +353,64 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
353
353
|
|
|
354
354
|
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>2
|
|
355
355
|
a = @c1.eager(:tags).all
|
|
356
|
-
a.
|
|
356
|
+
a.must_equal [@o1]
|
|
357
357
|
sqls = @db.sqls
|
|
358
|
-
sqls.pop.
|
|
359
|
-
sqls.
|
|
360
|
-
a.first.tags.
|
|
361
|
-
@db.sqls.
|
|
358
|
+
sqls.pop.must_match(/SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
359
|
+
sqls.must_equal ["SELECT * FROM artists"]
|
|
360
|
+
a.first.tags.must_equal [@c2.load(:id=>1), @c2.load(:id=>2)]
|
|
361
|
+
@db.sqls.must_equal []
|
|
362
362
|
|
|
363
363
|
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[1, 1]
|
|
364
364
|
a = @c1.eager(:tags).all
|
|
365
|
-
a.
|
|
365
|
+
a.must_equal [@o1]
|
|
366
366
|
sqls = @db.sqls
|
|
367
|
-
sqls.pop.
|
|
368
|
-
sqls.
|
|
369
|
-
a.first.tags.
|
|
370
|
-
@db.sqls.
|
|
367
|
+
sqls.pop.must_match(/SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
368
|
+
sqls.must_equal ["SELECT * FROM artists"]
|
|
369
|
+
a.first.tags.must_equal [@c2.load(:id=>2)]
|
|
370
|
+
@db.sqls.must_equal []
|
|
371
371
|
|
|
372
372
|
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[nil, 1]
|
|
373
373
|
a = @c1.eager(:tags).all
|
|
374
|
-
a.
|
|
374
|
+
a.must_equal [@o1]
|
|
375
375
|
sqls = @db.sqls
|
|
376
|
-
sqls.pop.
|
|
377
|
-
sqls.
|
|
378
|
-
a.first.tags.
|
|
379
|
-
@db.sqls.length.
|
|
376
|
+
sqls.pop.must_match(/SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/)
|
|
377
|
+
sqls.must_equal ["SELECT * FROM artists"]
|
|
378
|
+
a.first.tags.must_equal [@c2.load(:id=>2), @c2.load(:id=>3)]
|
|
379
|
+
@db.sqls.length.must_equal 0
|
|
380
380
|
|
|
381
381
|
@c2.dataset._fetch = [{:id=>2}]
|
|
382
382
|
@c1.dataset._fetch = [{:id=>5, :tag_ids=>Sequel.pg_array([1,2,3])},{:id=>6, :tag_ids=>Sequel.pg_array([2,3])}, {:id=>7, :tag_ids=>Sequel.pg_array([1,2])}]
|
|
383
383
|
|
|
384
384
|
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>2
|
|
385
385
|
a = @c2.eager(:artists).all
|
|
386
|
-
a.
|
|
387
|
-
@db.sqls.
|
|
388
|
-
a.first.artists.
|
|
389
|
-
@db.sqls.
|
|
386
|
+
a.must_equal [@o2]
|
|
387
|
+
@db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
|
|
388
|
+
a.first.artists.must_equal [@c1.load(:id=>5, :tag_ids=>Sequel.pg_array([1,2,3])), @c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3]))]
|
|
389
|
+
@db.sqls.must_equal []
|
|
390
390
|
|
|
391
391
|
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[1, 1]
|
|
392
392
|
a = @c2.eager(:artists).all
|
|
393
|
-
a.
|
|
394
|
-
@db.sqls.
|
|
395
|
-
a.first.artists.
|
|
396
|
-
@db.sqls.
|
|
393
|
+
a.must_equal [@o2]
|
|
394
|
+
@db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
|
|
395
|
+
a.first.artists.must_equal [@c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3]))]
|
|
396
|
+
@db.sqls.must_equal []
|
|
397
397
|
|
|
398
398
|
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[nil, 1]
|
|
399
399
|
a = @c2.eager(:artists).all
|
|
400
|
-
a.
|
|
401
|
-
@db.sqls.
|
|
402
|
-
a.first.artists.
|
|
403
|
-
@db.sqls.
|
|
400
|
+
a.must_equal [@o2]
|
|
401
|
+
@db.sqls.must_equal ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::integer[])"]
|
|
402
|
+
a.first.artists.must_equal [@c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3])), @c1.load(:id=>7, :tag_ids=>Sequel.pg_array([1,2]))]
|
|
403
|
+
@db.sqls.must_equal []
|
|
404
404
|
end
|
|
405
405
|
|
|
406
406
|
it "should support association_join" do
|
|
407
|
-
@c1.association_join(:tags).sql.
|
|
408
|
-
@c2.association_join(:artists).sql.
|
|
407
|
+
@c1.association_join(:tags).sql.must_equal "SELECT * FROM artists INNER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
408
|
+
@c2.association_join(:artists).sql.must_equal "SELECT * FROM tags INNER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
409
409
|
end
|
|
410
410
|
|
|
411
411
|
it "should support custom selects when using association_join" do
|
|
412
|
-
@c1.select{a(b)}.association_join(:tags).sql.
|
|
413
|
-
@c2.select{a(b)}.association_join(:artists).sql.
|
|
412
|
+
@c1.select{a(b)}.association_join(:tags).sql.must_equal "SELECT a(b) FROM artists INNER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
413
|
+
@c2.select{a(b)}.association_join(:artists).sql.must_equal "SELECT a(b) FROM tags INNER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
414
414
|
end
|
|
415
415
|
|
|
416
416
|
it "should eagerly graph associations" do
|
|
@@ -418,16 +418,16 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
418
418
|
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
419
419
|
|
|
420
420
|
a = @c1.eager_graph(:tags).all
|
|
421
|
-
@db.sqls.
|
|
422
|
-
a.
|
|
423
|
-
a.first.tags.
|
|
424
|
-
@db.sqls.
|
|
421
|
+
@db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
422
|
+
a.must_equal [@o1]
|
|
423
|
+
a.first.tags.must_equal [@o2]
|
|
424
|
+
@db.sqls.must_equal []
|
|
425
425
|
|
|
426
426
|
a = @c2.eager_graph(:artists).all
|
|
427
|
-
@db.sqls.
|
|
428
|
-
a.
|
|
429
|
-
a.first.artists.
|
|
430
|
-
@db.sqls.
|
|
427
|
+
@db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
428
|
+
a.must_equal [@o2]
|
|
429
|
+
a.first.artists.must_equal [@o1]
|
|
430
|
+
@db.sqls.must_equal []
|
|
431
431
|
end
|
|
432
432
|
|
|
433
433
|
it "should allow cascading of eager graphing for associations of associated models" do
|
|
@@ -435,18 +435,18 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
435
435
|
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3]), :artists_0_id=>1, :artists_0_tag_ids=>Sequel.pg_array([1,2,3])}
|
|
436
436
|
|
|
437
437
|
a = @c1.eager_graph(:tags=>:artists).all
|
|
438
|
-
@db.sqls.
|
|
439
|
-
a.
|
|
440
|
-
a.first.tags.
|
|
441
|
-
a.first.tags.first.artists.
|
|
442
|
-
@db.sqls.
|
|
438
|
+
@db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id, artists_0.id AS artists_0_id, artists_0.tag_ids AS artists_0_tag_ids FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id]) LEFT OUTER JOIN artists AS artists_0 ON (artists_0.tag_ids @> ARRAY[tags.id])"]
|
|
439
|
+
a.must_equal [@o1]
|
|
440
|
+
a.first.tags.must_equal [@o2]
|
|
441
|
+
a.first.tags.first.artists.must_equal [@o1]
|
|
442
|
+
@db.sqls.must_equal []
|
|
443
443
|
|
|
444
444
|
a = @c2.eager_graph(:artists=>:tags).all
|
|
445
|
-
@db.sqls.
|
|
446
|
-
a.
|
|
447
|
-
a.first.artists.
|
|
448
|
-
a.first.artists.first.tags.
|
|
449
|
-
@db.sqls.
|
|
445
|
+
@db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id, artists.tag_ids, tags_0.id AS tags_0_id FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id]) LEFT OUTER JOIN tags AS tags_0 ON (artists.tag_ids @> ARRAY[tags_0.id])"]
|
|
446
|
+
a.must_equal [@o2]
|
|
447
|
+
a.first.artists.must_equal [@o1]
|
|
448
|
+
a.first.artists.first.tags.must_equal [@o2]
|
|
449
|
+
@db.sqls.must_equal []
|
|
450
450
|
end
|
|
451
451
|
|
|
452
452
|
it "eager graphing should respect key options" do
|
|
@@ -458,16 +458,16 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
458
458
|
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3]), :artists_0_id=>1, :artists_0_tag_ids=>Sequel.pg_array([1,2,3])}
|
|
459
459
|
|
|
460
460
|
a = @c1.eager_graph(:tags).all
|
|
461
|
-
a.
|
|
462
|
-
@db.sqls.
|
|
463
|
-
a.first.tags.
|
|
464
|
-
@db.sqls.
|
|
461
|
+
a.must_equal [@o1]
|
|
462
|
+
@db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids[1:2] @> ARRAY[(tags.id * 3)])"]
|
|
463
|
+
a.first.tags.must_equal [@o2]
|
|
464
|
+
@db.sqls.must_equal []
|
|
465
465
|
|
|
466
466
|
a = @c2.eager_graph(:artists).all
|
|
467
|
-
a.
|
|
468
|
-
@db.sqls.
|
|
469
|
-
a.first.artists.
|
|
470
|
-
@db.sqls.
|
|
467
|
+
a.must_equal [@o2]
|
|
468
|
+
@db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids[1:2] @> ARRAY[tags.id3])"]
|
|
469
|
+
a.first.artists.must_equal [@o1]
|
|
470
|
+
@db.sqls.must_equal []
|
|
471
471
|
end
|
|
472
472
|
|
|
473
473
|
it "should respect the association's :graph_select option" do
|
|
@@ -478,177 +478,177 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
478
478
|
@c1.dataset._fetch = {:id=>1, :id2=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
479
479
|
|
|
480
480
|
a = @c1.eager_graph(:tags).all
|
|
481
|
-
@db.sqls.
|
|
482
|
-
a.
|
|
483
|
-
a.first.tags.
|
|
484
|
-
@db.sqls.
|
|
481
|
+
@db.sqls.must_equal ["SELECT artists.id, artists.tag_ids, tags.id2 FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
482
|
+
a.must_equal [@o1]
|
|
483
|
+
a.first.tags.must_equal [@c2.load(:id2=>2)]
|
|
484
|
+
@db.sqls.must_equal []
|
|
485
485
|
|
|
486
486
|
a = @c2.eager_graph(:artists).all
|
|
487
|
-
@db.sqls.
|
|
488
|
-
a.
|
|
489
|
-
a.first.artists.
|
|
490
|
-
@db.sqls.
|
|
487
|
+
@db.sqls.must_equal ["SELECT tags.id, artists.id AS artists_id FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
488
|
+
a.must_equal [@o2]
|
|
489
|
+
a.first.artists.must_equal [@c1.load(:id=>1)]
|
|
490
|
+
@db.sqls.must_equal []
|
|
491
491
|
end
|
|
492
492
|
|
|
493
493
|
it "should respect the association's :graph_join_type option" do
|
|
494
494
|
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_join_type=>:inner
|
|
495
495
|
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_join_type=>:inner
|
|
496
|
-
@c1.eager_graph(:tags).sql.
|
|
497
|
-
@c2.eager_graph(:artists).sql.
|
|
496
|
+
@c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists INNER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
497
|
+
@c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags INNER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
498
498
|
end
|
|
499
499
|
|
|
500
500
|
it "should respect the association's :conditions option" do
|
|
501
501
|
@c1.pg_array_to_many :tags, :clone=>:tags, :conditions=>{:a=>1}
|
|
502
502
|
@c2.many_to_pg_array :artists, :clone=>:artists, :conditions=>{:a=>1}
|
|
503
|
-
@c1.eager_graph(:tags).sql.
|
|
504
|
-
@c2.eager_graph(:artists).sql.
|
|
503
|
+
@c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
|
|
504
|
+
@c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
|
|
505
505
|
end
|
|
506
506
|
|
|
507
507
|
it "should respect the association's :graph_conditions option" do
|
|
508
508
|
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_conditions=>{:a=>1}
|
|
509
509
|
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_conditions=>{:a=>1}
|
|
510
|
-
@c1.eager_graph(:tags).sql.
|
|
511
|
-
@c2.eager_graph(:artists).sql.
|
|
510
|
+
@c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
|
|
511
|
+
@c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
|
|
512
512
|
end
|
|
513
513
|
|
|
514
514
|
it "should respect the association's :graph_block option" do
|
|
515
515
|
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(ja, :a)=>1}}
|
|
516
516
|
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(ja, :a)=>1}}
|
|
517
|
-
@c1.eager_graph(:tags).sql.
|
|
518
|
-
@c2.eager_graph(:artists).sql.
|
|
517
|
+
@c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
|
|
518
|
+
@c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (artists.tag_ids @> ARRAY[tags.id]))"
|
|
519
519
|
end
|
|
520
520
|
|
|
521
521
|
it "should respect the association's :graph_only_conditions option" do
|
|
522
522
|
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_only_conditions=>{:a=>1}
|
|
523
523
|
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_only_conditions=>{:a=>1}
|
|
524
|
-
@c1.eager_graph(:tags).sql.
|
|
525
|
-
@c2.eager_graph(:artists).sql.
|
|
524
|
+
@c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (tags.a = 1)"
|
|
525
|
+
@c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.a = 1)"
|
|
526
526
|
end
|
|
527
527
|
|
|
528
528
|
it "should respect the association's :graph_only_conditions with :graph_block option" do
|
|
529
529
|
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_only_conditions=>{:a=>1}, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(lja, :b)=>1}}
|
|
530
530
|
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_only_conditions=>{:a=>1}, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(lja, :b)=>1}}
|
|
531
|
-
@c1.eager_graph(:tags).sql.
|
|
532
|
-
@c2.eager_graph(:artists).sql.
|
|
531
|
+
@c1.eager_graph(:tags).sql.must_equal "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON ((tags.a = 1) AND (artists.b = 1))"
|
|
532
|
+
@c2.eager_graph(:artists).sql.must_equal "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON ((artists.a = 1) AND (tags.b = 1))"
|
|
533
533
|
end
|
|
534
534
|
|
|
535
535
|
it "should define an add_ method for adding associated objects" do
|
|
536
536
|
@o1.add_tag(@c2.load(:id=>4))
|
|
537
|
-
@o1.tag_ids.
|
|
538
|
-
@db.sqls.
|
|
537
|
+
@o1.tag_ids.must_equal [1,2,3,4]
|
|
538
|
+
@db.sqls.must_equal []
|
|
539
539
|
@o1.save_changes
|
|
540
|
-
@db.sqls.
|
|
540
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,2,3,4] WHERE (id = 1)"]
|
|
541
541
|
|
|
542
542
|
@o2.add_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([4])))
|
|
543
|
-
@db.sqls.
|
|
543
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4,2] WHERE (id = 1)"]
|
|
544
544
|
end
|
|
545
545
|
|
|
546
546
|
it "should define a remove_ method for removing associated objects" do
|
|
547
547
|
@o1.remove_tag(@o2)
|
|
548
|
-
@o1.tag_ids.
|
|
549
|
-
@db.sqls.
|
|
548
|
+
@o1.tag_ids.must_equal [1,3]
|
|
549
|
+
@db.sqls.must_equal []
|
|
550
550
|
@o1.save_changes
|
|
551
|
-
@db.sqls.
|
|
551
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,3] WHERE (id = 1)"]
|
|
552
552
|
|
|
553
553
|
@o2.remove_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([1,2,3,4])))
|
|
554
|
-
@db.sqls.
|
|
554
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,3,4] WHERE (id = 1)"]
|
|
555
555
|
end
|
|
556
556
|
|
|
557
557
|
it "should define a remove_all_ method for removing all associated objects" do
|
|
558
558
|
@o1.remove_all_tags
|
|
559
|
-
@o1.tag_ids.
|
|
560
|
-
@db.sqls.
|
|
559
|
+
@o1.tag_ids.must_equal []
|
|
560
|
+
@db.sqls.must_equal []
|
|
561
561
|
@o1.save_changes
|
|
562
|
-
@db.sqls.
|
|
562
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[] WHERE (id = 1)"]
|
|
563
563
|
|
|
564
564
|
@o2.remove_all_artists
|
|
565
|
-
@db.sqls.
|
|
565
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = array_remove(tag_ids, 2) WHERE (tag_ids @> ARRAY[2])"]
|
|
566
566
|
end
|
|
567
567
|
|
|
568
568
|
it "should allow calling add_ and remove_ methods on new objects for pg_array_to_many associations" do
|
|
569
569
|
a = Artist.new
|
|
570
570
|
a.add_tag(@c2.load(:id=>4))
|
|
571
|
-
a.tag_ids.
|
|
571
|
+
a.tag_ids.must_equal [4]
|
|
572
572
|
a.remove_tag(@c2.load(:id=>4))
|
|
573
|
-
a.tag_ids.
|
|
573
|
+
a.tag_ids.must_equal []
|
|
574
574
|
a.add_tag(@c2.load(:id=>4))
|
|
575
|
-
a.tag_ids.
|
|
575
|
+
a.tag_ids.must_equal [4]
|
|
576
576
|
a.remove_all_tags
|
|
577
|
-
a.tag_ids.
|
|
577
|
+
a.tag_ids.must_equal []
|
|
578
578
|
end
|
|
579
579
|
|
|
580
580
|
it "should have pg_array_to_many association modification methods save if :save_after_modify option is used" do
|
|
581
581
|
@c1.pg_array_to_many :tags, :clone=>:tags, :save_after_modify=>true
|
|
582
582
|
|
|
583
583
|
@o1.add_tag(@c2.load(:id=>4))
|
|
584
|
-
@o1.tag_ids.
|
|
585
|
-
@db.sqls.
|
|
584
|
+
@o1.tag_ids.must_equal [1,2,3,4]
|
|
585
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,2,3,4] WHERE (id = 1)"]
|
|
586
586
|
|
|
587
587
|
@o1.remove_tag(@o2)
|
|
588
|
-
@o1.tag_ids.
|
|
589
|
-
@db.sqls.
|
|
588
|
+
@o1.tag_ids.must_equal [1,3,4]
|
|
589
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1,3,4] WHERE (id = 1)"]
|
|
590
590
|
|
|
591
591
|
@o1.remove_all_tags
|
|
592
|
-
@o1.tag_ids.
|
|
593
|
-
@db.sqls.
|
|
592
|
+
@o1.tag_ids.must_equal []
|
|
593
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[] WHERE (id = 1)"]
|
|
594
594
|
end
|
|
595
595
|
|
|
596
596
|
it "should have association modification methods deal with nil values" do
|
|
597
597
|
v = @c1.load(:id=>1)
|
|
598
598
|
v.add_tag(@c2.load(:id=>4))
|
|
599
|
-
v.tag_ids.
|
|
600
|
-
@db.sqls.
|
|
599
|
+
v.tag_ids.must_equal [4]
|
|
600
|
+
@db.sqls.must_equal []
|
|
601
601
|
v.save_changes
|
|
602
|
-
@db.sqls.
|
|
602
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4]::integer[] WHERE (id = 1)"]
|
|
603
603
|
|
|
604
604
|
@o2.add_artist(@c1.load(:id=>1))
|
|
605
|
-
@db.sqls.
|
|
605
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[2]::integer[] WHERE (id = 1)"]
|
|
606
606
|
|
|
607
607
|
v = @c1.load(:id=>1)
|
|
608
608
|
v.remove_tag(@c2.load(:id=>4))
|
|
609
|
-
v.tag_ids.
|
|
610
|
-
@db.sqls.
|
|
609
|
+
v.tag_ids.must_equal nil
|
|
610
|
+
@db.sqls.must_equal []
|
|
611
611
|
v.save_changes
|
|
612
|
-
@db.sqls.
|
|
612
|
+
@db.sqls.must_equal []
|
|
613
613
|
|
|
614
614
|
@o2.remove_artist(@c1.load(:id=>1))
|
|
615
|
-
@db.sqls.
|
|
615
|
+
@db.sqls.must_equal []
|
|
616
616
|
|
|
617
617
|
v = @c1.load(:id=>1)
|
|
618
618
|
v.remove_all_tags
|
|
619
|
-
v.tag_ids.
|
|
620
|
-
@db.sqls.
|
|
619
|
+
v.tag_ids.must_equal nil
|
|
620
|
+
@db.sqls.must_equal []
|
|
621
621
|
v.save_changes
|
|
622
|
-
@db.sqls.
|
|
622
|
+
@db.sqls.must_equal []
|
|
623
623
|
end
|
|
624
624
|
|
|
625
625
|
it "should have association modification methods deal with empty arrays values" do
|
|
626
626
|
v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
|
|
627
627
|
v.add_tag(@c2.load(:id=>4))
|
|
628
|
-
v.tag_ids.
|
|
629
|
-
@db.sqls.
|
|
628
|
+
v.tag_ids.must_equal [4]
|
|
629
|
+
@db.sqls.must_equal []
|
|
630
630
|
v.save_changes
|
|
631
|
-
@db.sqls.
|
|
631
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4] WHERE (id = 1)"]
|
|
632
632
|
|
|
633
633
|
@o2.add_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([])))
|
|
634
|
-
@db.sqls.
|
|
634
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[2] WHERE (id = 1)"]
|
|
635
635
|
|
|
636
636
|
v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
|
|
637
637
|
v.remove_tag(@c2.load(:id=>4))
|
|
638
|
-
v.tag_ids.
|
|
639
|
-
@db.sqls.
|
|
638
|
+
v.tag_ids.must_equal []
|
|
639
|
+
@db.sqls.must_equal []
|
|
640
640
|
v.save_changes
|
|
641
|
-
@db.sqls.
|
|
641
|
+
@db.sqls.must_equal []
|
|
642
642
|
|
|
643
643
|
@o2.remove_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([])))
|
|
644
|
-
@db.sqls.
|
|
644
|
+
@db.sqls.must_equal []
|
|
645
645
|
|
|
646
646
|
v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
|
|
647
647
|
v.remove_all_tags
|
|
648
|
-
v.tag_ids.
|
|
649
|
-
@db.sqls.
|
|
648
|
+
v.tag_ids.must_equal []
|
|
649
|
+
@db.sqls.must_equal []
|
|
650
650
|
v.save_changes
|
|
651
|
-
@db.sqls.
|
|
651
|
+
@db.sqls.must_equal []
|
|
652
652
|
end
|
|
653
653
|
|
|
654
654
|
it "should respect the :array_type option when manually creating arrays" do
|
|
@@ -656,39 +656,39 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
656
656
|
@c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:int8
|
|
657
657
|
v = @c1.load(:id=>1)
|
|
658
658
|
v.add_tag(@c2.load(:id=>4))
|
|
659
|
-
v.tag_ids.
|
|
660
|
-
@db.sqls.
|
|
659
|
+
v.tag_ids.must_equal [4]
|
|
660
|
+
@db.sqls.must_equal []
|
|
661
661
|
v.save_changes
|
|
662
|
-
@db.sqls.
|
|
662
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[4]::int8[] WHERE (id = 1)"]
|
|
663
663
|
|
|
664
664
|
@o2.add_artist(@c1.load(:id=>1))
|
|
665
|
-
@db.sqls.
|
|
665
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[2]::int8[] WHERE (id = 1)"]
|
|
666
666
|
end
|
|
667
667
|
|
|
668
668
|
it "should respect the :array_type option in the associations dataset" do
|
|
669
669
|
@c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:int8
|
|
670
|
-
@c2.load(:id=>1).artists_dataset.sql.
|
|
670
|
+
@c2.load(:id=>1).artists_dataset.sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[1]::int8[])'
|
|
671
671
|
end
|
|
672
672
|
|
|
673
673
|
it "should respect the :array_type option when eager loading" do
|
|
674
674
|
@c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:int8
|
|
675
675
|
@c2.eager(:artists).all
|
|
676
|
-
@db.sqls.
|
|
676
|
+
@db.sqls.must_equal ["SELECT * FROM tags", "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2]::int8[])"]
|
|
677
677
|
end
|
|
678
678
|
|
|
679
679
|
it "should respect the :array_type option when filtering by associations" do
|
|
680
680
|
@c1.pg_array_to_many :tags, :clone=>:tags, :array_type=>:int8
|
|
681
|
-
@c1.where(:tags=>@c2.load(:id=>1)).sql.
|
|
682
|
-
@c1.where(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.
|
|
681
|
+
@c1.where(:tags=>@c2.load(:id=>1)).sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[1]::int8[])'
|
|
682
|
+
@c1.where(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[1,2]::int8[])'
|
|
683
683
|
end
|
|
684
684
|
|
|
685
685
|
it "should automatically determine the array type by looking at the schema" do
|
|
686
686
|
@c1.db_schema[:tag_ids][:db_type] = 'int8'
|
|
687
687
|
@c2.many_to_pg_array :artists, :clone=>:artists
|
|
688
688
|
@c1.pg_array_to_many :tags, :clone=>:tags, :save_after_modify=>true
|
|
689
|
-
@c2.load(:id=>1).artists_dataset.sql.
|
|
689
|
+
@c2.load(:id=>1).artists_dataset.sql.must_equal 'SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[1]::int8[])'
|
|
690
690
|
@c1.load(:id=>1).add_tag(@c2.load(:id=>1))
|
|
691
|
-
@db.sqls.
|
|
691
|
+
@db.sqls.must_equal ["UPDATE artists SET tag_ids = ARRAY[1]::int8[] WHERE (id = 1)"]
|
|
692
692
|
end
|
|
693
693
|
|
|
694
694
|
it "should automatically determine the array type by looking at the schema" do
|
|
@@ -701,16 +701,16 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
701
701
|
t = @c2.load(:id=>2)
|
|
702
702
|
def a.validate() errors.add(:id, 'foo') end
|
|
703
703
|
a.associations[:tags] = []
|
|
704
|
-
a.add_tag(t).
|
|
705
|
-
a.tags.
|
|
706
|
-
a.remove_tag(t).
|
|
707
|
-
a.tags.
|
|
704
|
+
a.add_tag(t).must_equal t
|
|
705
|
+
a.tags.must_equal [t]
|
|
706
|
+
a.remove_tag(t).must_equal t
|
|
707
|
+
a.tags.must_equal []
|
|
708
708
|
|
|
709
709
|
t.associations[:artists] = []
|
|
710
|
-
t.add_artist(a).
|
|
711
|
-
t.artists.
|
|
712
|
-
t.remove_artist(a).
|
|
713
|
-
t.artists.
|
|
710
|
+
t.add_artist(a).must_equal a
|
|
711
|
+
t.artists.must_equal [a]
|
|
712
|
+
t.remove_artist(a).must_equal a
|
|
713
|
+
t.artists.must_equal []
|
|
714
714
|
end
|
|
715
715
|
|
|
716
716
|
it "should not raise exception in add_ and remove_ if the :raise_on_save_failure=>false option is used" do
|
|
@@ -720,17 +720,17 @@ describe Sequel::Model, "pg_array_associations" do
|
|
|
720
720
|
t = @c2.load(:id=>2)
|
|
721
721
|
def a.validate() errors.add(:id, 'foo') end
|
|
722
722
|
a.associations[:tags] = []
|
|
723
|
-
a.add_tag(t).
|
|
724
|
-
a.tags.
|
|
723
|
+
a.add_tag(t).must_equal nil
|
|
724
|
+
a.tags.must_equal []
|
|
725
725
|
a.associations[:tags] = [t]
|
|
726
|
-
a.remove_tag(t).
|
|
727
|
-
a.tags.
|
|
726
|
+
a.remove_tag(t).must_equal nil
|
|
727
|
+
a.tags.must_equal [t]
|
|
728
728
|
|
|
729
729
|
t.associations[:artists] = []
|
|
730
|
-
t.add_artist(a).
|
|
731
|
-
t.artists.
|
|
730
|
+
t.add_artist(a).must_equal nil
|
|
731
|
+
t.artists.must_equal []
|
|
732
732
|
t.associations[:artists] = [a]
|
|
733
|
-
t.remove_artist(a).
|
|
734
|
-
t.artists.
|
|
733
|
+
t.remove_artist(a).must_equal nil
|
|
734
|
+
t.artists.must_equal [a]
|
|
735
735
|
end
|
|
736
736
|
end
|