Class: Mysqlaudit::Audit
- Inherits:
-
Object
- Object
- Mysqlaudit::Audit
- Defined in:
- lib/mysqlaudit/audit.rb
Instance Method Summary collapse
- #connect ⇒ Object
- #create_table ⇒ Object
- #create_trigger(table, actionName) ⇒ Object
- #drop_table ⇒ Object
- #drop_trigger(table, actionName) ⇒ Object
- #get_columns(table) ⇒ Object
- #get_primary_key(table) ⇒ Object
- #get_tables ⇒ Object
- #has_table ⇒ Object
- #has_trigger(table, actionName) ⇒ Object
-
#initialize(host, user, password, schema) ⇒ Audit
constructor
A new instance of Audit.
- #rollback(table, statement) ⇒ Object
Constructor Details
#initialize(host, user, password, schema) ⇒ Audit
Returns a new instance of Audit.
14 15 16 17 18 19 20 21 |
# File 'lib/mysqlaudit/audit.rb', line 14 def initialize(host, user, password, schema) $host = host $user = user $password = password $schema = schema connect end |
Instance Method Details
#connect ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/mysqlaudit/audit.rb', line 23 def connect() begin @mysql = Mysql2::Client.new(:host => $host, :username => $user, :password => $password, :database => $schema) rescue puts "Can't connect to MySQL Server." exit 1 end end |
#create_table ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/mysqlaudit/audit.rb', line 35 def create_table() if !has_table sql = <<SQL CREATE TABLE IF NOT EXISTS audits ( id int(10) unsigned NOT NULL AUTO_INCREMENT, type enum('I', 'U', 'D') NOT NULL, `table` char(64) NOT NULL, `column` char(64) NOT NULL, `primary_key` int(10) unsigned, `old` TEXT DEFAULT NULL, `new` TEXT DEFAULT NULL, `trigger_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY id_UNIQUE (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 SQL @mysql.query(sql) puts "Created table audits in #{$schema} database." end end |
#create_trigger(table, actionName) ⇒ Object
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 |
# File 'lib/mysqlaudit/audit.rb', line 85 def create_trigger(table, actionName) if !has_trigger(table, actionName) columns = get_columns(table) key = get_primary_key(table) if key sql = "CREATE TRIGGER audit_#{table}_#{actionName.downcase} AFTER #{actionName.upcase} ON #{table}\nFOR EACH ROW BEGIN\n" columns.each do | column | case actionName.downcase when :insert sql << "INSERT INTO audits (type, `table`, `column`, primary_key, old, new) VALUES ('#{actionName[0,1].upcase}', '#{table}', '#{column}', NEW.#{key}, NULL, NEW.#{column});\n" when :update sql << "IF OLD.#{column} <> NEW.#{column} THEN\n" sql << " INSERT INTO audits (type, `table`, `column`, primary_key, old, new) VALUES ('#{actionName[0,1].upcase}', '#{table}', '#{column}', NEW.#{key}, OLD.#{column}, NEW.#{column});\n" sql << "END IF;\n" when :delete sql << "INSERT INTO audits (type, `table`, `column`, primary_key, old, new) VALUES ('#{actionName[0,1].upcase}', '#{table}', '#{column}', OLD.#{key}, OLD.#{column}, NULL);\n" end end sql << "END;" @mysql.query(sql) puts "Created trigger in #{table} table after #{actionName}." else puts "Impossible to create trigger in #{table}, not have primary key." end else puts "Impossible to create trigger in #{table}, has a trigger." end end |
#drop_table ⇒ Object
62 63 64 65 66 |
# File 'lib/mysqlaudit/audit.rb', line 62 def drop_table() return unless has_table() @mysql.query("DROP TABLE IF EXISTS audits;") puts "Delete table audits in #{$schema} database." end |
#drop_trigger(table, actionName) ⇒ Object
118 119 120 121 122 123 124 |
# File 'lib/mysqlaudit/audit.rb', line 118 def drop_trigger(table, actionName) if has_trigger(table, actionName) sql = "DROP TRIGGER IF EXISTS audit_#{table}_#{actionName};" @mysql.query(sql) puts "Deleted trigger in #{table} table after #{actionName}." end end |
#get_columns(table) ⇒ Object
79 80 81 82 83 |
# File 'lib/mysqlaudit/audit.rb', line 79 def get_columns(table) sql = "SELECT column_name AS name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='#{$schema}' AND TABLE_NAME='#{table}' AND column_key <> 'PRI';" sql_result = @mysql.query(sql) sql_result.map { |table| table['name']} end |
#get_primary_key(table) ⇒ Object
74 75 76 77 |
# File 'lib/mysqlaudit/audit.rb', line 74 def get_primary_key(table) sql = "SELECT column_name AS name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='#{$schema}' AND TABLE_NAME='#{table}' AND column_key = 'PRI';" @mysql.query(sql).first['name'] end |
#get_tables ⇒ Object
68 69 70 71 72 |
# File 'lib/mysqlaudit/audit.rb', line 68 def get_tables() sql = "SELECT table_name AS name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = '#{$schema}' AND table_name <> 'audits';" sql_result = @mysql.query(sql) sql_result.map { |table| table['name']} end |
#has_table ⇒ Object
57 58 59 60 |
# File 'lib/mysqlaudit/audit.rb', line 57 def has_table() sql = "SELECT true AS has FROM information_schema.tables WHERE table_schema = '#{$schema}' AND table_name = 'audits';" @mysql.query(sql).count == 1 end |
#has_trigger(table, actionName) ⇒ Object
126 127 128 129 |
# File 'lib/mysqlaudit/audit.rb', line 126 def has_trigger(table, actionName) sql = "SELECT true AS has FROM information_schema.triggers WHERE trigger_schema = '#{$schema}' AND trigger_name = 'audit_#{table}_#{actionName}';" @mysql.query(sql).count == 1 end |
#rollback(table, statement) ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/mysqlaudit/audit.rb', line 131 def rollback(table, statement) columns = get_columns(table) key = get_primary_key(table) case statement when :insert sql = <<SQL SELECT CONCAT('/* ', trigger_at, ' */ DELETE FROM #{table} WHERE id = ', MAX(primary_key),';') AS `row` FROM audits WHERE `type` = 'I' AND `table` = '#{table}' GROUP BY primary_key ORDER BY trigger_at, primary_key, `column` ASC; SQL when :delete sql = "SELECT CONCAT('/* ', trigger_at, ' */ INSERT INTO #{table} (#{key}, #{columns.join(', ')}) VALUES (', primary_key, ', ', " columns.each do | column | sql << " QUOTE(MAX(IF(`column` = '#{column}', `old`, NULL))), ', ', " end sql = sql.chomp(" ', ', ") sql << "');'" sql << ") AS `row` FROM audits WHERE `type` = 'D' AND `table` = '#{table}' GROUP BY primary_key ORDER BY trigger_at, primary_key, `column` ASC;" when :update sql = "SELECT CONCAT('/* ', trigger_at, ' */ UPDATE users SET ', `column`, ' = ', QUOTE(old), ' WHERE id = ', primary_key, ';') AS `row`" sql << "FROM audits WHERE `type` = 'U' AND `table` = '#{table}' ORDER BY trigger_at, primary_key, `column` ASC;" end sql_result = @mysql.query(sql) sql_result.each(:as => :array) do |row| puts row end end |