sequel 5.20.0 → 5.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +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
|