Skip to content

Bind literals in dictionary queries (all_*) instead of relying on cursor_sharing = force #2628

@yahonda

Description

@yahonda

Background

The adapter's schema introspection code (in lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb and friends) issues queries against Oracle's data dictionary (all_tab_columns, all_indexes, all_constraints, all_synonyms, all_objects, ...) with owner / table / column names embedded as literals, not as bind variables. Example shape (paraphrased):

select_value("SELECT column_name FROM all_tab_columns WHERE owner = '#{owner}' AND table_name = '#{table_name}'")

Because each unique (owner, table) combination produces a distinct SQL text, the server creates a separate cursor in the shared pool for each one. For installs with very large schemas this can put measurable pressure on the shared pool.

Why this matters now

Historically the adapter mitigated this with cursor_sharing = force set as a session default — the server then rewrote literals into system-generated bind variables (:"SYS_B_0" ...) and shared the cursors. #2626 removes that default because it was the trigger for the #2619 hang on amd64 servers under prepared statements + RETURNING. Once #2626 lands, dictionary queries are no longer protected by that session-level workaround.

The architecturally correct fix is to bind the literals at the call sites instead of relying on a session-level switch. That works regardless of cursor_sharing setting and does not depend on the user opting into anything.

Scope

  • Identify all dictionary queries in lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb, connection.rb, and any related files that interpolate owner/table/column/sequence/etc. names as literals.
  • Convert them to use bind parameters (:owner, :table_name, ...) where the surrounding select_* API supports binds.
  • Verify with v$sql.sql_text that distinct invocations share a cursor (i.e., the SQL text contains the bind names rather than the literal values).

Out of scope

Acceptance criteria

  • All all_* / user_* queries in adapter code use binds for owner/table/column names where applicable.
  • Spec assertion that the same dictionary query, called twice with different table_names, produces a single shared cursor on the server (queryable via v$sql).
  • No behavior change for cursor_sharing: 'force' users (the binds path also benefits them — they just get a single shared cursor either way).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions