Module: TemporalTables::TemporalAdapter

Defined in:
lib/temporal_tables/temporal_adapter.rb

Overview

rubocop:disable Metrics/ModuleLength

Instance Method Summary collapse

Instance Method Details

#add_column(table_name, column_name, type, **options) ⇒ Object



81
82
83
84
85
86
87
88
# File 'lib/temporal_tables/temporal_adapter.rb', line 81

def add_column(table_name, column_name, type, **options)
  super(table_name, column_name, type, **options)

  return unless table_exists?(temporal_name(table_name))

  super temporal_name(table_name), column_name, type, **options
  create_temporal_triggers table_name
end

#add_index(table_name, column_name, **options) ⇒ Object



126
127
128
129
130
131
132
133
# File 'lib/temporal_tables/temporal_adapter.rb', line 126

def add_index(table_name, column_name, **options)
  super(table_name, column_name, **options)

  return unless table_exists?(temporal_name(table_name))

  idx_name = temporal_index_name(options[:name] || index_name(table_name, column: column_name))
  super temporal_name(table_name), column_name, **options.except(:unique).merge(name: idx_name)
end

#add_temporal_table(table_name, **options) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/AbcSize



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/temporal_tables/temporal_adapter.rb', line 30

def add_temporal_table(table_name, **options) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  create_table(
    temporal_name(table_name),
    **options.merge(id: false, primary_key: 'history_id', temporal_bypass: true)
  ) do |t|
    t.column :id, options.fetch(:id, :integer) if options[:id] != false
    t.datetime :eff_from, null: false, limit: 6
    t.datetime :eff_to,   null: false, limit: 6, default: '9999-12-31'

    columns(table_name).each do |c|
      next if c.name == 'id'

      t.send c.type, c.name, limit: c.limit
    end
  end

  if TemporalTables.add_updated_by_field && !column_exists?(table_name, :updated_by)
    change_table table_name do |t|
      t.column :updated_by, TemporalTables.updated_by_type
    end
  end

  add_index temporal_name(table_name), [:id, :eff_to]
  create_temporal_triggers table_name
  create_temporal_indexes table_name
end

#change_column(table_name, column_name, type, **options) ⇒ Object



108
109
110
111
112
113
114
115
# File 'lib/temporal_tables/temporal_adapter.rb', line 108

def change_column(table_name, column_name, type, **options)
  super(table_name, column_name, type, **options)

  return unless table_exists?(temporal_name(table_name))

  super temporal_name(table_name), column_name, type, **options
  # Don't need to update triggers here...
end

#create_table(table_name, **options, &block) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/temporal_tables/temporal_adapter.rb', line 5

