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
|
@@ -143,10 +143,14 @@ module Sequel
|
|
|
143
143
|
compositions[name] = send(composer_meth)
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
|
-
|
|
146
|
+
alias_method(name, name)
|
|
147
|
+
|
|
148
|
+
meth = :"#{name}="
|
|
149
|
+
define_method(meth) do |v|
|
|
147
150
|
modified!
|
|
148
151
|
compositions[name] = v
|
|
149
152
|
end
|
|
153
|
+
alias_method(meth, meth)
|
|
150
154
|
end
|
|
151
155
|
end
|
|
152
156
|
|
|
@@ -167,8 +171,9 @@ module Sequel
|
|
|
167
171
|
|
|
168
172
|
# Freeze compositions hash when freezing model instance.
|
|
169
173
|
def freeze
|
|
170
|
-
compositions
|
|
174
|
+
compositions
|
|
171
175
|
super
|
|
176
|
+
compositions.freeze
|
|
172
177
|
end
|
|
173
178
|
|
|
174
179
|
# For each composition, set the columns in the model class based
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
extension 'async_thread_pool'
|
|
5
|
+
|
|
6
|
+
module Plugins
|
|
7
|
+
# The concurrent_eager_loading plugin allows for eager loading multiple associations
|
|
8
|
+
# concurrently in separate threads. You must load the async_thread_pool Database
|
|
9
|
+
# extension into the Database object the model class uses in order for this plugin
|
|
10
|
+
# to work.
|
|
11
|
+
#
|
|
12
|
+
# By default in Sequel, eager loading happens in a serial manner. If you have code
|
|
13
|
+
# such as:
|
|
14
|
+
#
|
|
15
|
+
# Album.eager(:artist, :genre, :tracks)
|
|
16
|
+
#
|
|
17
|
+
# Sequel will load the albums, then the artists for the albums, then
|
|
18
|
+
# the genres for the albums, then the tracks for the albums.
|
|
19
|
+
#
|
|
20
|
+
# With the concurrent_eager_loading plugin, you can use the +eager_load_concurrently+
|
|
21
|
+
# method to allow for concurrent eager loading:
|
|
22
|
+
#
|
|
23
|
+
# Album.eager_load_concurrently.eager(:artist, :genre, :tracks)
|
|
24
|
+
#
|
|
25
|
+
# This will load the albums, first, since it needs to load the albums to know
|
|
26
|
+
# which artists, genres, and tracks to eagerly load. However, it will load the
|
|
27
|
+
# artists, genres, and tracks for the albums concurrently in separate threads.
|
|
28
|
+
# This can significantly improve performance, especially if there is significant
|
|
29
|
+
# latency between the application and the database. Note that using separate threads
|
|
30
|
+
# is only used in the case where there are multiple associations to eagerly load.
|
|
31
|
+
# With only a single association to eagerly load, there is no reason to use a
|
|
32
|
+
# separate thread, since it would not improve performance.
|
|
33
|
+
#
|
|
34
|
+
# If you want to make concurrent eager loading the default, you can load the
|
|
35
|
+
# plugin with the +:always+ option. In this case, all eager loads will be
|
|
36
|
+
# concurrent. If you want to force a non-concurrent eager load, you can use
|
|
37
|
+
# +eager_load_serially+:
|
|
38
|
+
#
|
|
39
|
+
# Album.eager_load_serially.eager(:artist, :genre, :tracks)
|
|
40
|
+
#
|
|
41
|
+
# Note that making concurrent eager loading the default is probably a bad idea
|
|
42
|
+
# if you are eager loading inside transactions and want the eager load to
|
|
43
|
+
# reflect changes made inside the transaction, unless you plan to use
|
|
44
|
+
# +eager_load_serially+ for such cases. See the async_thread_pool
|
|
45
|
+
# Database extension documentation for more general caveats regarding its use.
|
|
46
|
+
#
|
|
47
|
+
# The default eager loaders for all of the association types that ship with Sequel
|
|
48
|
+
# support safe concurrent eager loading. However, if you are specifying a custom
|
|
49
|
+
# +:eager_loader+ for an association, it may not work safely unless it it modified to
|
|
50
|
+
# support concurrent eager loading. Taking this example from the
|
|
51
|
+
# {Advanced Associations guide}[rdoc-ref:doc/advanced_associations.rdoc]
|
|
52
|
+
#
|
|
53
|
+
# Album.many_to_one :artist, :eager_loader=>(proc do |eo_opts|
|
|
54
|
+
# eo_opts[:rows].each{|album| album.associations[:artist] = nil}
|
|
55
|
+
# id_map = eo_opts[:id_map]
|
|
56
|
+
# Artist.where(:id=>id_map.keys).all do |artist|
|
|
57
|
+
# if albums = id_map[artist.id]
|
|
58
|
+
# albums.each do |album|
|
|
59
|
+
# album.associations[:artist] = artist
|
|
60
|
+
# end
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
63
|
+
# end)
|
|
64
|
+
#
|
|
65
|
+
# This would not support concurrent eager loading safely. To support safe
|
|
66
|
+
# concurrent eager loading, you need to make sure you are not modifying
|
|
67
|
+
# the associations for objects concurrently by separate threads. This is
|
|
68
|
+
# implemented using a mutex, which you can access via <tt>eo_opts[:mutex]</tt>.
|
|
69
|
+
# To keep things simple, you can use +Sequel.synchronize_with+ to only
|
|
70
|
+
# use this mutex if it is available. You want to use the mutex around the
|
|
71
|
+
# code that initializes the associations (usually to +nil+ or <tt>[]</tt>),
|
|
72
|
+
# and also around the code that sets the associatied objects appropriately
|
|
73
|
+
# after they have been retreived. You do not want to use the mutex around
|
|
74
|
+
# the code that loads the objects, since that will prevent concurrent loading.
|
|
75
|
+
# So after the changes, the custom eager loader would look like this:
|
|
76
|
+
#
|
|
77
|
+
# Album.many_to_one :artist, :eager_loader=>(proc do |eo_opts|
|
|
78
|
+
# Sequel.synchronize_with(eo[:mutex]) do
|
|
79
|
+
# eo_opts[:rows].each{|album| album.associations[:artist] = nil}
|
|
80
|
+
# end
|
|
81
|
+
# id_map = eo_opts[:id_map]
|
|
82
|
+
# rows = Artist.where(:id=>id_map.keys).all
|
|
83
|
+
# Sequel.synchronize_with(eo[:mutex]) do
|
|
84
|
+
# rows.each do |artist|
|
|
85
|
+
# if albums = id_map[artist.id]
|
|
86
|
+
# albums.each do |album|
|
|
87
|
+
# album.associations[:artist] = artist
|
|
88
|
+
# end
|
|
89
|
+
# end
|
|
90
|
+
# end
|
|
91
|
+
# end
|
|
92
|
+
# end)
|
|
93
|
+
#
|
|
94
|
+
# Usage:
|
|
95
|
+
#
|
|
96
|
+
# # Make all model subclass datasets support concurrent eager loading
|
|
97
|
+
# Sequel::Model.plugin :concurrent_eager_loading
|
|
98
|
+
#
|
|
99
|
+
# # Make the Album class datasets support concurrent eager loading
|
|
100
|
+
# Album.plugin :concurrent_eager_loading
|
|
101
|
+
#
|
|
102
|
+
# # Make all model subclass datasets concurrently eager load by default
|
|
103
|
+
# Sequel::Model.plugin :concurrent_eager_loading, always: true
|
|
104
|
+
module ConcurrentEagerLoading
|
|
105
|
+
def self.configure(mod, opts=OPTS)
|
|
106
|
+
if opts.has_key?(:always)
|
|
107
|
+
mod.instance_variable_set(:@always_eager_load_concurrently, opts[:always])
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
module ClassMethods
|
|
112
|
+
Plugins.inherited_instance_variables(self, :@always_eager_load_concurrently => nil)
|
|
113
|
+
Plugins.def_dataset_methods(self, [:eager_load_concurrently, :eager_load_serially])
|
|
114
|
+
|
|
115
|
+
# Whether datasets for this class should eager load concurrently by default.
|
|
116
|
+
def always_eager_load_concurrently?
|
|
117
|
+
@always_eager_load_concurrently
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
module DatasetMethods
|
|
122
|
+
# Return a cloned dataset that will eager load associated results concurrently
|
|
123
|
+
# using the async thread pool.
|
|
124
|
+
def eager_load_concurrently
|
|
125
|
+
cached_dataset(:_eager_load_concurrently) do
|
|
126
|
+
clone(:eager_load_concurrently=>true)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Return a cloned dataset that will noteager load associated results concurrently
|
|
131
|
+
# using the async thread pool. Only useful if the current dataset has been marked
|
|
132
|
+
# as loading concurrently, or loading concurrently is the model's default behavior.
|
|
133
|
+
def eager_load_serially
|
|
134
|
+
cached_dataset(:_eager_load_serially) do
|
|
135
|
+
clone(:eager_load_concurrently=>false)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
|
|
141
|
+
# Whether this particular dataset will eager load results concurrently.
|
|
142
|
+
def eager_load_concurrently?
|
|
143
|
+
v = @opts[:eager_load_concurrently]
|
|
144
|
+
v.nil? ? model.always_eager_load_concurrently? : v
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# If performing eager loads concurrently, and at least 2 associations are being
|
|
148
|
+
# eagerly loaded, create a single mutex used for all eager loads. After the
|
|
149
|
+
# eager loads have been performed, force loading of any async results, so that
|
|
150
|
+
# all eager loads will have been completed before this method returns.
|
|
151
|
+
def perform_eager_loads(eager_load_data)
|
|
152
|
+
return super if !eager_load_concurrently? || eager_load_data.length < 2
|
|
153
|
+
|
|
154
|
+
mutex = Mutex.new
|
|
155
|
+
eager_load_data.each_value do |eo|
|
|
156
|
+
eo[:mutex] = mutex
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
super.each do |v|
|
|
160
|
+
if Sequel::Database::AsyncThreadPool::BaseProxy === v
|
|
161
|
+
v.__value
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# If performing eager loads concurrently, perform this eager load using the
|
|
167
|
+
# async thread pool.
|
|
168
|
+
def perform_eager_load(loader, eo)
|
|
169
|
+
eo[:mutex] ? db.send(:async_run){super} : super
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -65,8 +65,6 @@ module Sequel
|
|
|
65
65
|
# # Add CSV output capability to Album class instances
|
|
66
66
|
# Album.plugin :csv_serializer
|
|
67
67
|
module CsvSerializer
|
|
68
|
-
CSV = Object.const_defined?(:CSV) ? ::CSV : ::FasterCSV
|
|
69
|
-
|
|
70
68
|
# Set up the column readers to do deserialization and the column writers
|
|
71
69
|
# to save the value in deserialized_values
|
|
72
70
|
def self.configure(model, opts = OPTS)
|
|
@@ -75,13 +73,31 @@ module Sequel
|
|
|
75
73
|
end
|
|
76
74
|
end
|
|
77
75
|
|
|
76
|
+
# Avoid keyword argument separation warnings on Ruby 2.7, while still
|
|
77
|
+
# being compatible with 1.9.
|
|
78
|
+
if RUBY_VERSION >= "2.0"
|
|
79
|
+
instance_eval(<<-END, __FILE__, __LINE__+1)
|
|
80
|
+
def self.csv_call(*args, opts, &block)
|
|
81
|
+
CSV.send(*args, **opts, &block)
|
|
82
|
+
end
|
|
83
|
+
END
|
|
84
|
+
else
|
|
85
|
+
# :nocov:
|
|
86
|
+
# :nodoc:
|
|
87
|
+
def self.csv_call(*args, opts, &block)
|
|
88
|
+
CSV.send(*args, opts, &block)
|
|
89
|
+
end
|
|
90
|
+
# :nodoc:
|
|
91
|
+
# :nocov:
|
|
92
|
+
end
|
|
93
|
+
|
|
78
94
|
module ClassMethods
|
|
79
95
|
# The default opts to use when serializing model objects to CSV
|
|
80
96
|
attr_reader :csv_serializer_opts
|
|
81
97
|
|
|
82
98
|
# Attempt to parse an array of instances from the given CSV string
|
|
83
99
|
def array_from_csv(csv, opts = OPTS)
|
|
84
|
-
|
|
100
|
+
CsvSerializer.csv_call(:parse, csv, process_csv_serializer_opts(opts)).map do |row|
|
|
85
101
|
row = row.to_hash
|
|
86
102
|
row.delete(nil)
|
|
87
103
|
new(row)
|
|
@@ -108,7 +124,8 @@ module Sequel
|
|
|
108
124
|
opts_cols = opts.delete(:columns)
|
|
109
125
|
opts_include = opts.delete(:include)
|
|
110
126
|
opts_except = opts.delete(:except)
|
|
111
|
-
|
|
127
|
+
only = opts.delete(:only)
|
|
128
|
+
opts[:headers] ||= Array(only || opts_cols || columns) + Array(opts_include) - Array(opts_except)
|
|
112
129
|
opts
|
|
113
130
|
end
|
|
114
131
|
|
|
@@ -130,7 +147,7 @@ module Sequel
|
|
|
130
147
|
# :headers :: The headers to use for the CSV line. Use nil for a header
|
|
131
148
|
# to specify the column should be ignored.
|
|
132
149
|
def from_csv(csv, opts = OPTS)
|
|
133
|
-
row =
|
|
150
|
+
row = CsvSerializer.csv_call(:parse_line, csv, model.process_csv_serializer_opts(opts)).to_hash
|
|
134
151
|
row.delete(nil)
|
|
135
152
|
set(row)
|
|
136
153
|
end
|
|
@@ -146,9 +163,10 @@ module Sequel
|
|
|
146
163
|
# attributes to include in the CSV output.
|
|
147
164
|
def to_csv(opts = OPTS)
|
|
148
165
|
opts = model.process_csv_serializer_opts(opts)
|
|
166
|
+
headers = opts[:headers]
|
|
149
167
|
|
|
150
|
-
|
|
151
|
-
csv <<
|
|
168
|
+
CsvSerializer.csv_call(:generate, model.process_csv_serializer_opts(opts)) do |csv|
|
|
169
|
+
csv << headers.map{|k| public_send(k)}
|
|
152
170
|
end
|
|
153
171
|
end
|
|
154
172
|
end
|
|
@@ -164,10 +182,11 @@ module Sequel
|
|
|
164
182
|
def to_csv(opts = OPTS)
|
|
165
183
|
opts = model.process_csv_serializer_opts({:columns=>columns}.merge!(opts))
|
|
166
184
|
items = opts.delete(:array) || self
|
|
185
|
+
headers = opts[:headers]
|
|
167
186
|
|
|
168
|
-
|
|
187
|
+
CsvSerializer.csv_call(:generate, opts) do |csv|
|
|
169
188
|
items.each do |object|
|
|
170
|
-
csv <<
|
|
189
|
+
csv << headers.map{|header| object.public_send(header)}
|
|
171
190
|
end
|
|
172
191
|
end
|
|
173
192
|
end
|
|
@@ -62,7 +62,10 @@ module Sequel
|
|
|
62
62
|
ret = super
|
|
63
63
|
r = association_reflection(name)
|
|
64
64
|
meth = r.returns_array? ? name : pluralize(name).to_sym
|
|
65
|
-
dataset_module
|
|
65
|
+
dataset_module do
|
|
66
|
+
define_method(meth){associated(name)}
|
|
67
|
+
alias_method(meth, meth)
|
|
68
|
+
end
|
|
66
69
|
ret
|
|
67
70
|
end
|
|
68
71
|
|
data/lib/sequel/plugins/dirty.rb
CHANGED
|
@@ -41,6 +41,15 @@ module Sequel
|
|
|
41
41
|
# artist.column_changes # => {}
|
|
42
42
|
# artist.previous_changes # => {:name=>['Foo', 'Bar']}
|
|
43
43
|
#
|
|
44
|
+
# artist.column_previously_was(:name)
|
|
45
|
+
# # => 'Foo'
|
|
46
|
+
# artist.column_previously_changed?(:name)
|
|
47
|
+
# # => true
|
|
48
|
+
# artist.column_previously_changed?(:name, from: 'Foo', to: 'Bar')
|
|
49
|
+
# # => true
|
|
50
|
+
# artist.column_previously_changed?(:name, from: 'Foo', to: 'Baz')
|
|
51
|
+
# # => false
|
|
52
|
+
#
|
|
44
53
|
# There is one caveat; when used with a column that also uses the
|
|
45
54
|
# serialization plugin, setting the column back to its original value
|
|
46
55
|
# after changing it is not correctly detected and will leave an entry
|
|
@@ -61,6 +70,19 @@ module Sequel
|
|
|
61
70
|
# that were used in the update statement.
|
|
62
71
|
attr_reader :previous_changes
|
|
63
72
|
|
|
73
|
+
# Reset the initial values after saving.
|
|
74
|
+
def after_save
|
|
75
|
+
super
|
|
76
|
+
reset_initial_values
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Save the current changes so they are available after updating. This happens
|
|
80
|
+
# before after_save resets them.
|
|
81
|
+
def after_update
|
|
82
|
+
super
|
|
83
|
+
@previous_changes = column_changes
|
|
84
|
+
end
|
|
85
|
+
|
|
64
86
|
# An array with the initial value and the current value
|
|
65
87
|
# of the column, if the column has been changed. If the
|
|
66
88
|
# column has not been changed, returns nil.
|
|
@@ -92,6 +114,41 @@ module Sequel
|
|
|
92
114
|
initial_values.has_key?(column)
|
|
93
115
|
end
|
|
94
116
|
|
|
117
|
+
# Whether the column was previously changed.
|
|
118
|
+
# Options:
|
|
119
|
+
# :from :: If given, the previous initial value of the column must match this
|
|
120
|
+
# :to :: If given, the previous changed value of the column must match this
|
|
121
|
+
#
|
|
122
|
+
# update(name: 'Current')
|
|
123
|
+
# previous_changes # => {:name=>['Initial', 'Current']}
|
|
124
|
+
# column_previously_changed?(:name) # => true
|
|
125
|
+
# column_previously_changed?(:id) # => false
|
|
126
|
+
# column_previously_changed?(:name, from: 'Initial', to: 'Current') # => true
|
|
127
|
+
# column_previously_changed?(:name, from: 'Foo', to: 'Current') # => false
|
|
128
|
+
def column_previously_changed?(column, opts=OPTS)
|
|
129
|
+
return false unless (pc = @previous_changes) && (val = pc[column])
|
|
130
|
+
|
|
131
|
+
if opts.has_key?(:from)
|
|
132
|
+
return false unless val[0] == opts[:from]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
if opts.has_key?(:to)
|
|
136
|
+
return false unless val[1] == opts[:to]
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# The previous value of the column, which is the initial value of
|
|
143
|
+
# the column before the object was previously saved.
|
|
144
|
+
#
|
|
145
|
+
# initial_value(:name) # => 'Initial'
|
|
146
|
+
# update(name: 'Current')
|
|
147
|
+
# column_previously_was(:name) # => 'Initial'
|
|
148
|
+
def column_previously_was(column)
|
|
149
|
+
(pc = @previous_changes) && (val = pc[column]) && val[0]
|
|
150
|
+
end
|
|
151
|
+
|
|
95
152
|
# Freeze internal data structures
|
|
96
153
|
def freeze
|
|
97
154
|
initial_values.freeze
|
|
@@ -159,23 +216,10 @@ module Sequel
|
|
|
159
216
|
|
|
160
217
|
private
|
|
161
218
|
|
|
162
|
-
# Reset
|
|
163
|
-
def
|
|
164
|
-
reset_initial_values
|
|
165
|
-
super
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
# Reset the initial values after saving.
|
|
169
|
-
def after_save
|
|
170
|
-
super
|
|
171
|
-
reset_initial_values
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
# Save the current changes so they are available after updating. This happens
|
|
175
|
-
# before after_save resets them.
|
|
176
|
-
def after_update
|
|
219
|
+
# Reset initial values when clearing changed columns
|
|
220
|
+
def _clear_changed_columns(reason)
|
|
221
|
+
reset_initial_values if reason == :initialize || reason == :refresh
|
|
177
222
|
super
|
|
178
|
-
@previous_changes = column_changes
|
|
179
223
|
end
|
|
180
224
|
|
|
181
225
|
# When changing the column value, save the initial column value. If the column
|
|
@@ -214,12 +258,6 @@ module Sequel
|
|
|
214
258
|
self
|
|
215
259
|
end
|
|
216
260
|
|
|
217
|
-
# Reset the initial values when initializing.
|
|
218
|
-
def initialize_set(h)
|
|
219
|
-
super
|
|
220
|
-
reset_initial_values
|
|
221
|
-
end
|
|
222
|
-
|
|
223
261
|
# Array holding column symbols that were not present initially. This is necessary
|
|
224
262
|
# to differentiate between values that were not present and values that were
|
|
225
263
|
# present but equal to nil.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module Plugins
|
|
5
|
+
# The empty_failure_backtraces plugin uses empty backtraces when raising HookFailed and ValidationFailed
|
|
6
|
+
# exceptions. This can be significantly faster, and if you are using these exceptions for
|
|
7
|
+
# flow control, you do not need the backtraces. This plugin is about 10% faster on CRuby
|
|
8
|
+
# and 10-15x faster on JRuby 9.2.7.0+. This does not have an effect on JRuby <9.2.7.0.
|
|
9
|
+
#
|
|
10
|
+
# Usage:
|
|
11
|
+
#
|
|
12
|
+
# # Make all model subclass instances use empty backtraces for HookFailed
|
|
13
|
+
# # and ValidationFailed exceptions (called before loading subclasses)
|
|
14
|
+
# Sequel::Model.plugin :empty_failure_backtraces
|
|
15
|
+
#
|
|
16
|
+
# # Make the Album class use empty backtraces for HookFailed and ValidationFailed exceptions
|
|
17
|
+
# Album.plugin :empty_failure_backtraces
|
|
18
|
+
module EmptyFailureBacktraces
|
|
19
|
+
module InstanceMethods
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# Use empty backtrace for HookFailed exceptions.
|
|
23
|
+
def hook_failed_error(msg)
|
|
24
|
+
e = super
|
|
25
|
+
e.set_backtrace([])
|
|
26
|
+
e
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Use empty backtrace for ValidationFailed exceptions.
|
|
30
|
+
def validation_failed_error
|
|
31
|
+
e = super
|
|
32
|
+
e.set_backtrace([])
|
|
33
|
+
e
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module Plugins
|
|
5
|
+
# The forbid_lazy_load plugin forbids lazy loading of associations
|
|
6
|
+
# for objects in cases where the object wasn't loaded with a
|
|
7
|
+
# method that only returns a single object.
|
|
8
|
+
#
|
|
9
|
+
# The main reason for doing this is it makes it easier to detect
|
|
10
|
+
# N+1 query issues. Note that Sequel also offers a
|
|
11
|
+
# tactical_eager_loading plugin which will automatically eagerly
|
|
12
|
+
# load associations for all objects retrived in the same query
|
|
13
|
+
# if any object would attempt to lazily load an association. That
|
|
14
|
+
# approach may be simpler if you are trying to prevent N+1 issues,
|
|
15
|
+
# though it does retain more objects in memory.
|
|
16
|
+
#
|
|
17
|
+
# This plugin offers multiple different ways to forbid lazy
|
|
18
|
+
# loading. You can forbid lazy loading associations for individual
|
|
19
|
+
# model instances:
|
|
20
|
+
#
|
|
21
|
+
# obj = Album[1]
|
|
22
|
+
# obj.forbid_lazy_load
|
|
23
|
+
# obj.artist # raises Sequel::Plugins::ForbidLazyLoad::Error
|
|
24
|
+
#
|
|
25
|
+
# +forbid_lazy_load+ is automatically called on instances if the
|
|
26
|
+
# instances are loaded via a method such as Dataset#all,
|
|
27
|
+
# Dataset#each, and other methods that load multiple instances
|
|
28
|
+
# at once. These are the cases where lazily loading associations
|
|
29
|
+
# for such instances can cause N+1 issues.
|
|
30
|
+
#
|
|
31
|
+
# Album.all.first.artist
|
|
32
|
+
# objs.first.artist # raises Sequel::Plugins::ForbidLazyLoad::Error
|
|
33
|
+
#
|
|
34
|
+
# Album.each do |obj|
|
|
35
|
+
# obj.artist # raises Sequel::Plugins::ForbidLazyLoad::Error
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# Album[1].artist # no error
|
|
39
|
+
#
|
|
40
|
+
# Album.first.artist # no error
|
|
41
|
+
#
|
|
42
|
+
# You can allow lazy loading associations for an instance that it
|
|
43
|
+
# was previously forbidden for:
|
|
44
|
+
#
|
|
45
|
+
# obj = Album.all.first
|
|
46
|
+
# obj.allow_lazy_load
|
|
47
|
+
# obj.artist # no error
|
|
48
|
+
#
|
|
49
|
+
# You can forbid lazy loading associations on a per-call basis,
|
|
50
|
+
# even if lazy loading of associations is allowed for the instance:
|
|
51
|
+
#
|
|
52
|
+
# obj = Album[1]
|
|
53
|
+
# obj.artist(forbid_lazy_load: true)
|
|
54
|
+
# # raises Sequel::Plugins::ForbidLazyLoad::Error
|
|
55
|
+
#
|
|
56
|
+
# This also works for allowing lazy loading associations for a
|
|
57
|
+
# specific association load even if it is forbidden for the instance:
|
|
58
|
+
#
|
|
59
|
+
# obj = Album.all.first
|
|
60
|
+
# obj.artist(forbid_lazy_load: false)
|
|
61
|
+
# # nothing raised
|
|
62
|
+
#
|
|
63
|
+
# You can also forbid lazy loading on a per-association basis using the
|
|
64
|
+
# +:forbid_lazy_load+ association option with a +true+ value:
|
|
65
|
+
#
|
|
66
|
+
# Album.many_to_one :artist, forbid_lazy_load: true
|
|
67
|
+
# Album[1].artist # raises Sequel::Plugins::ForbidLazyLoad::Error
|
|
68
|
+
#
|
|
69
|
+
# However, you probably don't want to do this as it will forbid any
|
|
70
|
+
# lazy loading of the association, even if the loading could not
|
|
71
|
+
# result in an N+1 issue.
|
|
72
|
+
#
|
|
73
|
+
# On the flip side, you can allow lazy loading using the
|
|
74
|
+
# +:forbid_lazy_load+ association option with a +false+ value:
|
|
75
|
+
#
|
|
76
|
+
# Album.many_to_one :artist, forbid_lazy_load: false
|
|
77
|
+
# Album.all.first.artist # no error
|
|
78
|
+
#
|
|
79
|
+
# One reason to do this is when using a plugin like static_cache
|
|
80
|
+
# on the associated model, where a query is not actually issued
|
|
81
|
+
# when doing a lazy association load. To make that particular
|
|
82
|
+
# case easier, this plugin makes Model.finalize_associations
|
|
83
|
+
# automatically set the association option if the associated
|
|
84
|
+
# class uses the static_cache plugin.
|
|
85
|
+
#
|
|
86
|
+
# Note that even with this plugin, there can still be N+1 issues,
|
|
87
|
+
# such as:
|
|
88
|
+
#
|
|
89
|
+
# Album.each do |obj| # 1 query for all albums
|
|
90
|
+
# Artist[obj.artist_id] # 1 query per album for each artist
|
|
91
|
+
# end
|
|
92
|
+
#
|
|
93
|
+
# Usage:
|
|
94
|
+
#
|
|
95
|
+
# # Make all model subclasses support forbidding lazy load
|
|
96
|
+
# # (called before loading subclasses)
|
|
97
|
+
# Sequel::Model.plugin :forbid_lazy_load
|
|
98
|
+
#
|
|
99
|
+
# # Make the Album class support forbidding lazy load
|
|
100
|
+
# Album.plugin :forbid_lazy_load
|
|
101
|
+
module ForbidLazyLoad
|
|
102
|
+
# Error raised when attempting to lazy load an association when
|
|
103
|
+
# lazy loading has been forbidden.
|
|
104
|
+
class Error < StandardError
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
module ClassMethods
|
|
108
|
+
Plugins.def_dataset_methods(self, :forbid_lazy_load)
|
|
109
|
+
|
|
110
|
+
# If the static_cache plugin is used by the associated class for
|
|
111
|
+
# an association, allow lazy loading that association, since the
|
|
112
|
+
# lazy association load will use a hash table lookup and not a query.
|
|
113
|
+
def allow_lazy_load_for_static_cache_associations
|
|
114
|
+
# :nocov:
|
|
115
|
+
if defined?(::Sequel::Plugins::StaticCache::ClassMethods)
|
|
116
|
+
# :nocov:
|
|
117
|
+
@association_reflections.each_value do |ref|
|
|
118
|
+
if ref.associated_class.is_a?(::Sequel::Plugins::StaticCache::ClassMethods)
|
|
119
|
+
ref[:forbid_lazy_load] = false
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Allow lazy loading for static cache associations before finalizing.
|
|
126
|
+
def finalize_associations
|
|
127
|
+
allow_lazy_load_for_static_cache_associations
|
|
128
|
+
super
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
module InstanceMethods
|
|
133
|
+
# Set this model instance to allow lazy loading of associations.
|
|
134
|
+
def allow_lazy_load
|
|
135
|
+
@forbid_lazy_load = false
|
|
136
|
+
self
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Set this model instance to not allow lazy loading of associations.
|
|
140
|
+
def forbid_lazy_load
|
|
141
|
+
@forbid_lazy_load = true
|
|
142
|
+
self
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
|
|
147
|
+
# Allow lazy loading for objects returned by singular associations.
|
|
148
|
+
def _load_associated_object(opts, dynamic_opts)
|
|
149
|
+
# The implementation that loads these associations does
|
|
150
|
+
# .all.first, which would result in the object returned being
|
|
151
|
+
# marked as forbidding lazy load.
|
|
152
|
+
obj = super
|
|
153
|
+
obj.allow_lazy_load if obj.is_a?(InstanceMethods)
|
|
154
|
+
obj
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Raise an Error if lazy loading has been forbidden for
|
|
158
|
+
# the instance, association, or call.
|
|
159
|
+
def _load_associated_objects(opts, dynamic_opts=OPTS)
|
|
160
|
+
case dynamic_opts[:forbid_lazy_load]
|
|
161
|
+
when false
|
|
162
|
+
# nothing
|
|
163
|
+
when nil
|
|
164
|
+
unless dynamic_opts[:reload]
|
|
165
|
+
case opts[:forbid_lazy_load]
|
|
166
|
+
when nil
|
|
167
|
+
raise Error, "lazy loading forbidden for this object (association: #{opts.inspect}, object: #{inspect})" if @forbid_lazy_load
|
|
168
|
+
when false
|
|
169
|
+
# nothing
|
|
170
|
+
else
|
|
171
|
+
raise Error, "lazy loading forbidden for this association (#{opts.inspect})"
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
else
|
|
175
|
+
raise Error, "lazy loading forbidden for this association method call (association: #{opts.inspect})"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
super
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
module DatasetMethods
|
|
183
|
+
# Mark model instances retrieved in this call as forbidding lazy loading.
|
|
184
|
+
def each
|
|
185
|
+
if row_proc
|
|
186
|
+
super do |obj|
|
|
187
|
+
obj.forbid_lazy_load if obj.is_a?(InstanceMethods)
|
|
188
|
+
yield obj
|
|
189
|
+
end
|
|
190
|
+
else
|
|
191
|
+
super
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Mark model instances retrieved in this call as forbidding lazy loading.
|
|
196
|
+
def with_sql_each(sql)
|
|
197
|
+
if row_proc
|
|
198
|
+
super(sql) do |obj|
|
|
199
|
+
obj.forbid_lazy_load if obj.is_a?(InstanceMethods)
|
|
200
|
+
yield obj
|
|
201
|
+
end
|
|
202
|
+
else
|
|
203
|
+
super
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Mark model instances retrieved in this call as allowing lazy loading.
|
|
208
|
+
def with_sql_first(sql)
|
|
209
|
+
obj = super
|
|
210
|
+
obj.allow_lazy_load if obj.is_a?(InstanceMethods)
|
|
211
|
+
obj
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|