sequel 3.21.0 → 3.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +855 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -7
- data/Rakefile +42 -24
- data/bin/sequel +26 -8
- data/doc/active_record.rdoc +1 -0
- data/doc/advanced_associations.rdoc +171 -11
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +85 -552
- data/doc/model_hooks.rdoc +78 -27
- data/doc/object_model.rdoc +541 -0
- data/doc/opening_databases.rdoc +97 -50
- data/doc/prepared_statements.rdoc +40 -14
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +30 -4
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/schema_modification.rdoc +572 -0
- data/doc/sharding.rdoc +95 -3
- data/doc/testing.rdoc +129 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +51 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +1 -57
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +47 -0
- data/lib/sequel/adapters/jdbc/derby.rb +287 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +265 -94
- data/lib/sequel/adapters/mock.rb +361 -0
- data/lib/sequel/adapters/mysql.rb +118 -222
- data/lib/sequel/adapters/mysql2.rb +58 -57
- data/lib/sequel/adapters/odbc/mssql.rb +15 -7
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +356 -107
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +342 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +335 -118
- data/lib/sequel/adapters/shared/mysql.rb +340 -76
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +243 -45
- data/lib/sequel/adapters/shared/postgres.rb +524 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +265 -89
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +9 -12
- data/lib/sequel/adapters/swift/postgres.rb +9 -74
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +8 -7
- data/lib/sequel/adapters/tinytds.rb +161 -21
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +38 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +118 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +150 -46
- data/lib/sequel/database/query.rb +215 -65
- data/lib/sequel/database/schema_generator.rb +64 -20
- data/lib/sequel/database/schema_methods.rb +212 -54
- data/lib/sequel/dataset/actions.rb +322 -85
- data/lib/sequel/dataset/features.rb +96 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +237 -44
- data/lib/sequel/dataset/sql.rb +698 -278
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
- data/lib/sequel/extensions/migration.rb +97 -11
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_inet.rb +89 -0
- data/lib/sequel/extensions/pg_json.rb +178 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +251 -37
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/server_block.rb +139 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1187 -393
- data/lib/sequel/model/base.rb +578 -170
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +123 -8
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +12 -2
- data/lib/sequel/plugins/many_through_many.rb +79 -28
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +139 -63
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/schema.rb +7 -2
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +10 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +526 -59
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +142 -40
- data/spec/adapters/mysql_spec.rb +380 -234
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +1050 -212
- data/spec/adapters/spec_helper.rb +8 -5
- data/spec/adapters/sqlite_spec.rb +139 -27
- data/spec/core/connection_pool_spec.rb +196 -93
- data/spec/core/database_spec.rb +879 -510
- data/spec/core/dataset_spec.rb +1415 -1086
- data/spec/core/expression_filters_spec.rb +554 -109
- data/spec/core/mock_adapter_spec.rb +449 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +482 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +69 -92
- data/spec/extensions/identity_map_spec.rb +131 -22
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -6
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +48 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +251 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_inet_spec.rb +44 -0
- data/spec/extensions/pg_json_spec.rb +101 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +429 -22
- data/spec/extensions/schema_spec.rb +25 -21
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +85 -43
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +22 -61
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +9 -3
- data/spec/integration/dataset_test.rb +605 -91
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +454 -143
- data/spec/integration/prepared_statement_test.rb +263 -128
- data/spec/integration/schema_test.rb +309 -43
- data/spec/integration/spec_helper.rb +40 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +18 -4
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +1067 -661
- data/spec/model/base_spec.rb +329 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +240 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +490 -232
- data/spec/model/spec_helper.rb +14 -71
- data/spec/model/validations_spec.rb +11 -0
- data/spec/rcov.opts +2 -0
- metadata +178 -80
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
3
|
describe Sequel::Model, "#eager" do
|
|
4
|
-
before
|
|
5
|
-
MODEL_DB.reset
|
|
6
|
-
|
|
4
|
+
before do
|
|
7
5
|
class ::EagerAlbum < Sequel::Model(:albums)
|
|
8
6
|
columns :id, :band_id
|
|
9
7
|
many_to_one :band, :class=>'EagerBand', :key=>:band_id
|
|
@@ -48,63 +46,48 @@ describe Sequel::Model, "#eager" do
|
|
|
48
46
|
many_to_many :bands, :class=>'EagerBand', :left_key=>:member_id, :right_key=>:band_id, :join_table=>:bm, :order =>:id
|
|
49
47
|
end
|
|
50
48
|
|
|
51
|
-
EagerAlbum.dataset.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
h = if sql =~ /101/
|
|
58
|
-
{:id => 101, :band_id=> 101}
|
|
59
|
-
else
|
|
60
|
-
{:id => 1, :band_id=> 2}
|
|
61
|
-
end
|
|
62
|
-
h.merge!(:x_foreign_key_x=>4) if sql =~ /ag\.genre_id/
|
|
63
|
-
@db << sql
|
|
64
|
-
yield h
|
|
49
|
+
EagerAlbum.dataset.columns(:id, :band_id)
|
|
50
|
+
EagerAlbum.dataset._fetch = proc do |sql|
|
|
51
|
+
h = if sql =~ /101/
|
|
52
|
+
{:id => 101, :band_id=> 101}
|
|
53
|
+
else
|
|
54
|
+
{:id => 1, :band_id=> 2}
|
|
65
55
|
end
|
|
66
|
-
|
|
56
|
+
h[:x_foreign_key_x] = 4 if sql =~ /ag\.genre_id/
|
|
57
|
+
h
|
|
58
|
+
end
|
|
67
59
|
|
|
68
|
-
EagerBand.dataset.
|
|
69
|
-
|
|
60
|
+
EagerBand.dataset._fetch = proc do |sql|
|
|
61
|
+
case sql
|
|
62
|
+
when /id IN (101)/
|
|
63
|
+
# nothing
|
|
64
|
+
when /id > 100/
|
|
65
|
+
[{:id => 101}, {:id => 102}]
|
|
66
|
+
else
|
|
70
67
|
h = {:id => 2}
|
|
71
|
-
h
|
|
72
|
-
|
|
73
|
-
case sql
|
|
74
|
-
when /id IN (101)/
|
|
75
|
-
when /id > 100/
|
|
76
|
-
yield({:id => 101})
|
|
77
|
-
yield({:id => 102})
|
|
78
|
-
else
|
|
79
|
-
yield h
|
|
80
|
-
end
|
|
68
|
+
h[:x_foreign_key_x] = 5 if sql =~ /bm\.member_id/
|
|
69
|
+
h
|
|
81
70
|
end
|
|
82
|
-
|
|
71
|
+
end
|
|
83
72
|
|
|
84
|
-
EagerTrack.dataset.
|
|
85
|
-
def fetch_rows(sql)
|
|
86
|
-
@db << sql
|
|
87
|
-
yield({:id => 3, :album_id => 1})
|
|
88
|
-
end
|
|
89
|
-
})
|
|
73
|
+
EagerTrack.dataset._fetch = {:id => 3, :album_id => 1}
|
|
90
74
|
|
|
91
|
-
EagerGenre.dataset.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
yield h
|
|
97
|
-
end
|
|
98
|
-
})
|
|
75
|
+
EagerGenre.dataset._fetch = proc do |sql|
|
|
76
|
+
h = {:id => 4}
|
|
77
|
+
h[:x_foreign_key_x] = 1 if sql =~ /ag\.album_id/
|
|
78
|
+
h
|
|
79
|
+
end
|
|
99
80
|
|
|
100
|
-
EagerBandMember.dataset.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
81
|
+
EagerBandMember.dataset._fetch = proc do |sql|
|
|
82
|
+
h = {:id => 5}
|
|
83
|
+
h[:x_foreign_key_x] = 2 if sql =~ /bm\.band_id/
|
|
84
|
+
h
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
MODEL_DB.reset
|
|
88
|
+
end
|
|
89
|
+
after do
|
|
90
|
+
[:EagerAlbum, :EagerBand, :EagerTrack, :EagerGenre, :EagerBandMember].each{|x| Object.send(:remove_const, x)}
|
|
108
91
|
end
|
|
109
92
|
|
|
110
93
|
it "should raise an error if called without a symbol or hash" do
|
|
@@ -113,15 +96,20 @@ describe Sequel::Model, "#eager" do
|
|
|
113
96
|
|
|
114
97
|
it "should eagerly load a single many_to_one association" do
|
|
115
98
|
a = EagerAlbum.eager(:band).all
|
|
116
|
-
a.should be_a_kind_of(Array)
|
|
117
|
-
a.size.should == 1
|
|
118
|
-
a.first.should be_a_kind_of(EagerAlbum)
|
|
119
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
120
99
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM bands WHERE (bands.id IN (2))']
|
|
121
|
-
a
|
|
122
|
-
a.band.should
|
|
123
|
-
|
|
124
|
-
|
|
100
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
101
|
+
a.first.band.should == EagerBand.load(:id=>2)
|
|
102
|
+
MODEL_DB.sqls.should == []
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "should eagerly load a single many_to_one association with the same name as the column" do
|
|
106
|
+
EagerAlbum.def_column_alias(:band_id_id, :band_id)
|
|
107
|
+
EagerAlbum.many_to_one :band_id, :key_column=>:band_id, :class=>EagerBand
|
|
108
|
+
a = EagerAlbum.eager(:band_id).all
|
|
109
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM bands WHERE (bands.id IN (2))']
|
|
110
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
111
|
+
a.first.band_id.should == EagerBand.load(:id=>2)
|
|
112
|
+
MODEL_DB.sqls.should == []
|
|
125
113
|
end
|
|
126
114
|
|
|
127
115
|
it "should eagerly load a single one_to_one association" do
|
|
@@ -130,269 +118,203 @@ describe Sequel::Model, "#eager" do
|
|
|
130
118
|
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
131
119
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
|
|
132
120
|
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
|
133
|
-
MODEL_DB.sqls.
|
|
121
|
+
MODEL_DB.sqls.should == []
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should eagerly load a single one_to_one association using the :distinct_on strategy" do
|
|
125
|
+
EagerTrack.dataset.meta_def(:supports_distinct_on?){true}
|
|
126
|
+
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>true
|
|
127
|
+
a = EagerAlbum.eager(:track).all
|
|
128
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
129
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT DISTINCT ON (tracks.album_id) * FROM tracks WHERE (tracks.album_id IN (1)) ORDER BY tracks.album_id']
|
|
130
|
+
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
|
131
|
+
MODEL_DB.sqls.should == []
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "should eagerly load a single one_to_one association using the :window_function strategy" do
|
|
135
|
+
EagerTrack.dataset.meta_def(:supports_window_functions?){true}
|
|
136
|
+
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>true, :order=>:name
|
|
137
|
+
a = EagerAlbum.eager(:track).all
|
|
138
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
139
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x = 1)']
|
|
140
|
+
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
|
141
|
+
MODEL_DB.sqls.should == []
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "should eagerly load a single one_to_one association using the :correlated_subquery strategy" do
|
|
145
|
+
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>:name
|
|
146
|
+
a = EagerAlbum.eager(:track).all
|
|
147
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
148
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY name LIMIT 1))) ORDER BY name']
|
|
149
|
+
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
|
150
|
+
MODEL_DB.sqls.should == []
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should handle qualified order clauses when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
|
|
154
|
+
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>[:tracks__name, :tracks__name.desc, :name.qualify(:tracks), :name.qualify(:t), 1]
|
|
155
|
+
a = EagerAlbum.eager(:track).all
|
|
156
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
157
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY t1.name, t1.name DESC, t1.name, t.name, 1 LIMIT 1))) ORDER BY tracks.name, tracks.name DESC, tracks.name, t.name, 1']
|
|
158
|
+
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
|
159
|
+
MODEL_DB.sqls.should == []
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "should handle qualified composite keys when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
|
|
163
|
+
c1 = Class.new(EagerAlbum)
|
|
164
|
+
c2 = Class.new(EagerTrack)
|
|
165
|
+
c1.set_primary_key [:id, :band_id]
|
|
166
|
+
c2.set_primary_key [:id, :album_id]
|
|
167
|
+
c1.one_to_one :track, :class=>c2, :key=>[:album_id, :id], :eager_limit_strategy=>:correlated_subquery
|
|
168
|
+
c2.dataset._fetch = {:id => 2, :album_id=>1}
|
|
169
|
+
a = c1.eager(:track).all
|
|
170
|
+
a.should == [c1.load(:id => 1, :band_id => 2)]
|
|
171
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (((tracks.album_id, tracks.id) IN ((1, 2))) AND ((tracks.id, tracks.album_id) IN (SELECT t1.id, t1.album_id FROM tracks AS t1 WHERE ((t1.album_id = tracks.album_id) AND (t1.id = tracks.id)) LIMIT 1)))']
|
|
172
|
+
a.first.track.should == c2.load(:id => 2, :album_id=>1)
|
|
173
|
+
MODEL_DB.sqls.should == []
|
|
134
174
|
end
|
|
135
175
|
|
|
136
176
|
it "should eagerly load a single one_to_many association" do
|
|
137
177
|
a = EagerAlbum.eager(:tracks).all
|
|
138
|
-
a.should
|
|
139
|
-
a.size.should == 1
|
|
140
|
-
a.first.should be_a_kind_of(EagerAlbum)
|
|
141
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
178
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
142
179
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
|
|
143
|
-
a
|
|
144
|
-
|
|
145
|
-
a.tracks.size.should == 1
|
|
146
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
147
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
148
|
-
MODEL_DB.sqls.length.should == 2
|
|
180
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
181
|
+
MODEL_DB.sqls.should == []
|
|
149
182
|
end
|
|
150
183
|
|
|
151
184
|
it "should eagerly load a single many_to_many association" do
|
|
152
185
|
a = EagerAlbum.eager(:genres).all
|
|
153
|
-
a.should
|
|
154
|
-
a.size.should == 1
|
|
155
|
-
a.first.should be_a_kind_of(EagerAlbum)
|
|
156
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
186
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
157
187
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
|
158
|
-
a
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
188
|
+
a.first.genres.should == [EagerGenre.load(:id=>4)]
|
|
189
|
+
MODEL_DB.sqls.should == []
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "should correctly handle a :select=>[] option to many_to_many" do
|
|
193
|
+
EagerAlbum.many_to_many :sgenres, :clone=>:genres, :select=>[]
|
|
194
|
+
a = EagerAlbum.eager(:sgenres).all
|
|
195
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT *, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "should correctly handle an aliased join table in many_to_many" do
|
|
199
|
+
EagerAlbum.many_to_many :sgenres, :clone=>:genres, :join_table=>:ag___ga
|
|
200
|
+
a = EagerAlbum.eager(:sgenres).all
|
|
201
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ga.album_id AS x_foreign_key_x FROM genres INNER JOIN ag AS ga ON ((ga.genre_id = genres.id) AND (ga.album_id IN (1)))"]
|
|
164
202
|
end
|
|
165
203
|
|
|
166
204
|
it "should eagerly load multiple associations in a single call" do
|
|
167
205
|
a = EagerAlbum.eager(:genres, :tracks, :band).all
|
|
168
|
-
a.should
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (bands.id IN (2))'))
|
|
175
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (tracks.album_id IN (1))'))
|
|
176
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))'))
|
|
206
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
207
|
+
sqls = MODEL_DB.sqls
|
|
208
|
+
sqls.shift.should == 'SELECT * FROM albums'
|
|
209
|
+
sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
|
|
210
|
+
'SELECT * FROM tracks WHERE (tracks.album_id IN (1))',
|
|
211
|
+
'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))']
|
|
177
212
|
a = a.first
|
|
178
|
-
a.band.should
|
|
179
|
-
a.
|
|
180
|
-
a.
|
|
181
|
-
|
|
182
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
183
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
184
|
-
a.genres.should be_a_kind_of(Array)
|
|
185
|
-
a.genres.size.should == 1
|
|
186
|
-
a.genres.first.should be_a_kind_of(EagerGenre)
|
|
187
|
-
a.genres.first.values.should == {:id => 4}
|
|
188
|
-
MODEL_DB.sqls.length.should == 4
|
|
213
|
+
a.band.should == EagerBand.load(:id=>2)
|
|
214
|
+
a.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
215
|
+
a.genres.should == [EagerGenre.load(:id => 4)]
|
|
216
|
+
MODEL_DB.sqls.should == []
|
|
189
217
|
end
|
|
190
218
|
|
|
191
219
|
it "should eagerly load multiple associations in separate calls" do
|
|
192
220
|
a = EagerAlbum.eager(:genres).eager(:tracks).eager(:band).all
|
|
193
|
-
a.should
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (bands.id IN (2))'))
|
|
200
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (tracks.album_id IN (1))'))
|
|
201
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))'))
|
|
221
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
222
|
+
sqls = MODEL_DB.sqls
|
|
223
|
+
sqls.shift.should == 'SELECT * FROM albums'
|
|
224
|
+
sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
|
|
225
|
+
'SELECT * FROM tracks WHERE (tracks.album_id IN (1))',
|
|
226
|
+
'SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))']
|
|
202
227
|
a = a.first
|
|
203
|
-
a.band.should
|
|
204
|
-
a.
|
|
205
|
-
a.
|
|
206
|
-
|
|
207
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
208
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
209
|
-
a.genres.should be_a_kind_of(Array)
|
|
210
|
-
a.genres.size.should == 1
|
|
211
|
-
a.genres.first.should be_a_kind_of(EagerGenre)
|
|
212
|
-
a.genres.first.values.should == {:id => 4}
|
|
213
|
-
MODEL_DB.sqls.length.should == 4
|
|
228
|
+
a.band.should == EagerBand.load(:id=>2)
|
|
229
|
+
a.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
230
|
+
a.genres.should == [EagerGenre.load(:id => 4)]
|
|
231
|
+
MODEL_DB.sqls.should == []
|
|
214
232
|
end
|
|
215
233
|
|
|
216
234
|
it "should allow cascading of eager loading for associations of associated models" do
|
|
217
235
|
a = EagerTrack.eager(:album=>{:band=>:members}).all
|
|
218
|
-
a.should
|
|
219
|
-
a.size.should == 1
|
|
220
|
-
a.first.should be_a_kind_of(EagerTrack)
|
|
221
|
-
a.first.values.should == {:id => 3, :album_id => 1}
|
|
222
|
-
MODEL_DB.sqls.length.should == 4
|
|
236
|
+
a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
223
237
|
MODEL_DB.sqls.should == ['SELECT * FROM tracks',
|
|
224
238
|
'SELECT * FROM albums WHERE (albums.id IN (1))',
|
|
225
239
|
'SELECT * FROM bands WHERE (bands.id IN (2))',
|
|
226
240
|
"SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
|
|
227
241
|
a = a.first
|
|
228
|
-
a.album.should
|
|
229
|
-
a.album.
|
|
230
|
-
a.album.band.should
|
|
231
|
-
|
|
232
|
-
a.album.band.members.should be_a_kind_of(Array)
|
|
233
|
-
a.album.band.members.size.should == 1
|
|
234
|
-
a.album.band.members.first.should be_a_kind_of(EagerBandMember)
|
|
235
|
-
a.album.band.members.first.values.should == {:id => 5}
|
|
236
|
-
MODEL_DB.sqls.length.should == 4
|
|
242
|
+
a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
|
243
|
+
a.album.band.should == EagerBand.load(:id => 2)
|
|
244
|
+
a.album.band.members.should == [EagerBandMember.load(:id => 5)]
|
|
245
|
+
MODEL_DB.sqls.should == []
|
|
237
246
|
end
|
|
238
247
|
|
|
239
248
|
it "should cascade eagerly loading when the :eager association option is used" do
|
|
240
249
|
a = EagerBand.eager(:albums).all
|
|
241
|
-
a.should
|
|
242
|
-
a.size.should == 1
|
|
243
|
-
a.first.should be_a_kind_of(EagerBand)
|
|
244
|
-
a.first.values.should == {:id => 2}
|
|
250
|
+
a.should == [EagerBand.load(:id=>2)]
|
|
245
251
|
MODEL_DB.sqls.should == ['SELECT * FROM bands',
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
a
|
|
249
|
-
a.albums.should
|
|
250
|
-
|
|
251
|
-
a.albums.first.should be_a_kind_of(EagerAlbum)
|
|
252
|
-
a.albums.first.values.should == {:id => 1, :band_id => 2}
|
|
253
|
-
a = a.albums.first
|
|
254
|
-
a.tracks.should be_a_kind_of(Array)
|
|
255
|
-
a.tracks.size.should == 1
|
|
256
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
257
|
-
a.tracks.first.values.should == {:id => 3, :album_id => 1}
|
|
258
|
-
MODEL_DB.sqls.length.should == 3
|
|
252
|
+
'SELECT * FROM albums WHERE (albums.band_id IN (2))',
|
|
253
|
+
'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
|
|
254
|
+
a.first.albums.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
255
|
+
a.first.albums.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
256
|
+
MODEL_DB.sqls.should == []
|
|
259
257
|
end
|
|
260
258
|
|
|
261
259
|
it "should respect :eager when lazily loading an association" do
|
|
262
260
|
a = EagerBand.all
|
|
263
|
-
a.should
|
|
264
|
-
a.size.should == 1
|
|
265
|
-
a.first.should be_a_kind_of(EagerBand)
|
|
266
|
-
a.first.values.should == {:id => 2}
|
|
261
|
+
a.should == [EagerBand.load(:id=>2)]
|
|
267
262
|
MODEL_DB.sqls.should == ['SELECT * FROM bands']
|
|
268
|
-
a = a.first
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
a.albums.size.should == 1
|
|
275
|
-
a.albums.first.should be_a_kind_of(EagerAlbum)
|
|
276
|
-
a.albums.first.values.should == {:id => 1, :band_id => 2}
|
|
277
|
-
a = a.albums.first
|
|
278
|
-
a.tracks.should be_a_kind_of(Array)
|
|
279
|
-
a.tracks.size.should == 1
|
|
280
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
281
|
-
a.tracks.first.values.should == {:id => 3, :album_id => 1}
|
|
282
|
-
MODEL_DB.sqls.length.should == 3
|
|
263
|
+
a = a.first.albums
|
|
264
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (albums.band_id = 2)',
|
|
265
|
+
'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
|
|
266
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
267
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
268
|
+
MODEL_DB.sqls.should == []
|
|
283
269
|
end
|
|
284
270
|
|
|
285
271
|
it "should cascade eagerly loading when the :eager_graph association option is used" do
|
|
286
|
-
EagerAlbum.dataset.
|
|
287
|
-
def fetch_rows(sql)
|
|
288
|
-
@db << sql
|
|
289
|
-
yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
|
|
290
|
-
end
|
|
291
|
-
})
|
|
272
|
+
EagerAlbum.dataset._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
|
|
292
273
|
a = EagerBand.eager(:graph_albums).all
|
|
293
|
-
a.should
|
|
294
|
-
a.size.should == 1
|
|
295
|
-
a.first.should be_a_kind_of(EagerBand)
|
|
296
|
-
a.first.values.should == {:id => 2}
|
|
274
|
+
a.should == [EagerBand.load(:id=>2)]
|
|
297
275
|
MODEL_DB.sqls.should == ['SELECT * FROM bands',
|
|
298
|
-
|
|
299
|
-
a
|
|
300
|
-
a.graph_albums.should
|
|
301
|
-
|
|
302
|
-
a.graph_albums.first.should be_a_kind_of(EagerAlbum)
|
|
303
|
-
a.graph_albums.first.values.should == {:id => 1, :band_id => 2}
|
|
304
|
-
a = a.graph_albums.first
|
|
305
|
-
a.tracks.should be_a_kind_of(Array)
|
|
306
|
-
a.tracks.size.should == 1
|
|
307
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
308
|
-
a.tracks.first.values.should == {:id => 3, :album_id => 1}
|
|
309
|
-
MODEL_DB.sqls.length.should == 2
|
|
276
|
+
'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) WHERE (albums.band_id IN (2))']
|
|
277
|
+
a.first.graph_albums.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
278
|
+
a.first.graph_albums.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
279
|
+
MODEL_DB.sqls.should == []
|
|
310
280
|
end
|
|
311
281
|
|
|
312
|
-
it "should
|
|
313
|
-
|
|
314
|
-
def columns
|
|
315
|
-
[:id]
|
|
316
|
-
end
|
|
317
|
-
def fetch_rows(sql)
|
|
318
|
-
@db << sql
|
|
319
|
-
yield({:id=>5, :bands_id=>2, :p_k=>6, :x_foreign_key_x=>2})
|
|
320
|
-
yield({:id=>5, :bands_id=>3, :p_k=>6, :x_foreign_key_x=>2})
|
|
321
|
-
end
|
|
322
|
-
})
|
|
323
|
-
a = EagerBand.eager(:graph_members).all
|
|
324
|
-
a.should == [EagerBand.load(:id=>2)]
|
|
325
|
-
MODEL_DB.sqls.should == ['SELECT * FROM bands',
|
|
326
|
-
'SELECT members.id, bands.id AS bands_id, bands.p_k, bm.band_id AS x_foreign_key_x FROM (SELECT members.* FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))) AS members LEFT OUTER JOIN bm AS bm_0 ON (bm_0.member_id = members.id) LEFT OUTER JOIN bands ON (bands.id = bm_0.band_id) ORDER BY bands.id']
|
|
327
|
-
a = a.first
|
|
328
|
-
a.graph_members.should == [EagerBandMember.load(:id=>5)]
|
|
329
|
-
a.graph_members.first.bands.should == [EagerBand.load(:id=>2, :p_k=>6), EagerBand.load(:id=>3, :p_k=>6)]
|
|
330
|
-
MODEL_DB.sqls.length.should == 2
|
|
282
|
+
it "should raise an Error when eager loading a many_to_many association with the :eager_graph option" do
|
|
283
|
+
proc{EagerBand.eager(:graph_members).all}.should raise_error(Sequel::Error)
|
|
331
284
|
end
|
|
332
285
|
|
|
333
286
|
it "should respect :eager_graph when lazily loading an association" do
|
|
334
287
|
a = EagerBand.all
|
|
335
|
-
a.should
|
|
336
|
-
a.size.should == 1
|
|
337
|
-
a.first.should be_a_kind_of(EagerBand)
|
|
338
|
-
a.first.values.should == {:id => 2}
|
|
288
|
+
a.should == [EagerBand.load(:id=>2)]
|
|
339
289
|
MODEL_DB.sqls.should == ['SELECT * FROM bands']
|
|
340
290
|
a = a.first
|
|
341
|
-
EagerAlbum.dataset.
|
|
342
|
-
def fetch_rows(sql)
|
|
343
|
-
@db << sql
|
|
344
|
-
yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
|
|
345
|
-
end
|
|
346
|
-
})
|
|
291
|
+
EagerAlbum.dataset._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
|
|
347
292
|
a.graph_albums
|
|
348
|
-
MODEL_DB.sqls.should == ['SELECT
|
|
349
|
-
|
|
350
|
-
a.graph_albums.should
|
|
351
|
-
|
|
352
|
-
a.graph_albums.first.should be_a_kind_of(EagerAlbum)
|
|
353
|
-
a.graph_albums.first.values.should == {:id => 1, :band_id => 2}
|
|
354
|
-
a = a.graph_albums.first
|
|
355
|
-
a.tracks.should be_a_kind_of(Array)
|
|
356
|
-
a.tracks.size.should == 1
|
|
357
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
358
|
-
a.tracks.first.values.should == {:id => 3, :album_id => 1}
|
|
359
|
-
MODEL_DB.sqls.length.should == 2
|
|
293
|
+
MODEL_DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) WHERE (albums.band_id = 2)']
|
|
294
|
+
a.graph_albums.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
295
|
+
a.graph_albums.first.tracks.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
296
|
+
MODEL_DB.sqls.should == []
|
|
360
297
|
end
|
|
361
298
|
|
|
362
299
|
it "should respect :eager_graph when lazily loading a many_to_many association" do
|
|
363
|
-
EagerBandMember.dataset
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
end
|
|
367
|
-
def fetch_rows(sql)
|
|
368
|
-
@db << sql
|
|
369
|
-
yield({:id=>5, :bands_id=>2, :p_k=>6})
|
|
370
|
-
yield({:id=>5, :bands_id=>3, :p_k=>6})
|
|
371
|
-
end
|
|
372
|
-
})
|
|
300
|
+
ds = EagerBandMember.dataset
|
|
301
|
+
def ds.columns() [:id] end
|
|
302
|
+
ds._fetch = [{:id=>5, :bands_id=>2, :p_k=>6}, {:id=>5, :bands_id=>3, :p_k=>6}]
|
|
373
303
|
a = EagerBand.load(:id=>2)
|
|
374
304
|
a.graph_members.should == [EagerBandMember.load(:id=>5)]
|
|
375
305
|
MODEL_DB.sqls.should == ['SELECT members.id, bands.id AS bands_id, bands.p_k FROM (SELECT members.* FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id = 2))) AS members LEFT OUTER JOIN bm AS bm_0 ON (bm_0.member_id = members.id) LEFT OUTER JOIN bands ON (bands.id = bm_0.band_id) ORDER BY bands.id']
|
|
376
306
|
a.graph_members.first.bands.should == [EagerBand.load(:id=>2, :p_k=>6), EagerBand.load(:id=>3, :p_k=>6)]
|
|
377
|
-
MODEL_DB.sqls.
|
|
307
|
+
MODEL_DB.sqls.should == []
|
|
378
308
|
end
|
|
379
309
|
|
|
380
310
|
it "should respect :conditions when eagerly loading" do
|
|
381
311
|
EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>{:a=>32}
|
|
382
312
|
a = EagerBandMember.eager(:good_bands).all
|
|
383
|
-
a.should
|
|
384
|
-
a.size.should == 1
|
|
385
|
-
a.first.should be_a_kind_of(EagerBandMember)
|
|
386
|
-
a.first.values.should == {:id => 5}
|
|
313
|
+
a.should == [EagerBandMember.load(:id => 5)]
|
|
387
314
|
MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (a = 32) ORDER BY id']
|
|
388
|
-
a
|
|
389
|
-
|
|
390
|
-
a.good_bands.size.should == 1
|
|
391
|
-
a.good_bands.first.should be_a_kind_of(EagerBand)
|
|
392
|
-
a.good_bands.first.values.should == {:id => 2}
|
|
393
|
-
MODEL_DB.sqls.length.should == 2
|
|
315
|
+
a.first.good_bands.should == [EagerBand.load(:id => 2)]
|
|
316
|
+
MODEL_DB.sqls.should == []
|
|
394
317
|
|
|
395
|
-
MODEL_DB.sqls.clear
|
|
396
318
|
EagerBandMember.many_to_many :good_bands, :clone=>:bands, :conditions=>"x = 1"
|
|
397
319
|
a = EagerBandMember.eager(:good_bands).all
|
|
398
320
|
MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) WHERE (x = 1) ORDER BY id']
|
|
@@ -400,63 +322,36 @@ describe Sequel::Model, "#eager" do
|
|
|
400
322
|
|
|
401
323
|
it "should respect :order when eagerly loading" do
|
|
402
324
|
a = EagerBandMember.eager(:bands).all
|
|
403
|
-
a.should
|
|
404
|
-
a.size.should == 1
|
|
405
|
-
a.first.should be_a_kind_of(EagerBandMember)
|
|
406
|
-
a.first.values.should == {:id => 5}
|
|
325
|
+
a.should == [EagerBandMember.load(:id => 5)]
|
|
407
326
|
MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) ORDER BY id']
|
|
408
|
-
a
|
|
409
|
-
|
|
410
|
-
a.bands.size.should == 1
|
|
411
|
-
a.bands.first.should be_a_kind_of(EagerBand)
|
|
412
|
-
a.bands.first.values.should == {:id => 2}
|
|
413
|
-
MODEL_DB.sqls.length.should == 2
|
|
327
|
+
a.first.bands.should == [EagerBand.load(:id => 2)]
|
|
328
|
+
MODEL_DB.sqls.should == []
|
|
414
329
|
end
|
|
415
330
|
|
|
416
331
|
it "should populate the reciprocal many_to_one association when eagerly loading the one_to_many association" do
|
|
417
332
|
a = EagerAlbum.eager(:tracks).all
|
|
418
|
-
a.should
|
|
419
|
-
a.size.should == 1
|
|
420
|
-
a.first.should be_a_kind_of(EagerAlbum)
|
|
421
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
333
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
422
334
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (tracks.album_id IN (1))']
|
|
423
|
-
a
|
|
424
|
-
a.tracks.should
|
|
425
|
-
|
|
426
|
-
a.tracks.first.should be_a_kind_of(EagerTrack)
|
|
427
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
428
|
-
a.tracks.first.album.should be_a_kind_of(EagerAlbum)
|
|
429
|
-
a.tracks.first.album.should == a
|
|
430
|
-
MODEL_DB.sqls.length.should == 2
|
|
335
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
336
|
+
a.first.tracks.first.album.should == a.first
|
|
337
|
+
MODEL_DB.sqls.should == []
|
|
431
338
|
end
|
|
432
339
|
|
|
433
340
|
it "should cache the negative lookup when eagerly loading a many_to_one association" do
|
|
434
341
|
a = EagerAlbum.eager(:band).filter(:id=>101).all
|
|
435
|
-
a.should
|
|
436
|
-
a.size.should == 1
|
|
437
|
-
a.first.should be_a_kind_of(EagerAlbum)
|
|
438
|
-
a.first.values.should == {:id => 101, :band_id => 101}
|
|
342
|
+
a.should == [EagerAlbum.load(:id => 101, :band_id => 101)]
|
|
439
343
|
MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (id = 101)', 'SELECT * FROM bands WHERE (bands.id IN (101))']
|
|
440
|
-
a
|
|
441
|
-
a.
|
|
442
|
-
|
|
443
|
-
MODEL_DB.sqls.length.should == 2
|
|
344
|
+
a.first.associations.fetch(:band, 2).should be_nil
|
|
345
|
+
a.first.band.should be_nil
|
|
346
|
+
MODEL_DB.sqls.should == []
|
|
444
347
|
end
|
|
445
348
|
|
|
446
349
|
it "should cache the negative lookup when eagerly loading a *_to_many associations" do
|
|
447
350
|
a = EagerBand.eager(:albums).filter('id > 100').all
|
|
448
|
-
a.should
|
|
449
|
-
a.size.should == 2
|
|
450
|
-
a.first.should be_a_kind_of(EagerBand)
|
|
451
|
-
a.first.values.should == {:id => 101}
|
|
452
|
-
a.last.values.should == {:id => 102}
|
|
351
|
+
a.should == [EagerBand.load(:id => 101), EagerBand.load(:id =>102)]
|
|
453
352
|
MODEL_DB.sqls.should == ['SELECT * FROM bands WHERE (id > 100)', 'SELECT * FROM albums WHERE (albums.band_id IN (101, 102))', "SELECT * FROM tracks WHERE (tracks.album_id IN (101))"]
|
|
454
|
-
a.
|
|
455
|
-
|
|
456
|
-
a.first.albums.first.should be_a_kind_of(EagerAlbum)
|
|
457
|
-
a.last.associations[:albums].should == []
|
|
458
|
-
a.last.albums.should == []
|
|
459
|
-
MODEL_DB.sqls.length.should == 3
|
|
353
|
+
a.map{|b| b.associations[:albums]}.should == [[EagerAlbum.load({:band_id=>101, :id=>101})], []]
|
|
354
|
+
MODEL_DB.sqls.should == []
|
|
460
355
|
end
|
|
461
356
|
|
|
462
357
|
it "should use the association's block when eager loading by default" do
|
|
@@ -467,7 +362,6 @@ describe Sequel::Model, "#eager" do
|
|
|
467
362
|
it "should use the eager_block option when eager loading if given" do
|
|
468
363
|
EagerBand.eager(:good_albums).all
|
|
469
364
|
MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))"]
|
|
470
|
-
MODEL_DB.sqls.clear
|
|
471
365
|
EagerBand.eager(:good_albums=>:good_tracks).all
|
|
472
366
|
MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT * FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))", "SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (name = 'Good'))"]
|
|
473
367
|
end
|
|
@@ -480,34 +374,31 @@ describe Sequel::Model, "#eager" do
|
|
|
480
374
|
it "should respect the association's :select option" do
|
|
481
375
|
EagerAlbum.eager(:band_name).all
|
|
482
376
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, name FROM bands WHERE (bands.id IN (2))"]
|
|
483
|
-
MODEL_DB.sqls.clear
|
|
484
377
|
EagerAlbum.eager(:track_names).all
|
|
485
378
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, name FROM tracks WHERE (tracks.album_id IN (1))"]
|
|
486
|
-
MODEL_DB.sqls.clear
|
|
487
379
|
EagerAlbum.eager(:genre_names).all
|
|
488
380
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
|
489
381
|
end
|
|
490
382
|
|
|
383
|
+
it "should respect many_to_one association's :qualify option" do
|
|
384
|
+
EagerAlbum.many_to_one :special_band, :class=>:EagerBand, :qualify=>false, :key=>:band_id
|
|
385
|
+
EagerBand.dataset._fetch = {:id=>2}
|
|
386
|
+
as = EagerAlbum.eager(:special_band).all
|
|
387
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM bands WHERE (id IN (2))"]
|
|
388
|
+
as.map{|a| a.special_band}.should == [EagerBand.load(:id=>2)]
|
|
389
|
+
MODEL_DB.sqls.should == []
|
|
390
|
+
end
|
|
391
|
+
|
|
491
392
|
it "should respect the association's :primary_key option" do
|
|
492
393
|
EagerAlbum.many_to_one :special_band, :class=>:EagerBand, :primary_key=>:p_k, :key=>:band_id
|
|
493
|
-
EagerBand.dataset.
|
|
494
|
-
def fetch_rows(sql)
|
|
495
|
-
MODEL_DB.sqls << sql
|
|
496
|
-
yield({:p_k=>2, :id=>1})
|
|
497
|
-
end
|
|
498
|
-
})
|
|
394
|
+
EagerBand.dataset._fetch = {:p_k=>2, :id=>1}
|
|
499
395
|
as = EagerAlbum.eager(:special_band).all
|
|
500
396
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM bands WHERE (bands.p_k IN (2))"]
|
|
501
397
|
as.length.should == 1
|
|
502
398
|
as.first.special_band.should == EagerBand.load(:p_k=>2, :id=>1)
|
|
503
|
-
|
|
399
|
+
|
|
504
400
|
EagerAlbum.one_to_many :special_tracks, :class=>:EagerTrack, :primary_key=>:band_id, :key=>:album_id
|
|
505
|
-
EagerTrack.dataset.
|
|
506
|
-
def fetch_rows(sql)
|
|
507
|
-
MODEL_DB.sqls << sql
|
|
508
|
-
yield({:album_id=>2, :id=>1})
|
|
509
|
-
end
|
|
510
|
-
})
|
|
401
|
+
EagerTrack.dataset._fetch = {:album_id=>2, :id=>1}
|
|
511
402
|
as = EagerAlbum.eager(:special_tracks).all
|
|
512
403
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (2))"]
|
|
513
404
|
as.length.should == 1
|
|
@@ -516,12 +407,7 @@ describe Sequel::Model, "#eager" do
|
|
|
516
407
|
|
|
517
408
|
it "should respect the many_to_one association's composite keys" do
|
|
518
409
|
EagerAlbum.many_to_one :special_band, :class=>:EagerBand, :primary_key=>[:id, :p_k], :key=>[:band_id, :id]
|
|
519
|
-
EagerBand.dataset.
|
|
520
|
-
def fetch_rows(sql)
|
|
521
|
-
MODEL_DB.sqls << sql
|
|
522
|
-
yield({:p_k=>1, :id=>2})
|
|
523
|
-
end
|
|
524
|
-
})
|
|
410
|
+
EagerBand.dataset._fetch = {:p_k=>1, :id=>2}
|
|
525
411
|
as = EagerAlbum.eager(:special_band).all
|
|
526
412
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM bands WHERE ((bands.id, bands.p_k) IN ((2, 1)))"]
|
|
527
413
|
as.length.should == 1
|
|
@@ -530,12 +416,7 @@ describe Sequel::Model, "#eager" do
|
|
|
530
416
|
|
|
531
417
|
it "should respect the one_to_many association's composite keys" do
|
|
532
418
|
EagerAlbum.one_to_many :special_tracks, :class=>:EagerTrack, :primary_key=>[:band_id, :id], :key=>[:id, :album_id]
|
|
533
|
-
EagerTrack.dataset.
|
|
534
|
-
def fetch_rows(sql)
|
|
535
|
-
MODEL_DB.sqls << sql
|
|
536
|
-
yield({:album_id=>1, :id=>2})
|
|
537
|
-
end
|
|
538
|
-
})
|
|
419
|
+
EagerTrack.dataset._fetch = {:album_id=>1, :id=>2}
|
|
539
420
|
as = EagerAlbum.eager(:special_tracks).all
|
|
540
421
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE ((tracks.id, tracks.album_id) IN ((2, 1)))"]
|
|
541
422
|
as.length.should == 1
|
|
@@ -544,13 +425,7 @@ describe Sequel::Model, "#eager" do
|
|
|
544
425
|
|
|
545
426
|
it "should respect many_to_many association's composite keys" do
|
|
546
427
|
EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :left_primary_key=>[:band_id, :id], :left_key=>[:l1, :l2], :right_primary_key=>[:xxx, :id], :right_key=>[:r1, :r2], :join_table=>:ag
|
|
547
|
-
EagerGenre.dataset.
|
|
548
|
-
def fetch_rows(sql)
|
|
549
|
-
MODEL_DB.sqls << sql
|
|
550
|
-
yield({:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>5})
|
|
551
|
-
yield({:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>6})
|
|
552
|
-
end
|
|
553
|
-
})
|
|
428
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>5}, {:x_foreign_key_0_x=>2, :x_foreign_key_1_x=>1, :id=>6}]
|
|
554
429
|
as = EagerAlbum.eager(:special_genres).all
|
|
555
430
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.l1 AS x_foreign_key_0_x, ag.l2 AS x_foreign_key_1_x FROM genres INNER JOIN ag ON ((ag.r1 = genres.xxx) AND (ag.r2 = genres.id) AND ((ag.l1, ag.l2) IN ((2, 1))))"]
|
|
556
431
|
as.length.should == 1
|
|
@@ -559,19 +434,116 @@ describe Sequel::Model, "#eager" do
|
|
|
559
434
|
|
|
560
435
|
it "should respect many_to_many association's :left_primary_key and :right_primary_key options" do
|
|
561
436
|
EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_primary_key=>:xxx, :right_key=>:genre_id, :join_table=>:ag
|
|
562
|
-
EagerGenre.dataset.
|
|
563
|
-
def fetch_rows(sql)
|
|
564
|
-
MODEL_DB.sqls << sql
|
|
565
|
-
yield({:x_foreign_key_x=>2, :id=>5})
|
|
566
|
-
yield({:x_foreign_key_x=>2, :id=>6})
|
|
567
|
-
end
|
|
568
|
-
})
|
|
437
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
|
|
569
438
|
as = EagerAlbum.eager(:special_genres).all
|
|
570
439
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.xxx) AND (ag.album_id IN (2)))"]
|
|
571
440
|
as.length.should == 1
|
|
572
441
|
as.first.special_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
|
573
442
|
end
|
|
574
443
|
|
|
444
|
+
it "should respect the :limit option on a one_to_many association" do
|
|
445
|
+
EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>2
|
|
446
|
+
EagerTrack.dataset._fetch = [{:album_id=>1, :id=>2}, {:album_id=>1, :id=>3}, {:album_id=>1, :id=>4}]
|
|
447
|
+
as = EagerAlbum.eager(:first_two_tracks).all
|
|
448
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (1))"]
|
|
449
|
+
as.length.should == 1
|
|
450
|
+
as.first.first_two_tracks.should == [EagerTrack.load(:album_id=>1, :id=>2), EagerTrack.load(:album_id=>1, :id=>3)]
|
|
451
|
+
|
|
452
|
+
MODEL_DB.reset
|
|
453
|
+
EagerAlbum.one_to_many :first_two_tracks, :class=>:EagerTrack, :key=>:album_id, :limit=>[2,1]
|
|
454
|
+
as = EagerAlbum.eager(:first_two_tracks).all
|
|
455
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (1))"]
|
|
456
|
+
as.length.should == 1
|
|
457
|
+
as.first.first_two_tracks.should == [EagerTrack.load(:album_id=>1, :id=>3), EagerTrack.load(:album_id=>1, :id=>4)]
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
it "should respect the :limit option on a one_to_many association using the :window_function strategy" do
|
|
461
|
+
EagerTrack.dataset.meta_def(:supports_window_functions?){true}
|
|
462
|
+
EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>true, :order=>:name, :limit=>2
|
|
463
|
+
a = EagerAlbum.eager(:tracks).all
|
|
464
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
465
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE (x_sequel_row_number_x <= 2)']
|
|
466
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
467
|
+
MODEL_DB.sqls.should == []
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
it "should respect the :limit option with an offset on a one_to_many association using the :window_function strategy" do
|
|
471
|
+
EagerTrack.dataset.meta_def(:supports_window_functions?){true}
|
|
472
|
+
EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>true, :order=>:name, :limit=>[2, 1]
|
|
473
|
+
a = EagerAlbum.eager(:tracks).all
|
|
474
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
475
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY name) AS x_sequel_row_number_x FROM tracks WHERE (tracks.album_id IN (1))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))']
|
|
476
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
477
|
+
MODEL_DB.sqls.should == []
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
it "should respect the :limit option on a one_to_many association using the :correlated_subquery strategy" do
|
|
481
|
+
EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>:name, :limit=>2
|
|
482
|
+
a = EagerAlbum.eager(:tracks).all
|
|
483
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
484
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY name LIMIT 2))) ORDER BY name']
|
|
485
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
486
|
+
MODEL_DB.sqls.should == []
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
it "should respect the :limit option with an offset on a one_to_many association using the :correlated_subquery strategy" do
|
|
490
|
+
EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>:name, :limit=>[2, 1]
|
|
491
|
+
a = EagerAlbum.eager(:tracks).all
|
|
492
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
493
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE ((tracks.album_id IN (1)) AND (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) ORDER BY name LIMIT 2 OFFSET 1))) ORDER BY name']
|
|
494
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
495
|
+
MODEL_DB.sqls.should == []
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
it "should respect the limit option on a many_to_many association" do
|
|
499
|
+
EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2
|
|
500
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}, {:x_foreign_key_x=>2, :id=>7}]
|
|
501
|
+
as = EagerAlbum.eager(:first_two_genres).all
|
|
502
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))"]
|
|
503
|
+
as.length.should == 1
|
|
504
|
+
as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
|
505
|
+
|
|
506
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}, {:x_foreign_key_x=>2, :id=>7}]
|
|
507
|
+
EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>[2, 1]
|
|
508
|
+
as = EagerAlbum.eager(:first_two_genres).all
|
|
509
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))"]
|
|
510
|
+
as.length.should == 1
|
|
511
|
+
as.first.first_two_genres.should == [EagerGenre.load(:id=>6), EagerGenre.load(:id=>7)]
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
it "should respect the limit option on a many_to_many association using the :window_function strategy" do
|
|
515
|
+
EagerGenre.dataset.meta_def(:supports_window_functions?){true}
|
|
516
|
+
EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>true, :limit=>2, :order=>:name
|
|
517
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
|
|
518
|
+
as = EagerAlbum.eager(:first_two_genres).all
|
|
519
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))) AS t1 WHERE (x_sequel_row_number_x <= 2)"]
|
|
520
|
+
as.length.should == 1
|
|
521
|
+
as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
|
522
|
+
|
|
523
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
|
|
524
|
+
EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>true, :limit=>[2, 1], :order=>:name
|
|
525
|
+
as = EagerAlbum.eager(:first_two_genres).all
|
|
526
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM (SELECT genres.*, ag.album_id AS x_foreign_key_x, row_number() OVER (PARTITION BY ag.album_id ORDER BY name) AS x_sequel_row_number_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2)))) AS t1 WHERE ((x_sequel_row_number_x >= 2) AND (x_sequel_row_number_x < 4))"]
|
|
527
|
+
as.length.should == 1
|
|
528
|
+
as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
it "should respect the limit option on a many_to_many association using the :correlated_subquery strategy" do
|
|
532
|
+
EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>:correlated_subquery, :limit=>2, :order=>:name
|
|
533
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
|
|
534
|
+
as = EagerAlbum.eager(:first_two_genres).all
|
|
535
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2))) WHERE (genres.id IN (SELECT t1.id FROM genres AS t1 INNER JOIN ag AS t2 ON ((t2.genre_id = t1.id) AND (t2.album_id = ag.album_id)) ORDER BY name LIMIT 2)) ORDER BY name"]
|
|
536
|
+
as.length.should == 1
|
|
537
|
+
as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
|
538
|
+
|
|
539
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
|
|
540
|
+
EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>:correlated_subquery, :limit=>[2, 1], :order=>:name
|
|
541
|
+
as = EagerAlbum.eager(:first_two_genres).all
|
|
542
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (2))) WHERE (genres.id IN (SELECT t1.id FROM genres AS t1 INNER JOIN ag AS t2 ON ((t2.genre_id = t1.id) AND (t2.album_id = ag.album_id)) ORDER BY name LIMIT 2 OFFSET 1)) ORDER BY name"]
|
|
543
|
+
as.length.should == 1
|
|
544
|
+
as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
|
|
545
|
+
end
|
|
546
|
+
|
|
575
547
|
it "should use the :eager_loader association option when eager loading" do
|
|
576
548
|
EagerAlbum.many_to_one :special_band, :eager_loader=>(proc do |key_hash, records, assocs|
|
|
577
549
|
item = EagerBand.filter(:album_id=>records.collect{|r| [r.pk, r.pk*2]}.flatten).order(:name).first
|
|
@@ -586,27 +558,17 @@ describe Sequel::Model, "#eager" do
|
|
|
586
558
|
records.each{|r| r.associations[:special_genres] = items}
|
|
587
559
|
end)
|
|
588
560
|
a = EagerAlbum.eager(:special_genres, :special_tracks, :special_band).all
|
|
589
|
-
a.should
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (album_id IN (1, 2)) ORDER BY name LIMIT 1'))
|
|
596
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (album_id IN (1, 2))'))
|
|
597
|
-
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM genres INNER JOIN ag USING (genre_id) WHERE (album_id IN (1))'))
|
|
561
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
562
|
+
sqls = MODEL_DB.sqls
|
|
563
|
+
sqls.shift.should == 'SELECT * FROM albums'
|
|
564
|
+
sqls.sort.should == ['SELECT * FROM bands WHERE (album_id IN (1, 2)) ORDER BY name LIMIT 1',
|
|
565
|
+
'SELECT * FROM genres INNER JOIN ag USING (genre_id) WHERE (album_id IN (1))',
|
|
566
|
+
'SELECT * FROM tracks WHERE (album_id IN (1, 2))']
|
|
598
567
|
a = a.first
|
|
599
|
-
a.special_band.should
|
|
600
|
-
a.
|
|
601
|
-
a.
|
|
602
|
-
|
|
603
|
-
a.special_tracks.first.should be_a_kind_of(EagerTrack)
|
|
604
|
-
a.special_tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
605
|
-
a.special_genres.should be_a_kind_of(Array)
|
|
606
|
-
a.special_genres.size.should == 1
|
|
607
|
-
a.special_genres.first.should be_a_kind_of(EagerGenre)
|
|
608
|
-
a.special_genres.first.values.should == {:id => 4}
|
|
609
|
-
MODEL_DB.sqls.length.should == 4
|
|
568
|
+
a.special_band.should == EagerBand.load(:id => 2)
|
|
569
|
+
a.special_tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
570
|
+
a.special_genres.should == [EagerGenre.load(:id => 4)]
|
|
571
|
+
MODEL_DB.sqls.should == []
|
|
610
572
|
end
|
|
611
573
|
|
|
612
574
|
it "should raise an error if you use an :eager_loader proc with the wrong arity" do
|
|
@@ -626,13 +588,7 @@ describe Sequel::Model, "#eager" do
|
|
|
626
588
|
|
|
627
589
|
it "should respect :uniq option when eagerly loading many_to_many associations" do
|
|
628
590
|
EagerAlbum.many_to_many :al_genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :uniq=>true
|
|
629
|
-
EagerGenre.dataset.
|
|
630
|
-
def fetch_rows(sql)
|
|
631
|
-
MODEL_DB.sqls << sql
|
|
632
|
-
yield({:x_foreign_key_x=>1, :id=>8})
|
|
633
|
-
yield({:x_foreign_key_x=>1, :id=>8})
|
|
634
|
-
end
|
|
635
|
-
})
|
|
591
|
+
EagerGenre.dataset._fetch = [{:x_foreign_key_x=>1, :id=>8}, {:x_foreign_key_x=>1, :id=>8}]
|
|
636
592
|
a = EagerAlbum.eager(:al_genres).all.first
|
|
637
593
|
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
|
638
594
|
a.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
|
@@ -646,26 +602,103 @@ describe Sequel::Model, "#eager" do
|
|
|
646
602
|
a.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
|
647
603
|
a.al_genres.should == [EagerGenre.load(:id=>4)]
|
|
648
604
|
end
|
|
649
|
-
end
|
|
650
605
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
606
|
+
it "should eagerly load a many_to_one association with custom eager block" do
|
|
607
|
+
a = EagerAlbum.eager(:band => proc {|ds| ds.select(:id, :name)}).all
|
|
608
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
609
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id, name FROM bands WHERE (bands.id IN (2))']
|
|
610
|
+
a.first.band.should == EagerBand.load(:id => 2)
|
|
611
|
+
MODEL_DB.sqls.should == []
|
|
656
612
|
end
|
|
657
613
|
|
|
658
|
-
|
|
659
|
-
class
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
614
|
+
it "should eagerly load a one_to_one association with custom eager block" do
|
|
615
|
+
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id
|
|
616
|
+
a = EagerAlbum.eager(:track => proc {|ds| ds.select(:id)}).all
|
|
617
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
618
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id FROM tracks WHERE (tracks.album_id IN (1))']
|
|
619
|
+
a.first.track.should == EagerTrack.load(:id => 3, :album_id=>1)
|
|
620
|
+
MODEL_DB.sqls.should == []
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
it "should eagerly load a one_to_many association with custom eager block" do
|
|
624
|
+
a = EagerAlbum.eager(:tracks => proc {|ds| ds.select(:id)}).all
|
|
625
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
626
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT id FROM tracks WHERE (tracks.album_id IN (1))']
|
|
627
|
+
a.first.tracks.should == [EagerTrack.load(:id => 3, :album_id=>1)]
|
|
628
|
+
MODEL_DB.sqls.should == []
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
it "should eagerly load a many_to_many association with custom eager block" do
|
|
632
|
+
a = EagerAlbum.eager(:genres => proc {|ds| ds.select(:name)}).all
|
|
633
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
|
634
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT name, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
|
635
|
+
a.first.genres.should == [EagerGenre.load(:id => 4)]
|
|
636
|
+
MODEL_DB.sqls.should == []
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
it "should allow cascading of eager loading within a custom eager block" do
|
|
640
|
+
a = EagerTrack.eager(:album => proc {|ds| ds.eager(:band => :members)}).all
|
|
641
|
+
a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
642
|
+
MODEL_DB.sqls.should == ['SELECT * FROM tracks',
|
|
643
|
+
'SELECT * FROM albums WHERE (albums.id IN (1))',
|
|
644
|
+
'SELECT * FROM bands WHERE (bands.id IN (2))',
|
|
645
|
+
"SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
|
|
646
|
+
a = a.first
|
|
647
|
+
a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
|
648
|
+
a.album.band.should == EagerBand.load(:id => 2)
|
|
649
|
+
a.album.band.members.should == [EagerBandMember.load(:id => 5)]
|
|
650
|
+
MODEL_DB.sqls.should == []
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
it "should allow cascading of eager loading with custom callback with hash value" do
|
|
654
|
+
a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>{:band => :members}}).all
|
|
655
|
+
a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
656
|
+
MODEL_DB.sqls.should == ['SELECT * FROM tracks',
|
|
657
|
+
'SELECT id, band_id FROM albums WHERE (albums.id IN (1))',
|
|
658
|
+
'SELECT * FROM bands WHERE (bands.id IN (2))',
|
|
659
|
+
"SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
|
|
660
|
+
a = a.first
|
|
661
|
+
a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
|
662
|
+
a.album.band.should == EagerBand.load(:id => 2)
|
|
663
|
+
a.album.band.members.should == [EagerBandMember.load(:id => 5)]
|
|
664
|
+
MODEL_DB.sqls.should == []
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
it "should allow cascading of eager loading with custom callback with symbol value" do
|
|
668
|
+
a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>:band}).all
|
|
669
|
+
a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
670
|
+
MODEL_DB.sqls.should == ['SELECT * FROM tracks',
|
|
671
|
+
'SELECT id, band_id FROM albums WHERE (albums.id IN (1))',
|
|
672
|
+
'SELECT * FROM bands WHERE (bands.id IN (2))']
|
|
673
|
+
a = a.first
|
|
674
|
+
a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
|
675
|
+
a.album.band.should == EagerBand.load(:id => 2)
|
|
676
|
+
MODEL_DB.sqls.should == []
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
it "should allow cascading of eager loading with custom callback with array value" do
|
|
680
|
+
a = EagerTrack.eager(:album=>{proc{|ds| ds.select(:id, :band_id)}=>[:band, :band_name]}).all
|
|
681
|
+
a.should == [EagerTrack.load(:id => 3, :album_id => 1)]
|
|
682
|
+
sqls = MODEL_DB.sqls
|
|
683
|
+
sqls.slice!(0..1).should == ['SELECT * FROM tracks',
|
|
684
|
+
'SELECT id, band_id FROM albums WHERE (albums.id IN (1))']
|
|
685
|
+
sqls.sort.should == ['SELECT * FROM bands WHERE (bands.id IN (2))',
|
|
686
|
+
'SELECT id, name FROM bands WHERE (bands.id IN (2))']
|
|
687
|
+
a = a.first
|
|
688
|
+
a.album.should == EagerAlbum.load(:id => 1, :band_id => 2)
|
|
689
|
+
a.album.band.should == EagerBand.load(:id => 2)
|
|
690
|
+
a.album.band_name.should == EagerBand.load(:id => 2)
|
|
691
|
+
MODEL_DB.sqls.should == []
|
|
692
|
+
end
|
|
668
693
|
|
|
694
|
+
it "should call both association and custom eager blocks" do
|
|
695
|
+
EagerBand.eager(:good_albums => proc {|ds| ds.select(:name)}).all
|
|
696
|
+
MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT name FROM albums WHERE ((albums.band_id IN (2)) AND (name = 'good'))"]
|
|
697
|
+
end
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
describe Sequel::Model, "#eager_graph" do
|
|
701
|
+
before(:all) do
|
|
669
702
|
class ::GraphAlbum < Sequel::Model(:albums)
|
|
670
703
|
dataset.opts[:from] = [:albums]
|
|
671
704
|
columns :id, :band_id
|
|
@@ -702,6 +735,9 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
702
735
|
many_to_many :bands, :class=>'GraphBand', :left_key=>:member_id, :right_key=>:band_id, :join_table=>:bm
|
|
703
736
|
end
|
|
704
737
|
end
|
|
738
|
+
after(:all) do
|
|
739
|
+
[:GraphAlbum, :GraphBand, :GraphTrack, :GraphGenre, :GraphBandMember].each{|x| Object.send(:remove_const, x)}
|
|
740
|
+
end
|
|
705
741
|
|
|
706
742
|
it "should raise an error if called without a symbol or hash" do
|
|
707
743
|
proc{GraphAlbum.eager_graph(Object.new)}.should raise_error(Sequel::Error)
|
|
@@ -710,35 +746,43 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
710
746
|
it "should not split results and assign associations if ungraphed is called" do
|
|
711
747
|
ds = GraphAlbum.eager_graph(:band).ungraphed
|
|
712
748
|
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
|
713
|
-
|
|
714
|
-
yield({:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3})
|
|
715
|
-
end
|
|
749
|
+
ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
|
|
716
750
|
ds.all.should == [GraphAlbum.load(:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3)]
|
|
717
751
|
end
|
|
718
752
|
|
|
753
|
+
it "should not modify existing dataset" do
|
|
754
|
+
ds1 = GraphAlbum.dataset
|
|
755
|
+
ds2 = ds1.eager_graph(:band)
|
|
756
|
+
proc{ds1.eager_graph(:band)}.should_not raise_error
|
|
757
|
+
proc{ds2.eager_graph(:tracks)}.should_not raise_error
|
|
758
|
+
proc{ds2.eager_graph(:tracks)}.should_not raise_error
|
|
759
|
+
end
|
|
760
|
+
|
|
719
761
|
it "should eagerly load a single many_to_one association" do
|
|
720
762
|
ds = GraphAlbum.eager_graph(:band)
|
|
721
763
|
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
|
722
|
-
|
|
723
|
-
yield({:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3})
|
|
724
|
-
end
|
|
764
|
+
ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
|
|
725
765
|
a = ds.all
|
|
726
|
-
a.should
|
|
727
|
-
a.
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
766
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
767
|
+
a.first.band.should == GraphBand.load(:id => 2, :vocalist_id=>3)
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
it "should eagerly load a single many_to_one association with the same name as a column" do
|
|
771
|
+
GraphAlbum.def_column_alias(:band_id_id, :band_id)
|
|
772
|
+
GraphAlbum.many_to_one :band_id, :key_column=>:band_id, :class=>GraphBand
|
|
773
|
+
ds = GraphAlbum.eager_graph(:band_id)
|
|
774
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, band_id.id AS band_id_id, band_id.vocalist_id FROM albums LEFT OUTER JOIN bands AS band_id ON (band_id.id = albums.band_id)'
|
|
775
|
+
ds._fetch = {:id=>1, :band_id=>2, :band_id_id=>2, :vocalist_id=>3}
|
|
776
|
+
a = ds.all
|
|
777
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
778
|
+
a.first.band_id.should == GraphBand.load(:id => 2, :vocalist_id=>3)
|
|
733
779
|
end
|
|
734
780
|
|
|
735
781
|
it "should eagerly load a single one_to_one association" do
|
|
736
782
|
GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
|
|
737
783
|
ds = GraphAlbum.eager_graph(:track)
|
|
738
784
|
ds.sql.should == 'SELECT albums.id, albums.band_id, track.id AS track_id, track.album_id FROM albums LEFT OUTER JOIN tracks AS track ON (track.album_id = albums.id)'
|
|
739
|
-
|
|
740
|
-
yield({:id=>1, :band_id=>2, :track_id=>3, :album_id=>1})
|
|
741
|
-
end
|
|
785
|
+
ds._fetch = {:id=>1, :band_id=>2, :track_id=>3, :album_id=>1}
|
|
742
786
|
a = ds.all
|
|
743
787
|
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
744
788
|
a.first.track.should == GraphTrack.load(:id => 3, :album_id=>1)
|
|
@@ -747,130 +791,88 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
747
791
|
it "should eagerly load a single one_to_many association" do
|
|
748
792
|
ds = GraphAlbum.eager_graph(:tracks)
|
|
749
793
|
ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)'
|
|
750
|
-
|
|
751
|
-
yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
|
|
752
|
-
end
|
|
794
|
+
ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
|
|
753
795
|
a = ds.all
|
|
754
|
-
a.should
|
|
755
|
-
a.
|
|
756
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
757
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
758
|
-
a = a.first
|
|
759
|
-
a.tracks.should be_a_kind_of(Array)
|
|
760
|
-
a.tracks.size.should == 1
|
|
761
|
-
a.tracks.first.should be_a_kind_of(GraphTrack)
|
|
762
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
796
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
797
|
+
a.first.tracks.should == [GraphTrack.load(:id => 3, :album_id=>1)]
|
|
763
798
|
end
|
|
764
799
|
|
|
765
800
|
it "should eagerly load a single many_to_many association" do
|
|
766
801
|
ds = GraphAlbum.eager_graph(:genres)
|
|
767
802
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id)'
|
|
768
|
-
|
|
769
|
-
yield({:id=>1, :band_id=>2, :genres_id=>4})
|
|
770
|
-
end
|
|
803
|
+
ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4}
|
|
771
804
|
a = ds.all
|
|
772
|
-
a.should
|
|
773
|
-
a.
|
|
774
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
775
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
776
|
-
a = a.first
|
|
777
|
-
a.genres.should be_a_kind_of(Array)
|
|
778
|
-
a.genres.size.should == 1
|
|
779
|
-
a.genres.first.should be_a_kind_of(GraphGenre)
|
|
780
|
-
a.genres.first.values.should == {:id => 4}
|
|
805
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
806
|
+
a.first.genres.should == [GraphGenre.load(:id => 4)]
|
|
781
807
|
end
|
|
782
808
|
|
|
809
|
+
it "should correctly handle an aliased join table in many_to_many" do
|
|
810
|
+
c = Class.new(GraphAlbum)
|
|
811
|
+
c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___ga
|
|
812
|
+
c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS ga ON (ga.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ga.genre_id)'
|
|
813
|
+
|
|
814
|
+
c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___albums
|
|
815
|
+
c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS albums_0 ON (albums_0.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = albums_0.genre_id)'
|
|
816
|
+
|
|
817
|
+
c.many_to_many :genres, :clone=>:genres, :join_table=>:ag___genres
|
|
818
|
+
c.eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag AS genres_0 ON (genres_0.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = genres_0.genre_id)'
|
|
819
|
+
end
|
|
820
|
+
|
|
783
821
|
it "should eagerly load multiple associations in a single call" do
|
|
784
822
|
ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
|
|
785
823
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
|
786
|
-
|
|
787
|
-
yield({:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6})
|
|
788
|
-
end
|
|
824
|
+
ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6}
|
|
789
825
|
a = ds.all
|
|
790
|
-
a.should
|
|
791
|
-
a.size.should == 1
|
|
792
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
793
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
826
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
794
827
|
a = a.first
|
|
795
|
-
a.band.should
|
|
796
|
-
a.
|
|
797
|
-
a.
|
|
798
|
-
a.tracks.size.should == 1
|
|
799
|
-
a.tracks.first.should be_a_kind_of(GraphTrack)
|
|
800
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
801
|
-
a.genres.should be_a_kind_of(Array)
|
|
802
|
-
a.genres.size.should == 1
|
|
803
|
-
a.genres.first.should be_a_kind_of(GraphGenre)
|
|
804
|
-
a.genres.first.values.should == {:id => 4}
|
|
828
|
+
a.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
|
|
829
|
+
a.tracks.should == [GraphTrack.load({:id => 3, :album_id=>1})]
|
|
830
|
+
a.genres.should == [GraphGenre.load(:id => 4)]
|
|
805
831
|
end
|
|
806
832
|
|
|
807
833
|
it "should eagerly load multiple associations in separate calls" do
|
|
808
834
|
ds = GraphAlbum.eager_graph(:genres).eager_graph(:tracks).eager_graph(:band)
|
|
809
835
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
|
810
|
-
|
|
811
|
-
yield({:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6})
|
|
812
|
-
end
|
|
836
|
+
ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6}
|
|
813
837
|
a = ds.all
|
|
814
|
-
a.should
|
|
815
|
-
a.size.should == 1
|
|
816
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
817
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
838
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
818
839
|
a = a.first
|
|
819
|
-
a.band.should
|
|
820
|
-
a.
|
|
821
|
-
a.
|
|
822
|
-
a.tracks.size.should == 1
|
|
823
|
-
a.tracks.first.should be_a_kind_of(GraphTrack)
|
|
824
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
825
|
-
a.genres.should be_a_kind_of(Array)
|
|
826
|
-
a.genres.size.should == 1
|
|
827
|
-
a.genres.first.should be_a_kind_of(GraphGenre)
|
|
828
|
-
a.genres.first.values.should == {:id => 4}
|
|
840
|
+
a.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
|
|
841
|
+
a.tracks.should == [GraphTrack.load({:id => 3, :album_id=>1})]
|
|
842
|
+
a.genres.should == [GraphGenre.load(:id => 4)]
|
|
829
843
|
end
|
|
830
844
|
|
|
831
845
|
it "should allow cascading of eager loading for associations of associated models" do
|
|
832
846
|
ds = GraphTrack.eager_graph(:album=>{:band=>:members})
|
|
833
847
|
ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
|
|
834
|
-
|
|
835
|
-
yield({:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6})
|
|
836
|
-
end
|
|
848
|
+
ds._fetch = {:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6}
|
|
837
849
|
a = ds.all
|
|
838
|
-
a.should
|
|
839
|
-
a.size.should == 1
|
|
840
|
-
a.first.should be_a_kind_of(GraphTrack)
|
|
841
|
-
a.first.values.should == {:id => 3, :album_id => 1}
|
|
850
|
+
a.should == [GraphTrack.load(:id => 3, :album_id => 1)]
|
|
842
851
|
a = a.first
|
|
843
|
-
a.album.should
|
|
844
|
-
a.album.
|
|
845
|
-
a.album.band.should
|
|
846
|
-
a.album.band.values.should == {:id => 2, :vocalist_id=>6}
|
|
847
|
-
a.album.band.members.should be_a_kind_of(Array)
|
|
848
|
-
a.album.band.members.size.should == 1
|
|
849
|
-
a.album.band.members.first.should be_a_kind_of(GraphBandMember)
|
|
850
|
-
a.album.band.members.first.values.should == {:id => 5}
|
|
852
|
+
a.album.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
|
853
|
+
a.album.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
|
|
854
|
+
a.album.band.members.should == [GraphBandMember.load(:id => 5)]
|
|
851
855
|
end
|
|
852
856
|
|
|
853
857
|
it "should allow cascading of eager loading for multiple *_to_many associations, eliminating duplicates caused by cartesian products" do
|
|
854
858
|
ds = GraphBand.eager_graph({:albums=>:tracks}, :members)
|
|
855
859
|
ds.sql.should == 'SELECT bands.id, bands.vocalist_id, albums.id AS albums_id, albums.band_id, tracks.id AS tracks_id, tracks.album_id, members.id AS members_id FROM bands LEFT OUTER JOIN albums ON (albums.band_id = bands.id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
yield({:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>2, :album_id=>6, :members_id=>6})
|
|
873
|
-
end
|
|
860
|
+
ds._fetch = [{:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>4, :album_id=>3, :members_id=>5},
|
|
861
|
+
{:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>4, :album_id=>3, :members_id=>6},
|
|
862
|
+
{:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>5, :album_id=>3, :members_id=>5},
|
|
863
|
+
{:id=>1, :vocalist_id=>2, :albums_id=>3, :band_id=>1, :tracks_id=>5, :album_id=>3, :members_id=>6},
|
|
864
|
+
{:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>6, :album_id=>4, :members_id=>5},
|
|
865
|
+
{:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>6, :album_id=>4, :members_id=>6},
|
|
866
|
+
{:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>7, :album_id=>4, :members_id=>5},
|
|
867
|
+
{:id=>1, :vocalist_id=>2, :albums_id=>4, :band_id=>1, :tracks_id=>7, :album_id=>4, :members_id=>6},
|
|
868
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>8, :album_id=>5, :members_id=>5},
|
|
869
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>8, :album_id=>5, :members_id=>6},
|
|
870
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>9, :album_id=>5, :members_id=>5},
|
|
871
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>5, :band_id=>2, :tracks_id=>9, :album_id=>5, :members_id=>6},
|
|
872
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>1, :album_id=>6, :members_id=>5},
|
|
873
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>1, :album_id=>6, :members_id=>6},
|
|
874
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>2, :album_id=>6, :members_id=>5},
|
|
875
|
+
{:id=>2, :vocalist_id=>2, :albums_id=>6, :band_id=>2, :tracks_id=>2, :album_id=>6, :members_id=>6}]
|
|
874
876
|
a = ds.all
|
|
875
877
|
a.should == [GraphBand.load(:id=>1, :vocalist_id=>2), GraphBand.load(:id=>2, :vocalist_id=>2)]
|
|
876
878
|
members = a.map{|x| x.members}
|
|
@@ -885,85 +887,49 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
885
887
|
MODEL_DB.reset
|
|
886
888
|
ds = GraphAlbum.eager_graph(:tracks)
|
|
887
889
|
ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)'
|
|
888
|
-
|
|
889
|
-
@db << sql
|
|
890
|
-
yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
|
|
891
|
-
end
|
|
890
|
+
ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
|
|
892
891
|
a = ds.all
|
|
893
|
-
a.should
|
|
894
|
-
a.size.should == 1
|
|
895
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
896
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
892
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
897
893
|
a = a.first
|
|
898
|
-
a.tracks.should
|
|
899
|
-
a.tracks.size.should == 1
|
|
900
|
-
a.tracks.first.should be_a_kind_of(GraphTrack)
|
|
901
|
-
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
|
902
|
-
a.tracks.first.album.should be_a_kind_of(GraphAlbum)
|
|
894
|
+
a.tracks.should == [GraphTrack.load(:id => 3, :album_id=>1)]
|
|
903
895
|
a.tracks.first.album.should == a
|
|
904
|
-
MODEL_DB.sqls.
|
|
896
|
+
MODEL_DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)']
|
|
905
897
|
end
|
|
906
898
|
|
|
907
899
|
it "should eager load multiple associations from the same table" do
|
|
908
900
|
ds = GraphBand.eager_graph(:vocalist, :members)
|
|
909
901
|
ds.sql.should == 'SELECT bands.id, bands.vocalist_id, vocalist.id AS vocalist_id_0, members.id AS members_id FROM bands LEFT OUTER JOIN members AS vocalist ON (vocalist.id = bands.vocalist_id) LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
|
|
910
|
-
|
|
911
|
-
yield({:id=>2, :vocalist_id=>6, :vocalist_id_0=>6, :members_id=>5})
|
|
912
|
-
end
|
|
902
|
+
ds._fetch = {:id=>2, :vocalist_id=>6, :vocalist_id_0=>6, :members_id=>5}
|
|
913
903
|
a = ds.all
|
|
914
|
-
a.should
|
|
915
|
-
a.size.should == 1
|
|
916
|
-
a.first.should be_a_kind_of(GraphBand)
|
|
917
|
-
a.first.values.should == {:id => 2, :vocalist_id => 6}
|
|
904
|
+
a.should == [GraphBand.load(:id => 2, :vocalist_id => 6)]
|
|
918
905
|
a = a.first
|
|
919
|
-
a.vocalist.should
|
|
920
|
-
a.
|
|
921
|
-
a.members.should be_a_kind_of(Array)
|
|
922
|
-
a.members.size.should == 1
|
|
923
|
-
a.members.first.should be_a_kind_of(GraphBandMember)
|
|
924
|
-
a.members.first.values.should == {:id => 5}
|
|
906
|
+
a.vocalist.should == GraphBandMember.load(:id => 6)
|
|
907
|
+
a.members.should == [GraphBandMember.load(:id => 5)]
|
|
925
908
|
end
|
|
926
909
|
|
|
927
|
-
it "should give you a
|
|
910
|
+
it "should give you a plain hash when called without .all" do
|
|
928
911
|
ds = GraphAlbum.eager_graph(:band)
|
|
929
912
|
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
end
|
|
933
|
-
ds.first.should == {:albums=>GraphAlbum.load(:id => 1, :band_id => 2), :band=>GraphBand.load(:id => 2, :vocalist_id=>3)}
|
|
913
|
+
ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
|
|
914
|
+
ds.first.should == {:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>3}
|
|
934
915
|
end
|
|
935
916
|
|
|
936
917
|
it "should not drop any associated objects if the graph could not be a cartesian product" do
|
|
937
918
|
ds = GraphBand.eager_graph(:members, :vocalist)
|
|
938
919
|
ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, vocalist.id AS vocalist_id_0 FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN members AS vocalist ON (vocalist.id = bands.vocalist_id)'
|
|
939
|
-
|
|
940
|
-
yield({:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6})
|
|
941
|
-
yield({:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6})
|
|
942
|
-
end
|
|
920
|
+
ds._fetch = [{:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6}, {:id=>2, :vocalist_id=>6, :members_id=>5, :vocalist_id_0=>6}]
|
|
943
921
|
a = ds.all
|
|
944
|
-
a.should
|
|
945
|
-
a.size.should == 1
|
|
946
|
-
a.first.should be_a_kind_of(GraphBand)
|
|
947
|
-
a.first.values.should == {:id => 2, :vocalist_id => 6}
|
|
922
|
+
a.should == [GraphBand.load(:id => 2, :vocalist_id => 6)]
|
|
948
923
|
a = a.first
|
|
949
|
-
a.vocalist.should
|
|
950
|
-
a.
|
|
951
|
-
a.members.should be_a_kind_of(Array)
|
|
952
|
-
a.members.size.should == 2
|
|
953
|
-
a.members.first.should be_a_kind_of(GraphBandMember)
|
|
954
|
-
a.members.first.values.should == {:id => 5}
|
|
955
|
-
a.members.last.should be_a_kind_of(GraphBandMember)
|
|
956
|
-
a.members.last.values.should == {:id => 5}
|
|
924
|
+
a.vocalist.should == GraphBandMember.load(:id => 6)
|
|
925
|
+
a.members.should == [GraphBandMember.load(:id => 5), GraphBandMember.load(:id => 5)]
|
|
957
926
|
end
|
|
958
927
|
|
|
959
928
|
it "should respect the :cartesian_product_number option" do
|
|
960
929
|
GraphBand.many_to_one :other_vocalist, :class=>'GraphBandMember', :key=>:vocalist_id, :cartesian_product_number=>1
|
|
961
930
|
ds = GraphBand.eager_graph(:members, :other_vocalist)
|
|
962
931
|
ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, other_vocalist.id AS other_vocalist_id FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN members AS other_vocalist ON (other_vocalist.id = bands.vocalist_id)'
|
|
963
|
-
|
|
964
|
-
yield({:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6})
|
|
965
|
-
yield({:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6})
|
|
966
|
-
end
|
|
932
|
+
ds._fetch = [{:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6}, {:id=>2, :vocalist_id=>6, :members_id=>5, :other_vocalist_id=>6}]
|
|
967
933
|
a = ds.all
|
|
968
934
|
a.should == [GraphBand.load(:id=>2, :vocalist_id => 6)]
|
|
969
935
|
a.first.other_vocalist.should == GraphBandMember.load(:id=>6)
|
|
@@ -973,57 +939,28 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
973
939
|
it "should drop duplicate items that occur in sequence if the graph could be a cartesian product" do
|
|
974
940
|
ds = GraphBand.eager_graph(:members, :genres)
|
|
975
941
|
ds.sql.should == 'SELECT bands.id, bands.vocalist_id, members.id AS members_id, genres.id AS genres_id FROM bands LEFT OUTER JOIN bm ON (bm.band_id = bands.id) LEFT OUTER JOIN members ON (members.id = bm.member_id) LEFT OUTER JOIN bg ON (bg.band_id = bands.id) LEFT OUTER JOIN genres ON (genres.id = bg.genre_id)'
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
yield({:id=>2, :vocalist_id=>6, :members_id=>6, :genres_id=>8})
|
|
981
|
-
end
|
|
942
|
+
ds._fetch = [{:id=>2, :vocalist_id=>6, :members_id=>5, :genres_id=>7},
|
|
943
|
+
{:id=>2, :vocalist_id=>6, :members_id=>5, :genres_id=>8},
|
|
944
|
+
{:id=>2, :vocalist_id=>6, :members_id=>6, :genres_id=>7},
|
|
945
|
+
{:id=>2, :vocalist_id=>6, :members_id=>6, :genres_id=>8}]
|
|
982
946
|
a = ds.all
|
|
983
|
-
a.should
|
|
984
|
-
a.size.should == 1
|
|
985
|
-
a.first.should be_a_kind_of(GraphBand)
|
|
986
|
-
a.first.values.should == {:id => 2, :vocalist_id => 6}
|
|
947
|
+
a.should == [GraphBand.load(:id => 2, :vocalist_id => 6)]
|
|
987
948
|
a = a.first
|
|
988
|
-
a.members.should
|
|
989
|
-
a.
|
|
990
|
-
a.members.first.should be_a_kind_of(GraphBandMember)
|
|
991
|
-
a.members.first.values.should == {:id => 5}
|
|
992
|
-
a.members.last.should be_a_kind_of(GraphBandMember)
|
|
993
|
-
a.members.last.values.should == {:id => 6}
|
|
994
|
-
a.genres.size.should == 2
|
|
995
|
-
a.genres.first.should be_a_kind_of(GraphGenre)
|
|
996
|
-
a.genres.first.values.should == {:id => 7}
|
|
997
|
-
a.genres.last.should be_a_kind_of(GraphGenre)
|
|
998
|
-
a.genres.last.values.should == {:id => 8}
|
|
949
|
+
a.members.should == [GraphBandMember.load(:id => 5), GraphBandMember.load(:id => 6)]
|
|
950
|
+
a.genres.should == [GraphGenre.load(:id => 7), GraphGenre.load(:id => 8)]
|
|
999
951
|
end
|
|
1000
952
|
|
|
1001
953
|
it "should be able to be used in combination with #eager" do
|
|
1002
954
|
MODEL_DB.reset
|
|
1003
955
|
ds = GraphAlbum.eager_graph(:tracks).eager(:genres)
|
|
1004
|
-
|
|
1005
|
-
@db << sql
|
|
1006
|
-
yield({:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1})
|
|
1007
|
-
end
|
|
956
|
+
ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>3, :album_id=>1}
|
|
1008
957
|
ds2 = GraphGenre.dataset
|
|
1009
|
-
|
|
1010
|
-
@db << sql
|
|
1011
|
-
yield({:id=>6, :x_foreign_key_x=>1})
|
|
1012
|
-
end
|
|
958
|
+
ds2._fetch = {:id=>6, :x_foreign_key_x=>1}
|
|
1013
959
|
a = ds.all
|
|
1014
|
-
a.should
|
|
1015
|
-
a.size.should == 1
|
|
1016
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
1017
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
960
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1018
961
|
a = a.first
|
|
1019
|
-
a.tracks.should
|
|
1020
|
-
a.
|
|
1021
|
-
a.tracks.first.should be_a_kind_of(GraphTrack)
|
|
1022
|
-
a.tracks.first.values.should == {:id=>3, :album_id=>1}
|
|
1023
|
-
a.genres.should be_a_kind_of(Array)
|
|
1024
|
-
a.genres.size.should == 1
|
|
1025
|
-
a.genres.first.should be_a_kind_of(GraphGenre)
|
|
1026
|
-
a.genres.first.values.should == {:id=>6}
|
|
962
|
+
a.tracks.should == [GraphTrack.load(:id=>3, :album_id=>1)]
|
|
963
|
+
a.genres.should == [GraphGenre.load(:id => 6)]
|
|
1027
964
|
MODEL_DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)',
|
|
1028
965
|
"SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
|
|
1029
966
|
end
|
|
@@ -1031,110 +968,65 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1031
968
|
it "should handle no associated records for a single many_to_one association" do
|
|
1032
969
|
ds = GraphAlbum.eager_graph(:band)
|
|
1033
970
|
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
|
1034
|
-
|
|
1035
|
-
yield({:id=>1, :band_id=>2, :band_id_0=>nil, :vocalist_id=>nil})
|
|
1036
|
-
end
|
|
971
|
+
ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>nil, :vocalist_id=>nil}
|
|
1037
972
|
a = ds.all
|
|
1038
|
-
a.should
|
|
1039
|
-
a.
|
|
1040
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
1041
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
1042
|
-
a.first.associations.fetch(:band, 2).should == nil
|
|
973
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
974
|
+
a.first.band.should == nil
|
|
1043
975
|
end
|
|
1044
976
|
|
|
1045
977
|
it "should handle no associated records for a single one_to_many association" do
|
|
1046
978
|
ds = GraphAlbum.eager_graph(:tracks)
|
|
1047
979
|
ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)'
|
|
1048
|
-
|
|
1049
|
-
yield({:id=>1, :band_id=>2, :tracks_id=>nil, :album_id=>nil})
|
|
1050
|
-
end
|
|
980
|
+
ds._fetch = {:id=>1, :band_id=>2, :tracks_id=>nil, :album_id=>nil}
|
|
1051
981
|
a = ds.all
|
|
1052
|
-
a.should
|
|
1053
|
-
a.size.should == 1
|
|
1054
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
1055
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
982
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1056
983
|
a.first.tracks.should == []
|
|
1057
984
|
end
|
|
1058
985
|
|
|
1059
986
|
it "should handle no associated records for a single many_to_many association" do
|
|
1060
987
|
ds = GraphAlbum.eager_graph(:genres)
|
|
1061
988
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id)'
|
|
1062
|
-
|
|
1063
|
-
yield({:id=>1, :band_id=>2, :genres_id=>nil})
|
|
1064
|
-
end
|
|
989
|
+
ds._fetch = {:id=>1, :band_id=>2, :genres_id=>nil}
|
|
1065
990
|
a = ds.all
|
|
1066
|
-
a.should
|
|
1067
|
-
a.size.should == 1
|
|
1068
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
1069
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
991
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1070
992
|
a.first.genres.should == []
|
|
1071
993
|
end
|
|
1072
994
|
|
|
1073
995
|
it "should handle missing associated records when loading multiple associations" do
|
|
1074
996
|
ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
|
|
1075
997
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
yield({:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>6, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil})
|
|
1081
|
-
end
|
|
998
|
+
ds._fetch = [{:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>3, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil},
|
|
999
|
+
{:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>4, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil},
|
|
1000
|
+
{:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>5, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil},
|
|
1001
|
+
{:id=>1, :band_id=>2, :genres_id=>nil, :tracks_id=>6, :album_id=>1, :band_id_0=>nil, :vocalist_id=>nil}]
|
|
1082
1002
|
a = ds.all
|
|
1083
|
-
a.should
|
|
1084
|
-
a.size.should == 1
|
|
1085
|
-
a.first.should be_a_kind_of(GraphAlbum)
|
|
1086
|
-
a.first.values.should == {:id => 1, :band_id => 2}
|
|
1003
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1087
1004
|
a = a.first
|
|
1088
|
-
a.tracks.should
|
|
1089
|
-
a.
|
|
1090
|
-
a.tracks.first.should be_a_kind_of(GraphTrack)
|
|
1091
|
-
a.tracks.collect{|x|x[:id]}.should == [3,4,5,6]
|
|
1092
|
-
a.associations.fetch(:band, 2).should == nil
|
|
1005
|
+
a.tracks.should == [GraphTrack.load(:id => 3, :album_id => 1), GraphTrack.load(:id => 4, :album_id => 1), GraphTrack.load(:id => 5, :album_id => 1), GraphTrack.load(:id => 6, :album_id => 1)]
|
|
1006
|
+
a.band.should == nil
|
|
1093
1007
|
a.genres.should == []
|
|
1094
1008
|
end
|
|
1095
1009
|
|
|
1096
1010
|
it "should handle missing associated records when cascading eager loading for associations of associated models" do
|
|
1097
1011
|
ds = GraphTrack.eager_graph(:album=>{:band=>:members})
|
|
1098
1012
|
ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
yield({:id=>5, :album_id=>1, :album_id_0=>1, :band_id=>4, :members_id=>6, :band_id_0=>4, :vocalist_id=>8})
|
|
1105
|
-
end
|
|
1013
|
+
ds._fetch = [{:id=>2, :album_id=>2, :album_id_0=>nil, :band_id=>nil, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil},
|
|
1014
|
+
{:id=>3, :album_id=>3, :album_id_0=>3, :band_id=>3, :members_id=>nil, :band_id_0=>nil, :vocalist_id=>nil},
|
|
1015
|
+
{:id=>4, :album_id=>4, :album_id_0=>4, :band_id=>2, :members_id=>nil, :band_id_0=>2, :vocalist_id=>6},
|
|
1016
|
+
{:id=>5, :album_id=>1, :album_id_0=>1, :band_id=>4, :members_id=>5, :band_id_0=>4, :vocalist_id=>8},
|
|
1017
|
+
{:id=>5, :album_id=>1, :album_id_0=>1, :band_id=>4, :members_id=>6, :band_id_0=>4, :vocalist_id=>8}]
|
|
1106
1018
|
a = ds.all
|
|
1107
|
-
a.should
|
|
1108
|
-
a.
|
|
1109
|
-
a.
|
|
1110
|
-
a.
|
|
1111
|
-
a[0].associations.fetch(:album, 2).should == nil
|
|
1112
|
-
a[1].album.should be_a_kind_of(GraphAlbum)
|
|
1113
|
-
a[1].album.values.should == {:id => 3, :band_id => 3}
|
|
1114
|
-
a[1].album.associations.fetch(:band, 2).should == nil
|
|
1115
|
-
a[2].album.should be_a_kind_of(GraphAlbum)
|
|
1116
|
-
a[2].album.values.should == {:id => 4, :band_id => 2}
|
|
1117
|
-
a[2].album.band.should be_a_kind_of(GraphBand)
|
|
1118
|
-
a[2].album.band.values.should == {:id => 2, :vocalist_id=>6}
|
|
1119
|
-
a[2].album.band.members.should == []
|
|
1120
|
-
a[3].album.should be_a_kind_of(GraphAlbum)
|
|
1121
|
-
a[3].album.values.should == {:id => 1, :band_id => 4}
|
|
1122
|
-
a[3].album.band.should be_a_kind_of(GraphBand)
|
|
1123
|
-
a[3].album.band.values.should == {:id => 4, :vocalist_id=>8}
|
|
1124
|
-
a[3].album.band.members.size.should == 2
|
|
1125
|
-
a[3].album.band.members.first.should be_a_kind_of(GraphBandMember)
|
|
1126
|
-
a[3].album.band.members.first.values.should == {:id => 5}
|
|
1127
|
-
a[3].album.band.members.last.should be_a_kind_of(GraphBandMember)
|
|
1128
|
-
a[3].album.band.members.last.values.should == {:id => 6}
|
|
1019
|
+
a.should == [GraphTrack.load(:id => 2, :album_id => 2), GraphTrack.load(:id => 3, :album_id => 3), GraphTrack.load(:id => 4, :album_id => 4), GraphTrack.load(:id => 5, :album_id => 1)]
|
|
1020
|
+
a.map{|x| x.album}.should == [nil, GraphAlbum.load(:id => 3, :band_id => 3), GraphAlbum.load(:id => 4, :band_id => 2), GraphAlbum.load(:id => 1, :band_id => 4)]
|
|
1021
|
+
a.map{|x| x.album.band if x.album}.should == [nil, nil, GraphBand.load(:id => 2, :vocalist_id=>6), GraphBand.load(:id => 4, :vocalist_id=>8)]
|
|
1022
|
+
a.map{|x| x.album.band.members if x.album && x.album.band}.should == [nil, nil, [], [GraphBandMember.load(:id => 5), GraphBandMember.load(:id => 6)]]
|
|
1129
1023
|
end
|
|
1130
1024
|
|
|
1131
1025
|
it "should respect the association's :primary_key option" do
|
|
1132
1026
|
GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :primary_key=>:vocalist_id
|
|
1133
1027
|
ds = GraphAlbum.eager_graph(:inner_band)
|
|
1134
1028
|
ds.sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS inner_band ON (inner_band.vocalist_id = albums.band_id)'
|
|
1135
|
-
|
|
1136
|
-
yield({:id=>3, :band_id=>2, :inner_band_id=>5, :vocalist_id=>2})
|
|
1137
|
-
end
|
|
1029
|
+
ds._fetch = {:id=>3, :band_id=>2, :inner_band_id=>5, :vocalist_id=>2}
|
|
1138
1030
|
as = ds.all
|
|
1139
1031
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
|
1140
1032
|
as.first.inner_band.should == GraphBand.load(:id=>5, :vocalist_id=>2)
|
|
@@ -1142,10 +1034,7 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1142
1034
|
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :primary_key=>:band_id
|
|
1143
1035
|
ds = GraphAlbum.eager_graph(:right_tracks)
|
|
1144
1036
|
ds.sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON (right_tracks.album_id = albums.band_id)'
|
|
1145
|
-
|
|
1146
|
-
yield({:id=>3, :band_id=>2, :right_tracks_id=>5, :album_id=>2})
|
|
1147
|
-
yield({:id=>3, :band_id=>2, :right_tracks_id=>6, :album_id=>2})
|
|
1148
|
-
end
|
|
1037
|
+
ds._fetch = [{:id=>3, :band_id=>2, :right_tracks_id=>5, :album_id=>2}, {:id=>3, :band_id=>2, :right_tracks_id=>6, :album_id=>2}]
|
|
1149
1038
|
as = ds.all
|
|
1150
1039
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
|
1151
1040
|
as.first.right_tracks.should == [GraphTrack.load(:id=>5, :album_id=>2), GraphTrack.load(:id=>6, :album_id=>2)]
|
|
@@ -1155,9 +1044,7 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1155
1044
|
GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>[:band_id, :id], :primary_key=>[:vocalist_id, :id]
|
|
1156
1045
|
ds = GraphAlbum.eager_graph(:inner_band)
|
|
1157
1046
|
ds.sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS inner_band ON ((inner_band.vocalist_id = albums.band_id) AND (inner_band.id = albums.id))'
|
|
1158
|
-
|
|
1159
|
-
yield({:id=>3, :band_id=>2, :inner_band_id=>3, :vocalist_id=>2})
|
|
1160
|
-
end
|
|
1047
|
+
ds._fetch = {:id=>3, :band_id=>2, :inner_band_id=>3, :vocalist_id=>2}
|
|
1161
1048
|
as = ds.all
|
|
1162
1049
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
|
1163
1050
|
as.first.inner_band.should == GraphBand.load(:id=>3, :vocalist_id=>2)
|
|
@@ -1167,9 +1054,7 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1167
1054
|
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>[:album_id, :id], :primary_key=>[:band_id, :id]
|
|
1168
1055
|
ds = GraphAlbum.eager_graph(:right_tracks)
|
|
1169
1056
|
ds.sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON ((right_tracks.album_id = albums.band_id) AND (right_tracks.id = albums.id))'
|
|
1170
|
-
|
|
1171
|
-
yield({:id=>3, :band_id=>2, :right_tracks_id=>3, :album_id=>2})
|
|
1172
|
-
end
|
|
1057
|
+
ds._fetch = {:id=>3, :band_id=>2, :right_tracks_id=>3, :album_id=>2}
|
|
1173
1058
|
as = ds.all
|
|
1174
1059
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
|
1175
1060
|
as.first.right_tracks.should == [GraphTrack.load(:id=>3, :album_id=>2)]
|
|
@@ -1179,10 +1064,7 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1179
1064
|
GraphAlbum.many_to_many :sbands, :class=>'GraphBand', :left_key=>[:l1, :l2], :left_primary_key=>[:band_id, :id], :right_key=>[:r1, :r2], :right_primary_key=>[:vocalist_id, :id], :join_table=>:b
|
|
1180
1065
|
ds = GraphAlbum.eager_graph(:sbands)
|
|
1181
1066
|
ds.sql.should == 'SELECT albums.id, albums.band_id, sbands.id AS sbands_id, sbands.vocalist_id FROM albums LEFT OUTER JOIN b ON ((b.l1 = albums.band_id) AND (b.l2 = albums.id)) LEFT OUTER JOIN bands AS sbands ON ((sbands.vocalist_id = b.r1) AND (sbands.id = b.r2))'
|
|
1182
|
-
|
|
1183
|
-
yield({:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6})
|
|
1184
|
-
yield({:id=>3, :band_id=>2, :sbands_id=>6, :vocalist_id=>22})
|
|
1185
|
-
end
|
|
1067
|
+
ds._fetch = [{:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6}, {:id=>3, :band_id=>2, :sbands_id=>6, :vocalist_id=>22}]
|
|
1186
1068
|
as = ds.all
|
|
1187
1069
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
|
1188
1070
|
as.first.sbands.should == [GraphBand.load(:id=>5, :vocalist_id=>6), GraphBand.load(:id=>6, :vocalist_id=>22)]
|
|
@@ -1192,15 +1074,31 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1192
1074
|
GraphAlbum.many_to_many :inner_genres, :class=>'GraphGenre', :left_key=>:album_id, :left_primary_key=>:band_id, :right_key=>:genre_id, :right_primary_key=>:xxx, :join_table=>:ag
|
|
1193
1075
|
ds = GraphAlbum.eager_graph(:inner_genres)
|
|
1194
1076
|
ds.sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.band_id) LEFT OUTER JOIN genres AS inner_genres ON (inner_genres.xxx = ag.genre_id)'
|
|
1195
|
-
|
|
1196
|
-
yield({:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12})
|
|
1197
|
-
yield({:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22})
|
|
1198
|
-
end
|
|
1077
|
+
ds._fetch = [{:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12}, {:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22}]
|
|
1199
1078
|
as = ds.all
|
|
1200
1079
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
|
1201
1080
|
as.first.inner_genres.should == [GraphGenre.load(:id=>5), GraphGenre.load(:id=>6)]
|
|
1202
1081
|
end
|
|
1203
1082
|
|
|
1083
|
+
it "should respect composite primary keys for classes when eager loading" do
|
|
1084
|
+
c1 = Class.new(GraphAlbum)
|
|
1085
|
+
c2 = Class.new(GraphBand)
|
|
1086
|
+
c1.set_primary_key [:band_id, :id]
|
|
1087
|
+
c2.set_primary_key [:vocalist_id, :id]
|
|
1088
|
+
c1.many_to_many :sbands, :class=>c2, :left_key=>[:l1, :l2], :right_key=>[:r1, :r2], :join_table=>:b
|
|
1089
|
+
c2.one_to_many :salbums, :class=>c1, :key=>[:band_id, :id]
|
|
1090
|
+
ds = c1.eager_graph(:sbands=>:salbums)
|
|
1091
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, sbands.id AS sbands_id, sbands.vocalist_id, salbums.id AS salbums_id, salbums.band_id AS salbums_band_id FROM albums LEFT OUTER JOIN b ON ((b.l1 = albums.band_id) AND (b.l2 = albums.id)) LEFT OUTER JOIN bands AS sbands ON ((sbands.vocalist_id = b.r1) AND (sbands.id = b.r2)) LEFT OUTER JOIN albums AS salbums ON ((salbums.band_id = sbands.vocalist_id) AND (salbums.id = sbands.id))'
|
|
1092
|
+
ds._fetch = [{:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6, :salbums_id=>7, :salbums_band_id=>8},
|
|
1093
|
+
{:id=>3, :band_id=>2, :sbands_id=>5, :vocalist_id=>6, :salbums_id=>9, :salbums_band_id=>10},
|
|
1094
|
+
{:id=>3, :band_id=>2, :sbands_id=>6, :vocalist_id=>22, :salbums_id=>nil, :salbums_band_id=>nil},
|
|
1095
|
+
{:id=>7, :band_id=>8, :sbands_id=>nil, :vocalist_id=>nil, :salbums_id=>nil, :salbums_band_id=>nil}]
|
|
1096
|
+
as = ds.all
|
|
1097
|
+
as.should == [c1.load(:id=>3, :band_id=>2), c1.load(:id=>7, :band_id=>8)]
|
|
1098
|
+
as.map{|x| x.sbands}.should == [[c2.load(:id=>5, :vocalist_id=>6), c2.load(:id=>6, :vocalist_id=>22)], []]
|
|
1099
|
+
as.map{|x| x.sbands.map{|y| y.salbums}}.should == [[[c1.load(:id=>7, :band_id=>8), c1.load(:id=>9, :band_id=>10)], []], []]
|
|
1100
|
+
end
|
|
1101
|
+
|
|
1204
1102
|
it "should respect the association's :graph_select option" do
|
|
1205
1103
|
GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :graph_select=>:vocalist_id
|
|
1206
1104
|
GraphAlbum.eager_graph(:inner_band).sql.should == 'SELECT albums.id, albums.band_id, inner_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS inner_band ON (inner_band.id = albums.band_id)'
|
|
@@ -1212,6 +1110,14 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1212
1110
|
GraphAlbum.eager_graph(:inner_genres).sql.should == 'SELECT albums.id, albums.band_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS inner_genres ON (inner_genres.id = ag.genre_id)'
|
|
1213
1111
|
end
|
|
1214
1112
|
|
|
1113
|
+
it "should respect the association's :graph_alias_base option" do
|
|
1114
|
+
GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :graph_alias_base=>:foo
|
|
1115
|
+
ds = GraphAlbum.eager_graph(:inner_band)
|
|
1116
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, foo.id AS foo_id, foo.vocalist_id FROM albums LEFT OUTER JOIN bands AS foo ON (foo.id = albums.band_id)'
|
|
1117
|
+
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :graph_alias_base=>:foo
|
|
1118
|
+
ds.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, foo.id AS foo_id, foo.vocalist_id, foo_0.id AS foo_0_id, foo_0.album_id FROM albums LEFT OUTER JOIN bands AS foo ON (foo.id = albums.band_id) LEFT OUTER JOIN tracks AS foo_0 ON (foo_0.album_id = albums.id)'
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1215
1121
|
it "should respect the association's :graph_join_type option" do
|
|
1216
1122
|
GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :graph_join_type=>:inner
|
|
1217
1123
|
GraphAlbum.eager_graph(:inner_band).sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums INNER JOIN bands AS inner_band ON (inner_band.id = albums.band_id)'
|
|
@@ -1284,13 +1190,17 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1284
1190
|
GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :eager_grapher=>proc{|ds, aa, ta| ds.graph(GraphBand, {:active=>true}, :table_alias=>aa, :join_type=>:inner)}
|
|
1285
1191
|
GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums INNER JOIN bands AS active_band ON (active_band.active IS TRUE)"
|
|
1286
1192
|
|
|
1287
|
-
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :eager_grapher=>proc{|
|
|
1193
|
+
GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :eager_grapher=>proc{|eo| eo[:self].graph(GraphTrack, nil, :join_type=>:natural, :table_alias=>eo[:table_alias])}
|
|
1288
1194
|
GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums NATURAL JOIN tracks AS right_tracks'
|
|
1289
1195
|
|
|
1290
1196
|
GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :eager_grapher=>proc{|ds, aa, ta| ds.graph(:ag, {:album_id=>:id}, :table_alias=>:a123, :implicit_qualifier=>ta).graph(GraphGenre, [:album_id], :table_alias=>aa)}
|
|
1291
1197
|
GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag AS a123 ON (a123.album_id = albums.id) LEFT OUTER JOIN genres AS active_genres USING (album_id)"
|
|
1292
1198
|
end
|
|
1293
1199
|
|
|
1200
|
+
it "should raise an error if you use an :eager_grapher proc with the wrong arity" do
|
|
1201
|
+
proc{GraphAlbum.many_to_one :special_band, :eager_grapher=>proc{|a, b|}}.should raise_error(Sequel::Error)
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1294
1204
|
it "should respect the association's :graph_only_conditions option" do
|
|
1295
1205
|
GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :graph_only_conditions=>{:active=>true}
|
|
1296
1206
|
GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS active_band ON (active_band.active IS TRUE)"
|
|
@@ -1360,13 +1270,12 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1360
1270
|
GraphAlbum.many_to_many :inner_genres, :class=>'GraphGenre', :left_key=>:album_id, :left_primary_key=>:band_id, :right_key=>:genre_id, :right_primary_key=>:xxx, :join_table=>:ag
|
|
1361
1271
|
ds = GraphAlbum.eager_graph(:inner_genres)
|
|
1362
1272
|
ds.sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.band_id) LEFT OUTER JOIN genres AS inner_genres ON (inner_genres.xxx = ag.genre_id)'
|
|
1363
|
-
|
|
1364
|
-
yield({:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12})
|
|
1365
|
-
yield({:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22})
|
|
1366
|
-
end
|
|
1273
|
+
ds._fetch = [{:id=>3, :band_id=>2, :inner_genres_id=>5, :xxx=>12}, {:id=>3, :band_id=>2, :inner_genres_id=>6, :xxx=>22}]
|
|
1367
1274
|
as = ds.all
|
|
1368
1275
|
as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
|
|
1369
1276
|
as.first.inner_genres.should == [GraphGenre.load(:id=>5), GraphGenre.load(:id=>6)]
|
|
1277
|
+
GraphAlbum.set_primary_key :id
|
|
1278
|
+
GraphGenre.set_primary_key :id
|
|
1370
1279
|
end
|
|
1371
1280
|
|
|
1372
1281
|
it "should handle eager loading with schemas and aliases of different types" do
|
|
@@ -1386,10 +1295,102 @@ describe Sequel::Model, "#eager_graph" do
|
|
|
1386
1295
|
it "should eagerly load schema qualified tables correctly with joins" do
|
|
1387
1296
|
c1 = Class.new(GraphAlbum)
|
|
1388
1297
|
c2 = Class.new(GraphGenre)
|
|
1389
|
-
c1.dataset = c1.dataset.from(:s__a)
|
|
1298
|
+
ds = c1.dataset = c1.dataset.from(:s__a)
|
|
1299
|
+
def ds.columns() [:id] end
|
|
1390
1300
|
c2.dataset = c2.dataset.from(:s__g)
|
|
1391
1301
|
c1.many_to_many :a_genres, :class=>c2, :left_primary_key=>:id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:s__ag
|
|
1392
1302
|
ds = c1.join(:s__t, [:b_id]).eager_graph(:a_genres)
|
|
1393
1303
|
ds.sql.should == 'SELECT a.id, a_genres.id AS a_genres_id FROM (SELECT * FROM s.a INNER JOIN s.t USING (b_id)) AS a LEFT OUTER JOIN s.ag AS ag ON (ag.album_id = a.id) LEFT OUTER JOIN s.g AS a_genres ON (a_genres.id = ag.genre_id)'
|
|
1394
1304
|
end
|
|
1305
|
+
|
|
1306
|
+
it "should respect :after_load callbacks on associations when eager graphing" do
|
|
1307
|
+
GraphAlbum.many_to_one :al_band, :class=>GraphBand, :key=>:band_id, :after_load=>proc{|o, a| a.id *=2}
|
|
1308
|
+
GraphAlbum.one_to_many :al_tracks, :class=>GraphTrack, :key=>:album_id, :after_load=>proc{|o, os| os.each{|a| a.id *=2}}
|
|
1309
|
+
GraphAlbum.many_to_many :al_genres, :class=>GraphGenre, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :after_load=>proc{|o, os| os.each{|a| a.id *=2}}
|
|
1310
|
+
ds = GraphAlbum.eager_graph(:al_band, :al_tracks, :al_genres)
|
|
1311
|
+
ds.sql.should == "SELECT albums.id, albums.band_id, al_band.id AS al_band_id, al_band.vocalist_id, al_tracks.id AS al_tracks_id, al_tracks.album_id, al_genres.id AS al_genres_id FROM albums LEFT OUTER JOIN bands AS al_band ON (al_band.id = albums.band_id) LEFT OUTER JOIN tracks AS al_tracks ON (al_tracks.album_id = albums.id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS al_genres ON (al_genres.id = ag.genre_id)"
|
|
1312
|
+
ds._fetch = {:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_tracks_id=>5, :album_id=>6, :al_genres_id=>7}
|
|
1313
|
+
a = ds.all.first
|
|
1314
|
+
a.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
|
1315
|
+
a.al_band.should == GraphBand.load(:id=>6, :vocalist_id=>4)
|
|
1316
|
+
a.al_tracks.should == [GraphTrack.load(:id=>10, :album_id=>6)]
|
|
1317
|
+
a.al_genres.should == [GraphGenre.load(:id=>14)]
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
it "should respect limits on associations when eager graphing" do
|
|
1321
|
+
GraphAlbum.many_to_one :al_band, :class=>GraphBand, :key=>:band_id
|
|
1322
|
+
GraphAlbum.one_to_many :al_tracks, :class=>GraphTrack, :key=>:album_id, :limit=>2
|
|
1323
|
+
GraphAlbum.many_to_many :al_genres, :class=>GraphGenre, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :limit=>2
|
|
1324
|
+
ds = GraphAlbum.eager_graph(:al_band, :al_tracks, :al_genres)
|
|
1325
|
+
ds.sql.should == "SELECT albums.id, albums.band_id, al_band.id AS al_band_id, al_band.vocalist_id, al_tracks.id AS al_tracks_id, al_tracks.album_id, al_genres.id AS al_genres_id FROM albums LEFT OUTER JOIN bands AS al_band ON (al_band.id = albums.band_id) LEFT OUTER JOIN tracks AS al_tracks ON (al_tracks.album_id = albums.id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS al_genres ON (al_genres.id = ag.genre_id)"
|
|
1326
|
+
ds._fetch = [{:id=>1, :band_id=>2, :al_band_id=>3, :vocalist_id=>4, :al_tracks_id=>5, :album_id=>6, :al_genres_id=>7},
|
|
1327
|
+
{:id=>1, :band_id=>2, :al_band_id=>8, :vocalist_id=>9, :al_tracks_id=>10, :album_id=>11, :al_genres_id=>12},
|
|
1328
|
+
{:id=>1, :band_id=>2, :al_band_id=>13, :vocalist_id=>14, :al_tracks_id=>15, :album_id=>16, :al_genres_id=>17}]
|
|
1329
|
+
a = ds.all.first
|
|
1330
|
+
a.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
|
1331
|
+
a.al_band.should == GraphBand.load(:id=>3, :vocalist_id=>4)
|
|
1332
|
+
a.al_tracks.should == [GraphTrack.load(:id=>5, :album_id=>6), GraphTrack.load(:id=>10, :album_id=>11)]
|
|
1333
|
+
a.al_genres.should == [GraphGenre.load(:id=>7), GraphGenre.load(:id=>12)]
|
|
1334
|
+
end
|
|
1335
|
+
|
|
1336
|
+
it "should eagerly load a many_to_one association with a custom callback" do
|
|
1337
|
+
ds = GraphAlbum.eager_graph(:band => proc {|ds| ds.select(:id).columns(:id)})
|
|
1338
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0 FROM albums LEFT OUTER JOIN (SELECT id FROM bands) AS band ON (band.id = albums.band_id)'
|
|
1339
|
+
ds._fetch = {:id=>1, :band_id=>2, :band_id_0=>2}
|
|
1340
|
+
a = ds.all
|
|
1341
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1342
|
+
a.first.band.should == GraphBand.load(:id => 2)
|
|
1343
|
+
end
|
|
1344
|
+
|
|
1345
|
+
it "should eagerly load a one_to_one association with a custom callback" do
|
|
1346
|
+
GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
|
|
1347
|
+
ds = GraphAlbum.eager_graph(:track => proc {|ds| ds.select(:album_id).columns(:album_id)})
|
|
1348
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, track.album_id FROM albums LEFT OUTER JOIN (SELECT album_id FROM tracks) AS track ON (track.album_id = albums.id)'
|
|
1349
|
+
ds._fetch = {:id=>1, :band_id=>2, :album_id=>1}
|
|
1350
|
+
a = ds.all
|
|
1351
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1352
|
+
a.first.track.should == GraphTrack.load(:album_id=>1)
|
|
1353
|
+
end
|
|
1354
|
+
|
|
1355
|
+
it "should eagerly load a one_to_many association with a custom callback" do
|
|
1356
|
+
ds = GraphAlbum.eager_graph(:tracks => proc {|ds| ds.select(:album_id).columns(:album_id)})
|
|
1357
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, tracks.album_id FROM albums LEFT OUTER JOIN (SELECT album_id FROM tracks) AS tracks ON (tracks.album_id = albums.id)'
|
|
1358
|
+
ds._fetch = {:id=>1, :band_id=>2, :album_id=>1}
|
|
1359
|
+
a = ds.all
|
|
1360
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1361
|
+
a.first.tracks.should == [GraphTrack.load(:album_id=>1)]
|
|
1362
|
+
end
|
|
1363
|
+
|
|
1364
|
+
it "should eagerly load a many_to_many association with a custom callback" do
|
|
1365
|
+
ds = GraphAlbum.eager_graph(:genres => proc {|ds| ds.select(:id).columns(:id)})
|
|
1366
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN (SELECT id FROM genres) AS genres ON (genres.id = ag.genre_id)'
|
|
1367
|
+
ds._fetch = {:id=>1, :band_id=>2, :genres_id=>4}
|
|
1368
|
+
a = ds.all
|
|
1369
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
|
1370
|
+
a.first.genres.should == [GraphGenre.load(:id => 4)]
|
|
1371
|
+
end
|
|
1372
|
+
|
|
1373
|
+
it "should allow cascading of eager loading with a custom callback with hash value" do
|
|
1374
|
+
ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select(:id, :band_id).columns(:id, :band_id)}=>{:band=>:members}})
|
|
1375
|
+
ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN (SELECT id, band_id FROM albums) AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
|
|
1376
|
+
ds._fetch = {:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :members_id=>5, :band_id_0=>2, :vocalist_id=>6}
|
|
1377
|
+
a = ds.all
|
|
1378
|
+
a.should == [GraphTrack.load(:id => 3, :album_id => 1)]
|
|
1379
|
+
a = a.first
|
|
1380
|
+
a.album.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
|
1381
|
+
a.album.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
|
|
1382
|
+
a.album.band.members.should == [GraphBandMember.load(:id => 5)]
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1385
|
+
it "should allow cascading of eager loading with a custom callback with array value" do
|
|
1386
|
+
ds = GraphTrack.eager_graph(:album=>{proc{|ds| ds.select(:id, :band_id).columns(:id, :band_id)}=>[:band, :tracks]})
|
|
1387
|
+
ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, tracks_0.id AS tracks_0_id, tracks_0.album_id AS tracks_0_album_id FROM tracks LEFT OUTER JOIN (SELECT id, band_id FROM albums) AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN tracks AS tracks_0 ON (tracks_0.album_id = album.id)'
|
|
1388
|
+
ds._fetch = {:id=>3, :album_id=>1, :album_id_0=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>6, :tracks_0_id=>3, :tracks_0_album_id=>1}
|
|
1389
|
+
a = ds.all
|
|
1390
|
+
a.should == [GraphTrack.load(:id => 3, :album_id => 1)]
|
|
1391
|
+
a = a.first
|
|
1392
|
+
a.album.should == GraphAlbum.load(:id => 1, :band_id => 2)
|
|
1393
|
+
a.album.band.should == GraphBand.load(:id => 2, :vocalist_id=>6)
|
|
1394
|
+
a.album.tracks.should == [GraphTrack.load(:id => 3, :album_id => 1)]
|
|
1395
|
+
end
|
|
1395
1396
|
end
|