123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::ConnectionAdapters::RactorConnectionHandler::AbstractProxyAdapter

Do not use. This class is for internal use only.

Constant Summary

::ActiveSupport::Callbacks - Included

CALLBACK_FILTER_TYPES

::ActiveRecord::ConnectionAdapters::SchemaStatements - Included

EMPTY_METADATA

::ActiveRecord::ConnectionAdapters::DatabaseStatements - Included

DEFAULT_INSERT_VALUE, HIGH_PRECISION_CURRENT_TIMESTAMP, TRANSACTION_ISOLATION_LEVELS

::ActiveRecord::ConnectionAdapters::AbstractAdapter - Inherited

ADAPTER_NAME, COMMENT_REGEX, DEFAULT_READ_QUERY, EXTENDED_TYPE_MAPS, MAX_JITTER, SIMPLE_INT, TYPE_MAP

Class Attribute Summary

::ActiveRecord::ConnectionAdapters::AbstractAdapter - Inherited

.__callbacks,
.migration_strategy

Allows configuration of migration strategy per adapter type.

.migration_strategy?

Class Method Summary

Instance Attribute Summary

::ActiveRecord::ConnectionAdapters::AbstractAdapter - Inherited

#__callbacks,
#active?

Checks whether the connection to the database is still active.

#connected?

Checks whether the connection to the database was established.

#database_exists?,
#in_use?
#lock, #logger, #migration_strategy, #migration_strategy?, #owner, #pool, #pool=,
#prepared_statements
#preventing_writes?

Determines whether writes are currently being prevented.

#replica?,
#requires_reloading?

Returns true if its required to reload the connection between requests for development mode.

#savepoint_errors_invalidate_transactions?

Do TransactionRollbackErrors on savepoints affect the parent transaction?

#sql_notifications?,
#supports_advisory_locks?

Does this adapter support application-enforced advisory locking?

#supports_bulk_alter?,
#supports_check_constraints?

Does this adapter support creating check constraints?

#supports_comments?

Does this adapter support metadata comments on database objects (tables, columns, indexes)?

#supports_comments_in_create?

Can comments for tables, columns, and indexes be specified in create/alter table statements?

#supports_common_table_expressions?, #supports_concurrent_connections?, #supports_datetime_with_precision?,
#supports_ddl_transactions?

Does this adapter support DDL rollbacks in transactions? That is, would CREATE TABLE or ALTER TABLE get rolled back by a transaction?

#supports_deferrable_constraints?

Does this adapter support creating deferrable constraints?

#supports_disabling_indexes?,
#supports_enforced_foreign_keys?

Does this adapter support NOT ENFORCED foreign key constraints?

#supports_exclusion_constraints?

Does this adapter support creating exclusion constraints?

#supports_explain?

Does this adapter support explain?

#supports_expression_index?

Does this adapter support expression indices?

#supports_extensions?

Does this adapter support database extensions?

#supports_foreign_keys?

Does this adapter support creating foreign key constraints?

#supports_foreign_tables?

Does this adapter support foreign/external tables?

#supports_index_include?

Does this adapter support including non-key columns?

#supports_index_sort_order?

Does this adapter support index sort order?

#supports_indexes_in_create?

Does this adapter support creating indexes in the same statement as creating the table?

#supports_insert_conflict_target?, #supports_insert_on_duplicate_skip?, #supports_insert_on_duplicate_update?, #supports_insert_returning?,
#supports_json?

Does this adapter support JSON data type?

#supports_lazy_transactions?,
#supports_materialized_views?

Does this adapter support materialized views?

#supports_nulls_not_distinct?,
#supports_optimizer_hints?

Does this adapter support optimizer hints?

#supports_partial_index?

Does this adapter support partial indices?

#supports_partitioned_indexes?, #supports_restart_db_transaction?,
#supports_savepoints?

Does this adapter support savepoints?

#supports_transaction_isolation?

Does this adapter support setting the isolation level for a transaction?

#supports_unique_constraints?

Does this adapter support creating unique constraints?

#supports_update_returning?,
#supports_validate_constraints?

Does this adapter support creating invalid constraints?

#supports_views?

Does this adapter support views?

#supports_virtual_columns?

Does this adapter support virtual columns?

#visitor, #reconnect_can_restore_state?, #advisory_locks_enabled?, #allow_preconnect, #allow_preconnect=, #async_enabled?, #lock_thread=, #needs_reconnect?, #pinned,
#proxied=

When true, this connection is the backend of a ractor proxy connection.

#proxied?, #verified?

::ActiveRecord::ConnectionAdapters::DatabaseStatements - Included

