Class: RR::LoggedChange

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyrep/logged_change.rb

Overview

Describes a single logged record change.

Note: The change loading functionality depends on the current database session being executed in an open database transaction. Also at the end of change processing the transaction must be committed.

Constant Summary collapse

TYPE_CHANGES =

A hash describing how the change state morph based on newly found change records.

  • key: String consisting of 2 letters

    • first letter: describes current type change (nothing, insert, update, delete)

    • second letter: the new change type as read of the change log table

  • value: The resulting change type.

[1]: such cases shouldn’t happen. but just in case, choose the most sensible solution.

{
  'NI' => 'I',
  'NU' => 'U',
  'ND' => 'D',
  'II' => 'I', # [1]
  'IU' => 'I',
  'ID' => 'N',
  'UI' => 'U', # [1]
  'UU' => 'U',
  'UD' => 'D',
  'DI' => 'U',
  'DU' => 'U', # [1]
  'DD' => 'D', # [1]
}
SHORT_TYPES =

A hash translating the short 1-letter types to the according symbols

{
  'I' => :insert,
  'U' => :update,
  'D' => :delete,
  'N' => :no_change
}
LONG_TYPES =

A hash translating the symbold types to according 1 letter types

SHORT_TYPES.invert

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(loader) ⇒ LoggedChange

Creates a new LoggedChange instance.

  • loader: the current LoggedChangeLoader

  • database: either :left or :right



46
47
48
49
# File 'lib/rubyrep/logged_change.rb', line 46

def initialize(loader)
  self.loader = loader
  self.type = :no_change
end

Instance Attribute Details

#first_changed_atObject

When the first change to the record happened



28
29
30
# File 'lib/rubyrep/logged_change.rb', line 28

def first_changed_at
  @first_changed_at
end

#keyObject

A column_name => value hash identifying the changed record



37
38
39
# File 'lib/rubyrep/logged_change.rb', line 37

def key
  @key
end

#last_changed_atObject

When the last change to the record happened



31
32
33
# File 'lib/rubyrep/logged_change.rb', line 31

def last_changed_at
  @last_changed_at
end

#loaderObject

The current LoggedChangeLoader



12
13
14
# File 'lib/rubyrep/logged_change.rb', line 12

def loader
  @loader
end

#new_keyObject

Only used for updates: a column_name => value hash of the original primary key of the updated record



41
42
43
# File 'lib/rubyrep/logged_change.rb', line 41

def new_key
  @new_key
end

#tableObject

The name of the changed table



25
26
27
# File 'lib/rubyrep/logged_change.rb', line 25

def table
  @table
end

#typeObject

Type of the change. Either :insert, :update or :delete.



34
35
36
# File 'lib/rubyrep/logged_change.rb', line 34

def type
  @type
end

Instance Method Details

#databaseObject

The current database (either :left or :right)



20
21
22
# File 'lib/rubyrep/logged_change.rb', line 20

def database
  @database ||= loader.database
end

#key_sepObject

Returns the configured key separator



86
87
88
# File 'lib/rubyrep/logged_change.rb', line 86

def key_sep
  @key_sep ||= session.configuration.options[:key_sep]
end

#key_to_hash(raw_key) ⇒ Object

Returns a column_name => value hash based on the provided raw_key string (which is a string in the format as read directly from the change log table).



92
93
94
95
96
97
# File 'lib/rubyrep/logged_change.rb', line 92

def key_to_hash(raw_key)
  result = {}
  #raw_key.split(key_sep).each_slice(2) {|a| result[a[0]] = a[1]}
  raw_key.split(key_sep).each_slice(2) {|field_name, value| result[field_name] = value}
  result
end

#loadObject

Loads the change as per #table and #key. Works if the LoggedChange instance is totally new or was already loaded before.



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/rubyrep/logged_change.rb', line 101

def load
  current_type = LONG_TYPES[type]

  org_key = new_key || key
  # change to key string as can be found in change log table
  org_key = session.send(database).primary_key_names(table).map do |key_name|
    "#{key_name}#{key_sep}#{org_key[key_name]}"
  end.join(key_sep)
  current_key = org_key

  while change = loader.load(table, current_key)

    new_type = change['change_type']
    current_type = TYPE_CHANGES["#{current_type}#{new_type}"]

    self.first_changed_at ||= change['change_time']
    self.last_changed_at = change['change_time']

    if change['change_type'] == 'U' and change['change_new_key'] != current_key
      current_key = change['change_new_key']
    end
  end

  self.type = SHORT_TYPES[current_type]
  self.new_key = nil
  if type == :update
    self.key ||= key_to_hash(org_key)
    self.new_key = key_to_hash(current_key)
  else
    self.key = key_to_hash(current_key)
  end
end

#load_oldestObject

Loads the oldest available change



144
145
146
147
148
149
150
151
152
# File 'lib/rubyrep/logged_change.rb', line 144

def load_oldest
  begin
    change = loader.oldest_change
    break unless change
    self.key = key_to_hash(change['change_key'])
    self.table = change['change_table']
    load
  end until type != :no_change
end

#load_specified(table, key) ⇒ Object

Loads the change with the specified key for the named table.

  • table: name of the table

  • key: a column_name => value hash for all primary key columns of the table



137
138
139
140
141
# File 'lib/rubyrep/logged_change.rb', line 137

def load_specified(table, key)
  self.table = table
  self.key = key
  load
end

#sessionObject

The current Session



15
16
17
# File 'lib/rubyrep/logged_change.rb', line 15

def session
  @session ||= loader.session
end

#to_yaml_propertiesObject

Prevents session from going into YAML output



155
156
157
# File 'lib/rubyrep/logged_change.rb', line 155

def to_yaml_properties
  instance_variables.sort.reject {|var_name| [:'@session', :'@loader'].include? var_name}
end