def create_table(table_name, **options, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
  if options[:temporal_bypass]
    super(table_name, **options, &block)
  else
    skip_table = TemporalTables.skipped_temporal_tables.include?(table_name.to_sym) || table_name.to_s =~ /_h$/

    super(table_name, **options) do |t|
      block.call t

      if TemporalTables.add_updated_by_field && !skip_table
        updated_by_already_exists = t.columns.any? { |c| c.name == 'updated_by' }
        if updated_by_already_exists
          puts "consider adding #{table_name} to TemporalTables skip_table" # rubocop:disable Rails/Output
        else
          t.column(:updated_by, TemporalTables.updated_by_type)
        end
      end
    end

    if options[:temporal] || (TemporalTables.create_by_default && !skip_table)
      add_temporal_table table_name, **options
    end
  end
end

#create_temporal_indexes(table_name) ⇒ Object

rubocop:disable Metrics/MethodLength



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/temporal_tables/temporal_adapter.rb', line 145

def create_temporal_indexes(table_name) # rubocop:disable Metrics/MethodLength
  indexes = ActiveRecord::Base.connection.indexes(table_name)

  indexes.each do |index|
    index_name = temporal_index_name(index.name)

    next if temporal_index_exists?(table_name, index_name)

    add_index(
      temporal_name(table_name),
      index.columns,
      # exclude unique constraints for temporal tables
      name: index_name,
      length: index.lengths,
      order: index.orders
    )
  end
end

#create_temporal_triggers(_table_name) ⇒ Object

Raises:

  • (NotImplementedError)


168
169
170
# File 'lib/temporal_tables/temporal_adapter.rb', line 168

def create_temporal_triggers(_table_name)
  raise NotImplementedError, 'create_temporal_triggers is not implemented'
end

#drop_table(table_name, **options) ⇒ Object



64
65
66
67
68
# File 'lib/temporal_tables/temporal_adapter.rb', line 64

def drop_table(table_name, **options)
  super(table_name, **options)

  super(temporal_name(table_name), **options) if table_exists?(temporal_name(table_name))
end

#drop_temporal_triggers(_table_name) ⇒ Object

Raises:

  • (NotImplementedError)


172
173
174
# File 'lib/temporal_tables/temporal_adapter.rb', line 172

def drop_temporal_triggers(_table_name)
  raise NotImplementedError, 'drop_temporal_triggers is not implemented'
end

#remove_column(table_name, column_name, type = nil, **options) ⇒ Object



99
100
101
102
103
104
105
106
# File 'lib/temporal_tables/temporal_adapter.rb', line 99

def remove_column(table_name, column_name, type = nil, **options)
  super(table_name, column_name, type, **options)

  return unless table_exists?(temporal_name(table_name))

  super temporal_name(table_name), column_name, type, **options
  create_temporal_triggers table_name
end

#remove_columns(table_name, *column_names, **options) ⇒ Object



90
91
92
93
94
95
96
97
# File 'lib/temporal_tables/temporal_adapter.rb', line 90

def remove_columns(table_name, *column_names, **options)
  super(table_name, *column_names, **options)

  return unless table_exists?(temporal_name(table_name))

  super temporal_name(table_name), *column_names, **options
  create_temporal_triggers table_name
end

#remove_index(table_name, column_name = nil, **options) ⇒ Object



135
136
137
138
139
140
141
142
143
# File 'lib/temporal_tables/temporal_adapter.rb', line 135

def remove_index(table_name, column_name = nil, **options)
  original_index_name = index_name_for_remove(table_name, column_name, options)
  super(table_name, column_name, **options)

  return unless table_exists?(temporal_name(table_name))

  idx_name = temporal_index_name(options[:name] || original_index_name)
  super temporal_name(table_name), column_name, name: idx_name
end

#remove_temporal_table(table_name) ⇒ Object



57
58
59
60
61
62
# File 'lib/temporal_tables/temporal_adapter.rb', line 57

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)
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object



117
118
119
120
121
122
123
124
# File 'lib/temporal_tables/temporal_adapter.rb', line 117

def rename_column(table_name, column_name, new_column_name)
  super(table_name, column_name, new_column_name)

  return unless table_exists?(temporal_name(table_name))

  super temporal_name(table_name), column_name, new_column_name
  create_temporal_triggers table_name
end

#rename_table(name, new_name) ⇒ Object



70
71
72
73
74
75
76
77
78
79
# File 'lib/temporal_tables/temporal_adapter.rb', line 70

def rename_table(name, new_name)
  drop_temporal_triggers name if table_exists?(temporal_name(name))

  super name, new_name

  return unless table_exists?(temporal_name(name))

  super(temporal_name(name), temporal_name(new_name))
  create_temporal_triggers new_name
end

#temporal_index_exists?(table_name, index_name) ⇒ Boolean

Returns:

  • (Boolean)


181
182
183
# File 'lib/temporal_tables/temporal_adapter.rb', line 181

def temporal_index_exists?(table_name, index_name)
  index_name_exists?(temporal_name(table_name), index_name)
end

#temporal_index_name(index_name) ⇒ Object

It’s important not to increase the length of the returned string.



177
178
179
# File 'lib/temporal_tables/temporal_adapter.rb', line 177

def temporal_index_name(index_name)
  index_name.to_s.sub(/^index/, 'ind_h').sub(/_ix(\d+)$/, '_hi\1')
end

#temporal_name(table_name) ⇒ Object



164
165
166
# File 'lib/temporal_tables/temporal_adapter.rb', line 164

def temporal_name(table_name)
  "#{table_name}_h"
end