::ActiveRecord::ConnectionAdapters::SchemaStatements - Included

Instance Method Summary

Proxy - Included

#boundary_safe_bind

Attribute types may close over procs, so the database value is resolved locally.

#checkin_all_connections

For supervisors tearing down worker Ractors, which cannot release their own tokens when they die.

#checkin_token, #connection_pinned?, #discard_token, #dump_binds, #dump_column_types, #dump_object,
#main_operation

Proxy work to the main ractor.

#remove_token

::ActiveRecord::ConnectionAdapters::AbstractAdapter - Inherited

#adapter_name

Returns the human-readable name of the adapter.

#check_all_foreign_keys_valid!

Override to check all foreign key constraints in a database.

#clear_cache!

Clear any caching the database adapter may be doing.

#close

Check the connection back in to the connection pool.

#connect!, #connection_retries, #default_timezone,
#disable_extension

This is meant to be implemented by the adapters that support extensions.

#disable_referential_integrity

Override to turn off referential integrity while executing &block.

#discard!

Immediately forget this connection ever existed.

#disconnect!

Disconnects from the database if already connected.

#enable_extension

This is meant to be implemented by the adapters that support extensions.

#extensions

A list of extensions, to be filled in by adapters that support them.

#index_algorithms

A list of index algorithms, to be filled by adapters that support them.

#lease

this method must only be called while holding connection pool's mutex.

#max_jitter, #pool_jitter,
#prefetch_primary_key?

Should primary key values be selected from their corresponding sequence before the insert statement? If true, next_sequence_value is called before each insert to set the record's primary key.

#prepared_statements?,
#raw_connection

Provides access to the underlying database driver for this adapter.

#reconnect!

Disconnects from the database if already connected, and establishes a new connection with the database.

#reset!

Reset the state of this connection, directing the DBMS to clear transactions and other connection-related server-side state.

#retry_deadline, #return_value_after_update?,
#role

The role (e.g. :writing) for the current connection.

#schema_cache,
#schema_version

Returns the version identifier of the schema currently available in the database.

#shard

The shard (e.g. :default) for the current connection.

#throw_away!

Removes the connection from the pool and disconnect it.

#unprepared_statement, #verify,
#verify!

Checks whether the connection to the database is still active (i.e. not stale).

#verify_timeout,
#any_raw_connection

Returns a raw connection for internal use with methods that are known to both be thread-safe and not rely upon actual server communication.

#arel_visitor, #attempt_configure_connection, #backoff, #build_retry_budget, #build_statement_pool, #can_perform_case_insensitive_comparison_for?, #collector, #column_for, #column_for_attribute,
#configure_connection

Perform any necessary initialization upon the newly-established connection settings, run queries to configure any application-global "session" variables, etc.

#default_prepared_statements,
#ensure_connection_ready

Ensure the connection is ready to execute a query.

#extended_type_map_key, #invalidate_transaction, #log, #reconnect, #retryable_connection_error?, #retryable_query_error?,
#skip_verification?

Decide whether the connection can be used without verification.

#translate_exception, #translate_exception_class, #type_map,
#valid_raw_connection

Similar to any_raw_connection, but ensures it is validated and connected.

#verified!

Mark the connection as verified.

#warning_ignored?,
#with_raw_connection

Lock the monitor, ensure we're properly connected and transactions are materialized, and then yield the underlying raw connection object.

#add_enum_value

This is meant to be implemented by the adapters that support custom enum types.

#attempt_retry

Consume from budget if exception warrants another attempt.

#build_insert_sql

Called by ::ActiveRecord::InsertAll, Passed an instance of ::ActiveRecord::InsertAll::Builder, This method implements standard bulk inserts for all databases, but should be overridden by adapters to implement common features with non-standard syntax like handling duplicates or returning values.

#case_insensitive_comparison, #case_sensitive_comparison, #check_version, #clean!,
#connection_age

Seconds since this connection was established.

#connection_descriptor,
#create_enum

This is meant to be implemented by the adapters that support custom enum types.

#create_or_find_by_lock

Lock used to read an existing record after a duplicate INSERT in a transaction.

#create_virtual_table

This is meant to be implemented by the adapters that support virtual tables.

#database_version, #default_index_type?, #downgrade_connection_after_error,
#drop_enum

This is meant to be implemented by the adapters that support custom enum types.

#drop_virtual_table

This is meant to be implemented by the adapters that support virtual tables.

#expire

this method must only be called while holding connection pool's mutex.

#force_retirement

Mark the connection as needing to be retired, as if the age has exceeded the maximum allowed.

#get_advisory_lock

