From 2aca1d55bd7f682bdc4147b123c38df5ac3eb9b3 Mon Sep 17 00:00:00 2001 From: Brian Thoman Date: Fri, 9 Jul 2021 16:45:57 -0400 Subject: [PATCH 1/5] Add some tests --- .../oracle_enhanced/schema_statements_spec.rb | 171 +++++++++++++----- 1 file changed, 126 insertions(+), 45 deletions(-) diff --git a/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb b/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb index 83ed52919..9ffa3a143 100644 --- a/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +++ b/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb @@ -334,58 +334,58 @@ class ::TestEmployee < ActiveRecord::Base; end else expect(@conn.index_name("test_employees", column: ["first_name", "middle_name", "last_name"])).to eq( "i" + Digest::SHA1.hexdigest("index_test_employees_on_first_name_and_middle_name_and_last_name")[0, 29] - ) + ) end end end describe "rename index" do - before(:each) do - @conn = ActiveRecord::Base.connection - schema_define do - create_table :test_employees do |t| - t.string :first_name - t.string :last_name + before(:each) do + @conn = ActiveRecord::Base.connection + schema_define do + create_table :test_employees do |t| + t.string :first_name + t.string :last_name + end + add_index :test_employees, :first_name end - add_index :test_employees, :first_name + class ::TestEmployee < ActiveRecord::Base; end end - class ::TestEmployee < ActiveRecord::Base; end - end - after(:each) do - schema_define do - drop_table :test_employees + after(:each) do + schema_define do + drop_table :test_employees + end + Object.send(:remove_const, "TestEmployee") + ActiveRecord::Base.clear_cache! end - Object.send(:remove_const, "TestEmployee") - ActiveRecord::Base.clear_cache! - end - it "should raise error when current index name and new index name are identical" do - expect do - @conn.rename_index("test_employees", "i_test_employees_first_name", "i_test_employees_first_name") - end.to raise_error(ActiveRecord::StatementInvalid) - end + it "should raise error when current index name and new index name are identical" do + expect do + @conn.rename_index("test_employees", "i_test_employees_first_name", "i_test_employees_first_name") + end.to raise_error(ActiveRecord::StatementInvalid) + end - it "should raise error when new index name length is too long" do - skip if @oracle12cr2_or_higher - expect do - @conn.rename_index("test_employees", "i_test_employees_first_name", "a" * 31) - end.to raise_error(ArgumentError) - end + it "should raise error when new index name length is too long" do + skip if @oracle12cr2_or_higher + expect do + @conn.rename_index("test_employees", "i_test_employees_first_name", "a" * 31) + end.to raise_error(ArgumentError) + end - it "should raise error when current index name does not exist" do - expect do - @conn.rename_index("test_employees", "nonexist_index_name", "new_index_name") - end.to raise_error(ActiveRecord::StatementInvalid) - end + it "should raise error when current index name does not exist" do + expect do + @conn.rename_index("test_employees", "nonexist_index_name", "new_index_name") + end.to raise_error(ActiveRecord::StatementInvalid) + end - it "should rename index name with new one" do - skip if @oracle12cr2_or_higher - expect do - @conn.rename_index("test_employees", "i_test_employees_first_name", "new_index_name") - end.not_to raise_error + it "should rename index name with new one" do + skip if @oracle12cr2_or_higher + expect do + @conn.rename_index("test_employees", "i_test_employees_first_name", "new_index_name") + end.not_to raise_error + end end -end describe "ignore options for LOB columns" do after(:each) do @@ -622,9 +622,9 @@ class ::TestPost < ActiveRecord::Base index_name = @conn.select_value( "SELECT index_name FROM all_constraints - WHERE table_name = 'TEST_POSTS' - AND constraint_type = 'P' - AND owner = SYS_CONTEXT('userenv', 'current_schema')") + WHERE table_name = 'TEST_POSTS' + AND constraint_type = 'P' + AND owner = SYS_CONTEXT('userenv', 'current_schema')") expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_indexes WHERE index_name = '#{index_name}'")).to eq("USERS") end @@ -637,9 +637,9 @@ class ::TestPost < ActiveRecord::Base index_name = @conn.select_value( "SELECT index_name FROM all_constraints - WHERE table_name = 'TEST_POSTS' - AND constraint_type = 'P' - AND owner = SYS_CONTEXT('userenv', 'current_schema')") + WHERE table_name = 'TEST_POSTS' + AND constraint_type = 'P' + AND owner = SYS_CONTEXT('userenv', 'current_schema')") expect(TestPost.connection.select_value("SELECT tablespace_name FROM user_indexes WHERE index_name = '#{index_name}'")).to eq(DATABASE_NON_DEFAULT_TABLESPACE) end @@ -1046,7 +1046,7 @@ class ::TestFraction < ActiveRecord::Base it "should change virtual column definition" do schema_define do change_column :test_fractions, :percent, :virtual, - as: "ROUND((numerator/NULLIF(denominator,0))*100, 2)", type: :decimal, precision: 15, scale: 2 + as: "ROUND((numerator/NULLIF(denominator,0))*100, 2)", type: :decimal, precision: 15, scale: 2 end TestFraction.reset_column_information tf = TestFraction.columns.detect { |c| c.name == "percent" } @@ -1249,4 +1249,85 @@ class << @conn ActiveRecord::SchemaMigration.drop_table end end + + describe "identity columns" do + before(:all) do + @conn = ActiveRecord::Base.connection + schema_define do + end + end + + before(:each) do + @conn.instance_variable_set :@would_execute_sql, @would_execute_sql = +"" + class << @conn + def execute(sql, name = nil); @would_execute_sql << sql << ";\n"; end + end + end + + after(:each) do + class << @conn + remove_method :execute + end + @conn.instance_eval { remove_instance_variable :@would_execute_sql } + end + + it "should 1" do + schema_define do + create_table :identity_test_table, primary_key_as_identity: true + end + expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + end + + it 'should 2' do + schema_define do + create_table :identity_test_table, id: false do |t| + t.primary_key :test, :primary_key, identity: true + end + end + expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + end + + it 'should 3' do + schema_define do + check_for_identity(true) { add_column :identity_test_table, :test_id, :primary_key, identity: true } + end + expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + end + + it 'should 4' do + schema_define do + create_table :identity_test_table, id: false, primary_key_as_identity: true do |t| + t.primary_key :test, :primary_key + end + end + expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + end + + it 'should 5' do + schema_define do + create_table :identity_test_table, id: false, primary_key_as_identity: false do |t| + t.primary_key :test, :primary_key, identity: true + end + end + expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + end + + it 'should 6' do + schema_define do + create_table :identity_test_table, id: false, primary_key_as_identity: true do |t| + t.primary_key :test, :primary_key, identity: true + end + end + expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + end + + it 'should 7' do + schema_define do + create_table :identity_test_table, id: false do |t| + t.primary_key :test, :primary_key, identity: true + end + end + expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + end + end end From 46c6638f22de0d06480527529d7797292388122d Mon Sep 17 00:00:00 2001 From: Brian Thoman Date: Fri, 9 Jul 2021 19:19:51 -0400 Subject: [PATCH 2/5] Add use_identity_for_pk option and helper method --- .../oracle_enhanced/schema_statements.rb | 106 ++++++++++-------- .../oracle_enhanced_adapter.rb | 32 +++++- .../oracle_enhanced/schema_statements_spec.rb | 4 +- 3 files changed, 88 insertions(+), 54 deletions(-) diff --git a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb index f22a30c63..f4817ea67 100644 --- a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +++ b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb @@ -200,56 +200,58 @@ def columns(table_name) # end def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options) - create_sequence = id != false - td = create_table_definition( - table_name, **options.extract!(:temporary, :options, :as, :comment, :tablespace, :organization) - ) + OracleEnhancedAdapter.using_identity(options[:primary_key_as_identity]) do + create_sequence = id != false + td = create_table_definition( + table_name, **options.extract!(:temporary, :options, :as, :comment, :tablespace, :organization) + ) - if id && !td.as - pk = primary_key || Base.get_primary_key(table_name.to_s.singularize) + if id && !td.as + pk = primary_key || Base.get_primary_key(table_name.to_s.singularize) - if pk.is_a?(Array) - td.primary_keys pk - else - td.primary_key pk, id, **options + if pk.is_a?(Array) + td.primary_keys pk + else + td.primary_key pk, id, **options + end end - end - # store that primary key was defined in create_table block - unless create_sequence - class << td - attr_accessor :create_sequence - def primary_key(*args) - self.create_sequence = true - super(*args) + # store that primary key was defined in create_table block + unless create_sequence + class << td + attr_accessor :create_sequence + def primary_key(*args) + self.create_sequence = true + super(*args) + end end end - end - yield td if block_given? - create_sequence = create_sequence || td.create_sequence + yield td if block_given? + create_sequence = create_sequence || td.create_sequence - if force && data_source_exists?(table_name) - drop_table(table_name, force: force, if_exists: true) - else - schema_cache.clear_data_source_cache!(table_name.to_s) - end + if force && data_source_exists?(table_name) + drop_table(table_name, force: force, if_exists: true) + else + schema_cache.clear_data_source_cache!(table_name.to_s) + end - execute schema_creation.accept td + execute schema_creation.accept td - create_sequence_and_trigger(table_name, options) if create_sequence + create_sequence_and_trigger(table_name, options) if create_sequence - if supports_comments? && !supports_comments_in_create? - if table_comment = td.comment.presence - change_table_comment(table_name, table_comment) - end - td.columns.each do |column| - change_column_comment(table_name, column.name, column.comment) if column.comment.present? + if supports_comments? && !supports_comments_in_create? + if table_comment = td.comment.presence + change_table_comment(table_name, table_comment) + end + td.columns.each do |column| + change_column_comment(table_name, column.name, column.comment) if column.comment.present? + end end - end - td.indexes.each { |c, o| add_index table_name, c, **o } + td.indexes.each { |c, o| add_index table_name, c, **o } - rebuild_primary_key_index_to_default_tablespace(table_name, options) + rebuild_primary_key_index_to_default_tablespace(table_name, options) + end end def rename_table(table_name, new_name) #:nodoc: @@ -413,14 +415,16 @@ def add_reference(table_name, ref_name, **options) end def add_column(table_name, column_name, type, **options) #:nodoc: - type = aliased_types(type.to_s, type) - at = create_alter_table table_name - at.add_column(column_name, type, **options) - add_column_sql = schema_creation.accept at - add_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, table_name, column_name) - execute add_column_sql - create_sequence_and_trigger(table_name, options) if type && type.to_sym == :primary_key - change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment) + OracleEnhancedAdapter.using_identity(options[:identity]) do + type = aliased_types(type.to_s, type) + at = create_alter_table table_name + at.add_column(column_name, type, **options) + add_column_sql = schema_creation.accept at + add_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, table_name, column_name) + execute add_column_sql + create_sequence_and_trigger(table_name, options) if type && type.to_sym == :primary_key + change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment) + end ensure clear_table_columns_cache(table_name) end @@ -535,11 +539,13 @@ def column_comment(table_name, column_name) #:nodoc: end # Maps logical Rails types to Oracle-specific data types. - def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) #:nodoc: - # Ignore options for :text, :ntext and :binary columns - return super(type) if ["text", "ntext", "binary"].include?(type.to_s) + def type_to_sql(type, limit: nil, precision: nil, scale: nil, identity: nil, **) #:nodoc: + OracleEnhancedAdapter.using_identity(identity) do + # Ignore options for :text, :ntext and :binary columns + return super(type) if ["text", "ntext", "binary"].include?(type.to_s) - super + super + end end def tablespace(table_name) @@ -702,6 +708,8 @@ def column_for(table_name, column_name) def create_sequence_and_trigger(table_name, options) # TODO: Needs rename since no triggers created # This method will be removed since sequence will not be created separately + return if OracleEnhancedAdapter.use_identity_for_pk + seq_name = options[:sequence_name] || default_sequence_name(table_name) seq_start_value = options[:sequence_start_value] || default_sequence_start_value execute "CREATE SEQUENCE #{quote_table_name(seq_name)} START WITH #{seq_start_value}" diff --git a/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb b/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb index a38d5d168..fbe25d71b 100644 --- a/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +++ b/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb @@ -229,6 +229,14 @@ class OracleEnhancedAdapter < AbstractAdapter cattr_accessor :permissions self.permissions = ["unlimited tablespace", "create session", "create table", "create view", "create sequence"] + ## + # :singleton-method: + # To generate primary key columns using IDENTITY: + # + # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.use_identity_for_pk = true + cattr_accessor :use_identity_for_pk + self.use_identity_for_pk = false + ## # :singleton-method: # Specify default sequence start with value (by default 1 if not explicitly set), e.g.: @@ -409,10 +417,17 @@ def supports_longer_identifier? NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS = NATIVE_DATABASE_TYPES.dup.merge( boolean: { name: "VARCHAR2", limit: 1 } ) + # if use_identity_for_pk then generate primary key as IDENTITY + NATIVE_DATABASE_TYPES_IDENTITY_PK = { + primary_key: "NUMBER(38) GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY" + } #:startdoc: def native_database_types #:nodoc: - emulate_booleans_from_strings ? NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS : NATIVE_DATABASE_TYPES + types = emulate_booleans_from_strings ? NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS : NATIVE_DATABASE_TYPES + types.merge!(NATIVE_DATABASE_TYPES_IDENTITY_PK) if use_identity_for_pk + + types end # CONNECTION MANAGEMENT ==================================== @@ -476,14 +491,25 @@ 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) - # if sequence_name is set to :autogenerated then it means that primary key will be populated by trigger - raise ArgumentError.new "Trigger based primary key is not supported" if sequence_name == AUTOGENERATED_SEQUENCE_NAME + # if sequence_name is set to :autogenerated it means that primary key will be populated by an identity sequence + return nil 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 SQL end + # Helper method for temporarily changing the value of OracleEnhancedAdapter.use_identity_for_pk (e.g., for a + # single create_table block) + def self.using_identity(value = nil, &block) + previous_value = self.use_identity_for_pk + self.use_identity_for_pk = value.nil? ? self.use_identity_for_pk : value + yield + ensure + self.use_identity_for_pk = previous_value + end + # Returns true for Oracle adapter (since Oracle requires primary key # values to be pre-fetched before insert). See also #next_sequence_value. def prefetch_primary_key?(table_name = nil) diff --git a/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb b/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb index 9ffa3a143..4f06042ac 100644 --- a/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +++ b/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb @@ -1289,9 +1289,9 @@ class << @conn it 'should 3' do schema_define do - check_for_identity(true) { add_column :identity_test_table, :test_id, :primary_key, identity: true } + add_column :identity_test_table, :test_id, :primary_key, identity: true end - expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) + expect(@would_execute_sql).to match(/ALTER +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) end it 'should 4' do From 62424c407898848d17b7e6a33efa13fef3be8ec7 Mon Sep 17 00:00:00 2001 From: Brian Thoman Date: Fri, 30 Jul 2021 15:48:10 -0400 Subject: [PATCH 3/5] Update test descriptions and remove some redundant tests --- .../oracle_enhanced/schema_statements.rb | 4 +-- .../oracle_enhanced/schema_statements_spec.rb | 28 ++++--------------- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb index f4817ea67..bf5acf9d4 100644 --- a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +++ b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb @@ -540,12 +540,12 @@ def column_comment(table_name, column_name) #:nodoc: # Maps logical Rails types to Oracle-specific data types. def type_to_sql(type, limit: nil, precision: nil, scale: nil, identity: nil, **) #:nodoc: - OracleEnhancedAdapter.using_identity(identity) do + # OracleEnhancedAdapter.using_identity(identity) do # Ignore options for :text, :ntext and :binary columns return super(type) if ["text", "ntext", "binary"].include?(type.to_s) super - end + # end end def tablespace(table_name) diff --git a/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb b/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb index 4f06042ac..fd3f886ac 100644 --- a/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +++ b/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb @@ -1271,14 +1271,14 @@ class << @conn @conn.instance_eval { remove_instance_variable :@would_execute_sql } end - it "should 1" do + it "should create an identity column when primary_key_as_identity: true is used" do schema_define do create_table :identity_test_table, primary_key_as_identity: true end expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) end - it 'should 2' do + it 'should create an identity column when identity: true is used with t.primary_key' do schema_define do create_table :identity_test_table, id: false do |t| t.primary_key :test, :primary_key, identity: true @@ -1287,14 +1287,14 @@ class << @conn expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) end - it 'should 3' do + it 'should create an identity column when identity: true is used with add_column' do schema_define do add_column :identity_test_table, :test_id, :primary_key, identity: true end expect(@would_execute_sql).to match(/ALTER +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) end - it 'should 4' do + it 'should create an identity column when primary_key_as_identity: true is used with a custom primary_key column' do schema_define do create_table :identity_test_table, id: false, primary_key_as_identity: true do |t| t.primary_key :test, :primary_key @@ -1303,7 +1303,7 @@ class << @conn expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) end - it 'should 5' do + it 'should create an identity column with primary_key_as_identity: false and identity: true' do schema_define do create_table :identity_test_table, id: false, primary_key_as_identity: false do |t| t.primary_key :test, :primary_key, identity: true @@ -1311,23 +1311,5 @@ class << @conn end expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) end - - it 'should 6' do - schema_define do - create_table :identity_test_table, id: false, primary_key_as_identity: true do |t| - t.primary_key :test, :primary_key, identity: true - end - end - expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) - end - - it 'should 7' do - schema_define do - create_table :identity_test_table, id: false do |t| - t.primary_key :test, :primary_key, identity: true - end - end - expect(@would_execute_sql).to match(/CREATE +TABLE .* GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY/) - end end end From eac1c2048cff73dd9310fd6a58e450e85cef09d6 Mon Sep 17 00:00:00 2001 From: Brian Thoman Date: Fri, 30 Jul 2021 16:36:42 -0400 Subject: [PATCH 4/5] Fix a couple things to get tests passing again --- .../connection_adapters/oracle_enhanced/schema_statements.rb | 4 ++-- .../connection_adapters/oracle_enhanced_adapter.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb index bf5acf9d4..f4817ea67 100644 --- a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +++ b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb @@ -540,12 +540,12 @@ def column_comment(table_name, column_name) #:nodoc: # Maps logical Rails types to Oracle-specific data types. def type_to_sql(type, limit: nil, precision: nil, scale: nil, identity: nil, **) #:nodoc: - # OracleEnhancedAdapter.using_identity(identity) do + OracleEnhancedAdapter.using_identity(identity) do # Ignore options for :text, :ntext and :binary columns return super(type) if ["text", "ntext", "binary"].include?(type.to_s) super - # end + end end def tablespace(table_name) diff --git a/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb b/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb index fbe25d71b..4dcb3450c 100644 --- a/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +++ b/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb @@ -425,7 +425,7 @@ def supports_longer_identifier? def native_database_types #:nodoc: types = emulate_booleans_from_strings ? NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS : NATIVE_DATABASE_TYPES - types.merge!(NATIVE_DATABASE_TYPES_IDENTITY_PK) if use_identity_for_pk + types = types.merge(NATIVE_DATABASE_TYPES_IDENTITY_PK) if use_identity_for_pk types end From 70ba3cf7eeab8261e0be0b4e3860b387482a3e69 Mon Sep 17 00:00:00 2001 From: Brian Thoman Date: Fri, 10 Dec 2021 15:05:24 -0500 Subject: [PATCH 5/5] Change the way arguments are passed to ColumnMethods#primary_key to be compatible with Ruby 3 --- .../connection_adapters/oracle_enhanced/schema_statements.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb index d7746c0d9..722262d7a 100644 --- a/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +++ b/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb @@ -220,9 +220,10 @@ def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **o unless create_sequence class << td attr_accessor :create_sequence - def primary_key(*args) + def primary_key(name, type = :primary_key, **options) self.create_sequence = true - super(*args) + + super(name, type, **options) end end end