Skip to content

Commit

Permalink
Allow unmanaged autogenerated sequence names
Browse files Browse the repository at this point in the history
To still support primary keys through db triggers, without adding back in
support for generating and maintaining them with migrations, add an
configuration boolen:

    unmanaged_autogenerated_sequences = false # default

Which can be used in an initializer file. When set to `true` there will not be
an exception raised when the sequence name is defined in the model with the
previously supported value:

   self.sequence_name = :autogenerated

This option allows for dbs managed outside of the application to use triggers
for primary keys. Without the `autogenerated` option an error is raised when
inserting the record:

    ORA-02289: sequence does not exist
  • Loading branch information
the-undefined authored and matthewtusker committed Jul 6, 2023
1 parent cb82744 commit eb2e63d
Showing 1 changed file with 13 additions and 0 deletions.
13 changes: 13 additions & 0 deletions lib/active_record/connection_adapters/oracle_enhanced_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,17 @@ class OracleEnhancedAdapter < AbstractAdapter
cattr_accessor :default_sequence_start_value
self.default_sequence_start_value = 1

##
# :singleton-method:
# By default trigger based sequences are not supported.
# Enable this if you wish to manage your own primary key triggers, then you can avoid an
# exception being raised when using autogenerated sequence names in your ActiveRecord models:
#
# self.sequence_name = :autogenerated
#
cattr_accessor :unmanaged_autogenerated_sequences
self.unmanaged_autogenerated_sequences = false

##
# :singleton-method:
# By default, OracleEnhanced adapter will use longer 128 bytes identifier
Expand Down Expand Up @@ -475,8 +486,10 @@ def discard!
# called directly; used by ActiveRecord to get the next primary key value
# when inserting a new database record (see #prefetch_primary_key?).
def next_sequence_value(sequence_name)
return nil if unmanaged_autogenerated_sequences
# if sequence_name is set to :autogenerated then it means that primary key will be populated by trigger
raise ArgumentError "Trigger based primary key is not supported" if sequence_name == AUTOGENERATED_SEQUENCE_NAME

# call directly connection method to avoid prepared statement which causes fetching of next sequence value twice
select_value(<<~SQL.squish, "SCHEMA")
SELECT #{quote_table_name(sequence_name)}.NEXTVAL FROM dual
Expand Down

0 comments on commit eb2e63d

Please sign in to comment.