activerecord 5.2.4.4 → 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 +777 -552
- data/MIT-LICENSE +3 -1
- data/README.rdoc +5 -3
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +10 -2
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +4 -3
- data/lib/active_record/association_relation.rb +10 -8
- data/lib/active_record/associations.rb +21 -16
- data/lib/active_record/associations/alias_tracker.rb +0 -1
- data/lib/active_record/associations/association.rb +56 -19
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/association.rb +14 -18
- data/lib/active_record/associations/builder/belongs_to.rb +19 -52
- data/lib/active_record/associations/builder/collection_association.rb +3 -13
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +35 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +12 -23
- data/lib/active_record/associations/collection_proxy.rb +13 -17
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +2 -11
- data/lib/active_record/associations/has_many_through_association.rb +14 -14
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +37 -28
- data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +39 -32
- data/lib/active_record/associations/preloader/association.rb +38 -36
- data/lib/active_record/associations/preloader/through_association.rb +48 -39
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -11
- data/lib/active_record/attribute_decorators.rb +0 -2
- data/lib/active_record/attribute_methods.rb +28 -100
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
- data/lib/active_record/attribute_methods/dirty.rb +111 -40
- data/lib/active_record/attribute_methods/primary_key.rb +15 -24
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +15 -54
- data/lib/active_record/attribute_methods/serialization.rb +1 -2
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
- data/lib/active_record/attribute_methods/write.rb +17 -25
- data/lib/active_record/attributes.rb +13 -1
- data/lib/active_record/autosave_association.rb +3 -5
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +6 -21
- data/lib/active_record/coders/yaml_column.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +103 -18
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +100 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
- data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
- data/lib/active_record/connection_adapters/abstract_adapter.rb +191 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +142 -215
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +132 -16
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
- 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/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -2
- 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 +5 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
- 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 +63 -75
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
- data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +135 -146
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +139 -26
- data/lib/active_record/core.rb +103 -61
- data/lib/active_record/counter_cache.rb +8 -30
- 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/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +37 -7
- data/lib/active_record/errors.rb +15 -7
- data/lib/active_record/explain.rb +1 -2
- 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 +144 -474
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +13 -6
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +68 -16
- data/lib/active_record/internal_metadata.rb +11 -3
- data/lib/active_record/locking/optimistic.rb +5 -7
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +8 -27
- 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 +104 -85
- data/lib/active_record/migration/command_recorder.rb +54 -22
- data/lib/active_record/migration/compatibility.rb +79 -52
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +33 -11
- data/lib/active_record/nested_attributes.rb +2 -4
- data/lib/active_record/no_touching.rb +9 -2
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +232 -29
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +33 -21
- data/lib/active_record/railtie.rb +80 -43
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +199 -46
- data/lib/active_record/reflection.rb +40 -38
- data/lib/active_record/relation.rb +322 -80
- data/lib/active_record/relation/batches.rb +13 -11
- data/lib/active_record/relation/calculations.rb +54 -48
- data/lib/active_record/relation/delegation.rb +33 -49
- data/lib/active_record/relation/finder_methods.rb +23 -28
- data/lib/active_record/relation/from_clause.rb +4 -0
- data/lib/active_record/relation/merger.rb +11 -21
- data/lib/active_record/relation/predicate_builder.rb +5 -11
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +221 -70
- data/lib/active_record/relation/spawn_methods.rb +1 -2
- data/lib/active_record/relation/where_clause.rb +14 -11
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -12
- data/lib/active_record/sanitization.rb +32 -40
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +22 -7
- data/lib/active_record/schema_migration.rb +6 -2
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/scoping/default.rb +4 -6
- data/lib/active_record/scoping/named.rb +21 -17
- data/lib/active_record/statement_cache.rb +30 -3
- data/lib/active_record/store.rb +87 -8
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +23 -15
- data/lib/active_record/tasks/database_tasks.rb +194 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +225 -0
- data/lib/active_record/timestamp.rb +39 -26
- data/lib/active_record/touch_later.rb +5 -4
- data/lib/active_record/transactions.rb +64 -73
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -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 +0 -1
- 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 -14
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/uniqueness.rb +15 -27
- 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/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +14 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +115 -29
- data/lib/active_record/collection_cache_key.rb +0 -53
@@ -40,24 +40,6 @@ module ActiveRecord
|
|
40
40
|
committed? || rolledback?
|
41
41
|
end
|
42
42
|
|
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
43
|
def rollback!
|
62
44
|
@children.each { |c| c.rollback! }
|
63
45
|
@state = :rolledback
|
@@ -91,13 +73,14 @@ module ActiveRecord
|
|
91
73
|
end
|
92
74
|
|
93
75
|
class Transaction #:nodoc:
|
94
|
-
attr_reader :connection, :state, :records, :savepoint_name
|
95
|
-
attr_writer :joinable
|
76
|
+
attr_reader :connection, :state, :records, :savepoint_name, :isolation_level
|
96
77
|
|
97
78
|
def initialize(connection, options, run_commit_callbacks: false)
|
98
79
|
@connection = connection
|
99
80
|
@state = TransactionState.new
|
100
81
|
@records = []
|
82
|
+
@isolation_level = options[:isolation]
|
83
|
+
@materialized = false
|
101
84
|
@joinable = options.fetch(:joinable, true)
|
102
85
|
@run_commit_callbacks = run_commit_callbacks
|
103
86
|
end
|
@@ -106,10 +89,22 @@ module ActiveRecord
|
|
106
89
|
records << record
|
107
90
|
end
|
108
91
|
|
92
|
+
def materialize!
|
93
|
+
@materialized = true
|
94
|
+
end
|
95
|
+
|
96
|
+
def materialized?
|
97
|
+
@materialized
|
98
|
+
end
|
99
|
+
|
109
100
|
def rollback_records
|
110
|
-
ite = records.uniq
|
101
|
+
ite = records.uniq(&:__id__)
|
102
|
+
already_run_callbacks = {}
|
111
103
|
while record = ite.shift
|
112
|
-
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)
|
113
108
|
end
|
114
109
|
ensure
|
115
110
|
ite.each do |i|
|
@@ -122,13 +117,17 @@ module ActiveRecord
|
|
122
117
|
end
|
123
118
|
|
124
119
|
def commit_records
|
125
|
-
ite = records.uniq
|
120
|
+
ite = records.uniq(&:__id__)
|
121
|
+
already_run_callbacks = {}
|
126
122
|
while record = ite.shift
|
127
123
|
if @run_commit_callbacks
|
128
|
-
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)
|
129
128
|
else
|
130
129
|
# if not running callbacks, only adds the record to the parent transaction
|
131
|
-
record
|
130
|
+
connection.add_transaction_record(record)
|
132
131
|
end
|
133
132
|
end
|
134
133
|
ensure
|
@@ -142,24 +141,30 @@ module ActiveRecord
|
|
142
141
|
end
|
143
142
|
|
144
143
|
class SavepointTransaction < Transaction
|
145
|
-
def initialize(connection, savepoint_name, parent_transaction,
|
146
|
-
super(connection,
|
144
|
+
def initialize(connection, savepoint_name, parent_transaction, *args, **options)
|
145
|
+
super(connection, *args, **options)
|
147
146
|
|
148
147
|
parent_transaction.state.add_child(@state)
|
149
148
|
|
150
|
-
if
|
149
|
+
if isolation_level
|
151
150
|
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
152
151
|
end
|
153
|
-
|
152
|
+
|
153
|
+
@savepoint_name = savepoint_name
|
154
|
+
end
|
155
|
+
|
156
|
+
def materialize!
|
157
|
+
connection.create_savepoint(savepoint_name)
|
158
|
+
super
|
154
159
|
end
|
155
160
|
|
156
161
|
def rollback
|
157
|
-
connection.rollback_to_savepoint(savepoint_name)
|
162
|
+
connection.rollback_to_savepoint(savepoint_name) if materialized?
|
158
163
|
@state.rollback!
|
159
164
|
end
|
160
165
|
|
161
166
|
def commit
|
162
|
-
connection.release_savepoint(savepoint_name)
|
167
|
+
connection.release_savepoint(savepoint_name) if materialized?
|
163
168
|
@state.commit!
|
164
169
|
end
|
165
170
|
|
@@ -167,22 +172,23 @@ module ActiveRecord
|
|
167
172
|
end
|
168
173
|
|
169
174
|
class RealTransaction < Transaction
|
170
|
-
def
|
171
|
-
|
172
|
-
|
173
|
-
connection.begin_isolated_db_transaction(options[:isolation])
|
175
|
+
def materialize!
|
176
|
+
if isolation_level
|
177
|
+
connection.begin_isolated_db_transaction(isolation_level)
|
174
178
|
else
|
175
179
|
connection.begin_db_transaction
|
176
180
|
end
|
181
|
+
|
182
|
+
super
|
177
183
|
end
|
178
184
|
|
179
185
|
def rollback
|
180
|
-
connection.rollback_db_transaction
|
186
|
+
connection.rollback_db_transaction if materialized?
|
181
187
|
@state.full_rollback!
|
182
188
|
end
|
183
189
|
|
184
190
|
def commit
|
185
|
-
connection.commit_db_transaction
|
191
|
+
connection.commit_db_transaction if materialized?
|
186
192
|
@state.full_commit!
|
187
193
|
end
|
188
194
|
end
|
@@ -191,6 +197,9 @@ module ActiveRecord
|
|
191
197
|
def initialize(connection)
|
192
198
|
@stack = []
|
193
199
|
@connection = connection
|
200
|
+
@has_unmaterialized_transactions = false
|
201
|
+
@materializing_transactions = false
|
202
|
+
@lazy_transactions_enabled = true
|
194
203
|
end
|
195
204
|
|
196
205
|
def begin_transaction(options = {})
|
@@ -204,11 +213,44 @@ module ActiveRecord
|
|
204
213
|
run_commit_callbacks: run_commit_callbacks)
|
205
214
|
end
|
206
215
|
|
216
|
+
if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && options[:_lazy] != false
|
217
|
+
@has_unmaterialized_transactions = true
|
218
|
+
else
|
219
|
+
transaction.materialize!
|
220
|
+
end
|
207
221
|
@stack.push(transaction)
|
208
222
|
transaction
|
209
223
|
end
|
210
224
|
end
|
211
225
|
|
226
|
+
def disable_lazy_transactions!
|
227
|
+
materialize_transactions
|
228
|
+
@lazy_transactions_enabled = false
|
229
|
+
end
|
230
|
+
|
231
|
+
def enable_lazy_transactions!
|
232
|
+
@lazy_transactions_enabled = true
|
233
|
+
end
|
234
|
+
|
235
|
+
def lazy_transactions_enabled?
|
236
|
+
@lazy_transactions_enabled
|
237
|
+
end
|
238
|
+
|
239
|
+
def materialize_transactions
|
240
|
+
return if @materializing_transactions
|
241
|
+
return unless @has_unmaterialized_transactions
|
242
|
+
|
243
|
+
@connection.lock.synchronize do
|
244
|
+
begin
|
245
|
+
@materializing_transactions = true
|
246
|
+
@stack.each { |t| t.materialize! unless t.materialized? }
|
247
|
+
ensure
|
248
|
+
@materializing_transactions = false
|
249
|
+
end
|
250
|
+
@has_unmaterialized_transactions = false
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
212
254
|
def commit_transaction
|
213
255
|
@connection.lock.synchronize do
|
214
256
|
transaction = @stack.last
|
@@ -234,26 +276,24 @@ module ActiveRecord
|
|
234
276
|
|
235
277
|
def within_new_transaction(options = {})
|
236
278
|
@connection.lock.synchronize do
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
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"
|
242
290
|
rollback_transaction
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
rollback_transaction if transaction
|
250
|
-
else
|
251
|
-
begin
|
252
|
-
commit_transaction if transaction
|
253
|
-
rescue Exception
|
254
|
-
rollback_transaction(transaction) unless transaction.state.completed?
|
255
|
-
raise
|
256
|
-
end
|
291
|
+
else
|
292
|
+
begin
|
293
|
+
commit_transaction
|
294
|
+
rescue Exception
|
295
|
+
rollback_transaction(transaction) unless transaction.state.completed?
|
296
|
+
raise
|
257
297
|
end
|
258
298
|
end
|
259
299
|
end
|
@@ -269,7 +309,6 @@ module ActiveRecord
|
|
269
309
|
end
|
270
310
|
|
271
311
|
private
|
272
|
-
|
273
312
|
NULL_TRANSACTION = NullTransaction.new
|
274
313
|
|
275
314
|
# Deallocate invalidated prepared statements outside of the transaction
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "set"
|
3
4
|
require "active_record/connection_adapters/determine_if_preparable_visitor"
|
4
5
|
require "active_record/connection_adapters/schema_cache"
|
5
6
|
require "active_record/connection_adapters/sql_type_metadata"
|
6
7
|
require "active_record/connection_adapters/abstract/schema_dumper"
|
7
8
|
require "active_record/connection_adapters/abstract/schema_creation"
|
8
9
|
require "active_support/concurrency/load_interlock_aware_monitor"
|
10
|
+
require "active_support/deprecation"
|
9
11
|
require "arel/collectors/bind"
|
10
12
|
require "arel/collectors/composite"
|
11
13
|
require "arel/collectors/sql_string"
|
@@ -65,7 +67,7 @@ module ActiveRecord
|
|
65
67
|
# Most of the methods in the adapter are useful during migrations. Most
|
66
68
|
# notably, the instance methods provided by SchemaStatements are very useful.
|
67
69
|
class AbstractAdapter
|
68
|
-
ADAPTER_NAME = "Abstract"
|
70
|
+
ADAPTER_NAME = "Abstract"
|
69
71
|
include ActiveSupport::Callbacks
|
70
72
|
define_callbacks :checkout, :checkin
|
71
73
|
|
@@ -75,15 +77,18 @@ module ActiveRecord
|
|
75
77
|
include Savepoints
|
76
78
|
|
77
79
|
SIMPLE_INT = /\A\d+\z/
|
80
|
+
COMMENT_REGEX = %r{/\*(?:[^\*]|\*[^/])*\*/}m
|
78
81
|
|
79
|
-
attr_accessor :
|
80
|
-
attr_reader :
|
82
|
+
attr_accessor :pool
|
83
|
+
attr_reader :visitor, :owner, :logger, :lock
|
81
84
|
alias :in_use? :owner
|
82
85
|
|
86
|
+
set_callback :checkin, :after, :enable_lazy_transactions!
|
87
|
+
|
83
88
|
def self.type_cast_config_to_integer(config)
|
84
89
|
if config.is_a?(Integer)
|
85
90
|
config
|
86
|
-
elsif config
|
91
|
+
elsif SIMPLE_INT.match?(config)
|
87
92
|
config.to_i
|
88
93
|
else
|
89
94
|
config
|
@@ -98,6 +103,19 @@ module ActiveRecord
|
|
98
103
|
end
|
99
104
|
end
|
100
105
|
|
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
|
118
|
+
|
101
119
|
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
102
120
|
super()
|
103
121
|
|
@@ -106,11 +124,10 @@ module ActiveRecord
|
|
106
124
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
107
125
|
@logger = logger
|
108
126
|
@config = config
|
109
|
-
@pool =
|
127
|
+
@pool = ActiveRecord::ConnectionAdapters::NullPool.new
|
110
128
|
@idle_since = Concurrent.monotonic_time
|
111
|
-
@schema_cache = SchemaCache.new self
|
112
|
-
@quoted_column_names, @quoted_table_names = {}, {}
|
113
129
|
@visitor = arel_visitor
|
130
|
+
@statements = build_statement_pool
|
114
131
|
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
115
132
|
|
116
133
|
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
@@ -119,6 +136,22 @@ module ActiveRecord
|
|
119
136
|
else
|
120
137
|
@prepared_statements = false
|
121
138
|
end
|
139
|
+
|
140
|
+
@advisory_locks_enabled = self.class.type_cast_config_to_boolean(
|
141
|
+
config.fetch(:advisory_locks, true)
|
142
|
+
)
|
143
|
+
end
|
144
|
+
|
145
|
+
def replica?
|
146
|
+
@config[:replica] || false
|
147
|
+
end
|
148
|
+
|
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
|
122
155
|
end
|
123
156
|
|
124
157
|
def migrations_paths # :nodoc:
|
@@ -126,19 +159,49 @@ module ActiveRecord
|
|
126
159
|
end
|
127
160
|
|
128
161
|
def migration_context # :nodoc:
|
129
|
-
MigrationContext.new(migrations_paths)
|
162
|
+
MigrationContext.new(migrations_paths, schema_migration)
|
163
|
+
end
|
164
|
+
|
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
|
178
|
+
end
|
179
|
+
|
180
|
+
def prepared_statements
|
181
|
+
@prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
|
182
|
+
end
|
183
|
+
|
184
|
+
def prepared_statements_disabled_cache # :nodoc:
|
185
|
+
Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
|
130
186
|
end
|
131
187
|
|
132
188
|
class Version
|
133
189
|
include Comparable
|
134
190
|
|
135
|
-
|
191
|
+
attr_reader :full_version_string
|
192
|
+
|
193
|
+
def initialize(version_string, full_version_string = nil)
|
136
194
|
@version = version_string.split(".").map(&:to_i)
|
195
|
+
@full_version_string = full_version_string
|
137
196
|
end
|
138
197
|
|
139
198
|
def <=>(version_string)
|
140
199
|
@version <=> version_string.split(".").map(&:to_i)
|
141
200
|
end
|
201
|
+
|
202
|
+
def to_s
|
203
|
+
@version.join(".")
|
204
|
+
end
|
142
205
|
end
|
143
206
|
|
144
207
|
def valid_type?(type) # :nodoc:
|
@@ -148,7 +211,7 @@ module ActiveRecord
|
|
148
211
|
# this method must only be called while holding connection pool's mutex
|
149
212
|
def lease
|
150
213
|
if in_use?
|
151
|
-
msg = "Cannot lease connection, "
|
214
|
+
msg = +"Cannot lease connection, "
|
152
215
|
if @owner == Thread.current
|
153
216
|
msg << "it is already leased by the current thread."
|
154
217
|
else
|
@@ -161,9 +224,13 @@ module ActiveRecord
|
|
161
224
|
@owner = Thread.current
|
162
225
|
end
|
163
226
|
|
227
|
+
def schema_cache
|
228
|
+
@pool.get_schema_cache(self)
|
229
|
+
end
|
230
|
+
|
164
231
|
def schema_cache=(cache)
|
165
232
|
cache.connection = self
|
166
|
-
@
|
233
|
+
@pool.set_schema_cache(cache)
|
167
234
|
end
|
168
235
|
|
169
236
|
# this method must only be called while holding connection pool's mutex
|
@@ -202,10 +269,10 @@ module ActiveRecord
|
|
202
269
|
end
|
203
270
|
|
204
271
|
def unprepared_statement
|
205
|
-
|
272
|
+
cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
|
206
273
|
yield
|
207
274
|
ensure
|
208
|
-
|
275
|
+
cache&.delete(object_id)
|
209
276
|
end
|
210
277
|
|
211
278
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
@@ -214,6 +281,11 @@ module ActiveRecord
|
|
214
281
|
self.class::ADAPTER_NAME
|
215
282
|
end
|
216
283
|
|
284
|
+
# Does the database for this adapter exist?
|
285
|
+
def self.database_exists?(config)
|
286
|
+
raise NotImplementedError
|
287
|
+
end
|
288
|
+
|
217
289
|
# Does this adapter support DDL rollbacks in transactions? That is, would
|
218
290
|
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
219
291
|
def supports_ddl_transactions?
|
@@ -241,6 +313,10 @@ module ActiveRecord
|
|
241
313
|
false
|
242
314
|
end
|
243
315
|
|
316
|
+
def supports_partitioned_indexes?
|
317
|
+
false
|
318
|
+
end
|
319
|
+
|
244
320
|
# Does this adapter support index sort order?
|
245
321
|
def supports_index_sort_order?
|
246
322
|
false
|
@@ -292,12 +368,18 @@ module ActiveRecord
|
|
292
368
|
def supports_foreign_keys_in_create?
|
293
369
|
supports_foreign_keys?
|
294
370
|
end
|
371
|
+
deprecate :supports_foreign_keys_in_create?
|
295
372
|
|
296
373
|
# Does this adapter support views?
|
297
374
|
def supports_views?
|
298
375
|
false
|
299
376
|
end
|
300
377
|
|
378
|
+
# Does this adapter support materialized views?
|
379
|
+
def supports_materialized_views?
|
380
|
+
false
|
381
|
+
end
|
382
|
+
|
301
383
|
# Does this adapter support datetime with precision?
|
302
384
|
def supports_datetime_with_precision?
|
303
385
|
false
|
@@ -322,6 +404,7 @@ module ActiveRecord
|
|
322
404
|
def supports_multi_insert?
|
323
405
|
true
|
324
406
|
end
|
407
|
+
deprecate :supports_multi_insert?
|
325
408
|
|
326
409
|
# Does this adapter support virtual columns?
|
327
410
|
def supports_virtual_columns?
|
@@ -333,6 +416,35 @@ module ActiveRecord
|
|
333
416
|
false
|
334
417
|
end
|
335
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
|
447
|
+
|
336
448
|
# This is meant to be implemented by the adapters that support extensions
|
337
449
|
def disable_extension(name)
|
338
450
|
end
|
@@ -341,6 +453,10 @@ module ActiveRecord
|
|
341
453
|
def enable_extension(name)
|
342
454
|
end
|
343
455
|
|
456
|
+
def advisory_locks_enabled? # :nodoc:
|
457
|
+
supports_advisory_locks? && @advisory_locks_enabled
|
458
|
+
end
|
459
|
+
|
344
460
|
# This is meant to be implemented by the adapters that support advisory
|
345
461
|
# locks
|
346
462
|
#
|
@@ -406,6 +522,9 @@ module ActiveRecord
|
|
406
522
|
#
|
407
523
|
# Prevent @connection's finalizer from touching the socket, or
|
408
524
|
# otherwise communicating with its server, when it is collected.
|
525
|
+
if schema_cache.connection == self
|
526
|
+
schema_cache.connection = nil
|
527
|
+
end
|
409
528
|
end
|
410
529
|
|
411
530
|
# Reset the state of this connection, directing the DBMS to clear
|
@@ -418,11 +537,9 @@ module ActiveRecord
|
|
418
537
|
# this should be overridden by concrete adapters
|
419
538
|
end
|
420
539
|
|
421
|
-
|
422
|
-
# Clear any caching the database adapter may be doing, for example
|
423
|
-
# clearing the prepared statement cache. This is database specific.
|
540
|
+
# Clear any caching the database adapter may be doing.
|
424
541
|
def clear_cache!
|
425
|
-
|
542
|
+
@lock.synchronize { @statements.clear } if @statements
|
426
543
|
end
|
427
544
|
|
428
545
|
# Returns true if its required to reload the connection between requests for development mode.
|
@@ -444,18 +561,25 @@ module ActiveRecord
|
|
444
561
|
# This is useful for when you need to call a proprietary method such as
|
445
562
|
# PostgreSQL's lo_* methods.
|
446
563
|
def raw_connection
|
564
|
+
disable_lazy_transactions!
|
447
565
|
@connection
|
448
566
|
end
|
449
567
|
|
450
|
-
def
|
451
|
-
|
568
|
+
def default_uniqueness_comparison(attribute, value, klass) # :nodoc:
|
569
|
+
attribute.eq(value)
|
452
570
|
end
|
453
571
|
|
454
|
-
def
|
572
|
+
def case_sensitive_comparison(attribute, value) # :nodoc:
|
573
|
+
attribute.eq(value)
|
574
|
+
end
|
575
|
+
|
576
|
+
def case_insensitive_comparison(attribute, value) # :nodoc:
|
577
|
+
column = column_for_attribute(attribute)
|
578
|
+
|
455
579
|
if can_perform_case_insensitive_comparison_for?(column)
|
456
|
-
|
580
|
+
attribute.lower.eq(attribute.relation.lower(value))
|
457
581
|
else
|
458
|
-
|
582
|
+
attribute.eq(value)
|
459
583
|
end
|
460
584
|
end
|
461
585
|
|
@@ -470,17 +594,36 @@ module ActiveRecord
|
|
470
594
|
end
|
471
595
|
|
472
596
|
def column_name_for_operation(operation, node) # :nodoc:
|
473
|
-
|
474
|
-
end
|
475
|
-
|
476
|
-
def column_name_from_arel_node(node) # :nodoc:
|
477
|
-
visitor.accept(node, Arel::Collectors::SQLString.new).value
|
597
|
+
visitor.compile(node)
|
478
598
|
end
|
479
599
|
|
480
600
|
def default_index_type?(index) # :nodoc:
|
481
601
|
index.using.nil?
|
482
602
|
end
|
483
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"
|
612
|
+
end
|
613
|
+
|
614
|
+
"INSERT #{insert.into} #{insert.values_list}"
|
615
|
+
end
|
616
|
+
|
617
|
+
def get_database_version # :nodoc:
|
618
|
+
end
|
619
|
+
|
620
|
+
def database_version # :nodoc:
|
621
|
+
schema_cache.database_version
|
622
|
+
end
|
623
|
+
|
624
|
+
def check_version # :nodoc:
|
625
|
+
end
|
626
|
+
|
484
627
|
private
|
485
628
|
def type_map
|
486
629
|
@type_map ||= Type::TypeMap.new.tap do |mapping|
|
@@ -555,14 +698,12 @@ module ActiveRecord
|
|
555
698
|
$1.to_i if sql_type =~ /\((.*)\)/
|
556
699
|
end
|
557
700
|
|
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
|
701
|
+
def translate_exception_class(e, sql, binds)
|
702
|
+
message = "#{e.class.name}: #{e.message}"
|
564
703
|
|
565
|
-
exception = translate_exception(
|
704
|
+
exception = translate_exception(
|
705
|
+
e, message: message, sql: sql, binds: binds
|
706
|
+
)
|
566
707
|
exception.set_backtrace e.backtrace
|
567
708
|
exception
|
568
709
|
end
|
@@ -575,24 +716,23 @@ module ActiveRecord
|
|
575
716
|
binds: binds,
|
576
717
|
type_casted_binds: type_casted_binds,
|
577
718
|
statement_name: statement_name,
|
578
|
-
connection_id: object_id
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
end
|
583
|
-
rescue => e
|
584
|
-
raise translate_exception_class(e, sql)
|
719
|
+
connection_id: object_id,
|
720
|
+
connection: self) do
|
721
|
+
@lock.synchronize do
|
722
|
+
yield
|
585
723
|
end
|
724
|
+
rescue => e
|
725
|
+
raise translate_exception_class(e, sql, binds)
|
586
726
|
end
|
587
727
|
end
|
588
728
|
|
589
|
-
def translate_exception(exception, message)
|
729
|
+
def translate_exception(exception, message:, sql:, binds:)
|
590
730
|
# override in derived class
|
591
731
|
case exception
|
592
732
|
when RuntimeError
|
593
733
|
exception
|
594
734
|
else
|
595
|
-
ActiveRecord::StatementInvalid.new(message)
|
735
|
+
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
596
736
|
end
|
597
737
|
end
|
598
738
|
|
@@ -606,6 +746,11 @@ module ActiveRecord
|
|
606
746
|
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
607
747
|
end
|
608
748
|
|
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
|
+
|
609
754
|
def collector
|
610
755
|
if prepared_statements
|
611
756
|
Arel::Collectors::Composite.new(
|
@@ -623,6 +768,9 @@ module ActiveRecord
|
|
623
768
|
def arel_visitor
|
624
769
|
Arel::Visitors::ToSql.new(self)
|
625
770
|
end
|
771
|
+
|
772
|
+
def build_statement_pool
|
773
|
+
end
|
626
774
|
end
|
627
775
|
end
|
628
776
|
end
|