This is meant to be implemented by the adapters that support advisory locks.

#get_database_version, #inspect, #native_database_types, #prepared_statements_disabled_cache, #ractor_connection_capabilities, #ractor_connection_profile,
#release_advisory_lock

This is meant to be implemented by the adapters that support advisory locks.

#rename_enum

This is meant to be implemented by the adapters that support custom enum types.

#rename_enum_value

This is meant to be implemented by the adapters that support custom enum types.

#retryable_failure?, #return_value_after_insert?,
#seconds_idle

Seconds since this connection was returned to the pool.

#seconds_since_last_activity

Seconds since this connection last communicated with the server.

#steal!

this method must only be called while holding connection pool's mutex (and a desire for segfaults).

#valid_type?, #instrumenter

::ActiveRecord::ConnectionAdapters::Savepoints - Included

::ActiveRecord::ConnectionAdapters::DatabaseLimits - Included

#index_name_length

Returns the maximum length of an index name.

#table_alias_length

Returns the maximum length of a table alias.

#table_name_length

Returns the maximum length of a table name.

#bind_params_length, #max_identifier_length

::ActiveRecord::ConnectionAdapters::Quoting - Included

#quote

Quotes the column value to help preventSQL injection attacks.

#quote_column_name

Quotes the column name.

#quote_string

Quotes a string, escaping any ' (single quote) and \ (backslash) characters.

#quote_table_name

Quotes the table name.

#quote_table_name_for_assignment

Override to return the quoted table name for assignment.

#quoted_date

Quote date/time values for use in SQL input.

#quoted_false, #quoted_true,
#type_cast

Cast a value to a type that the database understands.

#unquoted_false, #unquoted_true,
#cast_bound_value

Cast a value to be used as a bound parameter of unknown type.

#lookup_cast_type, #quote_default_expression, #quoted_binary, #quoted_time, #sanitize_as_sql_comment, #type_casted_binds

::ActiveRecord::ConnectionAdapters::DatabaseStatements - Included

#add_transaction_record

Register a record with the current transaction so that its after_commit and after_rollback callbacks can be called.

#begin_db_transaction

Begins the transaction (and turns off auto-committing).

#begin_isolated_db_transaction

Begins the transaction with the isolation level set.

#commit_db_transaction

Commits the transaction (and turns on auto-committing).

#create
#default_sequence_name,
#delete

Executes the delete statement and returns the number of rows affected.

#disable_lazy_transactions!, #empty_insert_statement_value, #enable_lazy_transactions!,
#exec_delete

Executes delete sql statement in the context of this connection using binds as the bind substitutes.

#exec_insert

Executes insert sql statement in the context of this connection using binds as the bind substitutes.

#exec_query

Executes sql statement in the context of this connection using binds as the bind substitutes.

#exec_update

Executes update sql statement in the context of this connection using binds as the bind substitutes.

#execute

Executes the SQL statement in the context of this connection and returns the raw result from the connection adapter.

#high_precision_current_timestamp

Returns an ::Arel SQL literal for the CURRENT_TIMESTAMP for usage with arbitrary precision date/time columns.

#initialize,
#insert

Executes an INSERT query and returns the new record's ID.

#insert_fixture

Inserts the given fixture into the table.

#insert_fixtures_set,
#reset_isolation_level

Hook point called after an isolated DB transaction is committed or rolled back.

#reset_sequence!

Set the sequence to the max value of the table's column.

#restart_db_transaction,
#rollback_db_transaction

Rolls back the transaction (and turns on auto-committing).

#rollback_to_savepoint,
#select_all

Returns an ::ActiveRecord::Result instance.

#select_one

Returns a record hash with the column names as keys and column values as values.

#select_rows

Returns an array of arrays containing the field values.

#select_value

Returns a single value from a record.

#select_values

Returns an array of the values of the first column in a select:

#to_sql,
#transaction

Runs the given block in a database transaction, and returns the result of the block.

#transaction_isolation_levels,
#truncate

Executes the truncate statement.

#update

Executes the update statement and returns the number of rows affected.

#write_query?

Determines whether the SQL statement is a write query.

#affected_rows, #apply_returning_to!, #arel_from_relation, #build_delete_from_statements, #build_fixture_sql, #build_fixture_statements, #build_truncate_statement, #build_truncate_statements,
#cast_result

Receive a native adapter result object and returns an ::ActiveRecord::Result object.

#collect_warnings, #combine_multi_statements, #extract_table_ref_from_insert_sql, #internal_build_intent, #last_inserted_id, #perform_query, #primary_key_for_insert,
#raw_intent_last_inserted_id

