activerecord 5.2.6 → 6.1.3.2
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 +1038 -571
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +13 -12
- data/lib/active_record/aggregations.rb +9 -8
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations.rb +137 -25
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +95 -42
- data/lib/active_record/associations/association_scope.rb +23 -21
- data/lib/active_record/associations/belongs_to_association.rb +54 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
- data/lib/active_record/associations/builder/association.rb +45 -22
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +31 -29
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/preloader/association.rb +71 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attributes.rb +46 -9
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +207 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
- data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
- data/lib/active_record/connection_adapters/abstract_adapter.rb +228 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
- data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +293 -33
- data/lib/active_record/core.rb +323 -97
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +111 -37
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +200 -481
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +26 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +37 -23
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +35 -35
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/migration.rb +206 -157
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +142 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +115 -58
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +408 -78
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation.rb +374 -104
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/calculations.rb +153 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder.rb +62 -45
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +475 -186
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +111 -61
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/scoping/default.rb +4 -6
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +277 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +62 -118
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +10 -5
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/arel.rb +54 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +119 -34
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -5,10 +5,11 @@ module ActiveRecord
|
|
5
5
|
class TransactionState
|
6
6
|
def initialize(state = nil)
|
7
7
|
@state = state
|
8
|
-
@children =
|
8
|
+
@children = nil
|
9
9
|
end
|
10
10
|
|
11
11
|
def add_child(state)
|
12
|
+
@children ||= []
|
12
13
|
@children << state
|
13
14
|
end
|
14
15
|
|
@@ -40,31 +41,13 @@ module ActiveRecord
|
|
40
41
|
committed? || rolledback?
|
41
42
|
end
|
42
43
|
|
43
|
-
def set_state(state)
|
44
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
45
|
-
The set_state method is deprecated and will be removed in
|
46
|
-
Rails 6.0. Please use rollback! or commit! to set transaction
|
47
|
-
state directly.
|
48
|
-
MSG
|
49
|
-
case state
|
50
|
-
when :rolledback
|
51
|
-
rollback!
|
52
|
-
when :committed
|
53
|
-
commit!
|
54
|
-
when nil
|
55
|
-
nullify!
|
56
|
-
else
|
57
|
-
raise ArgumentError, "Invalid transaction state: #{state}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
44
|
def rollback!
|
62
|
-
@children
|
45
|
+
@children&.each { |c| c.rollback! }
|
63
46
|
@state = :rolledback
|
64
47
|
end
|
65
48
|
|
66
49
|
def full_rollback!
|
67
|
-
@children
|
50
|
+
@children&.each { |c| c.rollback! }
|
68
51
|
@state = :fully_rolledback
|
69
52
|
end
|
70
53
|
|
@@ -87,52 +70,87 @@ module ActiveRecord
|
|
87
70
|
def closed?; true; end
|
88
71
|
def open?; false; end
|
89
72
|
def joinable?; false; end
|
90
|
-
def add_record(record); end
|
73
|
+
def add_record(record, _ = true); end
|
91
74
|
end
|
92
75
|
|
93
76
|
class Transaction #:nodoc:
|
94
|
-
attr_reader :connection, :state, :
|
95
|
-
|
77
|
+
attr_reader :connection, :state, :savepoint_name, :isolation_level
|
78
|
+
attr_accessor :written
|
96
79
|
|
97
|
-
def initialize(connection,
|
80
|
+
def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
|
98
81
|
@connection = connection
|
99
82
|
@state = TransactionState.new
|
100
|
-
@records =
|
101
|
-
@
|
83
|
+
@records = nil
|
84
|
+
@isolation_level = isolation
|
85
|
+
@materialized = false
|
86
|
+
@joinable = joinable
|
102
87
|
@run_commit_callbacks = run_commit_callbacks
|
88
|
+
@lazy_enrollment_records = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_record(record, ensure_finalize = true)
|
92
|
+
@records ||= []
|
93
|
+
if ensure_finalize
|
94
|
+
@records << record
|
95
|
+
else
|
96
|
+
@lazy_enrollment_records ||= ObjectSpace::WeakMap.new
|
97
|
+
@lazy_enrollment_records[record] = record
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def records
|
102
|
+
if @lazy_enrollment_records
|
103
|
+
@records.concat @lazy_enrollment_records.values
|
104
|
+
@lazy_enrollment_records = nil
|
105
|
+
end
|
106
|
+
@records
|
103
107
|
end
|
104
108
|
|
105
|
-
def
|
106
|
-
|
109
|
+
def materialize!
|
110
|
+
@materialized = true
|
111
|
+
end
|
112
|
+
|
113
|
+
def materialized?
|
114
|
+
@materialized
|
107
115
|
end
|
108
116
|
|
109
117
|
def rollback_records
|
110
|
-
|
118
|
+
return unless records
|
119
|
+
ite = records.uniq(&:__id__)
|
120
|
+
already_run_callbacks = {}
|
111
121
|
while record = ite.shift
|
112
|
-
record.
|
122
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
123
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
124
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
125
|
+
record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
|
113
126
|
end
|
114
127
|
ensure
|
115
|
-
ite
|
128
|
+
ite&.each do |i|
|
116
129
|
i.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: false)
|
117
130
|
end
|
118
131
|
end
|
119
132
|
|
120
133
|
def before_commit_records
|
121
|
-
records.uniq.each(&:before_committed!) if @run_commit_callbacks
|
134
|
+
records.uniq.each(&:before_committed!) if records && @run_commit_callbacks
|
122
135
|
end
|
123
136
|
|
124
137
|
def commit_records
|
125
|
-
|
138
|
+
return unless records
|
139
|
+
ite = records.uniq(&:__id__)
|
140
|
+
already_run_callbacks = {}
|
126
141
|
while record = ite.shift
|
127
142
|
if @run_commit_callbacks
|
128
|
-
record.
|
143
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
144
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
145
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
146
|
+
record.committed!(should_run_callbacks: should_run_callbacks)
|
129
147
|
else
|
130
148
|
# if not running callbacks, only adds the record to the parent transaction
|
131
|
-
record
|
149
|
+
connection.add_transaction_record(record)
|
132
150
|
end
|
133
151
|
end
|
134
152
|
ensure
|
135
|
-
ite
|
153
|
+
ite&.each { |i| i.committed!(should_run_callbacks: false) }
|
136
154
|
end
|
137
155
|
|
138
156
|
def full_rollback?; true; end
|
@@ -142,24 +160,30 @@ module ActiveRecord
|
|
142
160
|
end
|
143
161
|
|
144
162
|
class SavepointTransaction < Transaction
|
145
|
-
def initialize(connection, savepoint_name, parent_transaction, options
|
146
|
-
super(connection, options
|
163
|
+
def initialize(connection, savepoint_name, parent_transaction, **options)
|
164
|
+
super(connection, **options)
|
147
165
|
|
148
166
|
parent_transaction.state.add_child(@state)
|
149
167
|
|
150
|
-
if
|
168
|
+
if isolation_level
|
151
169
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
152
170
|
end
|
153
|
-
|
171
|
+
|
172
|
+
@savepoint_name = savepoint_name
|
173
|
+
end
|
174
|
+
|
175
|
+
def materialize!
|
176
|
+
connection.create_savepoint(savepoint_name)
|
177
|
+
super
|
154
178
|
end
|
155
179
|
|
156
180
|
def rollback
|
157
|
-
connection.rollback_to_savepoint(savepoint_name)
|
181
|
+
connection.rollback_to_savepoint(savepoint_name) if materialized?
|
158
182
|
@state.rollback!
|
159
183
|
end
|
160
184
|
|
161
185
|
def commit
|
162
|
-
connection.release_savepoint(savepoint_name)
|
186
|
+
connection.release_savepoint(savepoint_name) if materialized?
|
163
187
|
@state.commit!
|
164
188
|
end
|
165
189
|
|
@@ -167,22 +191,23 @@ module ActiveRecord
|
|
167
191
|
end
|
168
192
|
|
169
193
|
class RealTransaction < Transaction
|
170
|
-
def
|
171
|
-
|
172
|
-
|
173
|
-
connection.begin_isolated_db_transaction(options[:isolation])
|
194
|
+
def materialize!
|
195
|
+
if isolation_level
|
196
|
+
connection.begin_isolated_db_transaction(isolation_level)
|
174
197
|
else
|
175
198
|
connection.begin_db_transaction
|
176
199
|
end
|
200
|
+
|
201
|
+
super
|
177
202
|
end
|
178
203
|
|
179
204
|
def rollback
|
180
|
-
connection.rollback_db_transaction
|
205
|
+
connection.rollback_db_transaction if materialized?
|
181
206
|
@state.full_rollback!
|
182
207
|
end
|
183
208
|
|
184
209
|
def commit
|
185
|
-
connection.commit_db_transaction
|
210
|
+
connection.commit_db_transaction if materialized?
|
186
211
|
@state.full_commit!
|
187
212
|
end
|
188
213
|
end
|
@@ -191,24 +216,71 @@ module ActiveRecord
|
|
191
216
|
def initialize(connection)
|
192
217
|
@stack = []
|
193
218
|
@connection = connection
|
219
|
+
@has_unmaterialized_transactions = false
|
220
|
+
@materializing_transactions = false
|
221
|
+
@lazy_transactions_enabled = true
|
194
222
|
end
|
195
223
|
|
196
|
-
def begin_transaction(
|
224
|
+
def begin_transaction(isolation: nil, joinable: true, _lazy: true)
|
197
225
|
@connection.lock.synchronize do
|
198
226
|
run_commit_callbacks = !current_transaction.joinable?
|
199
227
|
transaction =
|
200
228
|
if @stack.empty?
|
201
|
-
RealTransaction.new(
|
229
|
+
RealTransaction.new(
|
230
|
+
@connection,
|
231
|
+
isolation: isolation,
|
232
|
+
joinable: joinable,
|
233
|
+
run_commit_callbacks: run_commit_callbacks
|
234
|
+
)
|
202
235
|
else
|
203
|
-
SavepointTransaction.new(
|
204
|
-
|
236
|
+
SavepointTransaction.new(
|
237
|
+
@connection,
|
238
|
+
"active_record_#{@stack.size}",
|
239
|
+
@stack.last,
|
240
|
+
isolation: isolation,
|
241
|
+
joinable: joinable,
|
242
|
+
run_commit_callbacks: run_commit_callbacks
|
243
|
+
)
|
205
244
|
end
|
206
245
|
|
246
|
+
if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
|
247
|
+
@has_unmaterialized_transactions = true
|
248
|
+
else
|
249
|
+
transaction.materialize!
|
250
|
+
end
|
207
251
|
@stack.push(transaction)
|
208
252
|
transaction
|
209
253
|
end
|
210
254
|
end
|
211
255
|
|
256
|
+
def disable_lazy_transactions!
|
257
|
+
materialize_transactions
|
258
|
+
@lazy_transactions_enabled = false
|
259
|
+
end
|
260
|
+
|
261
|
+
def enable_lazy_transactions!
|
262
|
+
@lazy_transactions_enabled = true
|
263
|
+
end
|
264
|
+
|
265
|
+
def lazy_transactions_enabled?
|
266
|
+
@lazy_transactions_enabled
|
267
|
+
end
|
268
|
+
|
269
|
+
def materialize_transactions
|
270
|
+
return if @materializing_transactions
|
271
|
+
return unless @has_unmaterialized_transactions
|
272
|
+
|
273
|
+
@connection.lock.synchronize do
|
274
|
+
begin
|
275
|
+
@materializing_transactions = true
|
276
|
+
@stack.each { |t| t.materialize! unless t.materialized? }
|
277
|
+
ensure
|
278
|
+
@materializing_transactions = false
|
279
|
+
end
|
280
|
+
@has_unmaterialized_transactions = false
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
212
284
|
def commit_transaction
|
213
285
|
@connection.lock.synchronize do
|
214
286
|
transaction = @stack.last
|
@@ -232,24 +304,40 @@ module ActiveRecord
|
|
232
304
|
end
|
233
305
|
end
|
234
306
|
|
235
|
-
def within_new_transaction(
|
307
|
+
def within_new_transaction(isolation: nil, joinable: true)
|
236
308
|
@connection.lock.synchronize do
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
309
|
+
transaction = begin_transaction(isolation: isolation, joinable: joinable)
|
310
|
+
ret = yield
|
311
|
+
completed = true
|
312
|
+
ret
|
313
|
+
rescue Exception => error
|
314
|
+
if transaction
|
315
|
+
rollback_transaction
|
316
|
+
after_failure_actions(transaction, error)
|
317
|
+
end
|
318
|
+
raise
|
319
|
+
ensure
|
320
|
+
if transaction
|
321
|
+
if error
|
322
|
+
# @connection still holds an open transaction, so we must not
|
323
|
+
# put it back in the pool for reuse
|
324
|
+
@connection.throw_away! unless transaction.state.rolledback?
|
325
|
+
else
|
248
326
|
if Thread.current.status == "aborting"
|
249
|
-
rollback_transaction
|
327
|
+
rollback_transaction
|
250
328
|
else
|
329
|
+
if !completed && transaction.written
|
330
|
+
ActiveSupport::Deprecation.warn(<<~EOW)
|
331
|
+
Using `return`, `break` or `throw` to exit a transaction block is
|
332
|
+
deprecated without replacement. If the `throw` came from
|
333
|
+
`Timeout.timeout(duration)`, pass an exception class as a second
|
334
|
+
argument so it doesn't use `throw` to abort its block. This results
|
335
|
+
in the transaction being committed, but in the next release of Rails
|
336
|
+
it will rollback.
|
337
|
+
EOW
|
338
|
+
end
|
251
339
|
begin
|
252
|
-
commit_transaction
|
340
|
+
commit_transaction
|
253
341
|
rescue Exception
|
254
342
|
rollback_transaction(transaction) unless transaction.state.completed?
|
255
343
|
raise
|
@@ -269,7 +357,6 @@ module ActiveRecord
|
|
269
357
|
end
|
270
358
|
|
271
359
|
private
|
272
|
-
|
273
360
|
NULL_TRANSACTION = NullTransaction.new
|
274
361
|
|
275
362
|
# Deallocate invalidated prepared statements outside of the transaction
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "set"
|
4
4
|
require "active_record/connection_adapters/schema_cache"
|
5
5
|
require "active_record/connection_adapters/sql_type_metadata"
|
6
6
|
require "active_record/connection_adapters/abstract/schema_dumper"
|
@@ -13,44 +13,6 @@ require "arel/collectors/substitute_binds"
|
|
13
13
|
|
14
14
|
module ActiveRecord
|
15
15
|
module ConnectionAdapters # :nodoc:
|
16
|
-
extend ActiveSupport::Autoload
|
17
|
-
|
18
|
-
autoload :Column
|
19
|
-
autoload :ConnectionSpecification
|
20
|
-
|
21
|
-
autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
|
22
|
-
autoload :IndexDefinition
|
23
|
-
autoload :ColumnDefinition
|
24
|
-
autoload :ChangeColumnDefinition
|
25
|
-
autoload :ForeignKeyDefinition
|
26
|
-
autoload :TableDefinition
|
27
|
-
autoload :Table
|
28
|
-
autoload :AlterTable
|
29
|
-
autoload :ReferenceDefinition
|
30
|
-
end
|
31
|
-
|
32
|
-
autoload_at "active_record/connection_adapters/abstract/connection_pool" do
|
33
|
-
autoload :ConnectionHandler
|
34
|
-
end
|
35
|
-
|
36
|
-
autoload_under "abstract" do
|
37
|
-
autoload :SchemaStatements
|
38
|
-
autoload :DatabaseStatements
|
39
|
-
autoload :DatabaseLimits
|
40
|
-
autoload :Quoting
|
41
|
-
autoload :ConnectionPool
|
42
|
-
autoload :QueryCache
|
43
|
-
autoload :Savepoints
|
44
|
-
end
|
45
|
-
|
46
|
-
autoload_at "active_record/connection_adapters/abstract/transaction" do
|
47
|
-
autoload :TransactionManager
|
48
|
-
autoload :NullTransaction
|
49
|
-
autoload :RealTransaction
|
50
|
-
autoload :SavepointTransaction
|
51
|
-
autoload :TransactionState
|
52
|
-
end
|
53
|
-
|
54
16
|
# Active Record supports multiple database systems. AbstractAdapter and
|
55
17
|
# related classes form the abstraction layer which makes this possible.
|
56
18
|
# An AbstractAdapter represents a connection to a database, and provides an
|
@@ -65,7 +27,7 @@ module ActiveRecord
|
|
65
27
|
# Most of the methods in the adapter are useful during migrations. Most
|
66
28
|
# notably, the instance methods provided by SchemaStatements are very useful.
|
67
29
|
class AbstractAdapter
|
68
|
-
ADAPTER_NAME = "Abstract"
|
30
|
+
ADAPTER_NAME = "Abstract"
|
69
31
|
include ActiveSupport::Callbacks
|
70
32
|
define_callbacks :checkout, :checkin
|
71
33
|
|
@@ -75,15 +37,18 @@ module ActiveRecord
|
|
75
37
|
include Savepoints
|
76
38
|
|
77
39
|
SIMPLE_INT = /\A\d+\z/
|
40
|
+
COMMENT_REGEX = %r{(?:\-\-.*\n)*|/\*(?:[^\*]|\*[^/])*\*/}m
|
78
41
|
|
79
|
-
attr_accessor :
|
80
|
-
attr_reader :
|
42
|
+
attr_accessor :pool
|
43
|
+
attr_reader :visitor, :owner, :logger, :lock
|
81
44
|
alias :in_use? :owner
|
82
45
|
|
46
|
+
set_callback :checkin, :after, :enable_lazy_transactions!
|
47
|
+
|
83
48
|
def self.type_cast_config_to_integer(config)
|
84
49
|
if config.is_a?(Integer)
|
85
50
|
config
|
86
|
-
elsif config
|
51
|
+
elsif SIMPLE_INT.match?(config)
|
87
52
|
config.to_i
|
88
53
|
else
|
89
54
|
config
|
@@ -98,6 +63,23 @@ module ActiveRecord
|
|
98
63
|
end
|
99
64
|
end
|
100
65
|
|
66
|
+
DEFAULT_READ_QUERY = [:begin, :commit, :explain, :release, :rollback, :savepoint, :select, :with] # :nodoc:
|
67
|
+
private_constant :DEFAULT_READ_QUERY
|
68
|
+
|
69
|
+
def self.build_read_query_regexp(*parts) # :nodoc:
|
70
|
+
parts += DEFAULT_READ_QUERY
|
71
|
+
parts = parts.map { |part| /#{part}/i }
|
72
|
+
/\A(?:[\(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.quoted_column_names # :nodoc:
|
76
|
+
@quoted_column_names ||= {}
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.quoted_table_names # :nodoc:
|
80
|
+
@quoted_table_names ||= {}
|
81
|
+
end
|
82
|
+
|
101
83
|
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
102
84
|
super()
|
103
85
|
|
@@ -106,19 +88,44 @@ module ActiveRecord
|
|
106
88
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
107
89
|
@logger = logger
|
108
90
|
@config = config
|
109
|
-
@pool =
|
91
|
+
@pool = ActiveRecord::ConnectionAdapters::NullPool.new
|
110
92
|
@idle_since = Concurrent.monotonic_time
|
111
|
-
@schema_cache = SchemaCache.new self
|
112
|
-
@quoted_column_names, @quoted_table_names = {}, {}
|
113
93
|
@visitor = arel_visitor
|
94
|
+
@statements = build_statement_pool
|
114
95
|
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
115
96
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
97
|
+
@prepared_statements = self.class.type_cast_config_to_boolean(
|
98
|
+
config.fetch(:prepared_statements, true)
|
99
|
+
)
|
100
|
+
|
101
|
+
@advisory_locks_enabled = self.class.type_cast_config_to_boolean(
|
102
|
+
config.fetch(:advisory_locks, true)
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
def replica?
|
107
|
+
@config[:replica] || false
|
108
|
+
end
|
109
|
+
|
110
|
+
def use_metadata_table?
|
111
|
+
@config.fetch(:use_metadata_table, true)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Determines whether writes are currently being prevented.
|
115
|
+
#
|
116
|
+
# Returns true if the connection is a replica.
|
117
|
+
#
|
118
|
+
# If the application is using legacy handling, returns
|
119
|
+
# true if +connection_handler.prevent_writes+ is set.
|
120
|
+
#
|
121
|
+
# If the application is using the new connection handling
|
122
|
+
# will return true based on +current_preventing_writes+.
|
123
|
+
def preventing_writes?
|
124
|
+
return true if replica?
|
125
|
+
return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord::Base.legacy_connection_handling
|
126
|
+
return false if connection_klass.nil?
|
127
|
+
|
128
|
+
connection_klass.current_preventing_writes
|
122
129
|
end
|
123
130
|
|
124
131
|
def migrations_paths # :nodoc:
|
@@ -126,19 +133,52 @@ module ActiveRecord
|
|
126
133
|
end
|
127
134
|
|
128
135
|
def migration_context # :nodoc:
|
129
|
-
MigrationContext.new(migrations_paths)
|
136
|
+
MigrationContext.new(migrations_paths, schema_migration)
|
137
|
+
end
|
138
|
+
|
139
|
+
def schema_migration # :nodoc:
|
140
|
+
@schema_migration ||= begin
|
141
|
+
conn = self
|
142
|
+
spec_name = conn.pool.pool_config.connection_specification_name
|
143
|
+
|
144
|
+
return ActiveRecord::SchemaMigration if spec_name == "ActiveRecord::Base"
|
145
|
+
|
146
|
+
schema_migration_name = "#{spec_name}::SchemaMigration"
|
147
|
+
|
148
|
+
Class.new(ActiveRecord::SchemaMigration) do
|
149
|
+
define_singleton_method(:name) { schema_migration_name }
|
150
|
+
define_singleton_method(:to_s) { schema_migration_name }
|
151
|
+
|
152
|
+
self.connection_specification_name = spec_name
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def prepared_statements
|
158
|
+
@prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
|
159
|
+
end
|
160
|
+
|
161
|
+
def prepared_statements_disabled_cache # :nodoc:
|
162
|
+
Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
|
130
163
|
end
|
131
164
|
|
132
165
|
class Version
|
133
166
|
include Comparable
|
134
167
|
|
135
|
-
|
168
|
+
attr_reader :full_version_string
|
169
|
+
|
170
|
+
def initialize(version_string, full_version_string = nil)
|
136
171
|
@version = version_string.split(".").map(&:to_i)
|
172
|
+
@full_version_string = full_version_string
|
137
173
|
end
|
138
174
|
|
139
175
|
def <=>(version_string)
|
140
176
|
@version <=> version_string.split(".").map(&:to_i)
|
141
177
|
end
|
178
|
+
|
179
|
+
def to_s
|
180
|
+
@version.join(".")
|
181
|
+
end
|
142
182
|
end
|
143
183
|
|
144
184
|
def valid_type?(type) # :nodoc:
|
@@ -148,7 +188,7 @@ module ActiveRecord
|
|
148
188
|
# this method must only be called while holding connection pool's mutex
|
149
189
|
def lease
|
150
190
|
if in_use?
|
151
|
-
msg = "Cannot lease connection, "
|
191
|
+
msg = +"Cannot lease connection, "
|
152
192
|
if @owner == Thread.current
|
153
193
|
msg << "it is already leased by the current thread."
|
154
194
|
else
|
@@ -161,9 +201,17 @@ module ActiveRecord
|
|
161
201
|
@owner = Thread.current
|
162
202
|
end
|
163
203
|
|
204
|
+
def connection_klass # :nodoc:
|
205
|
+
@pool.connection_klass
|
206
|
+
end
|
207
|
+
|
208
|
+
def schema_cache
|
209
|
+
@pool.get_schema_cache(self)
|
210
|
+
end
|
211
|
+
|
164
212
|
def schema_cache=(cache)
|
165
213
|
cache.connection = self
|
166
|
-
@
|
214
|
+
@pool.set_schema_cache(cache)
|
167
215
|
end
|
168
216
|
|
169
217
|
# this method must only be called while holding connection pool's mutex
|
@@ -202,10 +250,10 @@ module ActiveRecord
|
|
202
250
|
end
|
203
251
|
|
204
252
|
def unprepared_statement
|
205
|
-
|
253
|
+
cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
|
206
254
|
yield
|
207
255
|
ensure
|
208
|
-
|
256
|
+
cache&.delete(object_id)
|
209
257
|
end
|
210
258
|
|
211
259
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
@@ -214,6 +262,11 @@ module ActiveRecord
|
|
214
262
|
self.class::ADAPTER_NAME
|
215
263
|
end
|
216
264
|
|
265
|
+
# Does the database for this adapter exist?
|
266
|
+
def self.database_exists?(config)
|
267
|
+
raise NotImplementedError
|
268
|
+
end
|
269
|
+
|
217
270
|
# Does this adapter support DDL rollbacks in transactions? That is, would
|
218
271
|
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
219
272
|
def supports_ddl_transactions?
|
@@ -241,6 +294,10 @@ module ActiveRecord
|
|
241
294
|
false
|
242
295
|
end
|
243
296
|
|
297
|
+
def supports_partitioned_indexes?
|
298
|
+
false
|
299
|
+
end
|
300
|
+
|
244
301
|
# Does this adapter support index sort order?
|
245
302
|
def supports_index_sort_order?
|
246
303
|
false
|
@@ -287,10 +344,9 @@ module ActiveRecord
|
|
287
344
|
false
|
288
345
|
end
|
289
346
|
|
290
|
-
# Does this adapter support creating
|
291
|
-
|
292
|
-
|
293
|
-
supports_foreign_keys?
|
347
|
+
# Does this adapter support creating check constraints?
|
348
|
+
def supports_check_constraints?
|
349
|
+
false
|
294
350
|
end
|
295
351
|
|
296
352
|
# Does this adapter support views?
|
@@ -298,6 +354,11 @@ module ActiveRecord
|
|
298
354
|
false
|
299
355
|
end
|
300
356
|
|
357
|
+
# Does this adapter support materialized views?
|
358
|
+
def supports_materialized_views?
|
359
|
+
false
|
360
|
+
end
|
361
|
+
|
301
362
|
# Does this adapter support datetime with precision?
|
302
363
|
def supports_datetime_with_precision?
|
303
364
|
false
|
@@ -318,11 +379,6 @@ module ActiveRecord
|
|
318
379
|
false
|
319
380
|
end
|
320
381
|
|
321
|
-
# Does this adapter support multi-value insert?
|
322
|
-
def supports_multi_insert?
|
323
|
-
true
|
324
|
-
end
|
325
|
-
|
326
382
|
# Does this adapter support virtual columns?
|
327
383
|
def supports_virtual_columns?
|
328
384
|
false
|
@@ -333,6 +389,35 @@ module ActiveRecord
|
|
333
389
|
false
|
334
390
|
end
|
335
391
|
|
392
|
+
# Does this adapter support optimizer hints?
|
393
|
+
def supports_optimizer_hints?
|
394
|
+
false
|
395
|
+
end
|
396
|
+
|
397
|
+
def supports_common_table_expressions?
|
398
|
+
false
|
399
|
+
end
|
400
|
+
|
401
|
+
def supports_lazy_transactions?
|
402
|
+
false
|
403
|
+
end
|
404
|
+
|
405
|
+
def supports_insert_returning?
|
406
|
+
false
|
407
|
+
end
|
408
|
+
|
409
|
+
def supports_insert_on_duplicate_skip?
|
410
|
+
false
|
411
|
+
end
|
412
|
+
|
413
|
+
def supports_insert_on_duplicate_update?
|
414
|
+
false
|
415
|
+
end
|
416
|
+
|
417
|
+
def supports_insert_conflict_target?
|
418
|
+
false
|
419
|
+
end
|
420
|
+
|
336
421
|
# This is meant to be implemented by the adapters that support extensions
|
337
422
|
def disable_extension(name)
|
338
423
|
end
|
@@ -341,6 +426,10 @@ module ActiveRecord
|
|
341
426
|
def enable_extension(name)
|
342
427
|
end
|
343
428
|
|
429
|
+
def advisory_locks_enabled? # :nodoc:
|
430
|
+
supports_advisory_locks? && @advisory_locks_enabled
|
431
|
+
end
|
432
|
+
|
344
433
|
# This is meant to be implemented by the adapters that support advisory
|
345
434
|
# locks
|
346
435
|
#
|
@@ -406,6 +495,9 @@ module ActiveRecord
|
|
406
495
|
#
|
407
496
|
# Prevent @connection's finalizer from touching the socket, or
|
408
497
|
# otherwise communicating with its server, when it is collected.
|
498
|
+
if schema_cache.connection == self
|
499
|
+
schema_cache.connection = nil
|
500
|
+
end
|
409
501
|
end
|
410
502
|
|
411
503
|
# Reset the state of this connection, directing the DBMS to clear
|
@@ -418,11 +510,15 @@ module ActiveRecord
|
|
418
510
|
# this should be overridden by concrete adapters
|
419
511
|
end
|
420
512
|
|
421
|
-
|
422
|
-
|
423
|
-
|
513
|
+
# Removes the connection from the pool and disconnect it.
|
514
|
+
def throw_away!
|
515
|
+
pool.remove self
|
516
|
+
disconnect!
|
517
|
+
end
|
518
|
+
|
519
|
+
# Clear any caching the database adapter may be doing.
|
424
520
|
def clear_cache!
|
425
|
-
|
521
|
+
@lock.synchronize { @statements.clear } if @statements
|
426
522
|
end
|
427
523
|
|
428
524
|
# Returns true if its required to reload the connection between requests for development mode.
|
@@ -444,18 +540,25 @@ module ActiveRecord
|
|
444
540
|
# This is useful for when you need to call a proprietary method such as
|
445
541
|
# PostgreSQL's lo_* methods.
|
446
542
|
def raw_connection
|
543
|
+
disable_lazy_transactions!
|
447
544
|
@connection
|
448
545
|
end
|
449
546
|
|
450
|
-
def
|
451
|
-
|
547
|
+
def default_uniqueness_comparison(attribute, value) # :nodoc:
|
548
|
+
attribute.eq(value)
|
549
|
+
end
|
550
|
+
|
551
|
+
def case_sensitive_comparison(attribute, value) # :nodoc:
|
552
|
+
attribute.eq(value)
|
452
553
|
end
|
453
554
|
|
454
|
-
def case_insensitive_comparison(
|
555
|
+
def case_insensitive_comparison(attribute, value) # :nodoc:
|
556
|
+
column = column_for_attribute(attribute)
|
557
|
+
|
455
558
|
if can_perform_case_insensitive_comparison_for?(column)
|
456
|
-
|
559
|
+
attribute.lower.eq(attribute.relation.lower(value))
|
457
560
|
else
|
458
|
-
|
561
|
+
attribute.eq(value)
|
459
562
|
end
|
460
563
|
end
|
461
564
|
|
@@ -469,16 +572,31 @@ module ActiveRecord
|
|
469
572
|
pool.checkin self
|
470
573
|
end
|
471
574
|
|
472
|
-
def
|
473
|
-
|
575
|
+
def default_index_type?(index) # :nodoc:
|
576
|
+
index.using.nil?
|
474
577
|
end
|
475
578
|
|
476
|
-
|
477
|
-
|
579
|
+
# Called by ActiveRecord::InsertAll,
|
580
|
+
# Passed an instance of ActiveRecord::InsertAll::Builder,
|
581
|
+
# This method implements standard bulk inserts for all databases, but
|
582
|
+
# should be overridden by adapters to implement common features with
|
583
|
+
# non-standard syntax like handling duplicates or returning values.
|
584
|
+
def build_insert_sql(insert) # :nodoc:
|
585
|
+
if insert.skip_duplicates? || insert.update_duplicates?
|
586
|
+
raise NotImplementedError, "#{self.class} should define `build_insert_sql` to implement adapter-specific logic for handling duplicates during INSERT"
|
587
|
+
end
|
588
|
+
|
589
|
+
"INSERT #{insert.into} #{insert.values_list}"
|
478
590
|
end
|
479
591
|
|
480
|
-
def
|
481
|
-
|
592
|
+
def get_database_version # :nodoc:
|
593
|
+
end
|
594
|
+
|
595
|
+
def database_version # :nodoc:
|
596
|
+
schema_cache.database_version
|
597
|
+
end
|
598
|
+
|
599
|
+
def check_version # :nodoc:
|
482
600
|
end
|
483
601
|
|
484
602
|
private
|
@@ -555,14 +673,12 @@ module ActiveRecord
|
|
555
673
|
$1.to_i if sql_type =~ /\((.*)\)/
|
556
674
|
end
|
557
675
|
|
558
|
-
def translate_exception_class(e, sql)
|
559
|
-
|
560
|
-
message = "#{e.class.name}: #{e.message}: #{sql}"
|
561
|
-
rescue Encoding::CompatibilityError
|
562
|
-
message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
|
563
|
-
end
|
676
|
+
def translate_exception_class(e, sql, binds)
|
677
|
+
message = "#{e.class.name}: #{e.message}"
|
564
678
|
|
565
|
-
exception = translate_exception(
|
679
|
+
exception = translate_exception(
|
680
|
+
e, message: message, sql: sql, binds: binds
|
681
|
+
)
|
566
682
|
exception.set_backtrace e.backtrace
|
567
683
|
exception
|
568
684
|
end
|
@@ -575,24 +691,22 @@ module ActiveRecord
|
|
575
691
|
binds: binds,
|
576
692
|
type_casted_binds: type_casted_binds,
|
577
693
|
statement_name: statement_name,
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
yield
|
582
|
-
end
|
583
|
-
rescue => e
|
584
|
-
raise translate_exception_class(e, sql)
|
694
|
+
connection: self) do
|
695
|
+
@lock.synchronize do
|
696
|
+
yield
|
585
697
|
end
|
698
|
+
rescue => e
|
699
|
+
raise translate_exception_class(e, sql, binds)
|
586
700
|
end
|
587
701
|
end
|
588
702
|
|
589
|
-
def translate_exception(exception, message)
|
703
|
+
def translate_exception(exception, message:, sql:, binds:)
|
590
704
|
# override in derived class
|
591
705
|
case exception
|
592
706
|
when RuntimeError
|
593
707
|
exception
|
594
708
|
else
|
595
|
-
ActiveRecord::StatementInvalid.new(message)
|
709
|
+
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
596
710
|
end
|
597
711
|
end
|
598
712
|
|
@@ -606,6 +720,11 @@ module ActiveRecord
|
|
606
720
|
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
607
721
|
end
|
608
722
|
|
723
|
+
def column_for_attribute(attribute)
|
724
|
+
table_name = attribute.relation.name
|
725
|
+
schema_cache.columns_hash(table_name)[attribute.name.to_s]
|
726
|
+
end
|
727
|
+
|
609
728
|
def collector
|
610
729
|
if prepared_statements
|
611
730
|
Arel::Collectors::Composite.new(
|
@@ -623,6 +742,17 @@ module ActiveRecord
|
|
623
742
|
def arel_visitor
|
624
743
|
Arel::Visitors::ToSql.new(self)
|
625
744
|
end
|
745
|
+
|
746
|
+
def build_statement_pool
|
747
|
+
end
|
748
|
+
|
749
|
+
# Builds the result object.
|
750
|
+
#
|
751
|
+
# This is an internal hook to make possible connection adapters to build
|
752
|
+
# custom result objects with connection-specific data.
|
753
|
+
def build_result(columns:, rows:, column_types: {})
|
754
|
+
ActiveRecord::Result.new(columns, rows, column_types)
|
755
|
+
end
|
626
756
|
end
|
627
757
|
end
|
628
758
|
end
|