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,319 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "concurrent/map"
|
|
4
|
+
require "concurrent/atomic/atomic_fixnum"
|
|
5
|
+
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module ConnectionAdapters # :nodoc:
|
|
8
|
+
module QueryCache
|
|
9
|
+
DEFAULT_SIZE = 100 # :nodoc:
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def included(base) # :nodoc:
|
|
13
|
+
dirties_query_cache base, :exec_query, :execute, :create, :insert, :update, :delete, :truncate,
|
|
14
|
+
:truncate_tables, :rollback_to_savepoint, :rollback_db_transaction, :restart_db_transaction,
|
|
15
|
+
:exec_insert_all
|
|
16
|
+
|
|
17
|
+
base.set_callback :checkin, :after, :unset_query_cache!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def dirties_query_cache(base, *method_names)
|
|
21
|
+
method_names.each do |method_name|
|
|
22
|
+
base.class_eval <<-end_code, __FILE__, __LINE__ + 1
|
|
23
|
+
def #{method_name}(...)
|
|
24
|
+
if pool.dirties_query_cache
|
|
25
|
+
ActiveRecord::Base.clear_query_caches_for_current_thread
|
|
26
|
+
end
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
end_code
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Store # :nodoc:
|
|
35
|
+
attr_accessor :enabled, :dirties
|
|
36
|
+
alias_method :enabled?, :enabled
|
|
37
|
+
alias_method :dirties?, :dirties
|
|
38
|
+
|
|
39
|
+
def initialize(version, max_size)
|
|
40
|
+
@version = version
|
|
41
|
+
@current_version = version.value
|
|
42
|
+
@map = {}
|
|
43
|
+
@max_size = max_size
|
|
44
|
+
@enabled = false
|
|
45
|
+
@dirties = true
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def size
|
|
49
|
+
check_version
|
|
50
|
+
@map.size
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def empty?
|
|
54
|
+
check_version
|
|
55
|
+
@map.empty?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def [](key)
|
|
59
|
+
check_version
|
|
60
|
+
return unless @enabled
|
|
61
|
+
|
|
62
|
+
if entry = @map.delete(key)
|
|
63
|
+
@map[key] = entry
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def compute_if_absent(key)
|
|
68
|
+
check_version
|
|
69
|
+
|
|
70
|
+
return yield unless @enabled
|
|
71
|
+
|
|
72
|
+
if entry = @map.delete(key)
|
|
73
|
+
return @map[key] = entry
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if @max_size && @map.size >= @max_size
|
|
77
|
+
@map.shift # evict the oldest entry
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
@map[key] ||= yield
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def clear
|
|
84
|
+
@map.clear
|
|
85
|
+
self
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
private
|
|
89
|
+
def check_version
|
|
90
|
+
if @current_version != @version.value
|
|
91
|
+
@map.clear
|
|
92
|
+
@current_version = @version.value
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
class QueryCacheRegistry # :nodoc:
|
|
98
|
+
def initialize
|
|
99
|
+
@mutex = Mutex.new
|
|
100
|
+
@map = ConnectionPool::WeakThreadKeyMap.new
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def compute_if_absent(context)
|
|
104
|
+
@map[context] || @mutex.synchronize do
|
|
105
|
+
@map[context] ||= yield
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def clear
|
|
110
|
+
@map.synchronize do
|
|
111
|
+
@map.clear
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
module ConnectionPoolConfiguration # :nodoc:
|
|
117
|
+
def initialize(...)
|
|
118
|
+
super
|
|
119
|
+
@query_cache_version = Concurrent::AtomicFixnum.new
|
|
120
|
+
@thread_query_caches = QueryCacheRegistry.new
|
|
121
|
+
@query_cache_max_size = \
|
|
122
|
+
case query_cache = db_config&.query_cache
|
|
123
|
+
when 0, false
|
|
124
|
+
nil
|
|
125
|
+
when Integer
|
|
126
|
+
query_cache
|
|
127
|
+
when nil
|
|
128
|
+
DEFAULT_SIZE
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def checkout_and_verify(connection)
|
|
133
|
+
super
|
|
134
|
+
connection.query_cache ||= query_cache
|
|
135
|
+
connection
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Disable the query cache within the block.
|
|
139
|
+
def disable_query_cache(dirties: true)
|
|
140
|
+
cache = query_cache
|
|
141
|
+
old_enabled, cache.enabled, old_dirties, cache.dirties = cache.enabled, false, cache.dirties, dirties
|
|
142
|
+
begin
|
|
143
|
+
yield
|
|
144
|
+
ensure
|
|
145
|
+
cache.enabled, cache.dirties = old_enabled, old_dirties
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def enable_query_cache
|
|
150
|
+
cache = query_cache
|
|
151
|
+
old_enabled, cache.enabled, old_dirties, cache.dirties = cache.enabled, true, cache.dirties, true
|
|
152
|
+
begin
|
|
153
|
+
yield
|
|
154
|
+
ensure
|
|
155
|
+
cache.enabled, cache.dirties = old_enabled, old_dirties
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def enable_query_cache!
|
|
160
|
+
query_cache.enabled, query_cache.dirties = true, true
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def disable_query_cache!
|
|
164
|
+
query_cache.enabled, query_cache.dirties = false, true
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def query_cache_enabled
|
|
168
|
+
query_cache.enabled
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def dirties_query_cache
|
|
172
|
+
query_cache.dirties
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def clear_query_cache
|
|
176
|
+
if @pinned_connection
|
|
177
|
+
# With transactional fixtures, and especially systems test
|
|
178
|
+
# another thread may use the same connection, but with a different
|
|
179
|
+
# query cache. So we must clear them all.
|
|
180
|
+
@query_cache_version.increment
|
|
181
|
+
end
|
|
182
|
+
query_cache.clear
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def query_cache
|
|
186
|
+
@thread_query_caches.compute_if_absent(ActiveSupport::IsolatedExecutionState.context) do
|
|
187
|
+
Store.new(@query_cache_version, @query_cache_max_size)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
attr_accessor :query_cache
|
|
193
|
+
|
|
194
|
+
def initialize(*)
|
|
195
|
+
super
|
|
196
|
+
@query_cache = nil
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def query_cache_enabled
|
|
200
|
+
@query_cache&.enabled?
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Enable the query cache within the block.
|
|
204
|
+
def cache(&block)
|
|
205
|
+
pool.enable_query_cache(&block)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def enable_query_cache!
|
|
209
|
+
pool.enable_query_cache!
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Disable the query cache within the block.
|
|
213
|
+
#
|
|
214
|
+
# Set <tt>dirties: false</tt> to prevent query caches on all connections from being cleared by write operations.
|
|
215
|
+
# (By default, write operations dirty all connections' query caches in case they are replicas whose cache would now be outdated.)
|
|
216
|
+
def uncached(dirties: true, &block)
|
|
217
|
+
pool.disable_query_cache(dirties: dirties, &block)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def disable_query_cache!
|
|
221
|
+
pool.disable_query_cache!
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Clears the query cache.
|
|
225
|
+
#
|
|
226
|
+
# One reason you may wish to call this method explicitly is between queries
|
|
227
|
+
# that ask the database to randomize results. Otherwise the cache would see
|
|
228
|
+
# the same SQL query and repeatedly return the same result each time, silently
|
|
229
|
+
# undermining the randomness you were expecting.
|
|
230
|
+
def clear_query_cache
|
|
231
|
+
pool.clear_query_cache
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def select_all(arel, name = nil, binds = [], preparable: nil, async: false, allow_retry: false) # :nodoc:
|
|
235
|
+
arel = arel_from_relation(arel)
|
|
236
|
+
|
|
237
|
+
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch.
|
|
238
|
+
# Such queries should not be cached.
|
|
239
|
+
if @query_cache&.enabled? && !(arel.respond_to?(:locked) && arel.locked)
|
|
240
|
+
sql, binds, preparable, allow_retry = to_sql_and_binds(arel, binds, preparable)
|
|
241
|
+
|
|
242
|
+
if async
|
|
243
|
+
result = lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async, allow_retry: allow_retry)
|
|
244
|
+
FutureResult.wrap(result)
|
|
245
|
+
else
|
|
246
|
+
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable, async: async, allow_retry: allow_retry) }
|
|
247
|
+
end
|
|
248
|
+
else
|
|
249
|
+
super
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
private
|
|
254
|
+
def unset_query_cache!
|
|
255
|
+
@query_cache = nil
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def lookup_sql_cache(sql, name, binds)
|
|
259
|
+
key = binds.empty? ? sql : [sql, binds]
|
|
260
|
+
|
|
261
|
+
result = nil
|
|
262
|
+
@lock.synchronize do
|
|
263
|
+
result = @query_cache[key]
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
if result
|
|
267
|
+
ActiveSupport::Notifications.instrument(
|
|
268
|
+
"sql.active_record",
|
|
269
|
+
cache_notification_info_result(sql, name, binds, result)
|
|
270
|
+
)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
result
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def cache_sql(sql, name, binds)
|
|
277
|
+
key = binds.empty? ? sql : [sql, binds]
|
|
278
|
+
result = nil
|
|
279
|
+
hit = true
|
|
280
|
+
|
|
281
|
+
@lock.synchronize do
|
|
282
|
+
result = @query_cache.compute_if_absent(key) do
|
|
283
|
+
hit = false
|
|
284
|
+
yield
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
if hit
|
|
289
|
+
ActiveSupport::Notifications.instrument(
|
|
290
|
+
"sql.active_record",
|
|
291
|
+
cache_notification_info_result(sql, name, binds, result)
|
|
292
|
+
)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
result.dup
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def cache_notification_info_result(sql, name, binds, result)
|
|
299
|
+
payload = cache_notification_info(sql, name, binds)
|
|
300
|
+
payload[:row_count] = result.length
|
|
301
|
+
payload
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Database adapters can override this method to
|
|
305
|
+
# provide custom cache information.
|
|
306
|
+
def cache_notification_info(sql, name, binds)
|
|
307
|
+
{
|
|
308
|
+
sql: sql,
|
|
309
|
+
binds: binds,
|
|
310
|
+
type_casted_binds: -> { type_casted_binds(binds) },
|
|
311
|
+
name: name,
|
|
312
|
+
connection: self,
|
|
313
|
+
transaction: current_transaction.user_transaction.presence,
|
|
314
|
+
cached: true
|
|
315
|
+
}
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
end
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/big_decimal/conversions"
|
|
4
|
+
require "active_support/multibyte/chars"
|
|
5
|
+
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
module ConnectionAdapters # :nodoc:
|
|
8
|
+
# = Active Record Connection Adapters \Quoting
|
|
9
|
+
module Quoting
|
|
10
|
+
extend ActiveSupport::Concern
|
|
11
|
+
|
|
12
|
+
module ClassMethods # :nodoc:
|
|
13
|
+
# Regexp for column names (with or without a table name prefix).
|
|
14
|
+
# Matches the following:
|
|
15
|
+
#
|
|
16
|
+
# "#{table_name}.#{column_name}"
|
|
17
|
+
# "#{column_name}"
|
|
18
|
+
def column_name_matcher
|
|
19
|
+
/
|
|
20
|
+
\A
|
|
21
|
+
(
|
|
22
|
+
(?:
|
|
23
|
+
# table_name.column_name | function(one or no argument)
|
|
24
|
+
((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
|
|
25
|
+
)
|
|
26
|
+
(?:(?:\s+AS)?\s+\w+)?
|
|
27
|
+
)
|
|
28
|
+
(?:\s*,\s*\g<1>)*
|
|
29
|
+
\z
|
|
30
|
+
/ix
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Regexp for column names with order (with or without a table name prefix,
|
|
34
|
+
# with or without various order modifiers). Matches the following:
|
|
35
|
+
#
|
|
36
|
+
# "#{table_name}.#{column_name}"
|
|
37
|
+
# "#{table_name}.#{column_name} #{direction}"
|
|
38
|
+
# "#{table_name}.#{column_name} #{direction} NULLS FIRST"
|
|
39
|
+
# "#{table_name}.#{column_name} NULLS LAST"
|
|
40
|
+
# "#{column_name}"
|
|
41
|
+
# "#{column_name} #{direction}"
|
|
42
|
+
# "#{column_name} #{direction} NULLS FIRST"
|
|
43
|
+
# "#{column_name} NULLS LAST"
|
|
44
|
+
def column_name_with_order_matcher
|
|
45
|
+
/
|
|
46
|
+
\A
|
|
47
|
+
(
|
|
48
|
+
(?:
|
|
49
|
+
# table_name.column_name | function(one or no argument)
|
|
50
|
+
((?:\w+\.)?\w+ | \w+\((?:|\g<2>)\))
|
|
51
|
+
)
|
|
52
|
+
(?:\s+ASC|\s+DESC)?
|
|
53
|
+
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
|
54
|
+
)
|
|
55
|
+
(?:\s*,\s*\g<1>)*
|
|
56
|
+
\z
|
|
57
|
+
/ix
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Quotes the column name. Must be implemented by subclasses
|
|
61
|
+
def quote_column_name(column_name)
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Quotes the table name. Defaults to column name quoting.
|
|
66
|
+
def quote_table_name(table_name)
|
|
67
|
+
quote_column_name(table_name)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Quotes the column value to help prevent
|
|
72
|
+
# {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
|
|
73
|
+
def quote(value)
|
|
74
|
+
case value
|
|
75
|
+
when String, Symbol, ActiveSupport::Multibyte::Chars
|
|
76
|
+
"'#{quote_string(value.to_s)}'"
|
|
77
|
+
when true then quoted_true
|
|
78
|
+
when false then quoted_false
|
|
79
|
+
when nil then "NULL"
|
|
80
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
|
81
|
+
when BigDecimal then value.to_s("F")
|
|
82
|
+
when Numeric then value.to_s
|
|
83
|
+
when Type::Binary::Data then quoted_binary(value)
|
|
84
|
+
when Type::Time::Value then "'#{quoted_time(value)}'"
|
|
85
|
+
when Date, Time then "'#{quoted_date(value)}'"
|
|
86
|
+
when Class then "'#{value}'"
|
|
87
|
+
else raise TypeError, "can't quote #{value.class.name}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Cast a +value+ to a type that the database understands. For example,
|
|
92
|
+
# SQLite does not understand dates, so this method will convert a Date
|
|
93
|
+
# to a String.
|
|
94
|
+
def type_cast(value)
|
|
95
|
+
case value
|
|
96
|
+
when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
|
|
97
|
+
value.to_s
|
|
98
|
+
when true then unquoted_true
|
|
99
|
+
when false then unquoted_false
|
|
100
|
+
# BigDecimals need to be put in a non-normalized form and quoted.
|
|
101
|
+
when BigDecimal then value.to_s("F")
|
|
102
|
+
when nil, Numeric, String then value
|
|
103
|
+
when Type::Time::Value then quoted_time(value)
|
|
104
|
+
when Date, Time then quoted_date(value)
|
|
105
|
+
else raise TypeError, "can't cast #{value.class.name}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Cast a value to be used as a bound parameter of unknown type. For example,
|
|
110
|
+
# MySQL might perform dangerous castings when comparing a string to a number,
|
|
111
|
+
# so this method will cast numbers to string.
|
|
112
|
+
def cast_bound_value(value) # :nodoc:
|
|
113
|
+
value
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# If you are having to call this function, you are likely doing something
|
|
117
|
+
# wrong. The column does not have sufficient type information if the user
|
|
118
|
+
# provided a custom type on the class level either explicitly (via
|
|
119
|
+
# Attributes::ClassMethods#attribute) or implicitly (via
|
|
120
|
+
# AttributeMethods::Serialization::ClassMethods#serialize, +time_zone_aware_attributes+).
|
|
121
|
+
# In almost all cases, the sql type should only be used to change quoting behavior, when the primitive to
|
|
122
|
+
# represent the type doesn't sufficiently reflect the differences
|
|
123
|
+
# (varchar vs binary) for example. The type used to get this primitive
|
|
124
|
+
# should have been provided before reaching the connection adapter.
|
|
125
|
+
def lookup_cast_type_from_column(column) # :nodoc:
|
|
126
|
+
lookup_cast_type(column.sql_type)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
|
130
|
+
# characters.
|
|
131
|
+
def quote_string(s)
|
|
132
|
+
s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Quotes the column name.
|
|
136
|
+
def quote_column_name(column_name)
|
|
137
|
+
self.class.quote_column_name(column_name)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Quotes the table name.
|
|
141
|
+
def quote_table_name(table_name)
|
|
142
|
+
self.class.quote_table_name(table_name)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Override to return the quoted table name for assignment. Defaults to
|
|
146
|
+
# table quoting.
|
|
147
|
+
#
|
|
148
|
+
# This works for MySQL where table.column can be used to
|
|
149
|
+
# resolve ambiguity.
|
|
150
|
+
#
|
|
151
|
+
# We override this in the sqlite3 and postgresql adapters to use only
|
|
152
|
+
# the column name (as per syntax requirements).
|
|
153
|
+
def quote_table_name_for_assignment(table, attr)
|
|
154
|
+
quote_table_name("#{table}.#{attr}")
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def quote_default_expression(value, column) # :nodoc:
|
|
158
|
+
if value.is_a?(Proc)
|
|
159
|
+
value.call
|
|
160
|
+
else
|
|
161
|
+
value = lookup_cast_type(column.sql_type).serialize(value)
|
|
162
|
+
quote(value)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def quoted_true
|
|
167
|
+
"TRUE"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def unquoted_true
|
|
171
|
+
true
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def quoted_false
|
|
175
|
+
"FALSE"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def unquoted_false
|
|
179
|
+
false
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Quote date/time values for use in SQL input. Includes microseconds
|
|
183
|
+
# if the value is a Time responding to usec.
|
|
184
|
+
def quoted_date(value)
|
|
185
|
+
if value.acts_like?(:time)
|
|
186
|
+
if default_timezone == :utc
|
|
187
|
+
value = value.getutc if !value.utc?
|
|
188
|
+
else
|
|
189
|
+
value = value.getlocal
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
result = value.to_fs(:db)
|
|
194
|
+
if value.respond_to?(:usec) && value.usec > 0
|
|
195
|
+
result << "." << sprintf("%06d", value.usec)
|
|
196
|
+
else
|
|
197
|
+
result
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def quoted_time(value) # :nodoc:
|
|
202
|
+
value = value.change(year: 2000, month: 1, day: 1)
|
|
203
|
+
quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "")
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def quoted_binary(value) # :nodoc:
|
|
207
|
+
"'#{quote_string(value.to_s)}'"
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def sanitize_as_sql_comment(value) # :nodoc:
|
|
211
|
+
# Sanitize a string to appear within a SQL comment
|
|
212
|
+
# For compatibility, this also surrounding "/*+", "/*", and "*/"
|
|
213
|
+
# charcacters, possibly with single surrounding space.
|
|
214
|
+
# Then follows that by replacing any internal "*/" or "/ *" with
|
|
215
|
+
# "* /" or "/ *"
|
|
216
|
+
comment = value.to_s.dup
|
|
217
|
+
comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
|
|
218
|
+
comment.gsub!("*/", "* /")
|
|
219
|
+
comment.gsub!("/*", "/ *")
|
|
220
|
+
comment
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
private
|
|
224
|
+
def type_casted_binds(binds)
|
|
225
|
+
binds&.map do |value|
|
|
226
|
+
if ActiveModel::Attribute === value
|
|
227
|
+
type_cast(value.value_for_database)
|
|
228
|
+
else
|
|
229
|
+
type_cast(value)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def lookup_cast_type(sql_type)
|
|
235
|
+
type_map.lookup(sql_type)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module ConnectionAdapters
|
|
5
|
+
# = Active Record Connection Adapters \Savepoints
|
|
6
|
+
module Savepoints
|
|
7
|
+
def current_savepoint_name
|
|
8
|
+
current_transaction.savepoint_name
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create_savepoint(name = current_savepoint_name)
|
|
12
|
+
internal_execute("SAVEPOINT #{name}", "TRANSACTION")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def exec_rollback_to_savepoint(name = current_savepoint_name)
|
|
16
|
+
internal_execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def release_savepoint(name = current_savepoint_name)
|
|
20
|
+
internal_execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|