The last inserted id computed eagerly for a raw intent: the raw driver result cannot cross the Ractor boundary, so it is read before the response is marshaled.

#returning_column_values, #single_value_from_rows, #table_ref_for_insert, #_exec_insert, #begin_deferred_transaction, #begin_savepoint_transaction,
#cacheable_query

This is used in the ::ActiveRecord::StatementCache object.

#commit_savepoint_transaction, #default_insert_value, #empty_all_tables, #exec_insert_all, #exec_restart_db_transaction, #exec_rollback_db_transaction,
#execute_batch

Executes SQL statements in the context of this connection without returning a result.

#execute_intent

Lowest-level abstract execution of a query, called only from the intent itself.

#execute_raw_intent

Executes intent below the public query pipeline — no logging or query transformers — and materializes the outcome.

#explain, #finalize_remaining_intents, #finish_intent_log, #handle_warnings, #perform_sync_attempt, #query_all, #query_command, #query_one, #query_rows, #query_value, #query_values, #reset_transaction, #rollback_savepoint_transaction, #start_intent_log, #tables_to_truncate, #to_sql_and_binds, #truncate_tables,
#update_with_result

Executes the update statement and returns an ::ActiveRecord::Result Some adapters support the returning keyword argument.

#with_yaml_fallback

::ActiveRecord::Fixture value is quoted by ::Arel, however scalar values are not quotable.

::ActiveRecord::ConnectionAdapters::SchemaStatements - Included

#add_belongs_to
#add_check_constraint

Adds a new check constraint to the table.

#add_column

Add a new type column named column_name to table_name.

#add_foreign_key

Adds a new foreign key.

#add_index

Adds a new index to the table.

#add_reference

Adds a reference.

#add_timestamps

Adds timestamps (created_at and updated_at) columns to table_name.

#assume_migrated_upto_version,
#build_create_table_definition

Returns a ::ActiveRecord::ConnectionAdapters::TableDefinition object containing information about the table that would be created if the same arguments were passed to #create_table.

#change_column

Changes the column's definition according to the new options.

#change_column_comment

Changes the comment for a column or removes it if nil.

#change_column_default

Sets a new default value for a column:

#change_column_null

Sets or removes a NOT NULL constraint on a column.

#change_foreign_key

Changes an existing foreign key on a table.

#change_table

A block for changing columns in table.

#change_table_comment

Changes the comment for a table or removes it if nil.

#check_constraint_exists?

Checks to see if a check constraint exists on a table for a given check constraint definition.

#check_constraints

Returns an array of check constraints for the given table, or a ::Hash of them keyed by table name when given an ::Array of tables.

#column_exists?

Checks to see if a column exists in a given table.

#columns

Returns an array of ::ActiveRecord::ConnectionAdapters::Column objects for the given table, or a ::Hash of them keyed by table name when given an ::Array of tables.

#create_join_table

Creates a new join table with the name created using the lexical order of the first two arguments.

#create_table

Creates a new table with the name table_name.

#data_source_exists?

Checks to see if the data source name exists on the database.

#data_sources

Returns the relation names usable to back Active Record models.

#disable_index

Prevents an index from being used by queries.

#drop_join_table

Drops the join table specified by the given arguments.

#drop_table

Drops a table or tables from the database.

#enable_index

Enables an index to be used by queries.

#foreign_key_exists?

Checks to see if a foreign key exists on a table for a given foreign key definition.

#foreign_keys

Returns an array of foreign keys for the given table, or a ::Hash of them keyed by table name when given an ::Array of tables.

#index_exists?

Checks to see if an index exists on a table for a given index definition.

#index_name_exists?

Verifies the existence of an index with a given name.

#indexes

Returns an array of indexes for the given table, or a ::Hash of them keyed by table name when given an ::Array of tables.

#max_index_name_size

Returns the maximum length of an index name in bytes.

#native_database_types

Returns a hash of mappings from the abstract data types to the native database types.

#options_include_default?,
#primary_key

Returns just a table's primary key.

#remove_belongs_to
#remove_check_constraint

Removes the given check constraint from the table.

#remove_column

Removes the column from the table definition.

#remove_columns

Removes the given columns from the table definition.

#remove_foreign_key

Removes the given foreign key from the table.

#remove_index

Removes the given index from the table.

#remove_reference

Removes the reference(s).

#remove_timestamps

Removes the timestamp columns (created_at and updated_at) from the table definition.

#rename_column

Renames a column.

#rename_index

Renames an index.

#rename_table

Renames a table.

#table_alias_for

Truncates a table alias according to the limits of the current adapter.

#table_comment

Returns the table comment that's stored in database metadata.

