Skip to content

Commit

Permalink
fix table cleanup (#38)
Browse files Browse the repository at this point in the history
- correctly remove temporal table
- remove functions, too
- add spec and refactor support
  • Loading branch information
doits authored Oct 19, 2024
1 parent 6afd324 commit e25f184
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 9 deletions.
5 changes: 5 additions & 0 deletions lib/temporal_tables/connection_adapters/postgresql_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ def drop_temporal_triggers(table_name)
execute "drop trigger #{table_name}_ai on #{table_name}"
execute "drop trigger #{table_name}_au on #{table_name}"
execute "drop trigger #{table_name}_ad on #{table_name}"

# remove functions that where created, too
execute "drop function #{table_name}_ai()"
execute "drop function #{table_name}_au()"
execute "drop function #{table_name}_ad()"
end

def create_temporal_triggers(table_name, primary_key) # rubocop:disable Metrics/MethodLength
Expand Down
2 changes: 1 addition & 1 deletion lib/temporal_tables/temporal_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def remove_temporal_table(table_name)
return unless table_exists?(temporal_name(table_name))

drop_temporal_triggers table_name
drop_table_without_temporal temporal_name(table_name)
drop_table temporal_name(table_name)
end

def drop_table(table_name, **options)
Expand Down
46 changes: 38 additions & 8 deletions spec/support/database.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
# frozen_string_literal: true

module TemporalTables
module DatabaseAdapter
def self.adapter_name
if Gemika::Env.gem?('pg')
'postgresql'
elsif Gemika::Env.gem?('mysql2')
'mysql'
end
def adapter_name
if Gemika::Env.gem?('pg')
'postgresql'
elsif Gemika::Env.gem?('mysql2')
'mysql'
else
raise 'Cannot determine adapter'
end
end

def table_exists?(name)
ActiveRecord::Base.connection.table_exists?(name)
end

def function_exists?(name)
case adapter_name
when 'postgresql'
begin
ActiveRecord::Base.connection.execute("select(pg_get_functiondef('#{name}'::regprocedure))").present?
rescue ActiveRecord::StatementInvalid
false
end
when 'mysql' then raise NotImplementedError
else raise "Unknown adapter #{adapter_name}"
end
end

def trigger_exists?(name) # rubocop:disable Metrics/MethodLength
case adapter_name
when 'postgresql'
ActiveRecord::Base.connection.execute(
"select (pg_get_triggerdef(oid)) FROM pg_trigger WHERE tgname = '#{name}'"
).first.present?
when 'mysql'
ActiveRecord::Base.connection.execute(
'SHOW TRIGGERS FROM temporal_tables_test'
).find { |row| row.first == name }.present?
else
raise "Unknown adapter #{adapter_name}"
end
end
32 changes: 32 additions & 0 deletions spec/temporal_tables/temporal_adapter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

require 'spec_helper'

describe TemporalTables::TemporalAdapter do
describe '#remove_temporal_table' do
it 'correctly removes history table, functions and triggers' do
skip 'mysql has no functions' if adapter_name == 'mysql'

expect do
ActiveRecord::Schema.define { remove_temporal_table :people }
end.to change { table_exists?('people_h') }.from(true).to(false)
.and change { function_exists?('people_ai()') }.from(true).to(false)
.and change { function_exists?('people_au()') }.from(true).to(false)
.and change { function_exists?('people_ad()') }.from(true).to(false)
.and change { trigger_exists?('people_ai') }.from(true).to(false)
.and change { trigger_exists?('people_au') }.from(true).to(false)
.and change { trigger_exists?('people_ad') }.from(true).to(false)
end

it 'correctly removes history table and triggers' do
skip 'other adapters than mysql have functions, too' if adapter_name != 'mysql'

expect do
ActiveRecord::Schema.define { remove_temporal_table :people }
end.to change { table_exists?('people_h') }.from(true).to(false)
.and change { trigger_exists?('people_ai') }.from(true).to(false)
.and change { trigger_exists?('people_au') }.from(true).to(false)
.and change { trigger_exists?('people_ad') }.from(true).to(false)
end
end
end

0 comments on commit e25f184

Please sign in to comment.