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