#table_exists?

Checks to see if the table table_name exists on the database.

#table_options

Returns the options the given table was created with, or a ::Hash of them keyed by table name when given an ::Array of tables.

#tables

Returns an array of table names defined in the database.

#view_exists?

Checks to see if the view view_name exists on the database.

#views

Returns an array of view names defined in the database.

#add_index_sort_order,
#add_options_for_index_columns

Overridden by the ::ActiveRecord::ConnectionAdapters::MySQL adapter for supporting index lengths and by the ::ActiveRecord::ConnectionAdapters::PostgreSQL adapter for supporting operator classes.

#can_remove_index_by_name?, #change_column_comment_sql, #change_index_comment_sql, #change_table_comment_sql, #check_constraint_for, #check_constraint_for!, #check_constraint_name, #column_options_keys, #create_alter_table, #create_index_definition, #create_table_definition, #data_source_sql, #drop_table_sql, #execute_alter_table,
#expression_column_name?

Try to identify whether the given column name is an expression.

#extract_foreign_key_action,
#extract_new_comment_value
#extract_new_default_value,
#fetch_by_schema

One read filters by one schema, so tables naming different schemas are read a schema at a time.

#fetch_column_definitions, #fetch_table_options, #fetch_type_metadata, #foreign_key_for, #foreign_key_for!, #foreign_key_name, #generate_index_name, #has_expression_column_name?, #index_column_names, #index_name_for_remove, #index_name_options, #insert_versions_sql, #options_for_index_columns, #quoted_scope, #quoted_table_names, #reference_name_for_table, #rename_column_indexes, #rename_table_indexes, #rows_for, #strip_table_name_prefix_and_suffix, #valid_index_options, #validate_change_column_null_argument!, #validate_create_table_options!, #validate_index_length!, #validate_table_length!, #add_columns, #add_index_options,
#build_alter_table_definition

Returns an ::ActiveRecord::ConnectionAdapters::AlterTable object containing information about changes that would be made to table_name.

#build_create_index_definition
#build_create_join_table_definition

Builds a ::ActiveRecord::ConnectionAdapters::TableDefinition object for a join table.

#bulk_change_table, #check_constraint_options,
#columns_for_distinct

Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.

#compatibility_behavior_for, #create_schema_dumper, #distinct_relation_for_primary_key, #dump_schema_versions, #foreign_key_column_for, #foreign_key_options, #index_algorithm, #index_name,
#inject_legacy_primary_key_default?

Whether to inject default: nil for an integer or bigint primary key.

#internal_string_options_for_primary_key, #quoted_columns_for_index, #remove_constraint,
#schema_creation

Returns an instance of ::ActiveRecord::ConnectionAdapters::SchemaCreation, which can be used to visit a schema definition object and return DDL.

#type_to_sql, #update_table_definition, #valid_column_definition_options, #valid_primary_key_options, #valid_table_definition_options

::ActiveSupport::Callbacks - Included

#run_callbacks

Runs the callbacks for the given event.

#halted_callback_hook

A hook invoked every time a before callback is halted.

Constructor Details

.new(pool, connection_token, profile, config) ⇒ AbstractProxyAdapter

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 22

def initialize(pool, connection_token, profile, config)
  @adapter_profile = profile
  super(nil, PLACEHOLDER_LOGGER, nil, config)
  @connection_token = connection_token
  @logger = nil
  @pool = pool
  @prepared_statements = profile[:prepared_statements]
  @main_transaction_manager_id = nil
  @capabilities = profile[:capabilities].dup
  @quoted_column_names = {}
  @quoted_table_names = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, **kwargs, &block) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 446

def method_missing(name, *args, **kwargs, &block)
  return super if name == :marshal_dump || name == :_dump

  if block
    raise ActiveRecordError, "Cannot forward a block to #{name} on the main-Ractor connection"
  end

  if PURE_REMOTE_METHOD_PATTERN.match?(name)
    remote_adapter_call(name, args, kwargs)
  else
    materialize_transactions
    remote_adapter_call(name, args, kwargs, transaction_manager_id: @main_transaction_manager_id)
  end
end

Instance Attribute Details

#active? ⇒ Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 45

def active?
  !!(@connection_token && call_main_connection(:active?))
end

#connected? ⇒ Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 41

def connected?
  !!(@connection_token && call_main_connection(:connected?))
end

#connection_token (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 39

attr_reader :connection_token # :nodoc:

#holds_main_connection? ⇒ Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 110

def holds_main_connection? # :nodoc:
  !!(@connection_token && connection_pinned?(@connection_token))
end

#restart_parent_transactions? ⇒ Boolean (readonly)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 247

