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,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module MessagePack # :nodoc:
|
|
5
|
+
FORMAT_VERSION = 1
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def dump(input)
|
|
9
|
+
encoder = Encoder.new
|
|
10
|
+
[FORMAT_VERSION, encoder.encode(input), encoder.entries]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def load(dumped)
|
|
14
|
+
format_version, top_level, entries = dumped
|
|
15
|
+
unless format_version == FORMAT_VERSION
|
|
16
|
+
raise "Invalid format version: #{format_version.inspect}"
|
|
17
|
+
end
|
|
18
|
+
Decoder.new(entries).decode(top_level)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module Extensions
|
|
23
|
+
extend self
|
|
24
|
+
|
|
25
|
+
def install(registry)
|
|
26
|
+
registry.register_type 119, ActiveModel::Type::Binary::Data,
|
|
27
|
+
packer: :to_s,
|
|
28
|
+
unpacker: :new
|
|
29
|
+
|
|
30
|
+
registry.register_type 120, ActiveRecord::Base,
|
|
31
|
+
packer: method(:write_record),
|
|
32
|
+
unpacker: method(:read_record),
|
|
33
|
+
recursive: true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def write_record(record, packer)
|
|
37
|
+
packer.write(ActiveRecord::MessagePack.dump(record))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def read_record(unpacker)
|
|
41
|
+
ActiveRecord::MessagePack.load(unpacker.read)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class Encoder
|
|
46
|
+
attr_reader :entries
|
|
47
|
+
|
|
48
|
+
def initialize
|
|
49
|
+
@entries = []
|
|
50
|
+
@refs = {}.compare_by_identity
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def encode(input)
|
|
54
|
+
if input.is_a?(Array)
|
|
55
|
+
input.map { |record| encode_record(record) }
|
|
56
|
+
elsif input
|
|
57
|
+
encode_record(input)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def encode_record(record)
|
|
62
|
+
ref = @refs[record]
|
|
63
|
+
|
|
64
|
+
if !ref
|
|
65
|
+
ref = @refs[record] = @entries.size
|
|
66
|
+
@entries << build_entry(record)
|
|
67
|
+
add_cached_associations(record, @entries.last)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
ref
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def build_entry(record)
|
|
74
|
+
[
|
|
75
|
+
ActiveSupport::MessagePack::Extensions.dump_class(record.class),
|
|
76
|
+
record.attributes_for_database,
|
|
77
|
+
record.new_record?
|
|
78
|
+
]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def add_cached_associations(record, entry)
|
|
82
|
+
record.class.normalized_reflections.each_value do |reflection|
|
|
83
|
+
if record.association_cached?(reflection.name) && record.association(reflection.name).loaded?
|
|
84
|
+
entry << reflection.name << encode(record.association(reflection.name).target)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
class Decoder
|
|
91
|
+
def initialize(entries)
|
|
92
|
+
@records = entries.map { |entry| build_record(entry) }
|
|
93
|
+
@records.zip(entries) { |record, entry| resolve_cached_associations(record, entry) }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def decode(ref)
|
|
97
|
+
if ref.is_a?(Array)
|
|
98
|
+
ref.map { |r| @records[r] }
|
|
99
|
+
elsif ref
|
|
100
|
+
@records[ref]
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def build_record(entry)
|
|
105
|
+
class_name, attributes_hash, is_new_record, * = entry
|
|
106
|
+
klass = ActiveSupport::MessagePack::Extensions.load_class(class_name)
|
|
107
|
+
attributes = klass.attributes_builder.build_from_database(attributes_hash)
|
|
108
|
+
klass.allocate.init_with_attributes(attributes, is_new_record)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def resolve_cached_associations(record, entry)
|
|
112
|
+
i = 3 # entry == [class_name, attributes_hash, is_new_record, *associations]
|
|
113
|
+
while i < entry.length
|
|
114
|
+
begin
|
|
115
|
+
record.association(entry[i]).target = decode(entry[i + 1])
|
|
116
|
+
rescue ActiveRecord::AssociationNotFoundError
|
|
117
|
+
# The association no longer exists, so just skip it.
|
|
118
|
+
end
|
|
119
|
+
i += 2
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Middleware
|
|
5
|
+
class DatabaseSelector
|
|
6
|
+
class Resolver
|
|
7
|
+
# The session class is used by the DatabaseSelector::Resolver to save
|
|
8
|
+
# timestamps of the last write in the session.
|
|
9
|
+
#
|
|
10
|
+
# The last_write is used to determine whether it's safe to read
|
|
11
|
+
# from the replica or the request needs to be sent to the primary.
|
|
12
|
+
class Session # :nodoc:
|
|
13
|
+
def self.call(request)
|
|
14
|
+
new(request.session)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Converts time to a timestamp that represents milliseconds since
|
|
18
|
+
# epoch.
|
|
19
|
+
def self.convert_time_to_timestamp(time)
|
|
20
|
+
time.to_i * 1000 + time.usec / 1000
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Converts milliseconds since epoch timestamp into a time object.
|
|
24
|
+
def self.convert_timestamp_to_time(timestamp)
|
|
25
|
+
timestamp ? Time.at(timestamp / 1000, (timestamp % 1000) * 1000) : Time.at(0)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(session)
|
|
29
|
+
@session = session
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
attr_reader :session
|
|
33
|
+
|
|
34
|
+
def last_write_timestamp
|
|
35
|
+
self.class.convert_timestamp_to_time(session[:last_write])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def update_last_write_timestamp
|
|
39
|
+
session[:last_write] = self.class.convert_time_to_timestamp(Time.now)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def save(response)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_record/middleware/database_selector/resolver/session"
|
|
4
|
+
require "active_support/core_ext/numeric/time"
|
|
5
|
+
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module Middleware
|
|
8
|
+
class DatabaseSelector
|
|
9
|
+
# The Resolver class is used by the DatabaseSelector middleware to
|
|
10
|
+
# determine which database the request should use.
|
|
11
|
+
#
|
|
12
|
+
# To change the behavior of the Resolver class in your application,
|
|
13
|
+
# create a custom resolver class that inherits from
|
|
14
|
+
# DatabaseSelector::Resolver and implements the methods that need to
|
|
15
|
+
# be changed.
|
|
16
|
+
#
|
|
17
|
+
# By default the Resolver class will send read traffic to the replica
|
|
18
|
+
# if it's been 2 seconds since the last write.
|
|
19
|
+
class Resolver # :nodoc:
|
|
20
|
+
SEND_TO_REPLICA_DELAY = 2.seconds
|
|
21
|
+
|
|
22
|
+
def self.call(context, options = {})
|
|
23
|
+
new(context, options)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize(context, options = {})
|
|
27
|
+
@context = context
|
|
28
|
+
@options = options
|
|
29
|
+
@delay = @options && @options[:delay] ? @options[:delay] : SEND_TO_REPLICA_DELAY
|
|
30
|
+
@instrumenter = ActiveSupport::Notifications.instrumenter
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :context, :delay, :instrumenter
|
|
34
|
+
|
|
35
|
+
def read(&blk)
|
|
36
|
+
if read_from_primary?
|
|
37
|
+
read_from_primary(&blk)
|
|
38
|
+
else
|
|
39
|
+
read_from_replica(&blk)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def write(&blk)
|
|
44
|
+
write_to_primary(&blk)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def update_context(response)
|
|
48
|
+
context.save(response)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def reading_request?(request)
|
|
52
|
+
request.get? || request.head?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
def read_from_primary(&blk)
|
|
57
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: true) do
|
|
58
|
+
instrumenter.instrument("database_selector.active_record.read_from_primary", &blk)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def read_from_replica(&blk)
|
|
63
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord.reading_role, prevent_writes: true) do
|
|
64
|
+
instrumenter.instrument("database_selector.active_record.read_from_replica", &blk)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def write_to_primary
|
|
69
|
+
ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: false) do
|
|
70
|
+
instrumenter.instrument("database_selector.active_record.wrote_to_primary") do
|
|
71
|
+
yield
|
|
72
|
+
ensure
|
|
73
|
+
context.update_last_write_timestamp
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def read_from_primary?
|
|
79
|
+
!time_since_last_write_ok?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def send_to_replica_delay
|
|
83
|
+
delay
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def time_since_last_write_ok?
|
|
87
|
+
Time.now - context.last_write_timestamp >= send_to_replica_delay
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_record/middleware/database_selector/resolver"
|
|
4
|
+
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module Middleware
|
|
7
|
+
# = Database Selector \Middleware
|
|
8
|
+
#
|
|
9
|
+
# The DatabaseSelector Middleware provides a framework for automatically
|
|
10
|
+
# swapping from the primary to the replica database connection. \Rails
|
|
11
|
+
# provides a basic framework to determine when to swap and allows for
|
|
12
|
+
# applications to write custom strategy classes to override the default
|
|
13
|
+
# behavior.
|
|
14
|
+
#
|
|
15
|
+
# The resolver class defines when the application should switch (i.e. read
|
|
16
|
+
# from the primary if a write occurred less than 2 seconds ago) and a
|
|
17
|
+
# resolver context class that sets a value that helps the resolver class
|
|
18
|
+
# decide when to switch.
|
|
19
|
+
#
|
|
20
|
+
# \Rails default middleware uses the request's session to set a timestamp
|
|
21
|
+
# that informs the application when to read from a primary or read from a
|
|
22
|
+
# replica.
|
|
23
|
+
#
|
|
24
|
+
# To use the DatabaseSelector in your application with default settings,
|
|
25
|
+
# run the provided generator.
|
|
26
|
+
#
|
|
27
|
+
# $ bin/rails g active_record:multi_db
|
|
28
|
+
#
|
|
29
|
+
# This will create a file named +config/initializers/multi_db.rb+ with the
|
|
30
|
+
# following contents:
|
|
31
|
+
#
|
|
32
|
+
# Rails.application.configure do
|
|
33
|
+
# config.active_record.database_selector = { delay: 2.seconds }
|
|
34
|
+
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
|
|
35
|
+
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# Alternatively you can set the options in your environment config or
|
|
39
|
+
# any other config file loaded on boot.
|
|
40
|
+
#
|
|
41
|
+
# The default behavior can be changed by setting the config options to a
|
|
42
|
+
# custom class:
|
|
43
|
+
#
|
|
44
|
+
# config.active_record.database_selector = { delay: 2.seconds }
|
|
45
|
+
# config.active_record.database_resolver = MyResolver
|
|
46
|
+
# config.active_record.database_resolver_context = MyResolver::MySession
|
|
47
|
+
#
|
|
48
|
+
# Note: If you are using <tt>rails new my_app --minimal</tt> you will need
|
|
49
|
+
# to call <tt>require "active_support/core_ext/integer/time"</tt> to load
|
|
50
|
+
# the core extension in order to use +2.seconds+
|
|
51
|
+
class DatabaseSelector
|
|
52
|
+
def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
|
|
53
|
+
@app = app
|
|
54
|
+
@resolver_klass = resolver_klass || Resolver
|
|
55
|
+
@context_klass = context_klass || Resolver::Session
|
|
56
|
+
@options = options
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
attr_reader :resolver_klass, :context_klass, :options
|
|
60
|
+
|
|
61
|
+
# Middleware that determines which database connection to use in a multiple
|
|
62
|
+
# database application.
|
|
63
|
+
def call(env)
|
|
64
|
+
request = ActionDispatch::Request.new(env)
|
|
65
|
+
|
|
66
|
+
select_database(request) do
|
|
67
|
+
@app.call(env)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
def select_database(request, &blk)
|
|
73
|
+
context = context_klass.call(request)
|
|
74
|
+
resolver = resolver_klass.call(context, options)
|
|
75
|
+
|
|
76
|
+
response = if resolver.reading_request?(request)
|
|
77
|
+
resolver.read(&blk)
|
|
78
|
+
else
|
|
79
|
+
resolver.write(&blk)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
resolver.update_context(response)
|
|
83
|
+
response
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Middleware
|
|
5
|
+
# = Shard Selector \Middleware
|
|
6
|
+
#
|
|
7
|
+
# The ShardSelector Middleware provides a framework for automatically
|
|
8
|
+
# swapping shards. \Rails provides a basic framework to determine which
|
|
9
|
+
# shard to switch to and allows for applications to write custom strategies
|
|
10
|
+
# for swapping if needed.
|
|
11
|
+
#
|
|
12
|
+
# The ShardSelector takes a set of options (currently only +lock+ is supported)
|
|
13
|
+
# that can be used by the middleware to alter behavior. +lock+ is
|
|
14
|
+
# true by default and will prohibit the request from switching shards once
|
|
15
|
+
# inside the block. If +lock+ is false, then shard swapping will be allowed.
|
|
16
|
+
# For tenant based sharding, +lock+ should always be true to prevent application
|
|
17
|
+
# code from mistakenly switching between tenants.
|
|
18
|
+
#
|
|
19
|
+
# Options can be set in the config:
|
|
20
|
+
#
|
|
21
|
+
# config.active_record.shard_selector = { lock: true }
|
|
22
|
+
#
|
|
23
|
+
# Applications must also provide the code for the resolver as it depends on application
|
|
24
|
+
# specific models. An example resolver would look like this:
|
|
25
|
+
#
|
|
26
|
+
# config.active_record.shard_resolver = ->(request) {
|
|
27
|
+
# subdomain = request.subdomain
|
|
28
|
+
# tenant = Tenant.find_by_subdomain!(subdomain)
|
|
29
|
+
# tenant.shard
|
|
30
|
+
# }
|
|
31
|
+
class ShardSelector
|
|
32
|
+
def initialize(app, resolver, options = {})
|
|
33
|
+
@app = app
|
|
34
|
+
@resolver = resolver
|
|
35
|
+
@options = options
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
attr_reader :resolver, :options
|
|
39
|
+
|
|
40
|
+
def call(env)
|
|
41
|
+
request = ActionDispatch::Request.new(env)
|
|
42
|
+
|
|
43
|
+
shard = selected_shard(request)
|
|
44
|
+
|
|
45
|
+
set_shard(shard) do
|
|
46
|
+
@app.call(env)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
def selected_shard(request)
|
|
52
|
+
resolver.call(request)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def set_shard(shard, &block)
|
|
56
|
+
ActiveRecord::Base.connected_to(shard: shard.to_sym) do
|
|
57
|
+
ActiveRecord::Base.prohibit_shard_swapping(options.fetch(:lock, true), &block)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|