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