def restart_parent_transactions? # :nodoc:
  false
end

#savepoint_errors_invalidate_transactions? ⇒ Boolean (readonly)

Regardless of whether the main-side connection invalidates its own transaction, we need the rollback to keep us in sync.

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 253

def savepoint_errors_invalidate_transactions? # :nodoc:
  false
end

Instance Method Details

#_exec_insert(intent, sequence_name = nil, returning: nil)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 198

def _exec_insert(intent, sequence_name = nil, returning: nil) # :nodoc:
  apply_returning_to!(intent, returning)
  intent.execute!
  intent.raw_result
end

#adapter_class (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 283

def adapter_class
  @adapter_profile[:adapter_class]
end

#adapter_name

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 35

def adapter_name
  @adapter_profile[:adapter_name]
end

#affected_rows(response) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 327

def affected_rows(response)
  response.affected_rows
end

#arel_visitor (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 267

def arel_visitor
  @adapter_profile[:arel_visitor_class].new(self)
end

#begin_db_transaction

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 204

def begin_db_transaction # :nodoc:
  begin_main_transaction(nil, true)
end

#begin_deferred_transaction(isolation_level = nil)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 212

def begin_deferred_transaction(isolation_level = nil) # :nodoc:
  begin_main_transaction(isolation_level, false)
end

#begin_isolated_db_transaction(isolation)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 208

def begin_isolated_db_transaction(isolation) # :nodoc:
  begin_main_transaction(isolation, true)
end

#begin_main_transaction(isolation, joinable) (private)

The main-side connection replaces its transaction manager whenever it resets its transactions without restoring them, so we record its identity to later notice if we get out of sync.

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 394

def begin_main_transaction(isolation, joinable)
  @main_transaction_manager_id = main_transaction_operation(nil) do |connection|
    connection.begin_transaction(isolation: isolation, joinable: joinable, _lazy: false)
    connection.transaction_manager.object_id
  end
end

#begin_savepoint_transaction(name)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 230

def begin_savepoint_transaction(name) # :nodoc:
  main_transaction_operation(@main_transaction_manager_id) do |connection|
    connection.begin_transaction(_lazy: false)
    nil
  end
end

#bind_params_length (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 271

def bind_params_length
  @adapter_profile[:bind_params_length]
end

#build_insert_sql(insert)

Raises:

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 190

def build_insert_sql(insert) # :nodoc:
  raise ActiveRecordError, "insert_all/upsert_all can only be executed on the main Ractor"
end

#build_retry_budget(allow_retry:, reconnectable:) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 263

def build_retry_budget(allow_retry:, reconnectable:)
  super(allow_retry: false, reconnectable: false)
end

#build_statement_pool (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 298

def build_statement_pool
  nil
end

#call_main_connection(method_name, args = [], kwargs = {}, transaction_manager_id: nil) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 368

def call_main_connection(method_name, args = [], kwargs = {}, transaction_manager_id: nil)
  main_args = ActiveSupport::Ractors.make_shareable(args)
  main_kwargs = ActiveSupport::Ractors.make_shareable(kwargs)

  main_transaction_operation(transaction_manager_id) do |connection|
    connection.__send__(method_name, *main_args, **main_kwargs)
  end
end

#cast_result(response) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 323

def cast_result(response)
  ActiveRecord::Result.new(response.columns, response.rows, response.column_types, affected_rows: response.affected_rows)
end

#clear_cache!(new_connection: false)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 105

def clear_cache!(new_connection: false)
  super
  remote_adapter_call(:clear_cache!, [], { new_connection: new_connection }) if @connection_token
end

#collect_warnings(response) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 331

def collect_warnings(response)
  response&.warnings
end

#columns

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 162

def columns(...)
  remote_dispatch(:columns, ...)
end

#commit_db_transaction

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 216

def commit_db_transaction # :nodoc:
  commit_main_transaction
ensure
  # Main-side transaction is gone, even if the commit failed
  @main_transaction_manager_id = nil
end

#commit_main_transaction (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 401

def commit_main_transaction
  transaction_manager_id = @main_transaction_manager_id
  main_transaction_operation(nil) do |connection|
    unless connection.transaction_manager.object_id == transaction_manager_id
      raise ConnectionNotEstablished, "Cannot commit: the Ractor-pinned connection was reset while the transaction was open, and the server rolled it back"
    end

    transaction = connection.current_transaction
    begin
      connection.commit_transaction
    rescue ConnectionFailed
      # The transaction has already gone with the connection, so there's
      # nothing to roll back.
      raise
    rescue Exception
      connection.rollback_transaction(transaction) unless transaction.state.completed?
      raise
    end
    nil
  end
