3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
|
# File 'lib/lims-core/persistence/sequel/migrations/add_audit_tables.rb', line 3
def self.migration(exclude_tables={}, additional_tables_to_update=[])
[:schema_info, :sessions, :primary_keys].each do |table|
exclude_tables[table] = true
end
this = self
Proc.new do
next unless defined?(DB)
table_names = []
change do
if additional_tables_to_update.size == 0
create_table :sessions do
primary_key :id
String :user
String :backend_application_id
String :parameters, :text => true
boolean :success
timestamp :start_time
DateTime :end_time
end
end
self << <<-EOS
INSERT INTO sessions(user, backend_application_id)
VALUES('admin', 'lims-core');
EOS
session_id = DB[:sessions].order(:id).last[:id]
tables_to_update = additional_tables_to_update.size == 0 ? DB.tables : additional_tables_to_update
tables_to_update.each do |table_name|
next if exclude_tables.include?(table_name)
table_names << table_name
table = DB[table_name]
if DB[table].columns.include?(:revision) == false
alter_table table_name do
add_column :revision, Integer, :default => 1
end
end
revision_table = "#{table_name}_revision"
self << <<-EOS
CREATE TABLE #{revision_table} AS
SELECT *, 'initial' AS `action`, #{session_id} as session_id
FROM #{table_name}
EOS
puts "adding key to #{revision_table}"
alter_table revision_table do
add_primary_key :internal_id
add_index [:id, :revision], :unique => true
add_index [:id, :session_id], :unique => true
add_foreign_key [:session_id], :sessions, :key => :id
end
trigger_name = "maintain_#{table_name}_on_insert"
self << "DROP TRIGGER IF EXISTS #{trigger_name};"
trigger_code = <<-EOT
CREATE TRIGGER #{trigger_name} AFTER INSERT ON #{table_name}
FOR EACH ROW
BEGIN
#{this.insert_into_revision(table, revision_table, :insert)}
EOT
puts trigger_code
self << trigger_code
trigger_name = "maintain_#{table_name}_on_update"
self << "DROP TRIGGER IF EXISTS #{trigger_name};"
trigger_code = <<-EOT
CREATE TRIGGER #{trigger_name} BEFORE UPDATE ON #{table_name}
FOR EACH ROW
BEGIN
# Update the revision number
SET NEW.revision = OLD.revision+1;
# Update the revision table
#{this.insert_into_revision(table, revision_table, :update)}
EOT
puts trigger_code
self << trigger_code
trigger_name = "maintain_#{table_name}_on_delete"
self << "DROP TRIGGER IF EXISTS #{trigger_name};"
trigger_code = <<-EOT
CREATE TRIGGER #{trigger_name} BEFORE DELETE ON #{table_name}
FOR EACH ROW
BEGIN
#{this.insert_into_revision(table, revision_table, :delete)}
EOT
puts trigger_code
self << trigger_code
end
if additional_tables_to_update.size > 0
self << "DROP VIEW IF EXISTS revisions"
end
revision_tables = DB.tables.map { |table| table unless table.match(/revision/) }.compact
revision_tables -= exclude_tables.keys
view_code = "CREATE VIEW revisions AS " + revision_tables.map do |table_name|
revision_table = "#{table_name}_revision"
%Q{ SELECT '#{table_name}' AS revision_table,
id,
action,
session_id
FROM #{revision_table}
}
end.join(' UNION ')
puts view_code
self << view_code
end
end
end
|