sequel 5.20.0 → 5.49.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +398 -1922
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -7
- data/doc/advanced_associations.rdoc +4 -4
- data/doc/association_basics.rdoc +80 -16
- data/doc/cheat_sheet.rdoc +6 -5
- data/doc/code_order.rdoc +10 -12
- data/doc/dataset_filtering.rdoc +17 -2
- data/doc/fork_safety.rdoc +84 -0
- data/doc/migration.rdoc +11 -5
- data/doc/model_dataset_method_design.rdoc +1 -1
- data/doc/model_plugins.rdoc +1 -1
- data/doc/opening_databases.rdoc +10 -2
- data/doc/postgresql.rdoc +82 -3
- data/doc/querying.rdoc +4 -4
- data/doc/release_notes/5.21.0.txt +87 -0
- data/doc/release_notes/5.22.0.txt +48 -0
- data/doc/release_notes/5.23.0.txt +56 -0
- data/doc/release_notes/5.24.0.txt +56 -0
- data/doc/release_notes/5.25.0.txt +32 -0
- data/doc/release_notes/5.26.0.txt +35 -0
- data/doc/release_notes/5.27.0.txt +21 -0
- data/doc/release_notes/5.28.0.txt +16 -0
- data/doc/release_notes/5.29.0.txt +22 -0
- data/doc/release_notes/5.30.0.txt +20 -0
- data/doc/release_notes/5.31.0.txt +148 -0
- data/doc/release_notes/5.32.0.txt +46 -0
- data/doc/release_notes/5.33.0.txt +24 -0
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/sharding.rdoc +2 -0
- data/doc/sql.rdoc +13 -1
- data/doc/testing.rdoc +20 -7
- data/doc/transactions.rdoc +0 -8
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +43 -35
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
- data/lib/sequel/adapters/jdbc/postgresql.rb +11 -17
- data/lib/sequel/adapters/jdbc/sqlite.rb +29 -0
- data/lib/sequel/adapters/jdbc.rb +24 -6
- data/lib/sequel/adapters/mysql.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +2 -3
- data/lib/sequel/adapters/odbc.rb +8 -6
- data/lib/sequel/adapters/oracle.rb +5 -4
- data/lib/sequel/adapters/postgres.rb +15 -9
- data/lib/sequel/adapters/shared/access.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +66 -21
- data/lib/sequel/adapters/shared/mysql.rb +27 -10
- data/lib/sequel/adapters/shared/oracle.rb +29 -23
- data/lib/sequel/adapters/shared/postgres.rb +271 -32
- data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
- data/lib/sequel/adapters/shared/sqlite.rb +161 -19
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +15 -2
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +4 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
- data/lib/sequel/connection_pool/single.rb +1 -1
- data/lib/sequel/connection_pool/threaded.rb +2 -2
- data/lib/sequel/core.rb +333 -319
- data/lib/sequel/database/connecting.rb +3 -4
- data/lib/sequel/database/logging.rb +7 -1
- data/lib/sequel/database/misc.rb +31 -12
- data/lib/sequel/database/query.rb +3 -1
- data/lib/sequel/database/schema_generator.rb +53 -51
- data/lib/sequel/database/schema_methods.rb +38 -23
- data/lib/sequel/database/transactions.rb +17 -18
- data/lib/sequel/dataset/actions.rb +14 -9
- data/lib/sequel/dataset/features.rb +16 -0
- data/lib/sequel/dataset/misc.rb +2 -2
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +26 -9
- data/lib/sequel/dataset/sql.rb +76 -25
- data/lib/sequel/dataset.rb +4 -2
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/connection_expiration.rb +2 -2
- data/lib/sequel/extensions/connection_validator.rb +2 -2
- data/lib/sequel/extensions/core_refinements.rb +2 -0
- data/lib/sequel/extensions/date_arithmetic.rb +36 -24
- data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/exclude_or_null.rb +68 -0
- data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
- data/lib/sequel/extensions/index_caching.rb +9 -7
- data/lib/sequel/extensions/inflector.rb +9 -1
- data/lib/sequel/extensions/integer64.rb +2 -0
- data/lib/sequel/extensions/migration.rb +11 -3
- data/lib/sequel/extensions/named_timezones.rb +56 -8
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +5 -0
- data/lib/sequel/extensions/pg_array_ops.rb +14 -6
- data/lib/sequel/extensions/pg_enum.rb +11 -3
- data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +6 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +54 -2
- data/lib/sequel/extensions/pg_inet.rb +15 -5
- data/lib/sequel/extensions/pg_interval.rb +36 -8
- data/lib/sequel/extensions/pg_json.rb +387 -123
- data/lib/sequel/extensions/pg_json_ops.rb +238 -0
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_range.rb +17 -9
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +4 -2
- data/lib/sequel/extensions/pg_row_ops.rb +24 -0
- data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +24 -7
- data/lib/sequel/extensions/server_block.rb +18 -7
- data/lib/sequel/extensions/sql_comments.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +1 -1
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model/associations.rb +356 -117
- data/lib/sequel/model/base.rb +107 -68
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +9 -3
- data/lib/sequel/model.rb +3 -1
- data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
- data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/association_proxies.rb +8 -2
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_validations.rb +39 -5
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/boolean_subsets.rb +4 -1
- data/lib/sequel/plugins/caching.rb +3 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +33 -28
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +7 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/csv_serializer.rb +28 -9
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +60 -22
- data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
- data/lib/sequel/plugins/insert_conflict.rb +72 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/json_serializer.rb +57 -35
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +15 -3
- data/lib/sequel/plugins/pg_array_associations.rb +58 -41
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +91 -30
- data/lib/sequel/plugins/prepared_statements.rb +15 -12
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +43 -35
- data/lib/sequel/plugins/serialization.rb +8 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +11 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +22 -15
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/static_cache.rb +9 -4
- data/lib/sequel/plugins/static_cache_cache.rb +53 -0
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +2 -0
- data/lib/sequel/plugins/throw_failures.rb +1 -1
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +9 -4
- data/lib/sequel/plugins/typecast_on_load.rb +3 -2
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/plugins/validation_helpers.rb +18 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +20 -5
- data/lib/sequel/timezones.rb +63 -17
- data/lib/sequel/version.rb +1 -1
- metadata +113 -381
- data/Rakefile +0 -151
- data/doc/release_notes/4.0.0.txt +0 -262
- data/doc/release_notes/4.1.0.txt +0 -85
- data/doc/release_notes/4.10.0.txt +0 -226
- data/doc/release_notes/4.11.0.txt +0 -147
- data/doc/release_notes/4.12.0.txt +0 -105
- data/doc/release_notes/4.13.0.txt +0 -169
- data/doc/release_notes/4.14.0.txt +0 -68
- data/doc/release_notes/4.15.0.txt +0 -56
- data/doc/release_notes/4.16.0.txt +0 -36
- data/doc/release_notes/4.17.0.txt +0 -38
- data/doc/release_notes/4.18.0.txt +0 -36
- data/doc/release_notes/4.19.0.txt +0 -45
- data/doc/release_notes/4.2.0.txt +0 -129
- data/doc/release_notes/4.20.0.txt +0 -79
- data/doc/release_notes/4.21.0.txt +0 -94
- data/doc/release_notes/4.22.0.txt +0 -72
- data/doc/release_notes/4.23.0.txt +0 -65
- data/doc/release_notes/4.24.0.txt +0 -99
- data/doc/release_notes/4.25.0.txt +0 -181
- data/doc/release_notes/4.26.0.txt +0 -44
- data/doc/release_notes/4.27.0.txt +0 -78
- data/doc/release_notes/4.28.0.txt +0 -57
- data/doc/release_notes/4.29.0.txt +0 -41
- data/doc/release_notes/4.3.0.txt +0 -40
- data/doc/release_notes/4.30.0.txt +0 -37
- data/doc/release_notes/4.31.0.txt +0 -57
- data/doc/release_notes/4.32.0.txt +0 -132
- data/doc/release_notes/4.33.0.txt +0 -88
- data/doc/release_notes/4.34.0.txt +0 -86
- data/doc/release_notes/4.35.0.txt +0 -130
- data/doc/release_notes/4.36.0.txt +0 -116
- data/doc/release_notes/4.37.0.txt +0 -50
- data/doc/release_notes/4.38.0.txt +0 -67
- data/doc/release_notes/4.39.0.txt +0 -127
- data/doc/release_notes/4.4.0.txt +0 -92
- data/doc/release_notes/4.40.0.txt +0 -179
- data/doc/release_notes/4.41.0.txt +0 -77
- data/doc/release_notes/4.42.0.txt +0 -221
- data/doc/release_notes/4.43.0.txt +0 -87
- data/doc/release_notes/4.44.0.txt +0 -125
- data/doc/release_notes/4.45.0.txt +0 -370
- data/doc/release_notes/4.46.0.txt +0 -404
- data/doc/release_notes/4.47.0.txt +0 -56
- data/doc/release_notes/4.48.0.txt +0 -293
- data/doc/release_notes/4.49.0.txt +0 -222
- data/doc/release_notes/4.5.0.txt +0 -34
- data/doc/release_notes/4.6.0.txt +0 -30
- data/doc/release_notes/4.7.0.txt +0 -103
- data/doc/release_notes/4.8.0.txt +0 -175
- data/doc/release_notes/4.9.0.txt +0 -190
- data/spec/adapter_spec.rb +0 -4
- data/spec/adapters/db2_spec.rb +0 -170
- data/spec/adapters/mssql_spec.rb +0 -804
- data/spec/adapters/mysql_spec.rb +0 -1065
- data/spec/adapters/oracle_spec.rb +0 -371
- data/spec/adapters/postgres_spec.rb +0 -4125
- data/spec/adapters/spec_helper.rb +0 -44
- data/spec/adapters/sqlanywhere_spec.rb +0 -97
- data/spec/adapters/sqlite_spec.rb +0 -652
- data/spec/bin_spec.rb +0 -278
- data/spec/core/connection_pool_spec.rb +0 -1250
- data/spec/core/database_spec.rb +0 -2865
- data/spec/core/dataset_spec.rb +0 -5515
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1455
- data/spec/core/mock_adapter_spec.rb +0 -722
- data/spec/core/object_graph_spec.rb +0 -336
- data/spec/core/placeholder_literalizer_spec.rb +0 -166
- data/spec/core/schema_generator_spec.rb +0 -214
- data/spec/core/schema_spec.rb +0 -1826
- data/spec/core/spec_helper.rb +0 -24
- data/spec/core/version_spec.rb +0 -14
- data/spec/core_extensions_spec.rb +0 -763
- data/spec/core_model_spec.rb +0 -2
- data/spec/core_spec.rb +0 -1
- data/spec/deprecation_helper.rb +0 -30
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -99
- data/spec/extensions/after_initialize_spec.rb +0 -28
- data/spec/extensions/arbitrary_servers_spec.rb +0 -109
- data/spec/extensions/association_dependencies_spec.rb +0 -125
- data/spec/extensions/association_pks_spec.rb +0 -423
- data/spec/extensions/association_proxies_spec.rb +0 -100
- data/spec/extensions/auto_literal_strings_spec.rb +0 -205
- data/spec/extensions/auto_validations_spec.rb +0 -229
- data/spec/extensions/blacklist_security_spec.rb +0 -95
- data/spec/extensions/blank_spec.rb +0 -69
- data/spec/extensions/boolean_readers_spec.rb +0 -93
- data/spec/extensions/boolean_subsets_spec.rb +0 -47
- data/spec/extensions/caching_spec.rb +0 -273
- data/spec/extensions/caller_logging_spec.rb +0 -52
- data/spec/extensions/class_table_inheritance_spec.rb +0 -750
- data/spec/extensions/column_conflicts_spec.rb +0 -75
- data/spec/extensions/column_select_spec.rb +0 -129
- data/spec/extensions/columns_introspection_spec.rb +0 -90
- data/spec/extensions/columns_updated_spec.rb +0 -35
- data/spec/extensions/composition_spec.rb +0 -248
- data/spec/extensions/connection_expiration_spec.rb +0 -151
- data/spec/extensions/connection_validator_spec.rb +0 -144
- data/spec/extensions/constant_sql_override_spec.rb +0 -24
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
- data/spec/extensions/constraint_validations_spec.rb +0 -439
- data/spec/extensions/core_refinements_spec.rb +0 -528
- data/spec/extensions/csv_serializer_spec.rb +0 -183
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -365
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -181
- data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
- data/spec/extensions/def_dataset_method_spec.rb +0 -100
- data/spec/extensions/defaults_setter_spec.rb +0 -150
- data/spec/extensions/delay_add_association_spec.rb +0 -73
- data/spec/extensions/dirty_spec.rb +0 -189
- data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
- data/spec/extensions/eager_each_spec.rb +0 -62
- data/spec/extensions/eager_graph_eager_spec.rb +0 -100
- data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
- data/spec/extensions/error_splitter_spec.rb +0 -18
- data/spec/extensions/error_sql_spec.rb +0 -20
- data/spec/extensions/escaped_like_spec.rb +0 -40
- data/spec/extensions/eval_inspect_spec.rb +0 -81
- data/spec/extensions/finder_spec.rb +0 -260
- data/spec/extensions/force_encoding_spec.rb +0 -126
- data/spec/extensions/freeze_datasets_spec.rb +0 -31
- data/spec/extensions/graph_each_spec.rb +0 -113
- data/spec/extensions/hook_class_methods_spec.rb +0 -402
- data/spec/extensions/identifier_mangling_spec.rb +0 -201
- data/spec/extensions/implicit_subquery_spec.rb +0 -58
- data/spec/extensions/index_caching_spec.rb +0 -66
- data/spec/extensions/inflector_spec.rb +0 -183
- data/spec/extensions/input_transformer_spec.rb +0 -69
- data/spec/extensions/insert_returning_select_spec.rb +0 -72
- data/spec/extensions/instance_filters_spec.rb +0 -79
- data/spec/extensions/instance_hooks_spec.rb +0 -246
- data/spec/extensions/integer64_spec.rb +0 -22
- data/spec/extensions/inverted_subsets_spec.rb +0 -33
- data/spec/extensions/json_serializer_spec.rb +0 -336
- data/spec/extensions/lazy_attributes_spec.rb +0 -183
- data/spec/extensions/list_spec.rb +0 -291
- data/spec/extensions/looser_typecasting_spec.rb +0 -43
- data/spec/extensions/many_through_many_spec.rb +0 -2177
- data/spec/extensions/migration_spec.rb +0 -864
- data/spec/extensions/modification_detection_spec.rb +0 -93
- data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
- data/spec/extensions/named_timezones_spec.rb +0 -111
- data/spec/extensions/nested_attributes_spec.rb +0 -767
- data/spec/extensions/null_dataset_spec.rb +0 -85
- data/spec/extensions/optimistic_locking_spec.rb +0 -127
- data/spec/extensions/pagination_spec.rb +0 -116
- data/spec/extensions/pg_array_associations_spec.rb +0 -802
- data/spec/extensions/pg_array_ops_spec.rb +0 -144
- data/spec/extensions/pg_array_spec.rb +0 -398
- data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -172
- data/spec/extensions/pg_enum_spec.rb +0 -118
- data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
- data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
- data/spec/extensions/pg_hstore_spec.rb +0 -219
- data/spec/extensions/pg_inet_ops_spec.rb +0 -102
- data/spec/extensions/pg_inet_spec.rb +0 -72
- data/spec/extensions/pg_interval_spec.rb +0 -103
- data/spec/extensions/pg_json_ops_spec.rb +0 -289
- data/spec/extensions/pg_json_spec.rb +0 -262
- data/spec/extensions/pg_loose_count_spec.rb +0 -23
- data/spec/extensions/pg_range_ops_spec.rb +0 -60
- data/spec/extensions/pg_range_spec.rb +0 -519
- data/spec/extensions/pg_row_ops_spec.rb +0 -61
- data/spec/extensions/pg_row_plugin_spec.rb +0 -60
- data/spec/extensions/pg_row_spec.rb +0 -363
- data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
- data/spec/extensions/pg_timestamptz_spec.rb +0 -17
- data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
- data/spec/extensions/prepared_statements_spec.rb +0 -177
- data/spec/extensions/pretty_table_spec.rb +0 -123
- data/spec/extensions/query_spec.rb +0 -94
- data/spec/extensions/rcte_tree_spec.rb +0 -381
- data/spec/extensions/round_timestamps_spec.rb +0 -39
- data/spec/extensions/s_spec.rb +0 -60
- data/spec/extensions/schema_caching_spec.rb +0 -64
- data/spec/extensions/schema_dumper_spec.rb +0 -870
- data/spec/extensions/select_remove_spec.rb +0 -38
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
- data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
- data/spec/extensions/serialization_spec.rb +0 -365
- data/spec/extensions/server_block_spec.rb +0 -97
- data/spec/extensions/server_logging_spec.rb +0 -45
- data/spec/extensions/sharding_spec.rb +0 -189
- data/spec/extensions/shared_caching_spec.rb +0 -151
- data/spec/extensions/single_table_inheritance_spec.rb +0 -347
- data/spec/extensions/singular_table_names_spec.rb +0 -22
- data/spec/extensions/skip_create_refresh_spec.rb +0 -18
- data/spec/extensions/spec_helper.rb +0 -63
- data/spec/extensions/split_array_nil_spec.rb +0 -24
- data/spec/extensions/split_values_spec.rb +0 -57
- data/spec/extensions/sql_comments_spec.rb +0 -33
- data/spec/extensions/sql_expr_spec.rb +0 -59
- data/spec/extensions/static_cache_spec.rb +0 -471
- data/spec/extensions/string_agg_spec.rb +0 -90
- data/spec/extensions/string_date_time_spec.rb +0 -95
- data/spec/extensions/string_stripper_spec.rb +0 -68
- data/spec/extensions/subclasses_spec.rb +0 -79
- data/spec/extensions/subset_conditions_spec.rb +0 -38
- data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
- data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
- data/spec/extensions/synchronize_sql_spec.rb +0 -124
- data/spec/extensions/table_select_spec.rb +0 -83
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
- data/spec/extensions/thread_local_timezones_spec.rb +0 -67
- data/spec/extensions/throw_failures_spec.rb +0 -74
- data/spec/extensions/timestamps_spec.rb +0 -209
- data/spec/extensions/to_dot_spec.rb +0 -153
- data/spec/extensions/touch_spec.rb +0 -226
- data/spec/extensions/tree_spec.rb +0 -334
- data/spec/extensions/typecast_on_load_spec.rb +0 -86
- data/spec/extensions/unlimited_update_spec.rb +0 -21
- data/spec/extensions/update_or_create_spec.rb +0 -83
- data/spec/extensions/update_primary_key_spec.rb +0 -105
- data/spec/extensions/update_refresh_spec.rb +0 -59
- data/spec/extensions/uuid_spec.rb +0 -101
- data/spec/extensions/validate_associated_spec.rb +0 -52
- data/spec/extensions/validation_class_methods_spec.rb +0 -1040
- data/spec/extensions/validation_contexts_spec.rb +0 -31
- data/spec/extensions/validation_helpers_spec.rb +0 -525
- data/spec/extensions/whitelist_security_spec.rb +0 -157
- data/spec/extensions/xml_serializer_spec.rb +0 -213
- data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
- data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
- data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
- data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
- data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/double_migration/001_create_sessions.rb +0 -9
- data/spec/files/double_migration/002_create_nodes.rb +0 -19
- data/spec/files/double_migration/003_3_create_users.rb +0 -4
- data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
- data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
- data/spec/files/empty_migration/001_create_sessions.rb +0 -9
- data/spec/files/empty_migration/002_create_nodes.rb +0 -0
- data/spec/files/empty_migration/003_3_create_users.rb +0 -4
- data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
- data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
- data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
- data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
- data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/reversible_migrations/001_reversible.rb +0 -5
- data/spec/files/reversible_migrations/002_reversible.rb +0 -5
- data/spec/files/reversible_migrations/003_reversible.rb +0 -5
- data/spec/files/reversible_migrations/004_reversible.rb +0 -5
- data/spec/files/reversible_migrations/005_reversible.rb +0 -10
- data/spec/files/reversible_migrations/006_reversible.rb +0 -10
- data/spec/files/reversible_migrations/007_reversible.rb +0 -10
- data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
- data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
- data/spec/guards_helper.rb +0 -59
- data/spec/integration/associations_test.rb +0 -2597
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -1981
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -262
- data/spec/integration/model_test.rb +0 -203
- data/spec/integration/plugin_test.rb +0 -2396
- data/spec/integration/prepared_statement_test.rb +0 -405
- data/spec/integration/schema_test.rb +0 -889
- data/spec/integration/spec_helper.rb +0 -65
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -603
- data/spec/integration/type_test.rb +0 -127
- data/spec/model/association_reflection_spec.rb +0 -803
- data/spec/model/associations_spec.rb +0 -4738
- data/spec/model/base_spec.rb +0 -875
- data/spec/model/class_dataset_methods_spec.rb +0 -146
- data/spec/model/dataset_methods_spec.rb +0 -198
- data/spec/model/eager_loading_spec.rb +0 -2377
- data/spec/model/hooks_spec.rb +0 -370
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -956
- data/spec/model/plugins_spec.rb +0 -429
- data/spec/model/record_spec.rb +0 -2118
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -220
- data/spec/model_no_assoc_spec.rb +0 -1
- data/spec/model_spec.rb +0 -1
- data/spec/plugin_spec.rb +0 -1
- data/spec/sequel_coverage.rb +0 -15
- data/spec/sequel_warning.rb +0 -4
- data/spec/spec_config.rb +0 -12
@@ -164,11 +164,11 @@ module Sequel
|
|
164
164
|
# range to return the object(s) at the correct offset/limit.
|
165
165
|
def apply_ruby_eager_limit_strategy(rows, limit_and_offset = limit_and_offset())
|
166
166
|
name = self[:name]
|
167
|
+
return unless range = slice_range(limit_and_offset)
|
167
168
|
if returns_array?
|
168
|
-
range = slice_range(limit_and_offset)
|
169
169
|
rows.each{|o| o.associations[name] = o.associations[name][range] || []}
|
170
|
-
|
171
|
-
offset =
|
170
|
+
else
|
171
|
+
offset = range.begin
|
172
172
|
rows.each{|o| o.associations[name] = o.associations[name][offset]}
|
173
173
|
end
|
174
174
|
end
|
@@ -263,7 +263,9 @@ module Sequel
|
|
263
263
|
# yielding each row to the block.
|
264
264
|
def eager_load_results(eo, &block)
|
265
265
|
rows = eo[:rows]
|
266
|
-
|
266
|
+
unless eo[:initialize_rows] == false
|
267
|
+
Sequel.synchronize_with(eo[:mutex]){initialize_association_cache(rows)}
|
268
|
+
end
|
267
269
|
if eo[:id_map]
|
268
270
|
ids = eo[:id_map].keys
|
269
271
|
return ids if ids.empty?
|
@@ -272,7 +274,9 @@ module Sequel
|
|
272
274
|
cascade = eo[:associations]
|
273
275
|
eager_limit = nil
|
274
276
|
|
275
|
-
if eo[:
|
277
|
+
if eo[:no_results]
|
278
|
+
no_results = true
|
279
|
+
elsif eo[:eager_block] || eo[:loader] == false
|
276
280
|
ds = eager_loading_dataset(eo)
|
277
281
|
|
278
282
|
strategy = ds.opts[:eager_limit_strategy] || strategy
|
@@ -311,7 +315,8 @@ module Sequel
|
|
311
315
|
objects = loader.all(ids)
|
312
316
|
end
|
313
317
|
|
314
|
-
objects.each(&block)
|
318
|
+
Sequel.synchronize_with(eo[:mutex]){objects.each(&block)} unless no_results
|
319
|
+
|
315
320
|
if strategy == :ruby
|
316
321
|
apply_ruby_eager_limit_strategy(rows, eager_limit || limit_and_offset)
|
317
322
|
end
|
@@ -356,7 +361,7 @@ module Sequel
|
|
356
361
|
def finalize
|
357
362
|
return unless cache = self[:cache]
|
358
363
|
|
359
|
-
|
364
|
+
finalizer = proc do |meth, key|
|
360
365
|
next if has_key?(key)
|
361
366
|
|
362
367
|
# Allow calling private methods to make sure caching is done appropriately
|
@@ -364,6 +369,13 @@ module Sequel
|
|
364
369
|
self[key] = cache.delete(key) if cache.has_key?(key)
|
365
370
|
end
|
366
371
|
|
372
|
+
finalize_settings.each(&finalizer)
|
373
|
+
|
374
|
+
unless self[:instance_specific]
|
375
|
+
finalizer.call(:associated_eager_dataset, :associated_eager_dataset)
|
376
|
+
finalizer.call(:filter_by_associations_conditions_dataset, :filter_by_associations_conditions_dataset)
|
377
|
+
end
|
378
|
+
|
367
379
|
nil
|
368
380
|
end
|
369
381
|
|
@@ -371,9 +383,7 @@ module Sequel
|
|
371
383
|
FINALIZE_SETTINGS = {
|
372
384
|
:associated_class=>:class,
|
373
385
|
:associated_dataset=>:_dataset,
|
374
|
-
:associated_eager_dataset=>:associated_eager_dataset,
|
375
386
|
:eager_limit_strategy=>:_eager_limit_strategy,
|
376
|
-
:filter_by_associations_conditions_dataset=>:filter_by_associations_conditions_dataset,
|
377
387
|
:placeholder_loader=>:placeholder_loader,
|
378
388
|
:predicate_key=>:predicate_key,
|
379
389
|
:predicate_keys=>:predicate_keys,
|
@@ -432,7 +442,11 @@ module Sequel
|
|
432
442
|
if use_placeholder_loader?
|
433
443
|
cached_fetch(:placeholder_loader) do
|
434
444
|
Sequel::Dataset::PlaceholderLiteralizer.loader(associated_dataset) do |pl, ds|
|
435
|
-
ds.where(Sequel.&(*predicate_keys.map{|k| SQL::BooleanExpression.new(:'=', k, pl.arg)}))
|
445
|
+
ds = ds.where(Sequel.&(*predicate_keys.map{|k| SQL::BooleanExpression.new(:'=', k, pl.arg)}))
|
446
|
+
if self[:block]
|
447
|
+
ds = self[:block].call(ds)
|
448
|
+
end
|
449
|
+
ds
|
436
450
|
end
|
437
451
|
end
|
438
452
|
end
|
@@ -626,9 +640,7 @@ module Sequel
|
|
626
640
|
# given the hash passed to the eager loader.
|
627
641
|
def eager_loading_dataset(eo=OPTS)
|
628
642
|
ds = eo[:dataset] || associated_eager_dataset
|
629
|
-
|
630
|
-
ds = ds.where(eager_loading_predicate_condition(id_map.keys))
|
631
|
-
end
|
643
|
+
ds = eager_loading_set_predicate_condition(ds, eo)
|
632
644
|
if associations = eo[:associations]
|
633
645
|
ds = ds.eager(associations)
|
634
646
|
end
|
@@ -655,6 +667,15 @@ module Sequel
|
|
655
667
|
self[:model].default_eager_limit_strategy || :ruby
|
656
668
|
end
|
657
669
|
|
670
|
+
# Set the predicate condition for the eager loading dataset based on the id map
|
671
|
+
# in the eager loading options.
|
672
|
+
def eager_loading_set_predicate_condition(ds, eo)
|
673
|
+
if id_map = eo[:id_map]
|
674
|
+
ds = ds.where(eager_loading_predicate_condition(id_map.keys))
|
675
|
+
end
|
676
|
+
ds
|
677
|
+
end
|
678
|
+
|
658
679
|
# The predicate condition to use for the eager_loader.
|
659
680
|
def eager_loading_predicate_condition(keys)
|
660
681
|
{predicate_key=>keys}
|
@@ -796,7 +817,7 @@ module Sequel
|
|
796
817
|
|
797
818
|
# Whether the placeholder loader can be used to load the association.
|
798
819
|
def use_placeholder_loader?
|
799
|
-
|
820
|
+
self[:use_placeholder_loader]
|
800
821
|
end
|
801
822
|
end
|
802
823
|
|
@@ -1244,7 +1265,9 @@ module Sequel
|
|
1244
1265
|
else
|
1245
1266
|
assoc_record.values.delete(left_key_alias)
|
1246
1267
|
end
|
1247
|
-
|
1268
|
+
|
1269
|
+
objects = h[hash_key]
|
1270
|
+
|
1248
1271
|
if assign_singular
|
1249
1272
|
objects.each do |object|
|
1250
1273
|
object.associations[name] ||= assoc_record
|
@@ -1304,7 +1327,7 @@ module Sequel
|
|
1304
1327
|
|
1305
1328
|
# many_to_many associations need to select a key in an associated table to eagerly load
|
1306
1329
|
def eager_loading_use_associated_key?
|
1307
|
-
|
1330
|
+
!separate_query_per_table?
|
1308
1331
|
end
|
1309
1332
|
|
1310
1333
|
# The source of the join table. This is the join table itself, unless it
|
@@ -1361,10 +1384,30 @@ module Sequel
|
|
1361
1384
|
cached_fetch(:select){default_select}
|
1362
1385
|
end
|
1363
1386
|
|
1387
|
+
# Whether a separate query should be used for the join table.
|
1388
|
+
def separate_query_per_table?
|
1389
|
+
self[:join_table_db]
|
1390
|
+
end
|
1391
|
+
|
1364
1392
|
private
|
1365
1393
|
|
1394
|
+
# Join to the the join table, unless using a separate query per table.
|
1366
1395
|
def _associated_dataset
|
1367
|
-
|
1396
|
+
if separate_query_per_table?
|
1397
|
+
super
|
1398
|
+
else
|
1399
|
+
super.inner_join(self[:join_table], self[:right_keys].zip(right_primary_keys), :qualify=>:deep)
|
1400
|
+
end
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
# Use the right_keys from the eager loading options if
|
1404
|
+
# using a separate query per table.
|
1405
|
+
def eager_loading_set_predicate_condition(ds, eo)
|
1406
|
+
if separate_query_per_table?
|
1407
|
+
ds.where(right_primary_key=>eo[:right_keys])
|
1408
|
+
else
|
1409
|
+
super
|
1410
|
+
end
|
1368
1411
|
end
|
1369
1412
|
|
1370
1413
|
# The default selection for associations that require joins. These do not use the default
|
@@ -1581,6 +1624,7 @@ module Sequel
|
|
1581
1624
|
# === Multiple Types
|
1582
1625
|
# :adder :: Proc used to define the private _add_* method for doing the database work
|
1583
1626
|
# to associate the given object to the current object (*_to_many assocations).
|
1627
|
+
# Set to nil to not define a add_* method for the association.
|
1584
1628
|
# :after_add :: Symbol, Proc, or array of both/either specifying a callback to call
|
1585
1629
|
# after a new item is added to the association.
|
1586
1630
|
# :after_load :: Symbol, Proc, or array of both/either specifying a callback to call
|
@@ -1591,6 +1635,8 @@ module Sequel
|
|
1591
1635
|
# after an item is set using the association setter method.
|
1592
1636
|
# :allow_eager :: If set to false, you cannot load the association eagerly
|
1593
1637
|
# via eager or eager_graph
|
1638
|
+
# :allow_eager_graph :: If set to false, you cannot load the association eagerly via eager_graph.
|
1639
|
+
# :allow_filtering_by :: If set to false, you cannot use the association when filtering
|
1594
1640
|
# :before_add :: Symbol, Proc, or array of both/either specifying a callback to call
|
1595
1641
|
# before a new item is added to the association.
|
1596
1642
|
# :before_remove :: Symbol, Proc, or array of both/either specifying a callback to call
|
@@ -1609,6 +1655,7 @@ module Sequel
|
|
1609
1655
|
# the class. <tt>class: 'Foo', class_namespace: 'Bar'</tt> looks for <tt>::Bar::Foo</tt>.)
|
1610
1656
|
# :clearer :: Proc used to define the private _remove_all_* method for doing the database work
|
1611
1657
|
# to remove all objects associated to the current object (*_to_many assocations).
|
1658
|
+
# Set to nil to not define a remove_all_* method for the association.
|
1612
1659
|
# :clone :: Merge the current options and block into the options and block used in defining
|
1613
1660
|
# the given association. Can be used to DRY up a bunch of similar associations that
|
1614
1661
|
# all share the same options such as :class and :key, while changing the order and block used.
|
@@ -1663,7 +1710,7 @@ module Sequel
|
|
1663
1710
|
# :graph_only_conditions :: The conditions to use on the SQL join when eagerly loading
|
1664
1711
|
# the association via +eager_graph+, instead of the default conditions specified by the
|
1665
1712
|
# foreign/primary keys. This option causes the :graph_conditions option to be ignored.
|
1666
|
-
# :graph_order ::
|
1713
|
+
# :graph_order :: the order to use when using eager_graph, instead of the default order. This should be used
|
1667
1714
|
# in the case where :order contains an identifier qualified by the table's name, which may not match
|
1668
1715
|
# the alias used when eager graphing. By setting this to the unqualified identifier, it will be
|
1669
1716
|
# automatically qualified when using eager_graph.
|
@@ -1675,6 +1722,10 @@ module Sequel
|
|
1675
1722
|
# limit (first element) and an offset (second element).
|
1676
1723
|
# :methods_module :: The module that methods the association creates will be placed into. Defaults
|
1677
1724
|
# to the module containing the model's columns.
|
1725
|
+
# :no_association_method :: Do not add a method for the association. This can save memory if the association
|
1726
|
+
# method is never used.
|
1727
|
+
# :no_dataset_method :: Do not add a method for the association dataset. This can save memory if the dataset
|
1728
|
+
# method is never used.
|
1678
1729
|
# :order :: the column(s) by which to order the association dataset. Can be a
|
1679
1730
|
# singular column symbol or an array of column symbols.
|
1680
1731
|
# :order_eager_graph :: Whether to add the association's order to the graphed dataset's order when graphing
|
@@ -1687,6 +1738,7 @@ module Sequel
|
|
1687
1738
|
# the current association's key(s). Set to nil to not use a reciprocal.
|
1688
1739
|
# :remover :: Proc used to define the private _remove_* method for doing the database work
|
1689
1740
|
# to remove the association between the given object and the current object (*_to_many assocations).
|
1741
|
+
# Set to nil to not define a remove_* method for the association.
|
1690
1742
|
# :select :: the columns to select. Defaults to the associated class's table_name.* in an association
|
1691
1743
|
# that uses joins, which means it doesn't include the attributes from the
|
1692
1744
|
# join table. If you want to include the join table attributes, you can
|
@@ -1695,6 +1747,7 @@ module Sequel
|
|
1695
1747
|
# the same name in both the join table and the associated table.
|
1696
1748
|
# :setter :: Proc used to define the private _*= method for doing the work to setup the assocation
|
1697
1749
|
# between the given object and the current object (*_to_one associations).
|
1750
|
+
# Set to nil to not define a setter method for the association.
|
1698
1751
|
# :subqueries_per_union :: The number of subqueries to use in each UNION query, for eager
|
1699
1752
|
# loading limited associations using the default :union strategy.
|
1700
1753
|
# :validate :: Set to false to not validate when implicitly saving any associated object.
|
@@ -1751,6 +1804,9 @@ module Sequel
|
|
1751
1804
|
# underscored, sorted, and joined with '_'.
|
1752
1805
|
# :join_table_block :: proc that can be used to modify the dataset used in the add/remove/remove_all
|
1753
1806
|
# methods. Should accept a dataset argument and return a modified dataset if present.
|
1807
|
+
# :join_table_db :: When retrieving records when using lazy loading or eager loading via +eager+, instead of
|
1808
|
+
# a join between to the join table and the associated table, use a separate query for the
|
1809
|
+
# join table using the given Database object.
|
1754
1810
|
# :left_key :: foreign key in join table that points to current model's
|
1755
1811
|
# primary key, as a symbol. Defaults to :"#{self.name.underscore}_id".
|
1756
1812
|
# Can use an array of symbols for a composite key association.
|
@@ -1791,11 +1847,12 @@ module Sequel
|
|
1791
1847
|
opts.merge!(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
|
1792
1848
|
|
1793
1849
|
opts[:block] = block if block
|
1794
|
-
|
1850
|
+
opts[:instance_specific] = true if orig_opts[:dataset]
|
1851
|
+
if !opts.has_key?(:instance_specific) && (block || orig_opts[:block])
|
1795
1852
|
# It's possible the association is instance specific, in that it depends on
|
1796
1853
|
# values other than the foreign key value. This needs to be checked for
|
1797
1854
|
# in certain places to disable optimizations.
|
1798
|
-
opts[:instance_specific] =
|
1855
|
+
opts[:instance_specific] = _association_instance_specific_default(name)
|
1799
1856
|
end
|
1800
1857
|
opts = assoc_class.new.merge!(opts)
|
1801
1858
|
|
@@ -1803,6 +1860,7 @@ module Sequel
|
|
1803
1860
|
raise(Error, "cannot clone an association to an association of different type (association #{name} with type #{type} cloning #{opts[:clone]} with type #{cloned_assoc[:type]})")
|
1804
1861
|
end
|
1805
1862
|
|
1863
|
+
opts[:use_placeholder_loader] = !opts[:instance_specific] && !opts[:eager_graph]
|
1806
1864
|
opts[:eager_block] = opts[:block] unless opts.include?(:eager_block)
|
1807
1865
|
opts[:graph_join_type] ||= :left_outer
|
1808
1866
|
opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph)
|
@@ -1825,8 +1883,7 @@ module Sequel
|
|
1825
1883
|
# Remove :class entry if it exists and is nil, to work with cached_fetch
|
1826
1884
|
opts.delete(:class) unless opts[:class]
|
1827
1885
|
|
1828
|
-
|
1829
|
-
def_association_instance_methods(opts)
|
1886
|
+
def_association(opts)
|
1830
1887
|
|
1831
1888
|
orig_opts.delete(:clone)
|
1832
1889
|
opts[:orig_class] = orig_opts[:class] || orig_opts[:class_name]
|
@@ -1899,6 +1956,12 @@ module Sequel
|
|
1899
1956
|
Plugins.def_dataset_methods(self, [:eager, :eager_graph, :eager_graph_with_options, :association_join, :association_full_join, :association_inner_join, :association_left_join, :association_right_join])
|
1900
1957
|
|
1901
1958
|
private
|
1959
|
+
|
1960
|
+
# The default value for the instance_specific option, if the association
|
1961
|
+
# could be instance specific and the :instance_specific option is not specified.
|
1962
|
+
def _association_instance_specific_default(_)
|
1963
|
+
true
|
1964
|
+
end
|
1902
1965
|
|
1903
1966
|
# The module to use for the association's methods. Defaults to
|
1904
1967
|
# the overridable_methods_module.
|
@@ -1910,7 +1973,22 @@ module Sequel
|
|
1910
1973
|
# can be easily overridden in the class itself while allowing for
|
1911
1974
|
# super to be called.
|
1912
1975
|
def association_module_def(name, opts=OPTS, &block)
|
1913
|
-
association_module(opts)
|
1976
|
+
mod = association_module(opts)
|
1977
|
+
mod.send(:define_method, name, &block)
|
1978
|
+
mod.send(:alias_method, name, name)
|
1979
|
+
end
|
1980
|
+
|
1981
|
+
# Add a method to the module included in the class, so the method
|
1982
|
+
# can be easily overridden in the class itself while allowing for
|
1983
|
+
# super to be called. This method allows passing keywords through
|
1984
|
+
# the defined methods.
|
1985
|
+
def association_module_delegate_def(name, opts, &block)
|
1986
|
+
mod = association_module(opts)
|
1987
|
+
mod.send(:define_method, name, &block)
|
1988
|
+
# :nocov:
|
1989
|
+
mod.send(:ruby2_keywords, name) if mod.respond_to?(:ruby2_keywords, true)
|
1990
|
+
# :nocov:
|
1991
|
+
mod.send(:alias_method, name, name)
|
1914
1992
|
end
|
1915
1993
|
|
1916
1994
|
# Add a private method to the module included in the class.
|
@@ -1919,6 +1997,13 @@ module Sequel
|
|
1919
1997
|
association_module(opts).send(:private, name)
|
1920
1998
|
end
|
1921
1999
|
|
2000
|
+
# Delegate to the type-specific association method to setup the
|
2001
|
+
# association, and define the association instance methods.
|
2002
|
+
def def_association(opts)
|
2003
|
+
send(:"def_#{opts[:type]}", opts)
|
2004
|
+
def_association_instance_methods(opts)
|
2005
|
+
end
|
2006
|
+
|
1922
2007
|
# Adds the association method to the association methods module.
|
1923
2008
|
def def_association_method(opts)
|
1924
2009
|
association_module_def(opts.association_method, opts) do |dynamic_opts=OPTS, &block|
|
@@ -1944,15 +2029,13 @@ module Sequel
|
|
1944
2029
|
opts[:setter_method] = :"#{opts[:name]}="
|
1945
2030
|
end
|
1946
2031
|
|
1947
|
-
association_module_def(opts.dataset_method, opts){_dataset(opts)}
|
2032
|
+
association_module_def(opts.dataset_method, opts){_dataset(opts)} unless opts[:no_dataset_method]
|
1948
2033
|
if opts[:block]
|
1949
2034
|
opts[:block_method] = Plugins.def_sequel_method(association_module(opts), "#{opts[:name]}_block", 1, &opts[:block])
|
1950
2035
|
end
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
end
|
1955
|
-
def_association_method(opts)
|
2036
|
+
opts[:dataset_opt_arity] = opts[:dataset].arity == 0 ? 0 : 1
|
2037
|
+
opts[:dataset_opt_method] = Plugins.def_sequel_method(association_module(opts), "#{opts[:name]}_dataset_opt", opts[:dataset_opt_arity], &opts[:dataset])
|
2038
|
+
def_association_method(opts) unless opts[:no_association_method]
|
1956
2039
|
|
1957
2040
|
return if opts[:read_only]
|
1958
2041
|
|
@@ -1964,17 +2047,17 @@ module Sequel
|
|
1964
2047
|
|
1965
2048
|
if adder = opts[:adder]
|
1966
2049
|
association_module_private_def(opts[:_add_method], opts, &adder)
|
1967
|
-
|
2050
|
+
association_module_delegate_def(opts[:add_method], opts){|o,*args| add_associated_object(opts, o, *args)}
|
1968
2051
|
end
|
1969
2052
|
|
1970
2053
|
if remover = opts[:remover]
|
1971
2054
|
association_module_private_def(opts[:_remove_method], opts, &remover)
|
1972
|
-
|
2055
|
+
association_module_delegate_def(opts[:remove_method], opts){|o,*args| remove_associated_object(opts, o, *args)}
|
1973
2056
|
end
|
1974
2057
|
|
1975
2058
|
if clearer = opts[:clearer]
|
1976
2059
|
association_module_private_def(opts[:_remove_all_method], opts, &clearer)
|
1977
|
-
|
2060
|
+
association_module_delegate_def(opts[:remove_all_method], opts){|*args| remove_all_associated_objects(opts, *args)}
|
1978
2061
|
end
|
1979
2062
|
end
|
1980
2063
|
|
@@ -1996,7 +2079,7 @@ module Sequel
|
|
1996
2079
|
raise(Error, "mismatched number of right keys: #{rcks.inspect} vs #{rcpks.inspect}") unless rcks.length == rcpks.length
|
1997
2080
|
end
|
1998
2081
|
opts[:uses_left_composite_keys] = lcks.length > 1
|
1999
|
-
opts[:uses_right_composite_keys] = rcks.length > 1
|
2082
|
+
uses_rcks = opts[:uses_right_composite_keys] = rcks.length > 1
|
2000
2083
|
opts[:cartesian_product_number] ||= one_through_one ? 0 : 1
|
2001
2084
|
join_table = (opts[:join_table] ||= opts.default_join_table)
|
2002
2085
|
opts[:left_key_alias] ||= opts.default_associated_key_alias
|
@@ -2005,8 +2088,75 @@ module Sequel
|
|
2005
2088
|
opts[:after_load] ||= []
|
2006
2089
|
opts[:after_load].unshift(:array_uniq!)
|
2007
2090
|
end
|
2008
|
-
opts[:
|
2009
|
-
|
2091
|
+
if join_table_db = opts[:join_table_db]
|
2092
|
+
opts[:use_placeholder_loader] = false
|
2093
|
+
opts[:allow_eager_graph] = false
|
2094
|
+
opts[:allow_filtering_by] = false
|
2095
|
+
opts[:eager_limit_strategy] = nil
|
2096
|
+
join_table_ds = join_table_db.from(join_table)
|
2097
|
+
opts[:dataset] ||= proc do |r|
|
2098
|
+
vals = join_table_ds.where(lcks.zip(lcpks.map{|k| get_column_value(k)})).select_map(right)
|
2099
|
+
ds = r.associated_dataset.where(opts.right_primary_key => vals)
|
2100
|
+
if uses_rcks
|
2101
|
+
vals.delete_if{|v| v.any?(&:nil?)}
|
2102
|
+
else
|
2103
|
+
vals.delete(nil)
|
2104
|
+
end
|
2105
|
+
ds = ds.clone(:no_results=>true) if vals.empty?
|
2106
|
+
ds
|
2107
|
+
end
|
2108
|
+
opts[:eager_loader] ||= proc do |eo|
|
2109
|
+
h = eo[:id_map]
|
2110
|
+
assign_singular = opts.assign_singular?
|
2111
|
+
rpk = opts.right_primary_key
|
2112
|
+
name = opts[:name]
|
2113
|
+
|
2114
|
+
join_map = join_table_ds.where(left=>h.keys).select_hash_groups(right, left)
|
2115
|
+
|
2116
|
+
if uses_rcks
|
2117
|
+
join_map.delete_if{|v,| v.any?(&:nil?)}
|
2118
|
+
else
|
2119
|
+
join_map.delete(nil)
|
2120
|
+
end
|
2121
|
+
|
2122
|
+
eo = Hash[eo]
|
2123
|
+
|
2124
|
+
if join_map.empty?
|
2125
|
+
eo[:no_results] = true
|
2126
|
+
else
|
2127
|
+
join_map.each_value do |vs|
|
2128
|
+
vs.replace(vs.flat_map{|v| h[v]})
|
2129
|
+
vs.uniq!
|
2130
|
+
end
|
2131
|
+
|
2132
|
+
eo[:loader] = false
|
2133
|
+
eo[:right_keys] = join_map.keys
|
2134
|
+
end
|
2135
|
+
|
2136
|
+
opts[:model].eager_load_results(opts, eo) do |assoc_record|
|
2137
|
+
rpkv = if uses_rcks
|
2138
|
+
assoc_record.values.values_at(*rpk)
|
2139
|
+
else
|
2140
|
+
assoc_record.values[rpk]
|
2141
|
+
end
|
2142
|
+
|
2143
|
+
objects = join_map[rpkv]
|
2144
|
+
|
2145
|
+
if assign_singular
|
2146
|
+
objects.each do |object|
|
2147
|
+
object.associations[name] ||= assoc_record
|
2148
|
+
end
|
2149
|
+
else
|
2150
|
+
objects.each do |object|
|
2151
|
+
object.associations[name].push(assoc_record)
|
2152
|
+
end
|
2153
|
+
end
|
2154
|
+
end
|
2155
|
+
end
|
2156
|
+
else
|
2157
|
+
opts[:dataset] ||= opts.association_dataset_proc
|
2158
|
+
opts[:eager_loader] ||= opts.method(:default_eager_loader)
|
2159
|
+
end
|
2010
2160
|
|
2011
2161
|
join_type = opts[:graph_join_type]
|
2012
2162
|
select = opts[:graph_select]
|
@@ -2040,50 +2190,60 @@ module Sequel
|
|
2040
2190
|
return if opts[:read_only]
|
2041
2191
|
|
2042
2192
|
if one_through_one
|
2043
|
-
opts
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2193
|
+
unless opts.has_key?(:setter)
|
2194
|
+
opts[:setter] = proc do |o|
|
2195
|
+
h = {}
|
2196
|
+
lh = lcks.zip(lcpks.map{|k| get_column_value(k)})
|
2197
|
+
jtds = _join_table_dataset(opts).where(lh)
|
2047
2198
|
|
2048
|
-
|
2049
|
-
|
2199
|
+
checked_transaction do
|
2200
|
+
current = jtds.first
|
2050
2201
|
|
2051
|
-
if o
|
2052
|
-
new_values = []
|
2053
|
-
rcks.zip(opts.right_primary_key_methods).each{|k, pk| new_values << (h[k] = o.get_column_value(pk))}
|
2054
|
-
end
|
2055
|
-
|
2056
|
-
if current
|
2057
|
-
current_values = rcks.map{|k| current[k]}
|
2058
|
-
jtds = jtds.where(rcks.zip(current_values))
|
2059
2202
|
if o
|
2060
|
-
|
2061
|
-
|
2203
|
+
new_values = []
|
2204
|
+
rcks.zip(opts.right_primary_key_methods).each{|k, pk| new_values << (h[k] = o.get_column_value(pk))}
|
2205
|
+
end
|
2206
|
+
|
2207
|
+
if current
|
2208
|
+
current_values = rcks.map{|k| current[k]}
|
2209
|
+
jtds = jtds.where(rcks.zip(current_values))
|
2210
|
+
if o
|
2211
|
+
if current_values != new_values
|
2212
|
+
jtds.update(h)
|
2213
|
+
end
|
2214
|
+
else
|
2215
|
+
jtds.delete
|
2062
2216
|
end
|
2063
|
-
|
2064
|
-
|
2217
|
+
elsif o
|
2218
|
+
lh.each{|k,v| h[k] = v}
|
2219
|
+
jtds.insert(h)
|
2065
2220
|
end
|
2066
|
-
elsif o
|
2067
|
-
lh.each{|k,v| h[k] = v}
|
2068
|
-
jtds.insert(h)
|
2069
2221
|
end
|
2070
2222
|
end
|
2071
2223
|
end
|
2072
|
-
opts
|
2224
|
+
if opts.fetch(:setter, true)
|
2225
|
+
opts[:_setter] = proc{|o| set_one_through_one_associated_object(opts, o)}
|
2226
|
+
end
|
2073
2227
|
else
|
2074
|
-
opts
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2228
|
+
unless opts.has_key?(:adder)
|
2229
|
+
opts[:adder] = proc do |o|
|
2230
|
+
h = {}
|
2231
|
+
lcks.zip(lcpks).each{|k, pk| h[k] = get_column_value(pk)}
|
2232
|
+
rcks.zip(opts.right_primary_key_methods).each{|k, pk| h[k] = o.get_column_value(pk)}
|
2233
|
+
_join_table_dataset(opts).insert(h)
|
2234
|
+
end
|
2079
2235
|
end
|
2080
2236
|
|
2081
|
-
opts
|
2082
|
-
|
2237
|
+
unless opts.has_key?(:remover)
|
2238
|
+
opts[:remover] = proc do |o|
|
2239
|
+
_join_table_dataset(opts).where(lcks.zip(lcpks.map{|k| get_column_value(k)}) + rcks.zip(opts.right_primary_key_methods.map{|k| o.get_column_value(k)})).delete
|
2240
|
+
end
|
2083
2241
|
end
|
2084
2242
|
|
2085
|
-
opts
|
2086
|
-
|
2243
|
+
unless opts.has_key?(:clearer)
|
2244
|
+
opts[:clearer] = proc do
|
2245
|
+
_join_table_dataset(opts).where(lcks.zip(lcpks.map{|k| get_column_value(k)})).delete
|
2246
|
+
end
|
2087
2247
|
end
|
2088
2248
|
end
|
2089
2249
|
end
|
@@ -2122,9 +2282,7 @@ module Sequel
|
|
2122
2282
|
|
2123
2283
|
eager_load_results(opts, eo) do |assoc_record|
|
2124
2284
|
hash_key = uses_cks ? pk_meths.map{|k| assoc_record.get_column_value(k)} : assoc_record.get_column_value(opts.primary_key_method)
|
2125
|
-
|
2126
|
-
objects.each{|object| object.associations[name] = assoc_record}
|
2127
|
-
end
|
2285
|
+
h[hash_key].each{|object| object.associations[name] = assoc_record}
|
2128
2286
|
end
|
2129
2287
|
end
|
2130
2288
|
|
@@ -2142,8 +2300,12 @@ module Sequel
|
|
2142
2300
|
|
2143
2301
|
return if opts[:read_only]
|
2144
2302
|
|
2145
|
-
|
2146
|
-
|
2303
|
+
unless opts.has_key?(:setter)
|
2304
|
+
opts[:setter] = proc{|o| cks.zip(opts.primary_key_methods).each{|k, pk| set_column_value(:"#{k}=", (o.get_column_value(pk) if o))}}
|
2305
|
+
end
|
2306
|
+
if opts.fetch(:setter, true)
|
2307
|
+
opts[:_setter] = proc{|o| set_associated_object(opts, o)}
|
2308
|
+
end
|
2147
2309
|
end
|
2148
2310
|
|
2149
2311
|
# Configures one_to_many and one_to_one association reflections and adds the related association methods
|
@@ -2171,7 +2333,7 @@ module Sequel
|
|
2171
2333
|
eager_load_results(opts, eo) do |assoc_record|
|
2172
2334
|
assoc_record.values.delete(delete_rn) if delete_rn
|
2173
2335
|
hash_key = uses_cks ? km.map{|k| assoc_record.get_column_value(k)} : assoc_record.get_column_value(km)
|
2174
|
-
|
2336
|
+
objects = h[hash_key]
|
2175
2337
|
if assign_singular
|
2176
2338
|
objects.each do |object|
|
2177
2339
|
unless object.associations[name]
|
@@ -2210,49 +2372,59 @@ module Sequel
|
|
2210
2372
|
cks.each{|k| ck_nil_hash[k] = nil}
|
2211
2373
|
|
2212
2374
|
if one_to_one
|
2213
|
-
opts
|
2214
|
-
|
2375
|
+
unless opts.has_key?(:setter)
|
2376
|
+
opts[:setter] = proc do |o|
|
2377
|
+
up_ds = _apply_association_options(opts, opts.associated_dataset.where(cks.zip(cpks.map{|k| get_column_value(k)})))
|
2215
2378
|
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2379
|
+
if (froms = up_ds.opts[:from]) && (from = froms[0]) && (from.is_a?(Sequel::Dataset) || (from.is_a?(Sequel::SQL::AliasedExpression) && from.expression.is_a?(Sequel::Dataset)))
|
2380
|
+
if old = up_ds.first
|
2381
|
+
cks.each{|k| old.set_column_value(:"#{k}=", nil)}
|
2382
|
+
end
|
2383
|
+
save_old = true
|
2219
2384
|
end
|
2220
|
-
save_old = true
|
2221
|
-
end
|
2222
2385
|
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2386
|
+
if o
|
2387
|
+
if !o.new? && !save_old
|
2388
|
+
up_ds = up_ds.exclude(o.pk_hash)
|
2389
|
+
end
|
2390
|
+
cks.zip(cpks).each{|k, pk| o.set_column_value(:"#{k}=", get_column_value(pk))}
|
2226
2391
|
end
|
2227
|
-
cks.zip(cpks).each{|k, pk| o.set_column_value(:"#{k}=", get_column_value(pk))}
|
2228
|
-
end
|
2229
2392
|
|
2230
|
-
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2393
|
+
checked_transaction do
|
2394
|
+
if save_old
|
2395
|
+
old.save(save_opts) || raise(Sequel::Error, "invalid previously associated object, cannot save") if old
|
2396
|
+
else
|
2397
|
+
up_ds.skip_limit_check.update(ck_nil_hash)
|
2398
|
+
end
|
2236
2399
|
|
2237
|
-
|
2400
|
+
o.save(save_opts) || raise(Sequel::Error, "invalid associated object, cannot save") if o
|
2401
|
+
end
|
2238
2402
|
end
|
2239
2403
|
end
|
2240
|
-
opts
|
2404
|
+
if opts.fetch(:setter, true)
|
2405
|
+
opts[:_setter] = proc{|o| set_one_to_one_associated_object(opts, o)}
|
2406
|
+
end
|
2241
2407
|
else
|
2242
2408
|
save_opts[:raise_on_failure] = opts[:raise_on_save_failure] != false
|
2243
2409
|
|
2244
|
-
opts
|
2245
|
-
|
2246
|
-
|
2410
|
+
unless opts.has_key?(:adder)
|
2411
|
+
opts[:adder] = proc do |o|
|
2412
|
+
cks.zip(cpks).each{|k, pk| o.set_column_value(:"#{k}=", get_column_value(pk))}
|
2413
|
+
o.save(save_opts)
|
2414
|
+
end
|
2247
2415
|
end
|
2248
2416
|
|
2249
|
-
opts
|
2250
|
-
|
2251
|
-
|
2417
|
+
unless opts.has_key?(:remover)
|
2418
|
+
opts[:remover] = proc do |o|
|
2419
|
+
cks.each{|k| o.set_column_value(:"#{k}=", nil)}
|
2420
|
+
o.save(save_opts)
|
2421
|
+
end
|
2252
2422
|
end
|
2253
2423
|
|
2254
|
-
opts
|
2255
|
-
|
2424
|
+
unless opts.has_key?(:clearer)
|
2425
|
+
opts[:clearer] = proc do
|
2426
|
+
_apply_association_options(opts, opts.associated_dataset.where(cks.zip(cpks.map{|k| get_column_value(k)}))).update(ck_nil_hash)
|
2427
|
+
end
|
2256
2428
|
end
|
2257
2429
|
end
|
2258
2430
|
end
|
@@ -2346,7 +2518,7 @@ module Sequel
|
|
2346
2518
|
|
2347
2519
|
# Dataset for the join table of the given many to many association reflection
|
2348
2520
|
def _join_table_dataset(opts)
|
2349
|
-
ds = model.db.from(opts.join_table_source)
|
2521
|
+
ds = (opts[:join_table_db] || model.db).from(opts.join_table_source)
|
2350
2522
|
opts[:join_table_block] ? opts[:join_table_block].call(ds) : ds
|
2351
2523
|
end
|
2352
2524
|
|
@@ -2367,7 +2539,12 @@ module Sequel
|
|
2367
2539
|
if loader = _associated_object_loader(opts, dynamic_opts)
|
2368
2540
|
loader.all(*opts.predicate_key_values(self))
|
2369
2541
|
else
|
2370
|
-
_associated_dataset(opts, dynamic_opts)
|
2542
|
+
ds = _associated_dataset(opts, dynamic_opts)
|
2543
|
+
if ds.opts[:no_results]
|
2544
|
+
[]
|
2545
|
+
else
|
2546
|
+
ds.all
|
2547
|
+
end
|
2371
2548
|
end
|
2372
2549
|
end
|
2373
2550
|
|
@@ -2408,6 +2585,9 @@ module Sequel
|
|
2408
2585
|
run_association_callbacks(opts, :after_add, o)
|
2409
2586
|
o
|
2410
2587
|
end
|
2588
|
+
# :nocov:
|
2589
|
+
ruby2_keywords(:add_associated_object) if respond_to?(:ruby2_keywords, true)
|
2590
|
+
# :nocov:
|
2411
2591
|
|
2412
2592
|
# Add/Set the current object to/as the given object's reciprocal association.
|
2413
2593
|
def add_reciprocal_object(opts, o)
|
@@ -2550,6 +2730,9 @@ module Sequel
|
|
2550
2730
|
associations[opts[:name]] = []
|
2551
2731
|
ret
|
2552
2732
|
end
|
2733
|
+
# :nocov:
|
2734
|
+
ruby2_keywords(:remove_all_associated_objects) if respond_to?(:ruby2_keywords, true)
|
2735
|
+
# :nocov:
|
2553
2736
|
|
2554
2737
|
# Remove the given associated object from the given association
|
2555
2738
|
def remove_associated_object(opts, o, *args)
|
@@ -2571,6 +2754,9 @@ module Sequel
|
|
2571
2754
|
run_association_callbacks(opts, :after_remove, o)
|
2572
2755
|
o
|
2573
2756
|
end
|
2757
|
+
# :nocov:
|
2758
|
+
ruby2_keywords(:remove_associated_object) if respond_to?(:ruby2_keywords, true)
|
2759
|
+
# :nocov:
|
2574
2760
|
|
2575
2761
|
# Check that the object from the associated table specified by the primary key
|
2576
2762
|
# is currently associated to the receiver. If it is associated, return the object, otherwise
|
@@ -2819,6 +3005,8 @@ module Sequel
|
|
2819
3005
|
(multiple = ((op == :IN || op == :'NOT IN') && ((is_ds = r.is_a?(Sequel::Dataset)) || (r.respond_to?(:all?) && r.all?{|x| x.is_a?(Sequel::Model)})))))
|
2820
3006
|
l = args[0]
|
2821
3007
|
if ar = model.association_reflections[l]
|
3008
|
+
raise Error, "filtering by associations is not allowed for #{ar.inspect}" if ar[:allow_filtering_by] == false
|
3009
|
+
|
2822
3010
|
if multiple
|
2823
3011
|
klass = ar.associated_class
|
2824
3012
|
if is_ds
|
@@ -2966,8 +3154,10 @@ module Sequel
|
|
2966
3154
|
# dataset. If that association also has dependent associations, instead of a callable object,
|
2967
3155
|
# use a hash with the callable object being the key, and the dependent association(s) as the value.
|
2968
3156
|
#
|
2969
|
-
# You can specify an alias
|
2970
|
-
# an a Symbol for the
|
3157
|
+
# You can specify an custom alias and/or join type on a per-association basis by providing an
|
3158
|
+
# Sequel::SQL::AliasedExpression object instead of an a Symbol for the association name.
|
3159
|
+
#
|
3160
|
+
# You cannot mix calls to +eager_graph+ and +graph+ on the same dataset.
|
2971
3161
|
#
|
2972
3162
|
# Examples:
|
2973
3163
|
#
|
@@ -2983,6 +3173,14 @@ module Sequel
|
|
2983
3173
|
# # FROM albums
|
2984
3174
|
# # LEFT OUTER JOIN artists AS a ON (a.id = albums.artist_id)
|
2985
3175
|
#
|
3176
|
+
# # For each album, eager_graph load the artist, using a specified alias
|
3177
|
+
# # and custom join type
|
3178
|
+
#
|
3179
|
+
# Album.eager_graph(Sequel[:artist].as(:a, join_type: :inner)).all
|
3180
|
+
# # SELECT ...
|
3181
|
+
# # FROM albums
|
3182
|
+
# # INNER JOIN artists AS a ON (a.id = albums.artist_id)
|
3183
|
+
#
|
2986
3184
|
# # For each album, eager_graph load the artist and genre
|
2987
3185
|
# Album.eager_graph(:artist, :genre).all
|
2988
3186
|
# Album.eager_graph(:artist).eager_graph(:genre).all
|
@@ -3056,6 +3254,8 @@ module Sequel
|
|
3056
3254
|
# significantly slower in some cases (perhaps even the majority of cases), so you should
|
3057
3255
|
# only use this if you have benchmarked that it is faster for your use cases.
|
3058
3256
|
def eager_graph_with_options(associations, opts=OPTS)
|
3257
|
+
return self if associations.empty?
|
3258
|
+
|
3059
3259
|
opts = opts.dup unless opts.frozen?
|
3060
3260
|
associations = [associations] unless associations.is_a?(Array)
|
3061
3261
|
ds = if eg = @opts[:eager_graph]
|
@@ -3125,11 +3325,16 @@ module Sequel
|
|
3125
3325
|
# ta :: table_alias used for the parent association
|
3126
3326
|
# requirements :: an array, used as a stack for requirements
|
3127
3327
|
# r :: association reflection for the current association, or an SQL::AliasedExpression
|
3128
|
-
# with the reflection as the expression
|
3328
|
+
# with the reflection as the expression, the alias base as the alias (or nil to
|
3329
|
+
# use the default alias), and an optional hash with a :join_type entry as the columns
|
3330
|
+
# to use a custom join type.
|
3129
3331
|
# *associations :: any associations dependent on this one
|
3130
3332
|
def eager_graph_association(ds, model, ta, requirements, r, *associations)
|
3131
3333
|
if r.is_a?(SQL::AliasedExpression)
|
3132
3334
|
alias_base = r.alias
|
3335
|
+
if r.columns.is_a?(Hash)
|
3336
|
+
join_type = r.columns[:join_type]
|
3337
|
+
end
|
3133
3338
|
r = r.expression
|
3134
3339
|
else
|
3135
3340
|
alias_base = r[:graph_alias_base]
|
@@ -3152,7 +3357,7 @@ module Sequel
|
|
3152
3357
|
raise Error, "Cannot eager_graph association when :conditions specified and not a hash or an array of pairs. Specify :graph_conditions, :graph_only_conditions, or :graph_block for the association. Model: #{r[:model]}, association: #{r[:name]}"
|
3153
3358
|
end
|
3154
3359
|
|
3155
|
-
ds = loader.call(:self=>ds, :table_alias=>assoc_table_alias, :implicit_qualifier=>(ta == ds.opts[:eager_graph][:master]) ? first_source : qualifier_from_alias_symbol(ta, first_source), :callback=>callback, :join_type=>local_opts[:join_type], :join_only=>local_opts[:join_only], :limit_strategy=>limit_strategy, :from_self_alias=>ds.opts[:eager_graph][:master])
|
3360
|
+
ds = loader.call(:self=>ds, :table_alias=>assoc_table_alias, :implicit_qualifier=>(ta == ds.opts[:eager_graph][:master]) ? first_source : qualifier_from_alias_symbol(ta, first_source), :callback=>callback, :join_type=>join_type || local_opts[:join_type], :join_only=>local_opts[:join_only], :limit_strategy=>limit_strategy, :from_self_alias=>ds.opts[:eager_graph][:master])
|
3156
3361
|
if r[:order_eager_graph] && (order = r.fetch(:graph_order, r[:order]))
|
3157
3362
|
ds = ds.order_append(*qualified_expression(order, assoc_table_alias))
|
3158
3363
|
end
|
@@ -3177,7 +3382,6 @@ module Sequel
|
|
3177
3382
|
# requirements :: an array, used as a stack for requirements
|
3178
3383
|
# *associations :: the associations to add to the graph
|
3179
3384
|
def eager_graph_associations(ds, model, ta, requirements, *associations)
|
3180
|
-
return ds if associations.empty?
|
3181
3385
|
associations.flatten.each do |association|
|
3182
3386
|
ds = case association
|
3183
3387
|
when Symbol, SQL::AliasedExpression
|
@@ -3298,7 +3502,7 @@ module Sequel
|
|
3298
3502
|
# Allow associations that are eagerly graphed to be specified as an SQL::AliasedExpression, for
|
3299
3503
|
# per-call determining of the alias base.
|
3300
3504
|
def eager_graph_check_association(model, association)
|
3301
|
-
if association.is_a?(SQL::AliasedExpression)
|
3505
|
+
reflection = if association.is_a?(SQL::AliasedExpression)
|
3302
3506
|
expr = association.expression
|
3303
3507
|
if expr.is_a?(SQL::Identifier)
|
3304
3508
|
expr = expr.value
|
@@ -3307,10 +3511,17 @@ module Sequel
|
|
3307
3511
|
end
|
3308
3512
|
end
|
3309
3513
|
|
3310
|
-
|
3514
|
+
check_reflection = check_association(model, expr)
|
3515
|
+
SQL::AliasedExpression.new(check_reflection, association.alias || expr, association.columns)
|
3311
3516
|
else
|
3312
|
-
check_association(model, association)
|
3517
|
+
check_reflection = check_association(model, association)
|
3313
3518
|
end
|
3519
|
+
|
3520
|
+
if check_reflection && check_reflection[:allow_eager_graph] == false
|
3521
|
+
raise Error, "eager_graph not allowed for #{reflection.inspect}"
|
3522
|
+
end
|
3523
|
+
|
3524
|
+
reflection
|
3314
3525
|
end
|
3315
3526
|
|
3316
3527
|
# The EagerGraphLoader instance used for converting eager_graph results.
|
@@ -3321,15 +3532,30 @@ module Sequel
|
|
3321
3532
|
egl.dup
|
3322
3533
|
end
|
3323
3534
|
|
3324
|
-
# Eagerly load all specified associations
|
3535
|
+
# Eagerly load all specified associations.
|
3325
3536
|
def eager_load(a, eager_assoc=@opts[:eager])
|
3326
3537
|
return if a.empty?
|
3538
|
+
|
3539
|
+
# Reflections for all associations to eager load
|
3540
|
+
reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
|
3541
|
+
|
3542
|
+
perform_eager_loads(prepare_eager_load(a, reflections, eager_assoc))
|
3543
|
+
|
3544
|
+
reflections.each do |r|
|
3545
|
+
a.each{|object| object.send(:run_association_callbacks, r, :after_load, object.associations[r[:name]])} if r[:after_load]
|
3546
|
+
end
|
3547
|
+
|
3548
|
+
nil
|
3549
|
+
end
|
3550
|
+
|
3551
|
+
# Prepare a hash loaders and eager options which will be used to implement the eager loading.
|
3552
|
+
def prepare_eager_load(a, reflections, eager_assoc)
|
3553
|
+
eager_load_data = {}
|
3554
|
+
|
3327
3555
|
# Key is foreign/primary key name symbol.
|
3328
3556
|
# Value is hash with keys being foreign/primary key values (generally integers)
|
3329
3557
|
# and values being an array of current model objects with that specific foreign/primary key
|
3330
3558
|
key_hash = {}
|
3331
|
-
# Reflections for all associations to eager load
|
3332
|
-
reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
|
3333
3559
|
|
3334
3560
|
# Populate the key_hash entry for each association being eagerly loaded
|
3335
3561
|
reflections.each do |r|
|
@@ -3360,7 +3586,6 @@ module Sequel
|
|
3360
3586
|
id_map = nil
|
3361
3587
|
end
|
3362
3588
|
|
3363
|
-
loader = r[:eager_loader]
|
3364
3589
|
associations = eager_assoc[r[:name]]
|
3365
3590
|
if associations.respond_to?(:call)
|
3366
3591
|
eager_block = associations
|
@@ -3368,9 +3593,23 @@ module Sequel
|
|
3368
3593
|
elsif associations.is_a?(Hash) && associations.length == 1 && (pr_assoc = associations.to_a.first) && pr_assoc.first.respond_to?(:call)
|
3369
3594
|
eager_block, associations = pr_assoc
|
3370
3595
|
end
|
3371
|
-
|
3372
|
-
|
3373
|
-
end
|
3596
|
+
|
3597
|
+
eager_load_data[r[:eager_loader]] = {:key_hash=>key_hash, :rows=>a, :associations=>associations, :self=>self, :eager_block=>eager_block, :id_map=>id_map}
|
3598
|
+
end
|
3599
|
+
|
3600
|
+
eager_load_data
|
3601
|
+
end
|
3602
|
+
|
3603
|
+
# Using the hash of loaders and eager options, perform the eager loading.
|
3604
|
+
def perform_eager_loads(eager_load_data)
|
3605
|
+
eager_load_data.map do |loader, eo|
|
3606
|
+
perform_eager_load(loader, eo)
|
3607
|
+
end
|
3608
|
+
end
|
3609
|
+
|
3610
|
+
# Perform eager loading for a single association using the loader and eager options.
|
3611
|
+
def perform_eager_load(loader, eo)
|
3612
|
+
loader.call(eo)
|
3374
3613
|
end
|
3375
3614
|
|
3376
3615
|
# Return a subquery expression for filering by a many_to_many association
|