sequel 3.48.0 → 4.0.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 +114 -0
- data/Rakefile +10 -7
- data/doc/association_basics.rdoc +25 -23
- data/doc/code_order.rdoc +7 -0
- data/doc/core_extensions.rdoc +0 -10
- data/doc/object_model.rdoc +4 -1
- data/doc/querying.rdoc +3 -3
- data/doc/release_notes/4.0.0.txt +262 -0
- data/doc/security.rdoc +0 -28
- data/doc/testing.rdoc +8 -14
- data/lib/sequel/adapters/ado.rb +7 -11
- data/lib/sequel/adapters/ado/access.rb +8 -8
- data/lib/sequel/adapters/ado/mssql.rb +4 -4
- data/lib/sequel/adapters/amalgalite.rb +6 -6
- data/lib/sequel/adapters/cubrid.rb +7 -7
- data/lib/sequel/adapters/db2.rb +5 -9
- data/lib/sequel/adapters/dbi.rb +2 -6
- data/lib/sequel/adapters/do.rb +4 -4
- data/lib/sequel/adapters/firebird.rb +4 -4
- data/lib/sequel/adapters/ibmdb.rb +8 -8
- data/lib/sequel/adapters/informix.rb +2 -10
- data/lib/sequel/adapters/jdbc.rb +17 -17
- data/lib/sequel/adapters/jdbc/as400.rb +2 -2
- data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
- data/lib/sequel/adapters/jdbc/db2.rb +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/jdbc/h2.rb +2 -2
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
- data/lib/sequel/adapters/jdbc/informix.rb +1 -1
- data/lib/sequel/adapters/jdbc/mssql.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +5 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -3
- data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
- data/lib/sequel/adapters/jdbc/transactions.rb +3 -3
- data/lib/sequel/adapters/mock.rb +7 -7
- data/lib/sequel/adapters/mysql.rb +3 -3
- data/lib/sequel/adapters/mysql2.rb +4 -4
- data/lib/sequel/adapters/odbc.rb +2 -6
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -5
- data/lib/sequel/adapters/oracle.rb +13 -17
- data/lib/sequel/adapters/postgres.rb +20 -25
- data/lib/sequel/adapters/shared/cubrid.rb +3 -3
- data/lib/sequel/adapters/shared/db2.rb +2 -2
- data/lib/sequel/adapters/shared/firebird.rb +7 -7
- data/lib/sequel/adapters/shared/mssql.rb +9 -9
- data/lib/sequel/adapters/shared/mysql.rb +29 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +7 -7
- data/lib/sequel/adapters/shared/oracle.rb +22 -13
- data/lib/sequel/adapters/shared/postgres.rb +61 -46
- data/lib/sequel/adapters/shared/sqlite.rb +9 -9
- data/lib/sequel/adapters/sqlite.rb +17 -11
- data/lib/sequel/adapters/swift.rb +3 -3
- data/lib/sequel/adapters/swift/mysql.rb +1 -1
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +8 -8
- data/lib/sequel/ast_transformer.rb +3 -1
- data/lib/sequel/connection_pool.rb +4 -2
- data/lib/sequel/connection_pool/sharded_single.rb +2 -2
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -5
- data/lib/sequel/connection_pool/threaded.rb +7 -7
- data/lib/sequel/core.rb +4 -67
- data/lib/sequel/database.rb +1 -0
- data/lib/sequel/database/connecting.rb +2 -8
- data/lib/sequel/database/dataset.rb +2 -7
- data/lib/sequel/database/dataset_defaults.rb +0 -18
- data/lib/sequel/database/features.rb +4 -4
- data/lib/sequel/database/misc.rb +6 -8
- data/lib/sequel/database/query.rb +5 -61
- data/lib/sequel/database/schema_generator.rb +22 -20
- data/lib/sequel/database/schema_methods.rb +48 -20
- data/lib/sequel/database/transactions.rb +7 -17
- data/lib/sequel/dataset.rb +2 -0
- data/lib/sequel/dataset/actions.rb +23 -91
- data/lib/sequel/dataset/features.rb +1 -4
- data/lib/sequel/dataset/graph.rb +3 -47
- data/lib/sequel/dataset/misc.rb +4 -33
- data/lib/sequel/dataset/prepared_statements.rb +3 -1
- data/lib/sequel/dataset/query.rb +116 -240
- data/lib/sequel/dataset/sql.rb +19 -97
- data/lib/sequel/deprecated.rb +0 -16
- data/lib/sequel/exceptions.rb +0 -3
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/columns_introspection.rb +1 -12
- data/lib/sequel/extensions/constraint_validations.rb +3 -3
- data/lib/sequel/extensions/core_extensions.rb +0 -9
- data/lib/sequel/extensions/date_arithmetic.rb +1 -2
- data/lib/sequel/extensions/graph_each.rb +11 -0
- data/lib/sequel/extensions/migration.rb +5 -5
- data/lib/sequel/extensions/null_dataset.rb +11 -13
- data/lib/sequel/extensions/pagination.rb +3 -6
- data/lib/sequel/extensions/pg_array.rb +6 -4
- data/lib/sequel/extensions/pg_array_ops.rb +35 -1
- data/lib/sequel/extensions/pg_json.rb +12 -2
- data/lib/sequel/extensions/pg_json_ops.rb +266 -0
- data/lib/sequel/extensions/pg_range.rb +2 -2
- data/lib/sequel/extensions/pg_range_ops.rb +0 -8
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/pretty_table.rb +0 -4
- data/lib/sequel/extensions/query.rb +3 -8
- data/lib/sequel/extensions/schema_caching.rb +0 -7
- data/lib/sequel/extensions/schema_dumper.rb +10 -17
- data/lib/sequel/extensions/select_remove.rb +0 -4
- data/lib/sequel/extensions/set_overrides.rb +28 -0
- data/lib/sequel/extensions/to_dot.rb +6 -10
- data/lib/sequel/model.rb +6 -7
- data/lib/sequel/model/associations.rb +127 -182
- data/lib/sequel/model/base.rb +88 -211
- data/lib/sequel/model/errors.rb +0 -13
- data/lib/sequel/model/plugins.rb +2 -2
- data/lib/sequel/no_core_ext.rb +0 -1
- data/lib/sequel/plugins/after_initialize.rb +11 -17
- data/lib/sequel/plugins/association_autoreloading.rb +1 -47
- data/lib/sequel/plugins/association_dependencies.rb +2 -2
- data/lib/sequel/plugins/auto_validations.rb +2 -8
- data/lib/sequel/plugins/blacklist_security.rb +32 -2
- data/lib/sequel/plugins/caching.rb +1 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/composition.rb +10 -8
- data/lib/sequel/plugins/constraint_validations.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +4 -0
- data/lib/sequel/plugins/defaults_setter.rb +8 -6
- data/lib/sequel/plugins/dirty.rb +6 -6
- data/lib/sequel/plugins/force_encoding.rb +13 -8
- data/lib/sequel/plugins/hook_class_methods.rb +1 -7
- data/lib/sequel/plugins/json_serializer.rb +13 -74
- data/lib/sequel/plugins/lazy_attributes.rb +2 -4
- data/lib/sequel/plugins/list.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +4 -11
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +1 -49
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +3 -5
- data/lib/sequel/plugins/pg_array_associations.rb +453 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +23 -7
- data/lib/sequel/plugins/prepared_statements.rb +1 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +20 -14
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +5 -4
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +7 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -2
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +19 -4
- data/lib/sequel/plugins/validation_class_methods.rb +0 -30
- data/lib/sequel/plugins/validation_helpers.rb +13 -31
- data/lib/sequel/plugins/xml_serializer.rb +18 -57
- data/lib/sequel/sql.rb +20 -22
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/db2_spec.rb +14 -23
- data/spec/adapters/firebird_spec.rb +25 -29
- data/spec/adapters/informix_spec.rb +11 -14
- data/spec/adapters/mssql_spec.rb +71 -77
- data/spec/adapters/mysql_spec.rb +165 -172
- data/spec/adapters/oracle_spec.rb +36 -39
- data/spec/adapters/postgres_spec.rb +175 -100
- data/spec/adapters/spec_helper.rb +13 -11
- data/spec/adapters/sqlite_spec.rb +36 -44
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +55 -55
- data/spec/core/dataset_spec.rb +45 -249
- data/spec/core/deprecated_spec.rb +0 -8
- data/spec/core/expression_filters_spec.rb +23 -5
- data/spec/core/object_graph_spec.rb +4 -66
- data/spec/core/schema_spec.rb +35 -12
- data/spec/core/spec_helper.rb +3 -2
- data/spec/core_extensions_spec.rb +17 -19
- data/spec/extensions/arbitrary_servers_spec.rb +2 -3
- data/spec/extensions/association_dependencies_spec.rb +14 -14
- data/spec/extensions/auto_validations_spec.rb +7 -0
- data/spec/extensions/blacklist_security_spec.rb +5 -5
- data/spec/extensions/blank_spec.rb +2 -0
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/extensions/columns_introspection_spec.rb +2 -29
- data/spec/extensions/composition_spec.rb +10 -17
- data/spec/extensions/core_refinements_spec.rb +5 -1
- data/spec/extensions/dataset_associations_spec.rb +18 -0
- data/spec/extensions/date_arithmetic_spec.rb +2 -2
- data/spec/extensions/defaults_setter_spec.rb +9 -9
- data/spec/extensions/dirty_spec.rb +0 -5
- data/spec/extensions/eval_inspect_spec.rb +2 -0
- data/spec/extensions/force_encoding_spec.rb +2 -18
- data/spec/extensions/hash_aliases_spec.rb +8 -0
- data/spec/extensions/hook_class_methods_spec.rb +39 -58
- data/spec/extensions/inflector_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +8 -8
- data/spec/extensions/json_serializer_spec.rb +1 -41
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +106 -109
- data/spec/extensions/migration_spec.rb +2 -0
- data/spec/extensions/named_timezones_spec.rb +1 -0
- data/spec/extensions/pg_array_associations_spec.rb +603 -0
- data/spec/extensions/pg_array_ops_spec.rb +25 -0
- data/spec/extensions/pg_array_spec.rb +9 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -0
- data/spec/extensions/pg_hstore_spec.rb +1 -0
- data/spec/extensions/pg_json_ops_spec.rb +131 -0
- data/spec/extensions/pg_json_spec.rb +10 -4
- data/spec/extensions/pg_range_ops_spec.rb +2 -5
- data/spec/extensions/pg_range_spec.rb +6 -2
- data/spec/extensions/pg_row_ops_spec.rb +2 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +26 -5
- data/spec/extensions/rcte_tree_spec.rb +15 -15
- data/spec/extensions/schema_dumper_spec.rb +0 -1
- data/spec/extensions/schema_spec.rb +9 -9
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +18 -29
- data/spec/extensions/set_overrides_spec.rb +4 -0
- data/spec/extensions/{many_to_one_pk_lookup_spec.rb → shared_caching_spec.rb} +1 -4
- data/spec/extensions/single_table_inheritance_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +8 -9
- data/spec/extensions/sql_expr_spec.rb +2 -0
- data/spec/extensions/string_date_time_spec.rb +2 -0
- data/spec/extensions/string_stripper_spec.rb +2 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +12 -12
- data/spec/extensions/thread_local_timezones_spec.rb +2 -0
- data/spec/extensions/timestamps_spec.rb +1 -1
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +24 -24
- data/spec/extensions/tree_spec.rb +7 -7
- data/spec/extensions/typecast_on_load_spec.rb +8 -1
- data/spec/extensions/update_primary_key_spec.rb +10 -10
- data/spec/extensions/validation_class_methods_spec.rb +10 -39
- data/spec/extensions/validation_helpers_spec.rb +29 -47
- data/spec/extensions/xml_serializer_spec.rb +1 -23
- data/spec/integration/associations_test.rb +231 -40
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +64 -64
- data/spec/integration/eager_loader_test.rb +28 -28
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +2 -2
- data/spec/integration/plugin_test.rb +21 -21
- data/spec/integration/prepared_statement_test.rb +7 -7
- data/spec/integration/schema_test.rb +115 -110
- data/spec/integration/spec_helper.rb +17 -27
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +10 -10
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/association_reflection_spec.rb +2 -28
- data/spec/model/associations_spec.rb +239 -188
- data/spec/model/base_spec.rb +27 -68
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +160 -172
- data/spec/model/hooks_spec.rb +62 -79
- data/spec/model/model_spec.rb +36 -51
- data/spec/model/plugins_spec.rb +5 -19
- data/spec/model/record_spec.rb +125 -151
- data/spec/model/spec_helper.rb +8 -6
- data/spec/model/validations_spec.rb +4 -17
- data/spec/spec_config.rb +2 -10
- metadata +50 -56
- data/lib/sequel/deprecated_core_extensions.rb +0 -135
- data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -185
- data/lib/sequel/extensions/pg_statement_cache.rb +0 -318
- data/lib/sequel/plugins/identity_map.rb +0 -260
- data/lib/sequel_core.rb +0 -2
- data/lib/sequel_model.rb +0 -2
- data/spec/extensions/association_autoreloading_spec.rb +0 -102
- data/spec/extensions/identity_map_spec.rb +0 -337
- data/spec/extensions/pg_auto_parameterize_spec.rb +0 -70
- data/spec/extensions/pg_statement_cache_spec.rb +0 -208
- data/spec/rcov.opts +0 -8
- data/spec/spec_config.rb.example +0 -10
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe Sequel::Model, "pg_array_associations" do
|
|
4
|
+
before do
|
|
5
|
+
class ::Artist < Sequel::Model
|
|
6
|
+
attr_accessor :yyy
|
|
7
|
+
columns :id, :tag_ids
|
|
8
|
+
plugin :pg_array_associations
|
|
9
|
+
pg_array_to_many :tags
|
|
10
|
+
end
|
|
11
|
+
class ::Tag < Sequel::Model
|
|
12
|
+
columns :id
|
|
13
|
+
plugin :pg_array_associations
|
|
14
|
+
many_to_pg_array :artists
|
|
15
|
+
def id3
|
|
16
|
+
id*3
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
@c1 = Artist
|
|
20
|
+
@c2 = Tag
|
|
21
|
+
@c1.dataset._fetch = {:id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
22
|
+
@c2.dataset._fetch = {:id=>2}
|
|
23
|
+
@o1 = @c1.first
|
|
24
|
+
@o2 = @c2.first
|
|
25
|
+
@n1 = @c1.new
|
|
26
|
+
@n2 = @c2.new
|
|
27
|
+
DB.reset
|
|
28
|
+
end
|
|
29
|
+
after do
|
|
30
|
+
Object.send(:remove_const, :Artist)
|
|
31
|
+
Object.send(:remove_const, :Tag)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should populate :key_hash and :id_map option correctly for custom eager loaders" do
|
|
35
|
+
khs = []
|
|
36
|
+
pr = proc{|h| khs << [h[:key_hash], h[:id_map]]}
|
|
37
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :eager_loader=>pr
|
|
38
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :eager_loader=>pr
|
|
39
|
+
@c1.eager(:tags).all
|
|
40
|
+
@c2.eager(:artists).all
|
|
41
|
+
khs.should == [[{}, nil], [{:id=>{2=>[Tag.load(:id=>2)]}}, {2=>[Tag.load(:id=>2)]}]]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should not issue queries if the object cannot have associated objects" do
|
|
45
|
+
@n1.tags.should == []
|
|
46
|
+
@c1.load(:tag_ids=>[]).tags.should == []
|
|
47
|
+
@n2.artists.should == []
|
|
48
|
+
DB.sqls.should == []
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should use correct SQL when loading associations lazily" do
|
|
52
|
+
@o1.tags.should == [@o2]
|
|
53
|
+
@o2.artists.should == [@o1]
|
|
54
|
+
DB.sqls.should == ["SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))", "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2])"]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should accept :primary_key option for primary keys to use in current and associated table" do
|
|
58
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel./(:id, 3)
|
|
59
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3
|
|
60
|
+
@o1.tags_dataset.sql.should == "SELECT * FROM tags WHERE ((tags.id / 3) IN (1, 2, 3))"
|
|
61
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[6])"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should allowing filtering by associations" do
|
|
65
|
+
@c1.filter(:tags=>@o2).sql.should == "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2])"
|
|
66
|
+
@c2.filter(:artists=>@o1).sql.should == "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should allowing excluding by associations" do
|
|
70
|
+
@c1.exclude(:tags=>@o2).sql.should == "SELECT * FROM artists WHERE (NOT (artists.tag_ids @> ARRAY[2]) OR (artists.tag_ids IS NULL))"
|
|
71
|
+
@c2.exclude(:artists=>@o1).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (1, 2, 3)) OR (tags.id IS NULL))"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should allowing filtering by multiple associations" do
|
|
75
|
+
@c1.filter(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.should == "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[1,2])"
|
|
76
|
+
@c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.should == "SELECT * FROM tags WHERE (tags.id IN (3, 4, 5))"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should allowing excluding by multiple associations" do
|
|
80
|
+
@c1.exclude(:tags=>[@c2.load(:id=>1), @c2.load(:id=>2)]).sql.should == "SELECT * FROM artists WHERE (NOT (artists.tag_ids && ARRAY[1,2]) OR (artists.tag_ids IS NULL))"
|
|
81
|
+
@c2.exclude(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.load(:tag_ids=>Sequel.pg_array([4, 5]))]).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (3, 4, 5)) OR (tags.id IS NULL))"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should allowing filtering/excluding associations with NULL or empty values" do
|
|
85
|
+
@c1.filter(:tags=>@c2.new).sql.should == 'SELECT * FROM artists WHERE \'f\''
|
|
86
|
+
@c1.exclude(:tags=>@c2.new).sql.should == 'SELECT * FROM artists WHERE \'t\''
|
|
87
|
+
@c2.filter(:artists=>@c1.new).sql.should == 'SELECT * FROM tags WHERE \'f\''
|
|
88
|
+
@c2.exclude(:artists=>@c1.new).sql.should == 'SELECT * FROM tags WHERE \'t\''
|
|
89
|
+
|
|
90
|
+
@c2.filter(:artists=>@c1.load(:tag_ids=>[])).sql.should == 'SELECT * FROM tags WHERE \'f\''
|
|
91
|
+
@c2.exclude(:artists=>@c1.load(:tag_ids=>[])).sql.should == 'SELECT * FROM tags WHERE \'t\''
|
|
92
|
+
|
|
93
|
+
@c1.filter(:tags=>[@c2.new, @c2.load(:id=>2)]).sql.should == "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2])"
|
|
94
|
+
@c2.filter(:artists=>[@c1.load(:tag_ids=>Sequel.pg_array([3, 4])), @c1.new]).sql.should == "SELECT * FROM tags WHERE (tags.id IN (3, 4))"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "should allowing filtering by association datasets" do
|
|
98
|
+
@c1.filter(:tags=>@c2.where(:id=>1)).sql.should == "SELECT * FROM artists WHERE coalesce((artists.tag_ids && (SELECT array_agg(tags.id) FROM tags WHERE (id = 1))), 'f')"
|
|
99
|
+
@c2.filter(:artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE (tags.id IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1)))"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should allowing excluding by association datasets" do
|
|
103
|
+
@c1.exclude(:tags=>@c2.where(:id=>1)).sql.should == "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))"
|
|
104
|
+
@c2.exclude(:artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE ((tags.id NOT IN (SELECT unnest(artists.tag_ids) FROM artists WHERE (id = 1))) OR (tags.id IS NULL))"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "filter by associations should respect key options" do
|
|
108
|
+
@c1.class_eval{def tag3_ids; tag_ids.map{|x| x*3} end}
|
|
109
|
+
@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]
|
|
110
|
+
@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]
|
|
111
|
+
|
|
112
|
+
@c1.filter(:tags=>@o2).sql.should == "SELECT * FROM artists WHERE (artists.tag_ids[1:2] @> ARRAY[6])"
|
|
113
|
+
@c2.filter(:artists=>@o1).sql.should == "SELECT * FROM tags WHERE ((tags.id * 3) IN (3, 6, 9))"
|
|
114
|
+
@c1.filter(:tags=>@c2.where(:id=>1)).sql.should == "SELECT * FROM artists WHERE coalesce((artists.tag_ids[1:2] && (SELECT array_agg((tags.id * 3)) FROM tags WHERE (id = 1))), 'f')"
|
|
115
|
+
@c2.filter(:artists=>@c1.where(:id=>1)).sql.should == "SELECT * FROM tags WHERE ((tags.id * 3) IN (SELECT unnest(artists.tag_ids[1:2]) FROM artists WHERE (id = 1)))"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should support a :key option" do
|
|
119
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :key=>:tag2_ids
|
|
120
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :key=>:tag2_ids
|
|
121
|
+
@c1.class_eval{def tag2_ids; tag_ids.map{|x| x * 2} end}
|
|
122
|
+
@o1.tags_dataset.sql.should == "SELECT * FROM tags WHERE (tags.id IN (2, 4, 6))"
|
|
123
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE (artists.tag2_ids @> ARRAY[2])"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "should support a :key_column option" do
|
|
127
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :key_column=>Sequel.pg_array(:tag_ids)[1..2], :key=>:tag2_ids
|
|
128
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE (artists.tag_ids[1:2] @> ARRAY[2])"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "should support a :primary_key option" do
|
|
132
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>:id2
|
|
133
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id2
|
|
134
|
+
@o1.tags_dataset.sql.should == "SELECT * FROM tags WHERE (tags.id2 IN (1, 2, 3))"
|
|
135
|
+
@c2.class_eval{def id2; id*2 end}
|
|
136
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[4])"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should support a :conditions option" do
|
|
140
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :conditions=>{:a=>1}
|
|
141
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :conditions=>{:a=>1}
|
|
142
|
+
@o1.tags_dataset.sql.should == "SELECT * FROM tags WHERE ((a = 1) AND (tags.id IN (1, 2, 3)))"
|
|
143
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE ((a = 1) AND (artists.tag_ids @> ARRAY[2]))"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should support an :order option" do
|
|
147
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :order=>[:a, :b]
|
|
148
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :order=>[:a, :b]
|
|
149
|
+
@o1.tags_dataset.sql.should == "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3)) ORDER BY a, b"
|
|
150
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]) ORDER BY a, b"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should support a select option" do
|
|
154
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :select=>[:a, :b]
|
|
155
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :select=>[:a, :b]
|
|
156
|
+
@c1.load(:tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.should == "SELECT a, b FROM tags WHERE (tags.id IN (1, 2, 3))"
|
|
157
|
+
@c2.load(:id=>1).artists_dataset.sql.should == "SELECT a, b FROM artists WHERE (artists.tag_ids @> ARRAY[1])"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "should accept a block" do
|
|
161
|
+
@c1.pg_array_to_many :tags, :clone=>:tags do |ds| ds.filter(:yyy=>@yyy) end
|
|
162
|
+
@c2.many_to_pg_array :artists, :clone=>:artists do |ds| ds.filter(:a=>1) end
|
|
163
|
+
@c1.new(:yyy=>6, :tag_ids=>Sequel.pg_array([1,2,3])).tags_dataset.sql.should == "SELECT * FROM tags WHERE ((tags.id IN (1, 2, 3)) AND (yyy = 6))"
|
|
164
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE ((artists.tag_ids @> ARRAY[2]) AND (a = 1))"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "should support a :dataset option that is used instead of the default" do
|
|
168
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :dataset=>proc{Tag.where(:id=>tag_ids.map{|x| x*2})}
|
|
169
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :dataset=>proc{Artist.where(Sequel.pg_array(Sequel.pg_array(:tag_ids)[1..2]).contains([id]))}
|
|
170
|
+
@o1.tags_dataset.sql.should == "SELECT * FROM tags WHERE (id IN (2, 4, 6))"
|
|
171
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE (tag_ids[1:2] @> ARRAY[2])"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "should support a :limit option" do
|
|
175
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[2, 3]
|
|
176
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[3, 2]
|
|
177
|
+
@o1.tags_dataset.sql.should == "SELECT * FROM tags WHERE (tags.id IN (1, 2, 3)) LIMIT 2 OFFSET 3"
|
|
178
|
+
@o2.artists_dataset.sql.should == "SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2]) LIMIT 3 OFFSET 2"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "should support a :uniq option that removes duplicates from the association" do
|
|
182
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :uniq=>true
|
|
183
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :uniq=>true
|
|
184
|
+
@c1.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
|
185
|
+
@c2.dataset._fetch = [{:id=>20}, {:id=>30}, {:id=>20}, {:id=>30}]
|
|
186
|
+
@o1.tags.should == [@c2.load(:id=>20), @c2.load(:id=>30)]
|
|
187
|
+
@o2.artists.should == [@c1.load(:id=>20), @c1.load(:id=>30)]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "reflection associated_object_keys should return correct values" do
|
|
191
|
+
@c1.association_reflection(:tags).associated_object_keys.should == [:id]
|
|
192
|
+
@c2.association_reflection(:artists).associated_object_keys.should == [:tag_ids]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "reflection remove_before_destroy? should return correct values" do
|
|
196
|
+
@c1.association_reflection(:tags).remove_before_destroy?.should be_true
|
|
197
|
+
@c2.association_reflection(:artists).remove_before_destroy?.should be_false
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "reflection reciprocal should be correct" do
|
|
201
|
+
@c1.association_reflection(:tags).reciprocal.should == :artists
|
|
202
|
+
@c2.association_reflection(:artists).reciprocal.should == :tags
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "should eagerly load correctly" do
|
|
206
|
+
a = @c1.eager(:tags).all
|
|
207
|
+
a.should == [@o1]
|
|
208
|
+
sqls = DB.sqls
|
|
209
|
+
sqls.pop.should =~ /SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/
|
|
210
|
+
sqls.should == ["SELECT * FROM artists"]
|
|
211
|
+
a.first.tags.should == [@o2]
|
|
212
|
+
DB.sqls.should == []
|
|
213
|
+
|
|
214
|
+
a = @c2.eager(:artists).all
|
|
215
|
+
a.should == [@o2]
|
|
216
|
+
DB.sqls.should == ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2])"]
|
|
217
|
+
a.first.artists.should == [@o1]
|
|
218
|
+
DB.sqls.should == []
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "should support using custom key options when eager loading associations" do
|
|
222
|
+
@c1.class_eval{def tag3_ids; tag_ids.map{|x| x*3} end}
|
|
223
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :primary_key=>Sequel.*(:id, 3), :primary_key_method=>:id3, :key=>:tag3_ids
|
|
224
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
|
|
225
|
+
|
|
226
|
+
a = @c1.eager(:tags).all
|
|
227
|
+
a.should == [@o1]
|
|
228
|
+
sqls = DB.sqls
|
|
229
|
+
sqls.pop.should =~ /SELECT \* FROM tags WHERE \(\(tags\.id \* 3\) IN \([369], [369], [369]\)\)/
|
|
230
|
+
sqls.should == ["SELECT * FROM artists"]
|
|
231
|
+
a.first.tags.should == [@o2]
|
|
232
|
+
DB.sqls.should == []
|
|
233
|
+
|
|
234
|
+
a = @c2.eager(:artists).all
|
|
235
|
+
a.should == [@o2]
|
|
236
|
+
DB.sqls.should == ["SELECT * FROM tags", "SELECT * FROM artists WHERE (artists.tag_ids[1:2] && ARRAY[6])"]
|
|
237
|
+
a.first.artists.should == [@o1]
|
|
238
|
+
DB.sqls.should == []
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it "should allow cascading of eager loading for associations of associated models" do
|
|
242
|
+
a = @c1.eager(:tags=>:artists).all
|
|
243
|
+
a.should == [@o1]
|
|
244
|
+
sqls = DB.sqls
|
|
245
|
+
sqls.slice!(1).should =~ /SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/
|
|
246
|
+
sqls.should == ['SELECT * FROM artists', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2])"]
|
|
247
|
+
a.first.tags.should == [@o2]
|
|
248
|
+
a.first.tags.first.artists.should == [@o1]
|
|
249
|
+
DB.sqls.should == []
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it "should respect :eager when lazily loading an association" do
|
|
253
|
+
@c1.pg_array_to_many :tags2, :clone=>:tags, :eager=>:artists, :key=>:tag_ids
|
|
254
|
+
@c2.many_to_pg_array :artists2, :clone=>:artists, :eager=>:tags
|
|
255
|
+
|
|
256
|
+
@o1.tags2.should == [@o2]
|
|
257
|
+
DB.sqls.should == ["SELECT * FROM tags WHERE (tags.id IN (1, 2, 3))", "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2])"]
|
|
258
|
+
@o1.tags2.first.artists.should == [@o1]
|
|
259
|
+
DB.sqls.should == []
|
|
260
|
+
|
|
261
|
+
@o2.artists2.should == [@o1]
|
|
262
|
+
sqls = DB.sqls
|
|
263
|
+
sqls.pop.should =~ /SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/
|
|
264
|
+
sqls.should == ["SELECT * FROM artists WHERE (artists.tag_ids @> ARRAY[2])"]
|
|
265
|
+
@o2.artists2.first.tags.should == [@o2]
|
|
266
|
+
DB.sqls.should == []
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "should cascade eagerly loading when the :eager_graph association option is used" do
|
|
270
|
+
@c1.pg_array_to_many :tags2, :clone=>:tags, :eager_graph=>:artists, :key=>:tag_ids
|
|
271
|
+
@c2.many_to_pg_array :artists2, :clone=>:artists, :eager_graph=>:tags
|
|
272
|
+
|
|
273
|
+
@c2.dataset._fetch = {:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
274
|
+
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
275
|
+
|
|
276
|
+
@o1.tags2.should == [@o2]
|
|
277
|
+
DB.sqls.first.should =~ /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]\)\)/
|
|
278
|
+
@o1.tags2.first.artists.should == [@o1]
|
|
279
|
+
DB.sqls.should == []
|
|
280
|
+
|
|
281
|
+
@o2.artists2.should == [@o1]
|
|
282
|
+
DB.sqls.should == ["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])"]
|
|
283
|
+
@o2.artists2.first.tags.should == [@o2]
|
|
284
|
+
DB.sqls.should == []
|
|
285
|
+
|
|
286
|
+
@c2.dataset._fetch = {:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
287
|
+
@c1.dataset._fetch = {:id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
288
|
+
|
|
289
|
+
a = @c1.eager(:tags2).all
|
|
290
|
+
sqls = DB.sqls
|
|
291
|
+
sqls.pop.should =~ /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]\)\)/
|
|
292
|
+
sqls.should == ["SELECT * FROM artists"]
|
|
293
|
+
a.should == [@o1]
|
|
294
|
+
a.first.tags2.should == [@o2]
|
|
295
|
+
a.first.tags2.first.artists.should == [@o1]
|
|
296
|
+
DB.sqls.should == []
|
|
297
|
+
|
|
298
|
+
@c2.dataset._fetch = {:id=>2}
|
|
299
|
+
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
300
|
+
|
|
301
|
+
a = @c2.eager(:artists2).all
|
|
302
|
+
DB.sqls.should == ["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])"]
|
|
303
|
+
a.should == [@o2]
|
|
304
|
+
a.first.artists2.should == [@o1]
|
|
305
|
+
a.first.artists2.first.tags.should == [@o2]
|
|
306
|
+
DB.sqls.should == []
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
it "should respect the :limit option when eager loading" do
|
|
310
|
+
@c2.dataset._fetch = [{:id=>1},{:id=>2}, {:id=>3}]
|
|
311
|
+
|
|
312
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>2
|
|
313
|
+
a = @c1.eager(:tags).all
|
|
314
|
+
a.should == [@o1]
|
|
315
|
+
sqls = DB.sqls
|
|
316
|
+
sqls.pop.should =~ /SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/
|
|
317
|
+
sqls.should == ["SELECT * FROM artists"]
|
|
318
|
+
a.first.tags.should == [@c2.load(:id=>1), @c2.load(:id=>2)]
|
|
319
|
+
DB.sqls.should == []
|
|
320
|
+
|
|
321
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[1, 1]
|
|
322
|
+
a = @c1.eager(:tags).all
|
|
323
|
+
a.should == [@o1]
|
|
324
|
+
sqls = DB.sqls
|
|
325
|
+
sqls.pop.should =~ /SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/
|
|
326
|
+
sqls.should == ["SELECT * FROM artists"]
|
|
327
|
+
a.first.tags.should == [@c2.load(:id=>2)]
|
|
328
|
+
DB.sqls.should == []
|
|
329
|
+
|
|
330
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :limit=>[nil, 1]
|
|
331
|
+
a = @c1.eager(:tags).all
|
|
332
|
+
a.should == [@o1]
|
|
333
|
+
sqls = DB.sqls
|
|
334
|
+
sqls.pop.should =~ /SELECT \* FROM tags WHERE \(tags\.id IN \([123], [123], [123]\)\)/
|
|
335
|
+
sqls.should == ["SELECT * FROM artists"]
|
|
336
|
+
a.first.tags.should == [@c2.load(:id=>2), @c2.load(:id=>3)]
|
|
337
|
+
DB.sqls.length.should == 0
|
|
338
|
+
|
|
339
|
+
@c2.dataset._fetch = [{:id=>2}]
|
|
340
|
+
@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])}]
|
|
341
|
+
|
|
342
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>2
|
|
343
|
+
a = @c2.eager(:artists).all
|
|
344
|
+
a.should == [@o2]
|
|
345
|
+
DB.sqls.should == ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2])"]
|
|
346
|
+
a.first.artists.should == [@c1.load(:id=>5, :tag_ids=>Sequel.pg_array([1,2,3])), @c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3]))]
|
|
347
|
+
DB.sqls.should == []
|
|
348
|
+
|
|
349
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[1, 1]
|
|
350
|
+
a = @c2.eager(:artists).all
|
|
351
|
+
a.should == [@o2]
|
|
352
|
+
DB.sqls.should == ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2])"]
|
|
353
|
+
a.first.artists.should == [@c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3]))]
|
|
354
|
+
DB.sqls.should == []
|
|
355
|
+
|
|
356
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :limit=>[nil, 1]
|
|
357
|
+
a = @c2.eager(:artists).all
|
|
358
|
+
a.should == [@o2]
|
|
359
|
+
DB.sqls.should == ['SELECT * FROM tags', "SELECT * FROM artists WHERE (artists.tag_ids && ARRAY[2])"]
|
|
360
|
+
a.first.artists.should == [@c1.load(:id=>6, :tag_ids=>Sequel.pg_array([2,3])), @c1.load(:id=>7, :tag_ids=>Sequel.pg_array([1,2]))]
|
|
361
|
+
DB.sqls.should == []
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
it "should eagerly graph associations" do
|
|
365
|
+
@c2.dataset._fetch = {:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
366
|
+
@c1.dataset._fetch = {:id=>1, :tags_id=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
367
|
+
|
|
368
|
+
a = @c1.eager_graph(:tags).all
|
|
369
|
+
DB.sqls.should == ["SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
370
|
+
a.should == [@o1]
|
|
371
|
+
a.first.tags.should == [@o2]
|
|
372
|
+
DB.sqls.should == []
|
|
373
|
+
|
|
374
|
+
a = @c2.eager_graph(:artists).all
|
|
375
|
+
DB.sqls.should == ["SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
376
|
+
a.should == [@o2]
|
|
377
|
+
a.first.artists.should == [@o1]
|
|
378
|
+
DB.sqls.should == []
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
it "should allow cascading of eager graphing for associations of associated models" do
|
|
382
|
+
@c2.dataset._fetch = {:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3]), :tags_0_id=>2}
|
|
383
|
+
@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])}
|
|
384
|
+
|
|
385
|
+
a = @c1.eager_graph(:tags=>:artists).all
|
|
386
|
+
DB.sqls.should == ["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])"]
|
|
387
|
+
a.should == [@o1]
|
|
388
|
+
a.first.tags.should == [@o2]
|
|
389
|
+
a.first.tags.first.artists.should == [@o1]
|
|
390
|
+
DB.sqls.should == []
|
|
391
|
+
|
|
392
|
+
a = @c2.eager_graph(:artists=>:tags).all
|
|
393
|
+
DB.sqls.should == ["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])"]
|
|
394
|
+
a.should == [@o2]
|
|
395
|
+
a.first.artists.should == [@o1]
|
|
396
|
+
a.first.artists.first.tags.should == [@o2]
|
|
397
|
+
DB.sqls.should == []
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it "eager graphing should respect key options" do
|
|
401
|
+
@c1.class_eval{def tag3_ids; tag_ids.map{|x| x*3} end}
|
|
402
|
+
@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]
|
|
403
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :primary_key=>:id3, :key=>:tag3_ids, :key_column=>Sequel.pg_array(:tag_ids)[1..2]
|
|
404
|
+
|
|
405
|
+
@c2.dataset._fetch = {:id=>2, :artists_id=>1, :tag_ids=>Sequel.pg_array([1,2,3]), :tags_0_id=>2}
|
|
406
|
+
@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])}
|
|
407
|
+
|
|
408
|
+
a = @c1.eager_graph(:tags).all
|
|
409
|
+
a.should == [@o1]
|
|
410
|
+
DB.sqls.should == ["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)])"]
|
|
411
|
+
a.first.tags.should == [@o2]
|
|
412
|
+
DB.sqls.should == []
|
|
413
|
+
|
|
414
|
+
a = @c2.eager_graph(:artists).all
|
|
415
|
+
a.should == [@o2]
|
|
416
|
+
DB.sqls.should == ["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])"]
|
|
417
|
+
a.first.artists.should == [@o1]
|
|
418
|
+
DB.sqls.should == []
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
it "should respect the association's :graph_select option" do
|
|
422
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_select=>:id2
|
|
423
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_select=>:id
|
|
424
|
+
|
|
425
|
+
@c2.dataset._fetch = {:id=>2, :artists_id=>1}
|
|
426
|
+
@c1.dataset._fetch = {:id=>1, :id2=>2, :tag_ids=>Sequel.pg_array([1,2,3])}
|
|
427
|
+
|
|
428
|
+
a = @c1.eager_graph(:tags).all
|
|
429
|
+
DB.sqls.should == ["SELECT artists.id, artists.tag_ids, tags.id2 FROM artists LEFT OUTER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
430
|
+
a.should == [@o1]
|
|
431
|
+
a.first.tags.should == [@c2.load(:id2=>2)]
|
|
432
|
+
DB.sqls.should == []
|
|
433
|
+
|
|
434
|
+
a = @c2.eager_graph(:artists).all
|
|
435
|
+
DB.sqls.should == ["SELECT tags.id, artists.id AS artists_id FROM tags LEFT OUTER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"]
|
|
436
|
+
a.should == [@o2]
|
|
437
|
+
a.first.artists.should == [@c1.load(:id=>1)]
|
|
438
|
+
DB.sqls.should == []
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it "should respect the association's :graph_join_type option" do
|
|
442
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_join_type=>:inner
|
|
443
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_join_type=>:inner
|
|
444
|
+
@c1.eager_graph(:tags).sql.should == "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists INNER JOIN tags ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
445
|
+
@c2.eager_graph(:artists).sql.should == "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags INNER JOIN artists ON (artists.tag_ids @> ARRAY[tags.id])"
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
it "should respect the association's :conditions option" do
|
|
449
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :conditions=>{:a=>1}
|
|
450
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :conditions=>{:a=>1}
|
|
451
|
+
@c1.eager_graph(:tags).sql.should == "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]))"
|
|
452
|
+
@c2.eager_graph(:artists).sql.should == "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]))"
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
it "should respect the association's :graph_conditions option" do
|
|
456
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_conditions=>{:a=>1}
|
|
457
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_conditions=>{:a=>1}
|
|
458
|
+
@c1.eager_graph(:tags).sql.should == "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]))"
|
|
459
|
+
@c2.eager_graph(:artists).sql.should == "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]))"
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
it "should respect the association's :graph_block option" do
|
|
463
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(ja, :a)=>1}}
|
|
464
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(ja, :a)=>1}}
|
|
465
|
+
@c1.eager_graph(:tags).sql.should == "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]))"
|
|
466
|
+
@c2.eager_graph(:artists).sql.should == "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]))"
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it "should respect the association's :graph_only_conditions option" do
|
|
470
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_only_conditions=>{:a=>1}
|
|
471
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_only_conditions=>{:a=>1}
|
|
472
|
+
@c1.eager_graph(:tags).sql.should == "SELECT artists.id, artists.tag_ids, tags.id AS tags_id FROM artists LEFT OUTER JOIN tags ON (tags.a = 1)"
|
|
473
|
+
@c2.eager_graph(:artists).sql.should == "SELECT tags.id, artists.id AS artists_id, artists.tag_ids FROM tags LEFT OUTER JOIN artists ON (artists.a = 1)"
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
it "should respect the association's :graph_only_conditions with :graph_block option" do
|
|
477
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :graph_only_conditions=>{:a=>1}, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(lja, :b)=>1}}
|
|
478
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :graph_only_conditions=>{:a=>1}, :graph_block=>proc{|ja,lja,js| {Sequel.qualify(lja, :b)=>1}}
|
|
479
|
+
@c1.eager_graph(:tags).sql.should == "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))"
|
|
480
|
+
@c2.eager_graph(:artists).sql.should == "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))"
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
it "should define an add_ method for adding associated objects" do
|
|
484
|
+
@o1.add_tag(@c2.load(:id=>4))
|
|
485
|
+
@o1.tag_ids.should == [1,2,3,4]
|
|
486
|
+
DB.sqls.should == []
|
|
487
|
+
@o1.save_changes
|
|
488
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[1,2,3,4] WHERE (id = 1)"]
|
|
489
|
+
|
|
490
|
+
@o2.add_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([4])))
|
|
491
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[4,2] WHERE (id = 1)"]
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it "should define a remove_ method for removing associated objects" do
|
|
495
|
+
@o1.remove_tag(@o2)
|
|
496
|
+
@o1.tag_ids.should == [1,3]
|
|
497
|
+
DB.sqls.should == []
|
|
498
|
+
@o1.save_changes
|
|
499
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[1,3] WHERE (id = 1)"]
|
|
500
|
+
|
|
501
|
+
@o2.remove_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([1,2,3,4])))
|
|
502
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[1,3,4] WHERE (id = 1)"]
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
it "should define a remove_all_ method for removing all associated objects" do
|
|
506
|
+
@o1.remove_all_tags
|
|
507
|
+
@o1.tag_ids.should == []
|
|
508
|
+
DB.sqls.should == []
|
|
509
|
+
@o1.save_changes
|
|
510
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[] WHERE (id = 1)"]
|
|
511
|
+
|
|
512
|
+
@o2.remove_all_artists
|
|
513
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = array_remove(tag_ids, 2) WHERE (tag_ids @> ARRAY[2])"]
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
it "should have pg_array_to_many association modification methods save if :save_after_modify option is used" do
|
|
517
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :save_after_modify=>true
|
|
518
|
+
|
|
519
|
+
@o1.add_tag(@c2.load(:id=>4))
|
|
520
|
+
@o1.tag_ids.should == [1,2,3,4]
|
|
521
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[1,2,3,4] WHERE (id = 1)"]
|
|
522
|
+
|
|
523
|
+
@o1.remove_tag(@o2)
|
|
524
|
+
@o1.tag_ids.should == [1,3,4]
|
|
525
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[1,3,4] WHERE (id = 1)"]
|
|
526
|
+
|
|
527
|
+
@o1.remove_all_tags
|
|
528
|
+
@o1.tag_ids.should == []
|
|
529
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[] WHERE (id = 1)"]
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
it "should have association modification methods deal with nil values" do
|
|
533
|
+
v = @c1.load(:id=>1)
|
|
534
|
+
v.add_tag(@c2.load(:id=>4))
|
|
535
|
+
v.tag_ids.should == [4]
|
|
536
|
+
DB.sqls.should == []
|
|
537
|
+
v.save_changes
|
|
538
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[4]::integer[] WHERE (id = 1)"]
|
|
539
|
+
|
|
540
|
+
@o2.add_artist(@c1.load(:id=>1))
|
|
541
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[2]::integer[] WHERE (id = 1)"]
|
|
542
|
+
|
|
543
|
+
v = @c1.load(:id=>1)
|
|
544
|
+
v.remove_tag(@c2.load(:id=>4))
|
|
545
|
+
v.tag_ids.should == nil
|
|
546
|
+
DB.sqls.should == []
|
|
547
|
+
v.save_changes
|
|
548
|
+
DB.sqls.should == []
|
|
549
|
+
|
|
550
|
+
@o2.remove_artist(@c1.load(:id=>1))
|
|
551
|
+
DB.sqls.should == []
|
|
552
|
+
|
|
553
|
+
v = @c1.load(:id=>1)
|
|
554
|
+
v.remove_all_tags
|
|
555
|
+
v.tag_ids.should == nil
|
|
556
|
+
DB.sqls.should == []
|
|
557
|
+
v.save_changes
|
|
558
|
+
DB.sqls.should == []
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
it "should have association modification methods deal with empty arrays values" do
|
|
562
|
+
v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
|
|
563
|
+
v.add_tag(@c2.load(:id=>4))
|
|
564
|
+
v.tag_ids.should == [4]
|
|
565
|
+
DB.sqls.should == []
|
|
566
|
+
v.save_changes
|
|
567
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[4] WHERE (id = 1)"]
|
|
568
|
+
|
|
569
|
+
@o2.add_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([])))
|
|
570
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[2] WHERE (id = 1)"]
|
|
571
|
+
|
|
572
|
+
v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
|
|
573
|
+
v.remove_tag(@c2.load(:id=>4))
|
|
574
|
+
v.tag_ids.should == []
|
|
575
|
+
DB.sqls.should == []
|
|
576
|
+
v.save_changes
|
|
577
|
+
DB.sqls.should == []
|
|
578
|
+
|
|
579
|
+
@o2.remove_artist(@c1.load(:id=>1, :tag_ids=>Sequel.pg_array([])))
|
|
580
|
+
DB.sqls.should == []
|
|
581
|
+
|
|
582
|
+
v = @c1.load(:id=>1, :tag_ids=>Sequel.pg_array([]))
|
|
583
|
+
v.remove_all_tags
|
|
584
|
+
v.tag_ids.should == []
|
|
585
|
+
DB.sqls.should == []
|
|
586
|
+
v.save_changes
|
|
587
|
+
DB.sqls.should == []
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
it "should respect the :array_type option when manually creating arrays" do
|
|
591
|
+
@c1.pg_array_to_many :tags, :clone=>:tags, :array_type=>:int8
|
|
592
|
+
@c2.many_to_pg_array :artists, :clone=>:artists, :array_type=>:int8
|
|
593
|
+
v = @c1.load(:id=>1)
|
|
594
|
+
v.add_tag(@c2.load(:id=>4))
|
|
595
|
+
v.tag_ids.should == [4]
|
|
596
|
+
DB.sqls.should == []
|
|
597
|
+
v.save_changes
|
|
598
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[4]::int8[] WHERE (id = 1)"]
|
|
599
|
+
|
|
600
|
+
@o2.add_artist(@c1.load(:id=>1))
|
|
601
|
+
DB.sqls.should == ["UPDATE artists SET tag_ids = ARRAY[2]::int8[] WHERE (id = 1)"]
|
|
602
|
+
end
|
|
603
|
+
end
|