Skip to content

[Bug] Adapter 7.1.0 ignores self.sequence_name, includes ID in INSERT instead of using RETURNING ID (Rails 7.1) #2431

@TheSynthMaster

Description

@TheSynthMaster

Hi,

I'm in the process of porting a Rails 5 app to Rails 7.1.0 (using Ruby 3.4.1). Due to Oracle database requirements, I'm using the activerecord-oracle_enhanced-adapter gem, version 7.1.0.

I've encountered a persistent issue regarding primary key generation using Oracle sequences, and despite extensive debugging (with AI assistance), I haven't been able to resolve it.

Environment:

  • Rails: 7.1.0
  • Ruby: 3.4.1
  • Adapter: activerecord-oracle_enhanced-adapter 7.1.0
  • Database: Oracle 19c
  • Oracle Client: Oracle instant client 23.6.0.24.10

Scenario:

I have several tables, for example, CATEGORIES, with a primary key column named ID (Type NUMBER(10)). The primary key values are intended to be populated using a corresponding Oracle sequence, e.g., CATEGORIES_SEQ.

Crucially, there is NO database trigger (BEFORE INSERT) configured to populate the ID column from the sequence. The expectation is that the oracle-enhanced-adapter handles this automatically when self.sequence_name is set in the model.

Model Configuration (app/models/category.rb):

# Inheriting from ActiveRecord::Base in this specific model
# (Note: Tried inheriting from ApplicationRecord, but it made no difference)
class Category < ActiveRecord::Base
  # Explicitly set the sequence name
  self.sequence_name = 'CATEGORIES_SEQ'

  # Associations
  belongs_to :company
  belongs_to :service

  # Validations
  validates_presence_of :code
  validates_uniqueness_of :code, :case_sensitive => false, :scope => [:company_id, :service_id]

  # Simple callback (Note: Temporarily disabling this had no effect on the issue)
  # before_save {|category| category.code.upcase!}
end

Problem Description:

When attempting to create a new record (e.g., Category.create(attributes) or @category = Category.new(attributes); @category.save), the oracle-enhanced-adapter does not generate the expected SQL statement that omits the ID and uses the RETURNING clause.

Expected SQL Behavior:

INSERT INTO "CATEGORIES" ("CODE", "DESCRIPTION", "COMPANY_ID", "SERVICE_ID", "CREATED_AT", "UPDATED_AT", "LOCK_VERSION")
VALUES (:a1, :a2, :a3, :a4, :a5, :a6, :a7)
RETURNING "ID" INTO :returning_id

Actual SQL Behavior (Observed in Logs):

Instead, the adapter generates an SQL statement that includes the ID column in the INSERT statement, providing a seemingly arbitrary value (which is not coming from the sequence or the application code). This prevents the Oracle sequence from being used and causes the Rails model instance not to be populated with the correct, database-generated ID after saving.

-- Example from actual logs: Note the inclusion of "ID" and :a8

INSERT INTO "CATEGORIES" ("CODE", "DESCRIPTION", "CREATED_AT", "UPDATED_AT", "COMPANY_ID", "SERVICE_ID", "LOCK_VERSION", "ID")
VALUES (:a1, :a2, :a3, :a4, :a5, :a6, :a7, :a8)
-- Followed by bind parameters, where :a8 gets a value like 691, etc.
-- Example Bind Parameters: [["code", "T"], ..., ["lock_version", 0], ["id", 691]]

Consequently, after @category.save returns true, @category.id remains nil or has the incorrect value sent in the INSERT, causing subsequent operations (like redirects redirect_to @category) to fail.

Debugging Steps & Verifications Performed (None Resolved the Issue):

  • Sequence Name: Confirmed the sequence CATEGORIES_SEQ exists in the Oracle database and the name in self.sequence_name = 'CATEGORIES_SEQ' matches exactly (case-sensitive).

  • Primary Key: Confirmed the primary key column name is exactly ID in Oracle. The model does not explicitly set self.primary_key.

  • Adapter Version: Confirmed using the latest adapter version compatible with Rails 7.1 (7.1.0).

  • No Explicit ID Assignment: Thoroughly checked the application code (controllers new/create, model callbacks before_validation, before_create, after_initialize, concerns) and confirmed no code path assigns a value to category.id before saving a new record.

  • Request Parameters: Inspected incoming params in the create action; they do not contain an id key/value for the category being created.

  • Object State Before Save: Added debug logs immediately after Category.new(params) and confirmed that the object has id == nil and new_record? == true.

  • Inheritance: Changed model inheritance from ActiveRecord::Base to ApplicationRecord; this had no effect.

  • Callbacks: Temporarily removed a simple before_save callback; this had no effect.

  • Adapter Downgrade (Attempted/Considered): We considered downgrading the adapter to a ~> 7.0.x version to test for regressions, but encountered cross compatibility issues which prevented this test..

  • Database Trigger: Re-confirmed there is no BEFORE INSERT trigger on the CATEGORIES table responsible for setting the ID.

Conclusion:

Given that all standard configuration points and application-level causes seem to be ruled out, this strongly suggests a potential bug or unexpected behavior within the activerecord-oracle_enhanced-adapter version 7.1.0 (or its interaction with Rails 7.1) where the self.sequence_name directive is being ignored or misinterpreted, leading to incorrect SQL generation for new records.

Workaround:

The only way found to make saving work correctly without modifying the database structure (e.g., switching to Identity Columns, which caused other issues and is undesirable) was to implement a before_validation :set_id_from_sequence, on: :create callback in the Rails model to manually fetch the next sequence value from Oracle (SELECT CATEGORIES_SEQ.nextval FROM DUAL) and assign it to self.id. While functional, this is not ideal as it moves DB logic into the application and bypasses the adapter's intended mechanism.

Could you please look into this? Has anyone else reported similar behavior with sequences on Rails 7.1 / Adapter 7.1.0? Any insights or suggestions would be greatly appreciated.

Thanks!

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