end

#commit_savepoint_transaction(name)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 237

def commit_savepoint_transaction(name) # :nodoc:
  commit_main_transaction
end

#connect!

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 54

def connect!
  manage_main_connection(:connect!)
  self
end

#create_table_definition(name, **options) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 275

def create_table_definition(name, **options)
  table_definition_class.new(self, name, **options)
end

#data_source_exists? ⇒ Boolean

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 170

def data_source_exists?(...)
  remote_dispatch(:data_source_exists?, ...)
end

#data_sources

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 166

def data_sources
  remote_dispatch(:data_sources)
end

#discard!

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 73

def discard!
  if token = @connection_token
    @connection_token = nil
    discard_token(token)
  end
  reset_transaction
end

#disconnect!

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 64

def disconnect!
  # Disconnect the physical connection while maintaining the lease of that same instance.
  if @connection_token
    manage_main_connection(:disconnect!)
  else
    reset_transaction
  end
end

#ensure_connection_ready(allow_retry:, materialize_transactions:) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 258

def ensure_connection_ready(allow_retry:, materialize_transactions:)
  self.materialize_transactions if materialize_transactions
  false
end

#exec_rollback_db_transaction

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 223

def exec_rollback_db_transaction # :nodoc:
  # Already gone if this follows a failed commit
  rollback_main_transaction if @main_transaction_manager_id
ensure
  @main_transaction_manager_id = nil
end

#execute

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 194

def execute(...)
  cast_result(super)
end

#indexes

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 174

def indexes(...)
  remote_dispatch(:indexes, ...)
end

#last_inserted_id(response) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 335

def last_inserted_id(response)
  response.last_inserted_id
end

#main_transaction_operation(transaction_manager_id, &block) (private)

Yields the main-side connection on the main Ractor, first checking it still has the transaction manager identified by transaction_manager_id, if given.

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 380

def main_transaction_operation(transaction_manager_id, &block)
  unless token = @connection_token
    raise ConnectionNotEstablished, "The Ractor-pinned connection has been released"
  end

  operation = ActiveSupport::Ractors.shareable_proc(self: nil, &block)
  main_operation(connection_pool: @pool) do
    operation.call(fetch_transaction_connection(token, transaction_manager_id))
  end
end

#manage_main_connection(method_name, **kwargs) (private)

Runs a connection management method on the main-side connection. If we notice that the main transaction manager has been replaced, we reset ours to match.

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 434

def manage_main_connection(method_name, **kwargs)
  main_kwargs = ActiveSupport::Ractors.make_shareable(kwargs)
  transaction_manager_id = @main_transaction_manager_id
  kept = main_transaction_operation(nil) do |connection|
    transaction_manager = connection.transaction_manager
    connection.public_send(method_name, **main_kwargs)
    connection.transaction_manager.equal?(transaction_manager) &&
      (transaction_manager_id.nil? || transaction_manager.object_id == transaction_manager_id)
  end
  reset_transaction unless kept
end

#native_database_types

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 114

def native_database_types
  remote_adapter_call(:native_database_types)
end

#perform_query(_raw_connection, intent) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 302

def perform_query(_raw_connection, intent)
  request = QueryRequest.new(
    sql: intent.processed_sql,
    binds: intent.binds,
    name: intent.name,
    prepare: intent.prepare,
    batch: intent.batch,
    allow_retry: intent.allow_retry,
    materialize_transactions: intent.materialize_transactions,
  )

  token = @connection_token
  transaction_manager_id = @main_transaction_manager_id if intent.materialize_transactions
  response = main_operation(connection_pool: @pool) do
    request.perform(fetch_transaction_connection(token, transaction_manager_id))
  end
  intent.notification_payload[:affected_rows] = response.affected_rows
  intent.notification_payload[:row_count] = response.row_count
  response
end

#primary_key

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 178

def primary_key(...)
  remote_dispatch(:primary_key, ...)
end

#pure_remote_dispatch(method_name, *args, **kwargs, &block) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 350

def pure_remote_dispatch(method_name, *args, **kwargs, &block)
  if block
    raise ActiveRecordError, "Cannot forward a block to #{method_name} on the main-Ractor connection"
  end

  remote_adapter_call(method_name, args, kwargs)
end

#quote_column_name(name)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 122

def quote_column_name(name)
  @quoted_column_names[name] ||= remote_adapter_call(:quote_column_name, [name])
end

#quote_table_name(name)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 126

def quote_table_name(name)
  @quoted_table_names[name] ||= remote_adapter_call(:quote_table_name, [name])
