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