Repository navigation
Conversation
Rails can reload virtual columns on update with `UPDATE ... RETURNING` when the adapter opts in with `supports_update_returning?` (rails/rails#48628). Oracle needs `RETURNING ... INTO` with OUT binds, which Arel cannot express, so `update_with_result` appends the clause to the compiled SQL instead of setting `returning` on the Arel statement, the same way INSERT does. - Numeric virtual columns are read back as BigDecimal so fractions are kept. - Virtual columns of other types, such as DATE, are not returned and still need a reload. - An UPDATE that matches no rows returns no rows instead of a row of nils. - `cast_result` now passes `affected_rows` to `ActiveRecord::Result`. - JDBC reads every RETURNING column from the same row instead of advancing the return result set once per column. Optimistic locking takes the regular update path in Active Record, so models with a lock column still need a reload. Fix rsim#2795 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without a length, ruby-oci8 binds a String OUT parameter with a 1333-byte buffer, so a string virtual column longer than that came back as nil. Bind it with the VARCHAR2 maximum instead. Read `row_count` after fetching, as before, so SELECTs on OCI report the number of fetched rows instead of 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Oracle visitor now renders a non-empty `returning` on INSERT, UPDATE and DELETE statements as `RETURNING <columns> INTO <placeholders>`, adding an OUT bind for each column with its type from the schema cache. Active Record's `apply_returning_to!` and `update_with_result` set `returning` on the Arel statement, so oracle-enhanced no longer rewrites the compiled SQL for them, and direct Arel callers can use `returning` too. Without prepared statements, SubstituteBinds would inline the OUT binds as NULL, so statements with `returning` keep every bind as a placeholder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Raise ArgumentError for a returning column of another table, or of a type that cannot be read back through an OUT bind, such as DATE. - Raise ArgumentError instead of NoMethodError when the target relation is not a table. - Raise for binds passed with an Arel AST in the `to_sql_and_binds` override, as Active Record does. - Use the module function `OracleEnhanced::Quoting.oracle_downcase`. - Run INSERT, UPDATE and DELETE with returning with and without prepared statements; the UPDATE also binds its WHERE value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assert the returned columns for INSERT and UPDATE too, drop an unused helper, and name a rejected attribute as table.column in the error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
yahonda
force-pushed
the
arel-returning-into
branch
from
October 24, 2026 23:47
101ee0c to
4864934
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on #2941. This branch is stacked on it, so the first two commits belong to #2941; please review the last three commits (a738cfc, fd704bd and 101ee0c) here.
The Oracle Arel visitor now renders a non-empty
returningon INSERT, UPDATE and DELETE statements as Oracle'sRETURNING <columns> INTO <placeholders>, adding an OUT bind for each column with its type from the schema cache. The adapter already reads OUT binds back after execution, so Active Record's ownapply_returning_to!andupdate_with_resultwork unchanged.Changes
OracleCommon#visit_Arel_Nodes_{Insert,Update,Delete}StatementrenderreturningasRETURNING ... INTO. A node that is not a column of the target table, such asArel.staror a column of another table, raisesArgumentError, as does a column whose type cannot be read back through an OUT bind, such as DATE.apply_returning_to!delegates Arel INSERTs to Active Record and keeps the string append only for SQL strings.SubstituteBindswould inline the OUT binds as NULL, soto_sql_and_bindskeeps every bind as a placeholder for statements withreturning.Removed
update_with_resultoverride from Refresh virtual columns on update with RETURNING ... INTO #2941 and the query cache dirtying wrapper it needed.ArgumentErrorfor Arelreturningadded in Raise for Arel statements with returning #2936.Direct Arel callers can now use
returning, which is option (a) in #2796:The specs run INSERT, UPDATE and DELETE statements like this with and without prepared statements and read the returned rows.
INSERT statements built by Active Record now use the visitor's placeholders (
:aN) instead of:returning_<column>.Tests
Full suite against rails/rails@2fe713e2e0:
ORACLE_ENHANCED_PREPARED_STATEMENTS_FALSE=1