end

#raw_connection

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 140

def raw_connection
  unless ActiveSupport::Ractors.main?
    raise ActiveRecordError, "The raw connection of a Ractor-proxied connection can only be accessed from the main Ractor"
  end
  unless @connection_token
    raise ConnectionNotEstablished, "The Ractor-pinned connection has been released"
  end

  disable_lazy_transactions!
  Proxy.fetch_transaction_connection(@connection_token, @main_transaction_manager_id).raw_connection
end

#reconnect!(restore_transactions: false)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 59

def reconnect!(restore_transactions: false)
  manage_main_connection(:reconnect!, restore_transactions: restore_transactions)
  self
end

#release_connection

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 91

def release_connection
  if token = @connection_token
    @connection_token = nil
    checkin_token(token)
  end
end

#remote_adapter_call(method_name, args = [], kwargs = {}, transaction_manager_id: nil) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 358

def remote_adapter_call(method_name, args = [], kwargs = {}, transaction_manager_id: nil)
  if args.empty? && kwargs.empty? && CAPABILITY_METHOD_PATTERN.match?(method_name)
    @capabilities.fetch(method_name) do
      @capabilities[method_name] = call_main_connection(method_name, args, kwargs)
    end
  else
    call_main_connection(method_name, args, kwargs, transaction_manager_id: transaction_manager_id)
  end
end

#remote_dispatch(method_name, *args, **kwargs, &block) (private)

A lazily begun worker transaction must reach the main connection before remote work that may write through it (e.g. SQLite3#add_column).

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 341

def remote_dispatch(method_name, *args, **kwargs, &block)
  if block
    raise ActiveRecordError, "Cannot forward a block to #{method_name} on the main-Ractor connection"
  end

  materialize_transactions
  remote_adapter_call(method_name, args, kwargs, transaction_manager_id: @main_transaction_manager_id)
end

#remote_schema_creation_accept(node)

Raises:

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 186

def remote_schema_creation_accept(node) # :nodoc:
  raise ActiveRecordError, "Schema statements can only be executed on the main Ractor"
end

#remove_connection

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 98

def remove_connection
  if token = @connection_token
    @connection_token = nil
    remove_token(token)
  end
end

#reset!

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 81

def reset!
  manage_main_connection(:reset!)
  self
end

#reset_transaction

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 86

def reset_transaction(...) # :nodoc:
  @main_transaction_manager_id = nil
  super
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 461

def respond_to_missing?(name, include_private = false)
  return false if name == :marshal_dump || name == :_dump

  super
end

#rollback_main_transaction (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 423

def rollback_main_transaction
  transaction_manager_id = @main_transaction_manager_id
  main_transaction_operation(nil) do |connection|
    connection.rollback_transaction if connection.transaction_manager.object_id == transaction_manager_id
    nil
  end
end

#rollback_savepoint_transaction(name)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 241

def rollback_savepoint_transaction(name) # :nodoc:
  if current_transaction.savepoint_name == name
    rollback_main_transaction
  end
end

#run_callbacks(kind, &block)

Checkout/checkin callbacks are class-level state that is not Ractor-shareable; the concrete adapter runs them main-side when the connection returns to its pool.

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 154

def run_callbacks(kind, &block) # :nodoc:
  if kind == :checkin || kind == :checkout
    block ? yield : nil
  else
    super
  end
end

#schema_creation

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 182

def schema_creation # :nodoc:
  SchemaCreationProxy.new(self)
end

#table_definition_class (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 279

def table_definition_class
  @adapter_profile[:table_definition_class]
end

#type_casted_binds(binds)

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 130

def type_casted_binds(binds)
  return [] if binds.nil? || binds.empty?

  token = @connection_token
  binds_payload = dump_binds(binds)
  main_operation(connection_pool: @pool) do
    fetch_connection(token).type_casted_binds(Marshal.load(binds_payload))
  end
end

#type_map (private)

Local casting must match the concrete adapter (e.g. SQLite3's integer limit).

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 288

def type_map
  if key = extended_type_map_key
    adapter_class::EXTENDED_TYPE_MAPS.compute_if_absent(key) do
      adapter_class.extended_type_map(**key)
    end
  else
    adapter_class::TYPE_MAP
  end
end

#valid_type?(type) ⇒ Boolean

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 118

def valid_type?(type)
  !native_database_types[type].nil?
end

#verify!

[ GitHub ]

  
# File 'activerecord/lib/active_record/connection_adapters/ractor_connection_handler/abstract_proxy_adapter.rb', line 49

def verify!
  manage_main_connection(:verify!)
  self
end