activerecord 5.0.7.2 → 6.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +829 -2015
- data/MIT-LICENSE +3 -1
- data/README.rdoc +11 -9
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record.rb +37 -29
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +30 -18
- data/lib/active_record/associations.rb +1714 -1596
- data/lib/active_record/associations/alias_tracker.rb +36 -42
- data/lib/active_record/associations/association.rb +143 -68
- data/lib/active_record/associations/association_scope.rb +98 -94
- data/lib/active_record/associations/belongs_to_association.rb +76 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +27 -28
- data/lib/active_record/associations/builder/belongs_to.rb +52 -60
- data/lib/active_record/associations/builder/collection_association.rb +12 -22
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
- data/lib/active_record/associations/builder/has_many.rb +10 -2
- data/lib/active_record/associations/builder/has_one.rb +35 -2
- data/lib/active_record/associations/builder/singular_association.rb +5 -1
- data/lib/active_record/associations/collection_association.rb +104 -259
- data/lib/active_record/associations/collection_proxy.rb +169 -125
- data/lib/active_record/associations/foreign_association.rb +22 -0
- data/lib/active_record/associations/has_many_association.rb +46 -31
- data/lib/active_record/associations/has_many_through_association.rb +66 -46
- data/lib/active_record/associations/has_one_association.rb +71 -52
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +169 -180
- data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/preloader.rb +97 -104
- data/lib/active_record/associations/preloader/association.rb +109 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/attribute_assignment.rb +55 -60
- data/lib/active_record/attribute_methods.rb +111 -141
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
- data/lib/active_record/attribute_methods/dirty.rb +172 -112
- data/lib/active_record/attribute_methods/primary_key.rb +88 -91
- data/lib/active_record/attribute_methods/query.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +18 -50
- data/lib/active_record/attribute_methods/serialization.rb +38 -10
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
- data/lib/active_record/attribute_methods/write.rb +25 -32
- data/lib/active_record/attributes.rb +69 -31
- data/lib/active_record/autosave_association.rb +102 -66
- data/lib/active_record/base.rb +16 -25
- data/lib/active_record/callbacks.rb +202 -43
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +11 -12
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
- data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
- data/lib/active_record/connection_adapters/column.rb +55 -13
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- 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 +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
- data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +287 -45
- data/lib/active_record/core.rb +385 -181
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +122 -47
- data/lib/active_record/errors.rb +153 -22
- data/lib/active_record/explain.rb +13 -8
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +20 -22
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +246 -507
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +168 -95
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +114 -25
- data/lib/active_record/internal_metadata.rb +30 -24
- data/lib/active_record/legacy_yaml_adapter.rb +11 -5
- data/lib/active_record/locking/optimistic.rb +81 -85
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +68 -31
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/migration.rb +439 -342
- data/lib/active_record/migration/command_recorder.rb +152 -98
- data/lib/active_record/migration/compatibility.rb +229 -60
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/model_schema.rb +230 -122
- data/lib/active_record/nested_attributes.rb +213 -203
- data/lib/active_record/no_touching.rb +11 -2
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +471 -97
- data/lib/active_record/query_cache.rb +23 -12
- data/lib/active_record/querying.rb +43 -25
- data/lib/active_record/railtie.rb +155 -43
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +507 -195
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +245 -269
- data/lib/active_record/relation.rb +475 -324
- data/lib/active_record/relation/batches.rb +125 -72
- data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
- data/lib/active_record/relation/calculations.rb +267 -171
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +238 -248
- data/lib/active_record/relation/from_clause.rb +7 -9
- data/lib/active_record/relation/merger.rb +95 -77
- data/lib/active_record/relation/predicate_builder.rb +109 -110
- data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +654 -374
- data/lib/active_record/relation/record_fetch_warning.rb +8 -6
- data/lib/active_record/relation/spawn_methods.rb +15 -14
- data/lib/active_record/relation/where_clause.rb +171 -109
- data/lib/active_record/result.rb +88 -51
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +73 -100
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +101 -69
- data/lib/active_record/schema_migration.rb +16 -12
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +39 -30
- data/lib/active_record/secure_token.rb +19 -9
- data/lib/active_record/serialization.rb +7 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +80 -29
- data/lib/active_record/store.rb +122 -42
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +51 -39
- data/lib/active_record/tasks/database_tasks.rb +332 -115
- data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
- data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +26 -24
- data/lib/active_record/transactions.rb +121 -184
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +29 -17
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +20 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/type_caster/connection.rb +17 -13
- data/lib/active_record/type_caster/map.rb +10 -6
- data/lib/active_record/validations.rb +8 -5
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +4 -3
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +52 -45
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +54 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -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 +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -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/delete_statement.rb +45 -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/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -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/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -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 +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -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 +41 -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/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +22 -3
- data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
- 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 → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +141 -57
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute_decorators.rb +0 -67
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/relation/where_clause_factory.rb +0 -38
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,10 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters
|
3
5
|
class TransactionState
|
4
|
-
VALID_STATES = Set.new([:committed, :rolledback, nil])
|
5
|
-
|
6
6
|
def initialize(state = nil)
|
7
7
|
@state = state
|
8
|
+
@children = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_child(state)
|
12
|
+
@children ||= []
|
13
|
+
@children << state
|
8
14
|
end
|
9
15
|
|
10
16
|
def finalized?
|
@@ -12,22 +18,49 @@ module ActiveRecord
|
|
12
18
|
end
|
13
19
|
|
14
20
|
def committed?
|
15
|
-
@state == :committed
|
21
|
+
@state == :committed || @state == :fully_committed
|
22
|
+
end
|
23
|
+
|
24
|
+
def fully_committed?
|
25
|
+
@state == :fully_committed
|
16
26
|
end
|
17
27
|
|
18
28
|
def rolledback?
|
19
|
-
@state == :rolledback
|
29
|
+
@state == :rolledback || @state == :fully_rolledback
|
30
|
+
end
|
31
|
+
|
32
|
+
def fully_rolledback?
|
33
|
+
@state == :fully_rolledback
|
34
|
+
end
|
35
|
+
|
36
|
+
def fully_completed?
|
37
|
+
completed?
|
20
38
|
end
|
21
39
|
|
22
40
|
def completed?
|
23
41
|
committed? || rolledback?
|
24
42
|
end
|
25
43
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
44
|
+
def rollback!
|
45
|
+
@children&.each { |c| c.rollback! }
|
46
|
+
@state = :rolledback
|
47
|
+
end
|
48
|
+
|
49
|
+
def full_rollback!
|
50
|
+
@children&.each { |c| c.rollback! }
|
51
|
+
@state = :fully_rolledback
|
52
|
+
end
|
53
|
+
|
54
|
+
def commit!
|
55
|
+
@state = :committed
|
56
|
+
end
|
57
|
+
|
58
|
+
def full_commit!
|
59
|
+
@state = :fully_committed
|
60
|
+
end
|
61
|
+
|
62
|
+
def nullify!
|
63
|
+
@state = nil
|
31
64
|
end
|
32
65
|
end
|
33
66
|
|
@@ -37,61 +70,87 @@ module ActiveRecord
|
|
37
70
|
def closed?; true; end
|
38
71
|
def open?; false; end
|
39
72
|
def joinable?; false; end
|
40
|
-
def add_record(record); end
|
73
|
+
def add_record(record, _ = true); end
|
41
74
|
end
|
42
75
|
|
43
76
|
class Transaction #:nodoc:
|
77
|
+
attr_reader :connection, :state, :savepoint_name, :isolation_level
|
78
|
+
attr_accessor :written
|
44
79
|
|
45
|
-
|
46
|
-
attr_writer :joinable
|
47
|
-
|
48
|
-
def initialize(connection, options, run_commit_callbacks: false)
|
80
|
+
def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
|
49
81
|
@connection = connection
|
50
82
|
@state = TransactionState.new
|
51
|
-
@records =
|
52
|
-
@
|
83
|
+
@records = nil
|
84
|
+
@isolation_level = isolation
|
85
|
+
@materialized = false
|
86
|
+
@joinable = joinable
|
53
87
|
@run_commit_callbacks = run_commit_callbacks
|
88
|
+
@lazy_enrollment_records = nil
|
54
89
|
end
|
55
90
|
|
56
|
-
def add_record(record)
|
57
|
-
records
|
91
|
+
def add_record(record, ensure_finalize = true)
|
92
|
+
@records ||= []
|
93
|
+
if ensure_finalize
|
94
|
+
@records << record
|
95
|
+
else
|
96
|
+
@lazy_enrollment_records ||= ObjectSpace::WeakMap.new
|
97
|
+
@lazy_enrollment_records[record] = record
|
98
|
+
end
|
58
99
|
end
|
59
100
|
|
60
|
-
def
|
61
|
-
@
|
101
|
+
def records
|
102
|
+
if @lazy_enrollment_records
|
103
|
+
@records.concat @lazy_enrollment_records.values
|
104
|
+
@lazy_enrollment_records = nil
|
105
|
+
end
|
106
|
+
@records
|
107
|
+
end
|
108
|
+
|
109
|
+
def materialize!
|
110
|
+
@materialized = true
|
111
|
+
end
|
112
|
+
|
113
|
+
def materialized?
|
114
|
+
@materialized
|
62
115
|
end
|
63
116
|
|
64
117
|
def rollback_records
|
65
|
-
|
118
|
+
return unless records
|
119
|
+
ite = records.uniq(&:__id__)
|
120
|
+
already_run_callbacks = {}
|
66
121
|
while record = ite.shift
|
67
|
-
record.
|
122
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
123
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
124
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
125
|
+
record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
|
68
126
|
end
|
69
127
|
ensure
|
70
|
-
ite
|
128
|
+
ite&.each do |i|
|
71
129
|
i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
|
72
130
|
end
|
73
131
|
end
|
74
132
|
|
75
|
-
def commit
|
76
|
-
@state.set_state(:committed)
|
77
|
-
end
|
78
|
-
|
79
133
|
def before_commit_records
|
80
|
-
records.uniq.each(&:before_committed!) if @run_commit_callbacks
|
134
|
+
records.uniq.each(&:before_committed!) if records && @run_commit_callbacks
|
81
135
|
end
|
82
136
|
|
83
137
|
def commit_records
|
84
|
-
|
138
|
+
return unless records
|
139
|
+
ite = records.uniq(&:__id__)
|
140
|
+
already_run_callbacks = {}
|
85
141
|
while record = ite.shift
|
86
142
|
if @run_commit_callbacks
|
87
|
-
record.
|
143
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
144
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
145
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
146
|
+
record.committed!(should_run_callbacks: should_run_callbacks)
|
88
147
|
else
|
89
148
|
# if not running callbacks, only adds the record to the parent transaction
|
90
|
-
record
|
149
|
+
connection.add_transaction_record(record)
|
91
150
|
end
|
92
151
|
end
|
93
152
|
ensure
|
94
|
-
ite
|
153
|
+
ite&.each { |i| i.committed!(should_run_callbacks: false) }
|
95
154
|
end
|
96
155
|
|
97
156
|
def full_rollback?; true; end
|
@@ -101,47 +160,55 @@ module ActiveRecord
|
|
101
160
|
end
|
102
161
|
|
103
162
|
class SavepointTransaction < Transaction
|
163
|
+
def initialize(connection, savepoint_name, parent_transaction, **options)
|
164
|
+
super(connection, **options)
|
165
|
+
|
166
|
+
parent_transaction.state.add_child(@state)
|
104
167
|
|
105
|
-
|
106
|
-
super(connection, options, *args)
|
107
|
-
if options[:isolation]
|
168
|
+
if isolation_level
|
108
169
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
109
170
|
end
|
110
|
-
|
171
|
+
|
172
|
+
@savepoint_name = savepoint_name
|
111
173
|
end
|
112
174
|
|
113
|
-
def
|
114
|
-
connection.
|
175
|
+
def materialize!
|
176
|
+
connection.create_savepoint(savepoint_name)
|
115
177
|
super
|
116
178
|
end
|
117
179
|
|
180
|
+
def rollback
|
181
|
+
connection.rollback_to_savepoint(savepoint_name) if materialized?
|
182
|
+
@state.rollback!
|
183
|
+
end
|
184
|
+
|
118
185
|
def commit
|
119
|
-
connection.release_savepoint(savepoint_name)
|
120
|
-
|
186
|
+
connection.release_savepoint(savepoint_name) if materialized?
|
187
|
+
@state.commit!
|
121
188
|
end
|
122
189
|
|
123
190
|
def full_rollback?; false; end
|
124
191
|
end
|
125
192
|
|
126
193
|
class RealTransaction < Transaction
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
if options[:isolation]
|
131
|
-
connection.begin_isolated_db_transaction(options[:isolation])
|
194
|
+
def materialize!
|
195
|
+
if isolation_level
|
196
|
+
connection.begin_isolated_db_transaction(isolation_level)
|
132
197
|
else
|
133
198
|
connection.begin_db_transaction
|
134
199
|
end
|
200
|
+
|
201
|
+
super
|
135
202
|
end
|
136
203
|
|
137
204
|
def rollback
|
138
|
-
connection.rollback_db_transaction
|
139
|
-
|
205
|
+
connection.rollback_db_transaction if materialized?
|
206
|
+
@state.full_rollback!
|
140
207
|
end
|
141
208
|
|
142
209
|
def commit
|
143
|
-
connection.commit_db_transaction
|
144
|
-
|
210
|
+
connection.commit_db_transaction if materialized?
|
211
|
+
@state.full_commit!
|
145
212
|
end
|
146
213
|
end
|
147
214
|
|
@@ -149,60 +216,133 @@ module ActiveRecord
|
|
149
216
|
def initialize(connection)
|
150
217
|
@stack = []
|
151
218
|
@connection = connection
|
219
|
+
@has_unmaterialized_transactions = false
|
220
|
+
@materializing_transactions = false
|
221
|
+
@lazy_transactions_enabled = true
|
152
222
|
end
|
153
223
|
|
154
|
-
def begin_transaction(
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
224
|
+
def begin_transaction(isolation: nil, joinable: true, _lazy: true)
|
225
|
+
@connection.lock.synchronize do
|
226
|
+
run_commit_callbacks = !current_transaction.joinable?
|
227
|
+
transaction =
|
228
|
+
if @stack.empty?
|
229
|
+
RealTransaction.new(
|
230
|
+
@connection,
|
231
|
+
isolation: isolation,
|
232
|
+
joinable: joinable,
|
233
|
+
run_commit_callbacks: run_commit_callbacks
|
234
|
+
)
|
235
|
+
else
|
236
|
+
SavepointTransaction.new(
|
237
|
+
@connection,
|
238
|
+
"active_record_#{@stack.size}",
|
239
|
+
@stack.last,
|
240
|
+
isolation: isolation,
|
241
|
+
joinable: joinable,
|
242
|
+
run_commit_callbacks: run_commit_callbacks
|
243
|
+
)
|
244
|
+
end
|
245
|
+
|
246
|
+
if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
|
247
|
+
@has_unmaterialized_transactions = true
|
159
248
|
else
|
160
|
-
|
161
|
-
run_commit_callbacks: run_commit_callbacks)
|
249
|
+
transaction.materialize!
|
162
250
|
end
|
251
|
+
@stack.push(transaction)
|
252
|
+
transaction
|
253
|
+
end
|
254
|
+
end
|
163
255
|
|
164
|
-
|
165
|
-
|
256
|
+
def disable_lazy_transactions!
|
257
|
+
materialize_transactions
|
258
|
+
@lazy_transactions_enabled = false
|
166
259
|
end
|
167
260
|
|
168
|
-
def
|
169
|
-
|
261
|
+
def enable_lazy_transactions!
|
262
|
+
@lazy_transactions_enabled = true
|
263
|
+
end
|
170
264
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
265
|
+
def lazy_transactions_enabled?
|
266
|
+
@lazy_transactions_enabled
|
267
|
+
end
|
268
|
+
|
269
|
+
def materialize_transactions
|
270
|
+
return if @materializing_transactions
|
271
|
+
return unless @has_unmaterialized_transactions
|
272
|
+
|
273
|
+
@connection.lock.synchronize do
|
274
|
+
begin
|
275
|
+
@materializing_transactions = true
|
276
|
+
@stack.each { |t| t.materialize! unless t.materialized? }
|
277
|
+
ensure
|
278
|
+
@materializing_transactions = false
|
279
|
+
end
|
280
|
+
@has_unmaterialized_transactions = false
|
175
281
|
end
|
282
|
+
end
|
176
283
|
|
177
|
-
|
178
|
-
|
284
|
+
def commit_transaction
|
285
|
+
@connection.lock.synchronize do
|
286
|
+
transaction = @stack.last
|
287
|
+
|
288
|
+
begin
|
289
|
+
transaction.before_commit_records
|
290
|
+
ensure
|
291
|
+
@stack.pop
|
292
|
+
end
|
293
|
+
|
294
|
+
transaction.commit
|
295
|
+
transaction.commit_records
|
296
|
+
end
|
179
297
|
end
|
180
298
|
|
181
299
|
def rollback_transaction(transaction = nil)
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
def within_new_transaction(options = {})
|
188
|
-
transaction = begin_transaction options
|
189
|
-
yield
|
190
|
-
rescue Exception => error
|
191
|
-
if transaction
|
192
|
-
rollback_transaction
|
193
|
-
after_failure_actions(transaction, error)
|
300
|
+
@connection.lock.synchronize do
|
301
|
+
transaction ||= @stack.pop
|
302
|
+
transaction.rollback
|
303
|
+
transaction.rollback_records
|
194
304
|
end
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
305
|
+
end
|
306
|
+
|
307
|
+
def within_new_transaction(isolation: nil, joinable: true)
|
308
|
+
@connection.lock.synchronize do
|
309
|
+
transaction = begin_transaction(isolation: isolation, joinable: joinable)
|
310
|
+
ret = yield
|
311
|
+
completed = true
|
312
|
+
ret
|
313
|
+
rescue Exception => error
|
314
|
+
if transaction
|
315
|
+
rollback_transaction
|
316
|
+
after_failure_actions(transaction, error)
|
317
|
+
end
|
318
|
+
raise
|
319
|
+
ensure
|
320
|
+
if transaction
|
321
|
+
if error
|
322
|
+
# @connection still holds an open transaction, so we must not
|
323
|
+
# put it back in the pool for reuse
|
324
|
+
@connection.throw_away! unless transaction.state.rolledback?
|
325
|
+
else
|
326
|
+
if Thread.current.status == "aborting"
|
327
|
+
rollback_transaction
|
328
|
+
else
|
329
|
+
if !completed && transaction.written
|
330
|
+
ActiveSupport::Deprecation.warn(<<~EOW)
|
331
|
+
Using `return`, `break` or `throw` to exit a transaction block is
|
332
|
+
deprecated without replacement. If the `throw` came from
|
333
|
+
`Timeout.timeout(duration)`, pass an exception class as a second
|
334
|
+
argument so it doesn't use `throw` to abort its block. This results
|
335
|
+
in the transaction being committed, but in the next release of Rails
|
336
|
+
it will rollback.
|
337
|
+
EOW
|
338
|
+
end
|
339
|
+
begin
|
340
|
+
commit_transaction
|
341
|
+
rescue Exception
|
342
|
+
rollback_transaction(transaction) unless transaction.state.completed?
|
343
|
+
raise
|
344
|
+
end
|
345
|
+
end
|
206
346
|
end
|
207
347
|
end
|
208
348
|
end
|
@@ -217,7 +357,6 @@ module ActiveRecord
|
|
217
357
|
end
|
218
358
|
|
219
359
|
private
|
220
|
-
|
221
360
|
NULL_TRANSACTION = NullTransaction.new
|
222
361
|
|
223
362
|
# Deallocate invalidated prepared statements outside of the transaction
|
@@ -226,7 +365,6 @@ module ActiveRecord
|
|
226
365
|
return unless error.is_a?(ActiveRecord::PreparedStatementCacheExpired)
|
227
366
|
@connection.clear_cache!
|
228
367
|
end
|
229
|
-
|
230
368
|
end
|
231
369
|
end
|
232
370
|
end
|
@@ -1,52 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
require "active_record/connection_adapters/schema_cache"
|
5
|
+
require "active_record/connection_adapters/sql_type_metadata"
|
6
|
+
require "active_record/connection_adapters/abstract/schema_dumper"
|
7
|
+
require "active_record/connection_adapters/abstract/schema_creation"
|
8
|
+
require "active_support/concurrency/load_interlock_aware_monitor"
|
9
|
+
require "arel/collectors/bind"
|
10
|
+
require "arel/collectors/composite"
|
11
|
+
require "arel/collectors/sql_string"
|
12
|
+
require "arel/collectors/substitute_binds"
|
9
13
|
|
10
14
|
module ActiveRecord
|
11
15
|
module ConnectionAdapters # :nodoc:
|
12
|
-
extend ActiveSupport::Autoload
|
13
|
-
|
14
|
-
autoload :Column
|
15
|
-
autoload :ConnectionSpecification
|
16
|
-
|
17
|
-
autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
|
18
|
-
autoload :IndexDefinition
|
19
|
-
autoload :ColumnDefinition
|
20
|
-
autoload :ChangeColumnDefinition
|
21
|
-
autoload :ForeignKeyDefinition
|
22
|
-
autoload :TableDefinition
|
23
|
-
autoload :Table
|
24
|
-
autoload :AlterTable
|
25
|
-
autoload :ReferenceDefinition
|
26
|
-
end
|
27
|
-
|
28
|
-
autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
|
29
|
-
autoload :ConnectionHandler
|
30
|
-
end
|
31
|
-
|
32
|
-
autoload_under 'abstract' do
|
33
|
-
autoload :SchemaStatements
|
34
|
-
autoload :DatabaseStatements
|
35
|
-
autoload :DatabaseLimits
|
36
|
-
autoload :Quoting
|
37
|
-
autoload :ConnectionPool
|
38
|
-
autoload :QueryCache
|
39
|
-
autoload :Savepoints
|
40
|
-
end
|
41
|
-
|
42
|
-
autoload_at 'active_record/connection_adapters/abstract/transaction' do
|
43
|
-
autoload :TransactionManager
|
44
|
-
autoload :NullTransaction
|
45
|
-
autoload :RealTransaction
|
46
|
-
autoload :SavepointTransaction
|
47
|
-
autoload :TransactionState
|
48
|
-
end
|
49
|
-
|
50
16
|
# Active Record supports multiple database systems. AbstractAdapter and
|
51
17
|
# related classes form the abstraction layer which makes this possible.
|
52
18
|
# An AbstractAdapter represents a connection to a database, and provides an
|
@@ -61,24 +27,28 @@ module ActiveRecord
|
|
61
27
|
# Most of the methods in the adapter are useful during migrations. Most
|
62
28
|
# notably, the instance methods provided by SchemaStatements are very useful.
|
63
29
|
class AbstractAdapter
|
64
|
-
ADAPTER_NAME = "Abstract"
|
30
|
+
ADAPTER_NAME = "Abstract"
|
65
31
|
include ActiveSupport::Callbacks
|
66
32
|
define_callbacks :checkout, :checkin
|
67
33
|
|
68
34
|
include Quoting, DatabaseStatements, SchemaStatements
|
69
35
|
include DatabaseLimits
|
70
36
|
include QueryCache
|
71
|
-
include ColumnDumper
|
72
37
|
include Savepoints
|
73
38
|
|
74
39
|
SIMPLE_INT = /\A\d+\z/
|
40
|
+
COMMENT_REGEX = %r{(?:\-\-.*\n)*|/\*(?:[^\*]|\*[^/])*\*/}m
|
75
41
|
|
76
|
-
attr_accessor :
|
77
|
-
attr_reader :
|
42
|
+
attr_accessor :pool
|
43
|
+
attr_reader :visitor, :owner, :logger, :lock
|
78
44
|
alias :in_use? :owner
|
79
45
|
|
46
|
+
set_callback :checkin, :after, :enable_lazy_transactions!
|
47
|
+
|
80
48
|
def self.type_cast_config_to_integer(config)
|
81
|
-
if config
|
49
|
+
if config.is_a?(Integer)
|
50
|
+
config
|
51
|
+
elsif SIMPLE_INT.match?(config)
|
82
52
|
config.to_i
|
83
53
|
else
|
84
54
|
config
|
@@ -93,7 +63,22 @@ module ActiveRecord
|
|
93
63
|
end
|
94
64
|
end
|
95
65
|
|
96
|
-
|
66
|
+
DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
|
67
|
+
private_constant :DEFAULT_READ_QUERY
|
68
|
+
|
69
|
+
def self.build_read_query_regexp(*parts) # :nodoc:
|
70
|
+
parts += DEFAULT_READ_QUERY
|
71
|
+
parts = parts.map { |part| /#{part}/i }
|
72
|
+
/\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.quoted_column_names # :nodoc:
|
76
|
+
@quoted_column_names ||= {}
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.quoted_table_names # :nodoc:
|
80
|
+
@quoted_table_names ||= {}
|
81
|
+
end
|
97
82
|
|
98
83
|
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
99
84
|
super()
|
@@ -103,72 +88,112 @@ module ActiveRecord
|
|
103
88
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
104
89
|
@logger = logger
|
105
90
|
@config = config
|
106
|
-
@pool =
|
107
|
-
@
|
108
|
-
@
|
109
|
-
@
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
91
|
+
@pool = ActiveRecord::ConnectionAdapters::NullPool.new
|
92
|
+
@idle_since = Concurrent.monotonic_time
|
93
|
+
@visitor = arel_visitor
|
94
|
+
@statements = build_statement_pool
|
95
|
+
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
96
|
+
|
97
|
+
@prepared_statements = self.class.type_cast_config_to_boolean(
|
98
|
+
config.fetch(:prepared_statements, true)
|
99
|
+
)
|
100
|
+
|
101
|
+
@advisory_locks_enabled = self.class.type_cast_config_to_boolean(
|
102
|
+
config.fetch(:advisory_locks, true)
|
103
|
+
)
|
117
104
|
end
|
118
105
|
|
119
|
-
|
120
|
-
|
106
|
+
def replica?
|
107
|
+
@config[:replica] || false
|
108
|
+
end
|
121
109
|
|
122
|
-
|
123
|
-
|
124
|
-
|
110
|
+
def use_metadata_table?
|
111
|
+
@config.fetch(:use_metadata_table, true)
|
112
|
+
end
|
125
113
|
|
126
|
-
|
127
|
-
|
128
|
-
|
114
|
+
# Determines whether writes are currently being prevents.
|
115
|
+
#
|
116
|
+
# Returns true if the connection is a replica.
|
117
|
+
#
|
118
|
+
# If the application is using legacy handling, returns
|
119
|
+
# true if `connection_handler.prevent_writes` is set.
|
120
|
+
#
|
121
|
+
# If the application is using the new connection handling
|
122
|
+
# will return true based on `current_preventing_writes`.
|
123
|
+
def preventing_writes?
|
124
|
+
return true if replica?
|
125
|
+
return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord::Base.legacy_connection_handling
|
126
|
+
return false if owner_name.nil?
|
127
|
+
|
128
|
+
klass = self.owner_name.safe_constantize
|
129
|
+
klass&.current_preventing_writes
|
129
130
|
end
|
130
131
|
|
131
|
-
|
132
|
-
|
133
|
-
casted_binds = conn.prepare_binds_for_database(bvs)
|
134
|
-
super(casted_binds.map { |value| conn.quote(value) })
|
135
|
-
end
|
132
|
+
def migrations_paths # :nodoc:
|
133
|
+
@config[:migrations_paths] || Migrator.migrations_paths
|
136
134
|
end
|
137
135
|
|
138
|
-
|
139
|
-
|
140
|
-
super(bvs)
|
141
|
-
end
|
136
|
+
def migration_context # :nodoc:
|
137
|
+
MigrationContext.new(migrations_paths, schema_migration)
|
142
138
|
end
|
143
139
|
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
140
|
+
def schema_migration # :nodoc:
|
141
|
+
@schema_migration ||= begin
|
142
|
+
conn = self
|
143
|
+
spec_name = conn.pool.pool_config.connection_specification_name
|
144
|
+
|
145
|
+
return ActiveRecord::SchemaMigration if spec_name == "ActiveRecord::Base"
|
146
|
+
|
147
|
+
schema_migration_name = "#{spec_name}::SchemaMigration"
|
148
|
+
|
149
|
+
Class.new(ActiveRecord::SchemaMigration) do
|
150
|
+
define_singleton_method(:name) { schema_migration_name }
|
151
|
+
define_singleton_method(:to_s) { schema_migration_name }
|
152
|
+
|
153
|
+
self.connection_specification_name = spec_name
|
154
|
+
end
|
155
|
+
end
|
150
156
|
end
|
151
157
|
|
152
|
-
def
|
153
|
-
|
158
|
+
def prepared_statements
|
159
|
+
@prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
|
154
160
|
end
|
155
161
|
|
156
|
-
def
|
157
|
-
|
162
|
+
def prepared_statements_disabled_cache # :nodoc:
|
163
|
+
Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
|
158
164
|
end
|
159
165
|
|
160
|
-
|
161
|
-
|
166
|
+
class Version
|
167
|
+
include Comparable
|
168
|
+
|
169
|
+
attr_reader :full_version_string
|
170
|
+
|
171
|
+
def initialize(version_string, full_version_string = nil)
|
172
|
+
@version = version_string.split(".").map(&:to_i)
|
173
|
+
@full_version_string = full_version_string
|
174
|
+
end
|
175
|
+
|
176
|
+
def <=>(version_string)
|
177
|
+
@version <=> version_string.split(".").map(&:to_i)
|
178
|
+
end
|
179
|
+
|
180
|
+
def to_s
|
181
|
+
@version.join(".")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def valid_type?(type) # :nodoc:
|
186
|
+
!native_database_types[type].nil?
|
162
187
|
end
|
163
188
|
|
164
189
|
# this method must only be called while holding connection pool's mutex
|
165
190
|
def lease
|
166
191
|
if in_use?
|
167
|
-
msg =
|
192
|
+
msg = +"Cannot lease connection, "
|
168
193
|
if @owner == Thread.current
|
169
|
-
msg <<
|
194
|
+
msg << "it is already leased by the current thread."
|
170
195
|
else
|
171
|
-
msg << "it is already in use by a different thread: #{@owner}. "
|
196
|
+
msg << "it is already in use by a different thread: #{@owner}. " \
|
172
197
|
"Current thread: #{Thread.current}."
|
173
198
|
end
|
174
199
|
raise ActiveRecordError, msg
|
@@ -177,23 +202,32 @@ module ActiveRecord
|
|
177
202
|
@owner = Thread.current
|
178
203
|
end
|
179
204
|
|
205
|
+
def owner_name # :nodoc:
|
206
|
+
@pool.owner_name
|
207
|
+
end
|
208
|
+
|
209
|
+
def schema_cache
|
210
|
+
@pool.get_schema_cache(self)
|
211
|
+
end
|
212
|
+
|
180
213
|
def schema_cache=(cache)
|
181
214
|
cache.connection = self
|
182
|
-
@
|
215
|
+
@pool.set_schema_cache(cache)
|
183
216
|
end
|
184
217
|
|
185
218
|
# this method must only be called while holding connection pool's mutex
|
186
219
|
def expire
|
187
220
|
if in_use?
|
188
221
|
if @owner != Thread.current
|
189
|
-
raise ActiveRecordError, "Cannot expire connection, "
|
190
|
-
"it is owned by a different thread: #{@owner}. "
|
222
|
+
raise ActiveRecordError, "Cannot expire connection, " \
|
223
|
+
"it is owned by a different thread: #{@owner}. " \
|
191
224
|
"Current thread: #{Thread.current}."
|
192
225
|
end
|
193
226
|
|
227
|
+
@idle_since = Concurrent.monotonic_time
|
194
228
|
@owner = nil
|
195
229
|
else
|
196
|
-
raise ActiveRecordError,
|
230
|
+
raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
|
197
231
|
end
|
198
232
|
end
|
199
233
|
|
@@ -206,15 +240,21 @@ module ActiveRecord
|
|
206
240
|
@owner = Thread.current
|
207
241
|
end
|
208
242
|
else
|
209
|
-
raise ActiveRecordError,
|
243
|
+
raise ActiveRecordError, "Cannot steal connection, it is not currently leased."
|
210
244
|
end
|
211
245
|
end
|
212
246
|
|
247
|
+
# Seconds since this connection was returned to the pool
|
248
|
+
def seconds_idle # :nodoc:
|
249
|
+
return 0 if in_use?
|
250
|
+
Concurrent.monotonic_time - @idle_since
|
251
|
+
end
|
252
|
+
|
213
253
|
def unprepared_statement
|
214
|
-
|
254
|
+
cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
|
215
255
|
yield
|
216
256
|
ensure
|
217
|
-
|
257
|
+
cache&.delete(object_id)
|
218
258
|
end
|
219
259
|
|
220
260
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
@@ -223,15 +263,9 @@ module ActiveRecord
|
|
223
263
|
self.class::ADAPTER_NAME
|
224
264
|
end
|
225
265
|
|
226
|
-
# Does this adapter
|
227
|
-
def
|
228
|
-
|
229
|
-
end
|
230
|
-
|
231
|
-
# Can this adapter determine the primary key for tables not attached
|
232
|
-
# to an Active Record class, such as join tables?
|
233
|
-
def supports_primary_key?
|
234
|
-
false
|
266
|
+
# Does the database for this adapter exist?
|
267
|
+
def self.database_exists?(config)
|
268
|
+
raise NotImplementedError
|
235
269
|
end
|
236
270
|
|
237
271
|
# Does this adapter support DDL rollbacks in transactions? That is, would
|
@@ -261,6 +295,10 @@ module ActiveRecord
|
|
261
295
|
false
|
262
296
|
end
|
263
297
|
|
298
|
+
def supports_partitioned_indexes?
|
299
|
+
false
|
300
|
+
end
|
301
|
+
|
264
302
|
# Does this adapter support index sort order?
|
265
303
|
def supports_index_sort_order?
|
266
304
|
false
|
@@ -302,11 +340,26 @@ module ActiveRecord
|
|
302
340
|
false
|
303
341
|
end
|
304
342
|
|
343
|
+
# Does this adapter support creating invalid constraints?
|
344
|
+
def supports_validate_constraints?
|
345
|
+
false
|
346
|
+
end
|
347
|
+
|
348
|
+
# Does this adapter support creating check constraints?
|
349
|
+
def supports_check_constraints?
|
350
|
+
false
|
351
|
+
end
|
352
|
+
|
305
353
|
# Does this adapter support views?
|
306
354
|
def supports_views?
|
307
355
|
false
|
308
356
|
end
|
309
357
|
|
358
|
+
# Does this adapter support materialized views?
|
359
|
+
def supports_materialized_views?
|
360
|
+
false
|
361
|
+
end
|
362
|
+
|
310
363
|
# Does this adapter support datetime with precision?
|
311
364
|
def supports_datetime_with_precision?
|
312
365
|
false
|
@@ -327,9 +380,43 @@ module ActiveRecord
|
|
327
380
|
false
|
328
381
|
end
|
329
382
|
|
330
|
-
# Does this adapter support
|
331
|
-
def
|
332
|
-
|
383
|
+
# Does this adapter support virtual columns?
|
384
|
+
def supports_virtual_columns?
|
385
|
+
false
|
386
|
+
end
|
387
|
+
|
388
|
+
# Does this adapter support foreign/external tables?
|
389
|
+
def supports_foreign_tables?
|
390
|
+
false
|
391
|
+
end
|
392
|
+
|
393
|
+
# Does this adapter support optimizer hints?
|
394
|
+
def supports_optimizer_hints?
|
395
|
+
false
|
396
|
+
end
|
397
|
+
|
398
|
+
def supports_common_table_expressions?
|
399
|
+
false
|
400
|
+
end
|
401
|
+
|
402
|
+
def supports_lazy_transactions?
|
403
|
+
false
|
404
|
+
end
|
405
|
+
|
406
|
+
def supports_insert_returning?
|
407
|
+
false
|
408
|
+
end
|
409
|
+
|
410
|
+
def supports_insert_on_duplicate_skip?
|
411
|
+
false
|
412
|
+
end
|
413
|
+
|
414
|
+
def supports_insert_on_duplicate_update?
|
415
|
+
false
|
416
|
+
end
|
417
|
+
|
418
|
+
def supports_insert_conflict_target?
|
419
|
+
false
|
333
420
|
end
|
334
421
|
|
335
422
|
# This is meant to be implemented by the adapters that support extensions
|
@@ -340,6 +427,10 @@ module ActiveRecord
|
|
340
427
|
def enable_extension(name)
|
341
428
|
end
|
342
429
|
|
430
|
+
def advisory_locks_enabled? # :nodoc:
|
431
|
+
supports_advisory_locks? && @advisory_locks_enabled
|
432
|
+
end
|
433
|
+
|
343
434
|
# This is meant to be implemented by the adapters that support advisory
|
344
435
|
# locks
|
345
436
|
#
|
@@ -394,6 +485,22 @@ module ActiveRecord
|
|
394
485
|
reset_transaction
|
395
486
|
end
|
396
487
|
|
488
|
+
# Immediately forget this connection ever existed. Unlike disconnect!,
|
489
|
+
# this will not communicate with the server.
|
490
|
+
#
|
491
|
+
# After calling this method, the behavior of all other methods becomes
|
492
|
+
# undefined. This is called internally just before a forked process gets
|
493
|
+
# rid of a connection that belonged to its parent.
|
494
|
+
def discard!
|
495
|
+
# This should be overridden by concrete adapters.
|
496
|
+
#
|
497
|
+
# Prevent @connection's finalizer from touching the socket, or
|
498
|
+
# otherwise communicating with its server, when it is collected.
|
499
|
+
if schema_cache.connection == self
|
500
|
+
schema_cache.connection = nil
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
397
504
|
# Reset the state of this connection, directing the DBMS to clear
|
398
505
|
# transactions and other connection-related server-side state. Usually a
|
399
506
|
# database-dependent operation.
|
@@ -404,11 +511,15 @@ module ActiveRecord
|
|
404
511
|
# this should be overridden by concrete adapters
|
405
512
|
end
|
406
513
|
|
407
|
-
|
408
|
-
|
409
|
-
|
514
|
+
# Removes the connection from the pool and disconnect it.
|
515
|
+
def throw_away!
|
516
|
+
pool.remove self
|
517
|
+
disconnect!
|
518
|
+
end
|
519
|
+
|
520
|
+
# Clear any caching the database adapter may be doing.
|
410
521
|
def clear_cache!
|
411
|
-
|
522
|
+
@lock.synchronize { @statements.clear } if @statements
|
412
523
|
end
|
413
524
|
|
414
525
|
# Returns true if its required to reload the connection between requests for development mode.
|
@@ -419,7 +530,7 @@ module ActiveRecord
|
|
419
530
|
# Checks whether the connection to the database is still active (i.e. not stale).
|
420
531
|
# This is done under the hood by calling #active?. If the connection
|
421
532
|
# is no longer active, then this method will reconnect to the database.
|
422
|
-
def verify!
|
533
|
+
def verify!
|
423
534
|
reconnect! unless active?
|
424
535
|
end
|
425
536
|
|
@@ -430,22 +541,25 @@ module ActiveRecord
|
|
430
541
|
# This is useful for when you need to call a proprietary method such as
|
431
542
|
# PostgreSQL's lo_* methods.
|
432
543
|
def raw_connection
|
544
|
+
disable_lazy_transactions!
|
433
545
|
@connection
|
434
546
|
end
|
435
547
|
|
436
|
-
def
|
437
|
-
|
438
|
-
table[attribute].eq(value)
|
439
|
-
else
|
440
|
-
table[attribute].eq(Arel::Nodes::BindParam.new)
|
441
|
-
end
|
548
|
+
def default_uniqueness_comparison(attribute, value) # :nodoc:
|
549
|
+
attribute.eq(value)
|
442
550
|
end
|
443
551
|
|
444
|
-
def
|
552
|
+
def case_sensitive_comparison(attribute, value) # :nodoc:
|
553
|
+
attribute.eq(value)
|
554
|
+
end
|
555
|
+
|
556
|
+
def case_insensitive_comparison(attribute, value) # :nodoc:
|
557
|
+
column = column_for_attribute(attribute)
|
558
|
+
|
445
559
|
if can_perform_case_insensitive_comparison_for?(column)
|
446
|
-
|
560
|
+
attribute.lower.eq(attribute.relation.lower(value))
|
447
561
|
else
|
448
|
-
|
562
|
+
attribute.eq(value)
|
449
563
|
end
|
450
564
|
end
|
451
565
|
|
@@ -459,153 +573,187 @@ module ActiveRecord
|
|
459
573
|
pool.checkin self
|
460
574
|
end
|
461
575
|
|
462
|
-
def
|
463
|
-
|
464
|
-
|
576
|
+
def default_index_type?(index) # :nodoc:
|
577
|
+
index.using.nil?
|
578
|
+
end
|
579
|
+
|
580
|
+
# Called by ActiveRecord::InsertAll,
|
581
|
+
# Passed an instance of ActiveRecord::InsertAll::Builder,
|
582
|
+
# This method implements standard bulk inserts for all databases, but
|
583
|
+
# should be overridden by adapters to implement common features with
|
584
|
+
# non-standard syntax like handling duplicates or returning values.
|
585
|
+
def build_insert_sql(insert) # :nodoc:
|
586
|
+
if insert.skip_duplicates? || insert.update_duplicates?
|
587
|
+
raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
|
465
588
|
end
|
589
|
+
|
590
|
+
"INSERT #{insert.into} #{insert.values_list}"
|
466
591
|
end
|
467
592
|
|
468
|
-
def
|
469
|
-
Column.new(name, default, sql_type_metadata, null, table_name, default_function, collation)
|
593
|
+
def get_database_version # :nodoc:
|
470
594
|
end
|
471
595
|
|
472
|
-
def
|
473
|
-
|
596
|
+
def database_version # :nodoc:
|
597
|
+
schema_cache.database_version
|
474
598
|
end
|
475
599
|
|
476
|
-
def
|
477
|
-
visitor.accept(node, collector).value
|
600
|
+
def check_version # :nodoc:
|
478
601
|
end
|
479
602
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
limit: nil,
|
486
|
-
offset: nil
|
487
|
-
) # :nodoc:
|
488
|
-
result = from_clause + join_clause + where_clause + having_clause
|
489
|
-
if limit
|
490
|
-
result << limit
|
491
|
-
end
|
492
|
-
if offset
|
493
|
-
result << offset
|
603
|
+
private
|
604
|
+
def type_map
|
605
|
+
@type_map ||= Type::TypeMap.new.tap do |mapping|
|
606
|
+
initialize_type_map(mapping)
|
607
|
+
end
|
494
608
|
end
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
Type::Decimal.new(precision: precision, scale: scale)
|
609
|
+
|
610
|
+
def initialize_type_map(m = type_map)
|
611
|
+
register_class_with_limit m, %r(boolean)i, Type::Boolean
|
612
|
+
register_class_with_limit m, %r(char)i, Type::String
|
613
|
+
register_class_with_limit m, %r(binary)i, Type::Binary
|
614
|
+
register_class_with_limit m, %r(text)i, Type::Text
|
615
|
+
register_class_with_precision m, %r(date)i, Type::Date
|
616
|
+
register_class_with_precision m, %r(time)i, Type::Time
|
617
|
+
register_class_with_precision m, %r(datetime)i, Type::DateTime
|
618
|
+
register_class_with_limit m, %r(float)i, Type::Float
|
619
|
+
register_class_with_limit m, %r(int)i, Type::Integer
|
620
|
+
|
621
|
+
m.alias_type %r(blob)i, "binary"
|
622
|
+
m.alias_type %r(clob)i, "text"
|
623
|
+
m.alias_type %r(timestamp)i, "datetime"
|
624
|
+
m.alias_type %r(numeric)i, "decimal"
|
625
|
+
m.alias_type %r(number)i, "decimal"
|
626
|
+
m.alias_type %r(double)i, "float"
|
627
|
+
|
628
|
+
m.register_type %r(^json)i, Type::Json.new
|
629
|
+
|
630
|
+
m.register_type(%r(decimal)i) do |sql_type|
|
631
|
+
scale = extract_scale(sql_type)
|
632
|
+
precision = extract_precision(sql_type)
|
633
|
+
|
634
|
+
if scale == 0
|
635
|
+
# FIXME: Remove this class as well
|
636
|
+
Type::DecimalWithoutScale.new(precision: precision)
|
637
|
+
else
|
638
|
+
Type::Decimal.new(precision: precision, scale: scale)
|
639
|
+
end
|
527
640
|
end
|
528
641
|
end
|
529
|
-
end
|
530
642
|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
643
|
+
def reload_type_map
|
644
|
+
type_map.clear
|
645
|
+
initialize_type_map
|
646
|
+
end
|
535
647
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
648
|
+
def register_class_with_limit(mapping, key, klass)
|
649
|
+
mapping.register_type(key) do |*args|
|
650
|
+
limit = extract_limit(args.last)
|
651
|
+
klass.new(limit: limit)
|
652
|
+
end
|
540
653
|
end
|
541
|
-
end
|
542
654
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
655
|
+
def register_class_with_precision(mapping, key, klass)
|
656
|
+
mapping.register_type(key) do |*args|
|
657
|
+
precision = extract_precision(args.last)
|
658
|
+
klass.new(precision: precision)
|
659
|
+
end
|
547
660
|
end
|
548
|
-
end
|
549
661
|
|
550
|
-
|
551
|
-
|
662
|
+
def extract_scale(sql_type)
|
663
|
+
case sql_type
|
552
664
|
when /\((\d+)\)/ then 0
|
553
665
|
when /\((\d+)(,(\d+))\)/ then $3.to_i
|
666
|
+
end
|
554
667
|
end
|
555
|
-
end
|
556
668
|
|
557
|
-
|
558
|
-
|
559
|
-
|
669
|
+
def extract_precision(sql_type)
|
670
|
+
$1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
|
671
|
+
end
|
560
672
|
|
561
|
-
|
562
|
-
|
563
|
-
when /^bigint/i
|
564
|
-
8
|
565
|
-
when /\((.*)\)/
|
566
|
-
$1.to_i
|
673
|
+
def extract_limit(sql_type)
|
674
|
+
$1.to_i if sql_type =~ /\((.*)\)/
|
567
675
|
end
|
568
|
-
end
|
569
676
|
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
677
|
+
def translate_exception_class(e, sql, binds)
|
678
|
+
message = "#{e.class.name}: #{e.message}"
|
679
|
+
|
680
|
+
exception = translate_exception(
|
681
|
+
e, message: message, sql: sql, binds: binds
|
682
|
+
)
|
683
|
+
exception.set_backtrace e.backtrace
|
684
|
+
exception
|
575
685
|
end
|
576
686
|
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
687
|
+
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) # :doc:
|
688
|
+
@instrumenter.instrument(
|
689
|
+
"sql.active_record",
|
690
|
+
sql: sql,
|
691
|
+
name: name,
|
692
|
+
binds: binds,
|
693
|
+
type_casted_binds: type_casted_binds,
|
694
|
+
statement_name: statement_name,
|
695
|
+
connection: self) do
|
696
|
+
@lock.synchronize do
|
697
|
+
yield
|
698
|
+
end
|
699
|
+
rescue => e
|
700
|
+
raise translate_exception_class(e, sql, binds)
|
701
|
+
end
|
702
|
+
end
|
581
703
|
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
rescue => e
|
592
|
-
raise translate_exception_class(e, sql)
|
593
|
-
end
|
704
|
+
def translate_exception(exception, message:, sql:, binds:)
|
705
|
+
# override in derived class
|
706
|
+
case exception
|
707
|
+
when RuntimeError
|
708
|
+
exception
|
709
|
+
else
|
710
|
+
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
711
|
+
end
|
712
|
+
end
|
594
713
|
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
end
|
714
|
+
def without_prepared_statement?(binds)
|
715
|
+
!prepared_statements || binds.empty?
|
716
|
+
end
|
599
717
|
|
600
|
-
|
601
|
-
|
602
|
-
|
718
|
+
def column_for(table_name, column_name)
|
719
|
+
column_name = column_name.to_s
|
720
|
+
columns(table_name).detect { |c| c.name == column_name } ||
|
721
|
+
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
722
|
+
end
|
603
723
|
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
724
|
+
def column_for_attribute(attribute)
|
725
|
+
table_name = attribute.relation.name
|
726
|
+
schema_cache.columns_hash(table_name)[attribute.name.to_s]
|
727
|
+
end
|
728
|
+
|
729
|
+
def collector
|
730
|
+
if prepared_statements
|
731
|
+
Arel::Collectors::Composite.new(
|
732
|
+
Arel::Collectors::SQLString.new,
|
733
|
+
Arel::Collectors::Bind.new,
|
734
|
+
)
|
735
|
+
else
|
736
|
+
Arel::Collectors::SubstituteBinds.new(
|
737
|
+
self,
|
738
|
+
Arel::Collectors::SQLString.new,
|
739
|
+
)
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
def arel_visitor
|
744
|
+
Arel::Visitors::ToSql.new(self)
|
745
|
+
end
|
746
|
+
|
747
|
+
def build_statement_pool
|
748
|
+
end
|
749
|
+
|
750
|
+
# Builds the result object.
|
751
|
+
#
|
752
|
+
# This is an internal hook to make possible connection adapters to build
|
753
|
+
# custom result objects with connection-specific data.
|
754
|
+
def build_result(columns:, rows:, column_types: {})
|
755
|
+
ActiveRecord::Result.new(columns, rows, column_types)
|
756
|
+
end
|
609
757
|
end
|
610
758
|
end
|
611
759
|
end
|