omg-activerecord 8.0.0.alpha1
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 +7 -0
- data/CHANGELOG.md +355 -0
- data/MIT-LICENSE +22 -0
- data/README.rdoc +219 -0
- data/examples/performance.rb +185 -0
- data/examples/simple.rb +15 -0
- data/lib/active_record/aggregations.rb +287 -0
- data/lib/active_record/association_relation.rb +50 -0
- data/lib/active_record/associations/alias_tracker.rb +90 -0
- data/lib/active_record/associations/association.rb +417 -0
- data/lib/active_record/associations/association_scope.rb +175 -0
- data/lib/active_record/associations/belongs_to_association.rb +163 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
- data/lib/active_record/associations/builder/association.rb +170 -0
- data/lib/active_record/associations/builder/belongs_to.rb +160 -0
- data/lib/active_record/associations/builder/collection_association.rb +80 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +107 -0
- data/lib/active_record/associations/builder/has_many.rb +23 -0
- data/lib/active_record/associations/builder/has_one.rb +61 -0
- data/lib/active_record/associations/builder/singular_association.rb +48 -0
- data/lib/active_record/associations/collection_association.rb +535 -0
- data/lib/active_record/associations/collection_proxy.rb +1163 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +40 -0
- data/lib/active_record/associations/has_many_association.rb +167 -0
- data/lib/active_record/associations/has_many_through_association.rb +232 -0
- data/lib/active_record/associations/has_one_association.rb +142 -0
- data/lib/active_record/associations/has_one_through_association.rb +45 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +106 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
- data/lib/active_record/associations/join_dependency.rb +301 -0
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +316 -0
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +150 -0
- data/lib/active_record/associations/preloader.rb +135 -0
- data/lib/active_record/associations/singular_association.rb +76 -0
- data/lib/active_record/associations/through_association.rb +132 -0
- data/lib/active_record/associations.rb +1897 -0
- data/lib/active_record/asynchronous_queries_tracker.rb +64 -0
- data/lib/active_record/attribute_assignment.rb +82 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +106 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +262 -0
- data/lib/active_record/attribute_methods/primary_key.rb +158 -0
- data/lib/active_record/attribute_methods/query.rb +50 -0
- data/lib/active_record/attribute_methods/read.rb +46 -0
- data/lib/active_record/attribute_methods/serialization.rb +232 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +94 -0
- data/lib/active_record/attribute_methods/write.rb +49 -0
- data/lib/active_record/attribute_methods.rb +542 -0
- data/lib/active_record/attributes.rb +307 -0
- data/lib/active_record/autosave_association.rb +586 -0
- data/lib/active_record/base.rb +338 -0
- data/lib/active_record/callbacks.rb +452 -0
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +95 -0
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +290 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +210 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +923 -0
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +747 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +319 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +239 -0
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +24 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +190 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +961 -0
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +106 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1883 -0
- data/lib/active_record/connection_adapters/abstract/transaction.rb +676 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1218 -0
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1016 -0
- data/lib/active_record/connection_adapters/column.rb +122 -0
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +28 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +114 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +106 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +106 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +300 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +196 -0
- data/lib/active_record/connection_adapters/pool_config.rb +83 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +82 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +231 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +91 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +54 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +31 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +74 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +124 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +125 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +38 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +238 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +169 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +392 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +127 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1162 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +79 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1182 -0
- data/lib/active_record/connection_adapters/schema_cache.rb +478 -0
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +145 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +116 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +39 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +221 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +843 -0
- data/lib/active_record/connection_adapters/statement_pool.rb +67 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +69 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +212 -0
- data/lib/active_record/connection_adapters.rb +176 -0
- data/lib/active_record/connection_handling.rb +413 -0
- data/lib/active_record/core.rb +836 -0
- data/lib/active_record/counter_cache.rb +230 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +105 -0
- data/lib/active_record/database_configurations/database_config.rb +104 -0
- data/lib/active_record/database_configurations/hash_config.rb +172 -0
- data/lib/active_record/database_configurations/url_config.rb +78 -0
- data/lib/active_record/database_configurations.rb +309 -0
- data/lib/active_record/delegated_type.rb +289 -0
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +38 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +121 -0
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +70 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +184 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +177 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +159 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +107 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +424 -0
- data/lib/active_record/errors.rb +614 -0
- data/lib/active_record/explain.rb +63 -0
- data/lib/active_record/explain_registry.rb +37 -0
- data/lib/active_record/explain_subscriber.rb +34 -0
- data/lib/active_record/fixture_set/file.rb +89 -0
- data/lib/active_record/fixture_set/model_metadata.rb +42 -0
- data/lib/active_record/fixture_set/render_context.rb +19 -0
- data/lib/active_record/fixture_set/table_row.rb +208 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +850 -0
- data/lib/active_record/future_result.rb +182 -0
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +366 -0
- data/lib/active_record/insert_all.rb +328 -0
- data/lib/active_record/integration.rb +209 -0
- data/lib/active_record/internal_metadata.rb +164 -0
- data/lib/active_record/legacy_yaml_adapter.rb +15 -0
- data/lib/active_record/locale/en.yml +48 -0
- data/lib/active_record/locking/optimistic.rb +228 -0
- data/lib/active_record/locking/pessimistic.rb +102 -0
- data/lib/active_record/log_subscriber.rb +149 -0
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +87 -0
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +406 -0
- data/lib/active_record/migration/compatibility.rb +490 -0
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +16 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +1626 -0
- data/lib/active_record/model_schema.rb +635 -0
- data/lib/active_record/nested_attributes.rb +633 -0
- data/lib/active_record/no_touching.rb +65 -0
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +968 -0
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +56 -0
- data/lib/active_record/query_logs.rb +247 -0
- data/lib/active_record/query_logs_formatter.rb +30 -0
- data/lib/active_record/querying.rb +122 -0
- data/lib/active_record/railtie.rb +440 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -0
- data/lib/active_record/railties/controller_runtime.rb +65 -0
- data/lib/active_record/railties/databases.rake +641 -0
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +66 -0
- data/lib/active_record/reflection.rb +1287 -0
- data/lib/active_record/relation/batches/batch_enumerator.rb +115 -0
- data/lib/active_record/relation/batches.rb +491 -0
- data/lib/active_record/relation/calculations.rb +679 -0
- data/lib/active_record/relation/delegation.rb +154 -0
- data/lib/active_record/relation/finder_methods.rb +661 -0
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +192 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +76 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +60 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +24 -0
- data/lib/active_record/relation/predicate_builder.rb +181 -0
- data/lib/active_record/relation/query_attribute.rb +68 -0
- data/lib/active_record/relation/query_methods.rb +2235 -0
- data/lib/active_record/relation/record_fetch_warning.rb +52 -0
- data/lib/active_record/relation/spawn_methods.rb +78 -0
- data/lib/active_record/relation/where_clause.rb +218 -0
- data/lib/active_record/relation.rb +1495 -0
- data/lib/active_record/result.rb +249 -0
- data/lib/active_record/runtime_registry.rb +82 -0
- data/lib/active_record/sanitization.rb +254 -0
- data/lib/active_record/schema.rb +77 -0
- data/lib/active_record/schema_dumper.rb +364 -0
- data/lib/active_record/schema_migration.rb +106 -0
- data/lib/active_record/scoping/default.rb +205 -0
- data/lib/active_record/scoping/named.rb +202 -0
- data/lib/active_record/scoping.rb +136 -0
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +66 -0
- data/lib/active_record/serialization.rb +29 -0
- data/lib/active_record/signed_id.rb +137 -0
- data/lib/active_record/statement_cache.rb +164 -0
- data/lib/active_record/store.rb +299 -0
- data/lib/active_record/suppressor.rb +59 -0
- data/lib/active_record/table_metadata.rb +85 -0
- data/lib/active_record/tasks/database_tasks.rb +681 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +120 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +147 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +89 -0
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +321 -0
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +177 -0
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +70 -0
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +523 -0
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/type/adapter_specific_registry.rb +144 -0
- data/lib/active_record/type/date.rb +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +57 -0
- data/lib/active_record/type/internal/timezone.rb +22 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +76 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +35 -0
- data/lib/active_record/type/type_map.rb +58 -0
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type.rb +83 -0
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +65 -0
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +36 -0
- data/lib/active_record/validations/presence.rb +45 -0
- data/lib/active_record/validations/uniqueness.rb +295 -0
- data/lib/active_record/validations.rb +101 -0
- data/lib/active_record/version.rb +10 -0
- data/lib/active_record.rb +616 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +33 -0
- data/lib/arel/collectors/bind.rb +31 -0
- data/lib/arel/collectors/composite.rb +46 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +48 -0
- data/lib/arel/delete_manager.rb +32 -0
- data/lib/arel/errors.rb +19 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +53 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +48 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +125 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +44 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +45 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +68 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/nary.rb +39 -0
- data/lib/arel/nodes/node.rb +161 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +32 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +35 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +46 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +75 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +260 -0
- data/lib/arel/select_manager.rb +276 -0
- data/lib/arel/table.rb +121 -0
- data/lib/arel/tree_manager.rb +65 -0
- data/lib/arel/update_manager.rb +49 -0
- data/lib/arel/visitors/dot.rb +299 -0
- data/lib/arel/visitors/mysql.rb +111 -0
- data/lib/arel/visitors/postgresql.rb +99 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +1033 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +73 -0
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +76 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +29 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
- data/lib/rails/generators/active_record/migration.rb +54 -0
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +94 -0
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- data/lib/rails/generators/active_record.rb +19 -0
- metadata +505 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module LegacyYamlAdapter # :nodoc:
|
|
5
|
+
def self.convert(coder)
|
|
6
|
+
return coder unless coder.is_a?(Psych::Coder)
|
|
7
|
+
|
|
8
|
+
case coder["active_record_yaml_version"]
|
|
9
|
+
when 1, 2 then coder
|
|
10
|
+
else
|
|
11
|
+
raise("Active Record doesn't know how to load YAML with this format.")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
en:
|
|
2
|
+
# Attributes names common to most models
|
|
3
|
+
#attributes:
|
|
4
|
+
#created_at: "Created at"
|
|
5
|
+
#updated_at: "Updated at"
|
|
6
|
+
|
|
7
|
+
# Default error messages
|
|
8
|
+
errors:
|
|
9
|
+
messages:
|
|
10
|
+
required: "must exist"
|
|
11
|
+
taken: "has already been taken"
|
|
12
|
+
|
|
13
|
+
# Active Record models configuration
|
|
14
|
+
activerecord:
|
|
15
|
+
errors:
|
|
16
|
+
messages:
|
|
17
|
+
record_invalid: "Validation failed: %{errors}"
|
|
18
|
+
restrict_dependent_destroy:
|
|
19
|
+
has_one: "Cannot delete record because a dependent %{record} exists"
|
|
20
|
+
has_many: "Cannot delete record because dependent %{record} exist"
|
|
21
|
+
# Append your own errors here or at the model/attributes scope.
|
|
22
|
+
|
|
23
|
+
# You can define own errors for models or model attributes.
|
|
24
|
+
# The values :model, :attribute and :value are always available for interpolation.
|
|
25
|
+
#
|
|
26
|
+
# For example,
|
|
27
|
+
# models:
|
|
28
|
+
# user:
|
|
29
|
+
# blank: "This is a custom blank message for %{model}: %{attribute}"
|
|
30
|
+
# attributes:
|
|
31
|
+
# login:
|
|
32
|
+
# blank: "This is a custom blank message for User login"
|
|
33
|
+
# Will define custom blank validation message for User model and
|
|
34
|
+
# custom blank validation message for login attribute of User model.
|
|
35
|
+
#models:
|
|
36
|
+
|
|
37
|
+
# Translate model names. Used in Model.human_name().
|
|
38
|
+
#models:
|
|
39
|
+
# For example,
|
|
40
|
+
# user: "Dude"
|
|
41
|
+
# will translate User model name to "Dude"
|
|
42
|
+
|
|
43
|
+
# Translate model attribute names. Used in Model.human_attribute_name(attribute).
|
|
44
|
+
#attributes:
|
|
45
|
+
# For example,
|
|
46
|
+
# user:
|
|
47
|
+
# login: "Handle"
|
|
48
|
+
# will translate User attribute "login" as "Handle"
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Locking
|
|
5
|
+
# == What is \Optimistic \Locking
|
|
6
|
+
#
|
|
7
|
+
# Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
|
|
8
|
+
# conflicts with the data. It does this by checking whether another process has made changes to a record since
|
|
9
|
+
# it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
|
|
10
|
+
# and the update is ignored.
|
|
11
|
+
#
|
|
12
|
+
# Check out +ActiveRecord::Locking::Pessimistic+ for an alternative.
|
|
13
|
+
#
|
|
14
|
+
# == Usage
|
|
15
|
+
#
|
|
16
|
+
# Active Record supports optimistic locking if the +lock_version+ field is present. Each update to the
|
|
17
|
+
# record increments the integer column +lock_version+ and the locking facilities ensure that records instantiated twice
|
|
18
|
+
# will let the last one saved raise a +StaleObjectError+ if the first was also updated. Example:
|
|
19
|
+
#
|
|
20
|
+
# p1 = Person.find(1)
|
|
21
|
+
# p2 = Person.find(1)
|
|
22
|
+
#
|
|
23
|
+
# p1.first_name = "Michael"
|
|
24
|
+
# p1.save
|
|
25
|
+
#
|
|
26
|
+
# p2.first_name = "should fail"
|
|
27
|
+
# p2.save # Raises an ActiveRecord::StaleObjectError
|
|
28
|
+
#
|
|
29
|
+
# Optimistic locking will also check for stale data when objects are destroyed. Example:
|
|
30
|
+
#
|
|
31
|
+
# p1 = Person.find(1)
|
|
32
|
+
# p2 = Person.find(1)
|
|
33
|
+
#
|
|
34
|
+
# p1.first_name = "Michael"
|
|
35
|
+
# p1.save
|
|
36
|
+
#
|
|
37
|
+
# p2.destroy # Raises an ActiveRecord::StaleObjectError
|
|
38
|
+
#
|
|
39
|
+
# You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
|
|
40
|
+
# or otherwise apply the business logic needed to resolve the conflict.
|
|
41
|
+
#
|
|
42
|
+
# This locking mechanism will function inside a single Ruby process. To make it work across all
|
|
43
|
+
# web requests, the recommended approach is to add +lock_version+ as a hidden field to your form.
|
|
44
|
+
#
|
|
45
|
+
# This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>.
|
|
46
|
+
# To override the name of the +lock_version+ column, set the <tt>locking_column</tt> class attribute:
|
|
47
|
+
#
|
|
48
|
+
# class Person < ActiveRecord::Base
|
|
49
|
+
# self.locking_column = :lock_person
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
module Optimistic
|
|
53
|
+
extend ActiveSupport::Concern
|
|
54
|
+
|
|
55
|
+
included do
|
|
56
|
+
class_attribute :lock_optimistically, instance_writer: false, default: true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def locking_enabled? # :nodoc:
|
|
60
|
+
self.class.locking_enabled?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def increment!(*, **) # :nodoc:
|
|
64
|
+
super.tap do
|
|
65
|
+
if locking_enabled?
|
|
66
|
+
self[self.class.locking_column] += 1
|
|
67
|
+
clear_attribute_change(self.class.locking_column)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def initialize_dup(other) # :nodoc:
|
|
73
|
+
super
|
|
74
|
+
_clear_locking_column if locking_enabled?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
def _create_record(attribute_names = self.attribute_names)
|
|
79
|
+
if locking_enabled?
|
|
80
|
+
# We always want to persist the locking version, even if we don't detect
|
|
81
|
+
# a change from the default, since the database might have no default
|
|
82
|
+
attribute_names |= [self.class.locking_column]
|
|
83
|
+
end
|
|
84
|
+
super
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def _touch_row(attribute_names, time)
|
|
88
|
+
@_touch_attr_names << self.class.locking_column if locking_enabled?
|
|
89
|
+
super
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def _update_row(attribute_names, attempted_action = "update")
|
|
93
|
+
return super unless locking_enabled?
|
|
94
|
+
|
|
95
|
+
begin
|
|
96
|
+
locking_column = self.class.locking_column
|
|
97
|
+
lock_attribute_was = @attributes[locking_column]
|
|
98
|
+
|
|
99
|
+
update_constraints = _query_constraints_hash
|
|
100
|
+
|
|
101
|
+
attribute_names = attribute_names.dup if attribute_names.frozen?
|
|
102
|
+
attribute_names << locking_column
|
|
103
|
+
|
|
104
|
+
self[locking_column] += 1
|
|
105
|
+
|
|
106
|
+
affected_rows = self.class._update_record(
|
|
107
|
+
attributes_with_values(attribute_names),
|
|
108
|
+
update_constraints
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if affected_rows != 1
|
|
112
|
+
raise ActiveRecord::StaleObjectError.new(self, attempted_action)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
affected_rows
|
|
116
|
+
|
|
117
|
+
# If something went wrong, revert the locking_column value.
|
|
118
|
+
rescue Exception
|
|
119
|
+
@attributes[locking_column] = lock_attribute_was
|
|
120
|
+
raise
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def destroy_row
|
|
125
|
+
affected_rows = super
|
|
126
|
+
|
|
127
|
+
if locking_enabled? && affected_rows != 1
|
|
128
|
+
raise ActiveRecord::StaleObjectError.new(self, "destroy")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
affected_rows
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def _lock_value_for_database(locking_column)
|
|
135
|
+
if will_save_change_to_attribute?(locking_column)
|
|
136
|
+
@attributes[locking_column].value_for_database
|
|
137
|
+
else
|
|
138
|
+
@attributes[locking_column].original_value_for_database
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def _clear_locking_column
|
|
143
|
+
self[self.class.locking_column] = nil
|
|
144
|
+
clear_attribute_change(self.class.locking_column)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def _query_constraints_hash
|
|
148
|
+
return super unless locking_enabled?
|
|
149
|
+
|
|
150
|
+
locking_column = self.class.locking_column
|
|
151
|
+
super.merge(locking_column => _lock_value_for_database(locking_column))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
module ClassMethods
|
|
155
|
+
DEFAULT_LOCKING_COLUMN = "lock_version"
|
|
156
|
+
|
|
157
|
+
# Returns true if the +lock_optimistically+ flag is set to true
|
|
158
|
+
# (which it is, by default) and the table includes the
|
|
159
|
+
# +locking_column+ column (defaults to +lock_version+).
|
|
160
|
+
def locking_enabled?
|
|
161
|
+
lock_optimistically && columns_hash[locking_column]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Set the column to use for optimistic locking. Defaults to +lock_version+.
|
|
165
|
+
def locking_column=(value)
|
|
166
|
+
reload_schema_from_cache
|
|
167
|
+
@locking_column = value.to_s
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# The version column used for optimistic locking. Defaults to +lock_version+.
|
|
171
|
+
attr_reader :locking_column
|
|
172
|
+
|
|
173
|
+
# Reset the column used for optimistic locking back to the +lock_version+ default.
|
|
174
|
+
def reset_locking_column
|
|
175
|
+
self.locking_column = DEFAULT_LOCKING_COLUMN
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Make sure the lock version column gets updated when counters are
|
|
179
|
+
# updated.
|
|
180
|
+
def update_counters(id, counters)
|
|
181
|
+
counters = counters.merge(locking_column => 1) if locking_enabled?
|
|
182
|
+
super
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
private
|
|
186
|
+
def hook_attribute_type(name, cast_type)
|
|
187
|
+
if lock_optimistically && name == locking_column
|
|
188
|
+
cast_type = LockingType.new(cast_type)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
super
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def inherited(base)
|
|
195
|
+
super
|
|
196
|
+
base.class_eval do
|
|
197
|
+
@locking_column = DEFAULT_LOCKING_COLUMN
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# In de/serialize we change `nil` to 0, so that we can allow passing
|
|
204
|
+
# `nil` values to `lock_version`, and not result in `ActiveRecord::StaleObjectError`
|
|
205
|
+
# during update record.
|
|
206
|
+
class LockingType < DelegateClass(Type::Value) # :nodoc:
|
|
207
|
+
def self.new(subtype)
|
|
208
|
+
self === subtype ? subtype : super
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def deserialize(value)
|
|
212
|
+
super.to_i
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def serialize(value)
|
|
216
|
+
super.to_i
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def init_with(coder)
|
|
220
|
+
__setobj__(coder["subtype"])
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def encode_with(coder)
|
|
224
|
+
coder["subtype"] = __getobj__
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Locking
|
|
5
|
+
# = \Pessimistic \Locking
|
|
6
|
+
#
|
|
7
|
+
# Locking::Pessimistic provides support for row-level locking using
|
|
8
|
+
# SELECT ... FOR UPDATE and other lock types.
|
|
9
|
+
#
|
|
10
|
+
# Chain <tt>ActiveRecord::Base#find</tt> to ActiveRecord::QueryMethods#lock to obtain an exclusive
|
|
11
|
+
# lock on the selected rows:
|
|
12
|
+
# # select * from accounts where id=1 for update
|
|
13
|
+
# Account.lock.find(1)
|
|
14
|
+
#
|
|
15
|
+
# Call <tt>lock('some locking clause')</tt> to use a database-specific locking clause
|
|
16
|
+
# of your own such as 'LOCK IN SHARE MODE' or 'FOR UPDATE NOWAIT'. Example:
|
|
17
|
+
#
|
|
18
|
+
# Account.transaction do
|
|
19
|
+
# # select * from accounts where name = 'shugo' limit 1 for update nowait
|
|
20
|
+
# shugo = Account.lock("FOR UPDATE NOWAIT").find_by(name: "shugo")
|
|
21
|
+
# yuko = Account.lock("FOR UPDATE NOWAIT").find_by(name: "yuko")
|
|
22
|
+
# shugo.balance -= 100
|
|
23
|
+
# shugo.save!
|
|
24
|
+
# yuko.balance += 100
|
|
25
|
+
# yuko.save!
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# You can also use <tt>ActiveRecord::Base#lock!</tt> method to lock one record by id.
|
|
29
|
+
# This may be better if you don't need to lock every row. Example:
|
|
30
|
+
#
|
|
31
|
+
# Account.transaction do
|
|
32
|
+
# # select * from accounts where ...
|
|
33
|
+
# accounts = Account.where(...)
|
|
34
|
+
# account1 = accounts.detect { |account| ... }
|
|
35
|
+
# account2 = accounts.detect { |account| ... }
|
|
36
|
+
# # select * from accounts where id=? for update
|
|
37
|
+
# account1.lock!
|
|
38
|
+
# account2.lock!
|
|
39
|
+
# account1.balance -= 100
|
|
40
|
+
# account1.save!
|
|
41
|
+
# account2.balance += 100
|
|
42
|
+
# account2.save!
|
|
43
|
+
# end
|
|
44
|
+
#
|
|
45
|
+
# You can start a transaction and acquire the lock in one go by calling
|
|
46
|
+
# <tt>with_lock</tt> with a block. The block is called from within
|
|
47
|
+
# a transaction, the object is already locked. Example:
|
|
48
|
+
#
|
|
49
|
+
# account = Account.first
|
|
50
|
+
# account.with_lock do
|
|
51
|
+
# # This block is called within a transaction,
|
|
52
|
+
# # account is already locked.
|
|
53
|
+
# account.balance -= 100
|
|
54
|
+
# account.save!
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# Database-specific information on row locking:
|
|
58
|
+
#
|
|
59
|
+
# [MySQL]
|
|
60
|
+
# https://dev.mysql.com/doc/refman/en/innodb-locking-reads.html
|
|
61
|
+
#
|
|
62
|
+
# [PostgreSQL]
|
|
63
|
+
# https://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE
|
|
64
|
+
module Pessimistic
|
|
65
|
+
# Obtain a row lock on this record. Reloads the record to obtain the requested
|
|
66
|
+
# lock. Pass an SQL locking clause to append the end of the SELECT statement
|
|
67
|
+
# or pass true for "FOR UPDATE" (the default, an exclusive row lock). Returns
|
|
68
|
+
# the locked record.
|
|
69
|
+
def lock!(lock = true)
|
|
70
|
+
if persisted?
|
|
71
|
+
if has_changes_to_save?
|
|
72
|
+
raise(<<-MSG.squish)
|
|
73
|
+
Locking a record with unpersisted changes is not supported. Use
|
|
74
|
+
`save` to persist the changes, or `reload` to discard them
|
|
75
|
+
explicitly.
|
|
76
|
+
Changed attributes: #{changed.map(&:inspect).join(', ')}.
|
|
77
|
+
MSG
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
reload(lock: lock)
|
|
81
|
+
end
|
|
82
|
+
self
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Wraps the passed block in a transaction, reloading the object with a
|
|
86
|
+
# lock before yielding. You can pass the SQL locking clause
|
|
87
|
+
# as an optional argument (see #lock!).
|
|
88
|
+
#
|
|
89
|
+
# You can also pass options like <tt>requires_new:</tt>, <tt>isolation:</tt>,
|
|
90
|
+
# and <tt>joinable:</tt> to the wrapping transaction (see
|
|
91
|
+
# ActiveRecord::ConnectionAdapters::DatabaseStatements#transaction).
|
|
92
|
+
def with_lock(*args)
|
|
93
|
+
transaction_opts = args.extract_options!
|
|
94
|
+
lock = args.present? ? args.first : true
|
|
95
|
+
transaction(**transaction_opts) do
|
|
96
|
+
lock!(lock)
|
|
97
|
+
yield
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
|
5
|
+
IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
|
|
6
|
+
|
|
7
|
+
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
|
8
|
+
|
|
9
|
+
def strict_loading_violation(event)
|
|
10
|
+
debug do
|
|
11
|
+
owner = event.payload[:owner]
|
|
12
|
+
reflection = event.payload[:reflection]
|
|
13
|
+
color(reflection.strict_loading_violation_message(owner), RED)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
subscribe_log_level :strict_loading_violation, :debug
|
|
17
|
+
|
|
18
|
+
def sql(event)
|
|
19
|
+
payload = event.payload
|
|
20
|
+
|
|
21
|
+
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
|
22
|
+
|
|
23
|
+
name = if payload[:async]
|
|
24
|
+
"ASYNC #{payload[:name]} (#{payload[:lock_wait].round(1)}ms) (db time #{event.duration.round(1)}ms)"
|
|
25
|
+
else
|
|
26
|
+
"#{payload[:name]} (#{event.duration.round(1)}ms)"
|
|
27
|
+
end
|
|
28
|
+
name = "CACHE #{name}" if payload[:cached]
|
|
29
|
+
sql = payload[:sql]
|
|
30
|
+
binds = nil
|
|
31
|
+
|
|
32
|
+
if payload[:binds]&.any?
|
|
33
|
+
casted_params = type_casted_binds(payload[:type_casted_binds])
|
|
34
|
+
|
|
35
|
+
binds = []
|
|
36
|
+
payload[:binds].each_with_index do |attr, i|
|
|
37
|
+
attribute_name = if attr.respond_to?(:name)
|
|
38
|
+
attr.name
|
|
39
|
+
elsif attr.respond_to?(:[]) && attr[i].respond_to?(:name)
|
|
40
|
+
attr[i].name
|
|
41
|
+
else
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
filtered_params = filter(attribute_name, casted_params[i])
|
|
46
|
+
|
|
47
|
+
binds << render_bind(attr, filtered_params)
|
|
48
|
+
end
|
|
49
|
+
binds = binds.inspect
|
|
50
|
+
binds.prepend(" ")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
name = colorize_payload_name(name, payload[:name])
|
|
54
|
+
sql = color(sql, sql_color(sql), bold: true) if colorize_logging
|
|
55
|
+
|
|
56
|
+
debug " #{name} #{sql}#{binds}"
|
|
57
|
+
end
|
|
58
|
+
subscribe_log_level :sql, :debug
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
def type_casted_binds(casted_binds)
|
|
62
|
+
casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def render_bind(attr, value)
|
|
66
|
+
case attr
|
|
67
|
+
when ActiveModel::Attribute
|
|
68
|
+
if attr.type.binary? && attr.value
|
|
69
|
+
value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>"
|
|
70
|
+
end
|
|
71
|
+
when Array
|
|
72
|
+
attr = attr.first
|
|
73
|
+
else
|
|
74
|
+
attr = nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
[attr&.name, value]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def colorize_payload_name(name, payload_name)
|
|
81
|
+
if payload_name.blank? || payload_name == "SQL" # SQL vs Model Load/Exists
|
|
82
|
+
color(name, MAGENTA, bold: true)
|
|
83
|
+
else
|
|
84
|
+
color(name, CYAN, bold: true)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def sql_color(sql)
|
|
89
|
+
case sql
|
|
90
|
+
when /\A\s*rollback/mi
|
|
91
|
+
RED
|
|
92
|
+
when /select .*for update/mi, /\A\s*lock/mi
|
|
93
|
+
WHITE
|
|
94
|
+
when /\A\s*select/i
|
|
95
|
+
BLUE
|
|
96
|
+
when /\A\s*insert/i
|
|
97
|
+
GREEN
|
|
98
|
+
when /\A\s*update/i
|
|
99
|
+
YELLOW
|
|
100
|
+
when /\A\s*delete/i
|
|
101
|
+
RED
|
|
102
|
+
when /transaction\s*\Z/i
|
|
103
|
+
CYAN
|
|
104
|
+
else
|
|
105
|
+
MAGENTA
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def logger
|
|
110
|
+
ActiveRecord::Base.logger
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def debug(progname = nil, &block)
|
|
114
|
+
return unless super
|
|
115
|
+
|
|
116
|
+
if ActiveRecord.verbose_query_logs
|
|
117
|
+
log_query_source
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def log_query_source
|
|
122
|
+
source = query_source_location
|
|
123
|
+
|
|
124
|
+
if source
|
|
125
|
+
logger.debug(" ↳ #{source}")
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
if Thread.respond_to?(:each_caller_location)
|
|
130
|
+
def query_source_location
|
|
131
|
+
Thread.each_caller_location do |location|
|
|
132
|
+
frame = backtrace_cleaner.clean_frame(location)
|
|
133
|
+
return frame if frame
|
|
134
|
+
end
|
|
135
|
+
nil
|
|
136
|
+
end
|
|
137
|
+
else
|
|
138
|
+
def query_source_location
|
|
139
|
+
backtrace_cleaner.clean(caller(1).lazy).first
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def filter(name, value)
|
|
144
|
+
ActiveRecord::Base.inspection_filter.filter_param(name, value)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
ActiveRecord::LogSubscriber.attach_to :active_record
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Marshalling
|
|
5
|
+
@format_version = 6.1
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
attr_reader :format_version
|
|
9
|
+
|
|
10
|
+
def format_version=(version)
|
|
11
|
+
case version
|
|
12
|
+
when 6.1
|
|
13
|
+
Methods.remove_method(:marshal_dump) if Methods.method_defined?(:marshal_dump)
|
|
14
|
+
when 7.1
|
|
15
|
+
Methods.alias_method(:marshal_dump, :_marshal_dump_7_1)
|
|
16
|
+
else
|
|
17
|
+
raise ArgumentError, "Unknown marshalling format: #{version.inspect}"
|
|
18
|
+
end
|
|
19
|
+
@format_version = version
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module Methods
|
|
24
|
+
def _marshal_dump_7_1
|
|
25
|
+
payload = [attributes_for_database, new_record?]
|
|
26
|
+
|
|
27
|
+
cached_associations = self.class.reflect_on_all_associations.select do |reflection|
|
|
28
|
+
association_cached?(reflection.name) && association(reflection.name).loaded?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
unless cached_associations.empty?
|
|
32
|
+
payload << cached_associations.map do |reflection|
|
|
33
|
+
[reflection.name, association(reflection.name).target]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
payload
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def marshal_load(state)
|
|
41
|
+
attributes_from_database, new_record, associations = state
|
|
42
|
+
|
|
43
|
+
attributes = self.class.attributes_builder.build_from_database(attributes_from_database)
|
|
44
|
+
init_with_attributes(attributes, new_record)
|
|
45
|
+
|
|
46
|
+
if associations
|
|
47
|
+
associations.each do |name, target|
|
|
48
|
+
association(name).target = target
|
|
49
|
+
rescue ActiveRecord::AssociationNotFoundError
|
|
50
|
+
# the association no longer exist, we can just skip it.
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|