mysqlaudit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/LICENSE.txt +22 -0
- data/README.md +152 -0
- data/bin/mysqlaudit +58 -0
- data/lib/mysqlaudit/actions.rb +62 -0
- data/lib/mysqlaudit/audit.rb +168 -0
- data/lib/mysqlaudit/version.rb +3 -0
- data/lib/mysqlaudit.rb +7 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MjRmYmMyZjFiYjNiMGNkYzllNTY3NjZjMWJlZTljNjY0MTUwOTE1Zg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
N2MwYTg0NWFlZjQ5NzAyMTQzYWRmYzc0YWEwMDk4NGRmY2ViN2ZjNw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ODUzYWIxYWYxY2NhMTI2MTlmZTM0NzhmN2MyYTEyYWY0MjlhMzEwMGUxNWZh
|
10
|
+
MjVhMmI3ZDQ1YWVlZTE0YjRjM2E3MTJlZGQxMGFiYjA2YjA4NWQ1NWQyOWIz
|
11
|
+
NzQ1MDVmYmM5NWYzNWFkYzEzYWI0YTA1ZjQ5NjhlMDMxYTliNzU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MjI4ODI0MWQwODYyNWViZjdiMjFiYWIwZmM0ZmUyOWY2NzVkN2RkYjMyNzYx
|
14
|
+
OWZkNTc5NzNiZGFkYWNlYjNkMGJhMjlhMzgwYWFlZTk5NjRjYjI4Nzg5MWU5
|
15
|
+
NGY2N2EyYjc0ZTBkNDFlOWEzZWZkZTBkY2M2YzlhMDJiMWY0MzQ=
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Nicola Strappazzon C.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# Mysqlaudit
|
2
|
+
|
3
|
+
MySQL tool build in ruby for audit all tables with triggers, this is a change
|
4
|
+
log for SQL transactions executed sentences as INSERT, UPDATE, and DELETE.
|
5
|
+
|
6
|
+
## Useful for:
|
7
|
+
|
8
|
+
1. Log all changes on table.
|
9
|
+
2. Rollback changes.
|
10
|
+
3. Detecting unnecessary transactions.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Install this tool executing the following command:
|
15
|
+
|
16
|
+
```Shell
|
17
|
+
$ gem install mysqlaudit
|
18
|
+
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
This is a simple tutorial to understand this tool, please, follow next
|
23
|
+
instructions:
|
24
|
+
|
25
|
+
### Install test enviroment
|
26
|
+
|
27
|
+
Create test database and table:
|
28
|
+
|
29
|
+
```SQL
|
30
|
+
CREATE DATABASE audit CHARACTER SET utf8;
|
31
|
+
|
32
|
+
USE audit;
|
33
|
+
|
34
|
+
CREATE TABLE foo (
|
35
|
+
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
36
|
+
email char(255) NOT NULL,
|
37
|
+
name VARCHAR(45) NOT NULL,
|
38
|
+
birthday TIMESTAMP NOT NULL,
|
39
|
+
PRIMARY KEY (id),
|
40
|
+
UNIQUE KEY id_UNIQUE (id)
|
41
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
42
|
+
```
|
43
|
+
|
44
|
+
Install audit table and triggers on foo table:
|
45
|
+
|
46
|
+
```Shell
|
47
|
+
$ mysqlaudit install --host 127.0.0.1 --user root --pass admin --schema audit --table foo
|
48
|
+
```
|
49
|
+
|
50
|
+
The following query catch all changes of data with trigger audit:
|
51
|
+
|
52
|
+
```SQL
|
53
|
+
INSERT INTO foo (email, name, birthday) VALUES ('abc@abc.com','Fulano','1980-04-01');
|
54
|
+
INSERT INTO foo (email, name, birthday) VALUES ('def@def.org','Mengano','1979-03-28');
|
55
|
+
INSERT INTO foo (email, name, birthday) VALUES ('ghi@ghi.net','Jaimito','1980-06-15');
|
56
|
+
UPDATE foo SET name = 'Zutano' WHERE id = 3;
|
57
|
+
DELETE FROM foo WHERE id = 2;
|
58
|
+
```
|
59
|
+
|
60
|
+
To apply rollback with specific transaction, this generate SQL output:
|
61
|
+
|
62
|
+
### Get deleted data:
|
63
|
+
|
64
|
+
```Shell
|
65
|
+
$ mysqlaudit rollback --host 127.0.0.1 \
|
66
|
+
--user root \
|
67
|
+
--pass admin \
|
68
|
+
--schema audit \
|
69
|
+
--table foo \
|
70
|
+
--statement delete
|
71
|
+
```
|
72
|
+
|
73
|
+
Output of last executed command:
|
74
|
+
|
75
|
+
```
|
76
|
+
/* 2013-07-11 07:25:25 */ INSERT INTO foo (id, email, name, birthday) VALUES (2, 'def@def.org', 'Mengano', '1979-03-28 00:00:00');
|
77
|
+
```
|
78
|
+
|
79
|
+
### Get updated data:
|
80
|
+
```Shell
|
81
|
+
$ mysqlaudit rollback --host 127.0.0.1 \
|
82
|
+
--user root \
|
83
|
+
--pass admin \
|
84
|
+
--schema audit \
|
85
|
+
--table foo \
|
86
|
+
--statement update
|
87
|
+
```
|
88
|
+
|
89
|
+
Output of last executed command:
|
90
|
+
|
91
|
+
```
|
92
|
+
/* 2013-07-11 07:26:26 */ UPDATE users SET birthday = '1980-06-15 00:00:00' WHERE id = 3;
|
93
|
+
/* 2013-07-11 07:26:26 */ UPDATE users SET name = 'Jaimito' WHERE id = 3;
|
94
|
+
```
|
95
|
+
|
96
|
+
### Get inserted data:
|
97
|
+
```Shell
|
98
|
+
$ mysqlaudit rollback --host 127.0.0.1 \
|
99
|
+
--user root \
|
100
|
+
--pass admin \
|
101
|
+
--schema audit \
|
102
|
+
--table foo \
|
103
|
+
--statement insert
|
104
|
+
```
|
105
|
+
|
106
|
+
Output of last executed command:
|
107
|
+
|
108
|
+
```
|
109
|
+
/* 2013-07-11 07:27:27 */ DELETE FROM foo WHERE id = 1;
|
110
|
+
/* 2013-07-11 07:27:27 */ DELETE FROM foo WHERE id = 2;
|
111
|
+
/* 2013-07-11 07:27:27 */ DELETE FROM foo WHERE id = 3;
|
112
|
+
```
|
113
|
+
|
114
|
+
### Uninstall test enviroment:
|
115
|
+
|
116
|
+
Uninstall all triggers and drop audit table.
|
117
|
+
|
118
|
+
```Shell
|
119
|
+
$ mysqlaudit uninstall --host 127.0.0.1 \
|
120
|
+
--user root \
|
121
|
+
--pass admin \
|
122
|
+
--schema audit \
|
123
|
+
--table foo \
|
124
|
+
--drop-audit-table
|
125
|
+
```
|
126
|
+
|
127
|
+
Drop testing table and database:
|
128
|
+
|
129
|
+
```SQL
|
130
|
+
DROP TABLE audit;
|
131
|
+
DROP DATABASE foo;
|
132
|
+
```
|
133
|
+
|
134
|
+
For more information:
|
135
|
+
|
136
|
+
```Shell
|
137
|
+
$ mysqlaudit --help
|
138
|
+
```
|
139
|
+
|
140
|
+
## Warning
|
141
|
+
|
142
|
+
1. Do not use this tool in production before testing it.
|
143
|
+
2. Please, use when do you need.
|
144
|
+
3. The author is NOT responsible for misuse use of this tool.
|
145
|
+
|
146
|
+
## Contributing
|
147
|
+
|
148
|
+
1. Fork it
|
149
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
150
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
151
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
152
|
+
5. Create new Pull Request
|
data/bin/mysqlaudit
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Only for deploy this script.
|
4
|
+
$LOAD_PATH << './lib'
|
5
|
+
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'commander'
|
9
|
+
require 'commander/import'
|
10
|
+
require 'mysqlaudit'
|
11
|
+
require 'mysqlaudit/actions'
|
12
|
+
require 'mysqlaudit/version'
|
13
|
+
|
14
|
+
program :name, 'MySQL Audit Tool'
|
15
|
+
program :version, Mysqlaudit::VERSION
|
16
|
+
program :description, 'MySQL tool for audit all tables with triggers.'
|
17
|
+
program :help, 'Author', 'Nicola Strappazzon <nicola51980@gmail.com>'
|
18
|
+
|
19
|
+
command :install do |c|
|
20
|
+
c.description = 'Install audit table'
|
21
|
+
c.syntax = 'audits install --host 127.0.0.1 --user root [--pass admin] --schema sakila [--table foo]'
|
22
|
+
c.option '--host STRING', String, 'Host'
|
23
|
+
c.option '--user STRING', String, 'User'
|
24
|
+
c.option '--pass STRING', String, 'Password'
|
25
|
+
c.option '--schema STRING', String, 'Schema name'
|
26
|
+
c.option '--table STRING', String, 'Table name'
|
27
|
+
c.action do |args, options|
|
28
|
+
Mysqlaudit::Actions.new(options.host, options.user, options.pass, options.schema, options.table).install
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
command :uninstall do |c|
|
33
|
+
c.description = 'Uninstall audit table'
|
34
|
+
c.syntax = 'audits uninstall --host 127.0.0.1 --user root [--pass admin] --schema sakila [--table foo] [--[no-]drop-audit-table]'
|
35
|
+
c.option '--host STRING', String, 'Host'
|
36
|
+
c.option '--user STRING', String, 'User'
|
37
|
+
c.option '--pass STRING', String, 'Password'
|
38
|
+
c.option '--schema STRING', String, 'Schema name'
|
39
|
+
c.option '--table STRING', String, 'Table name'
|
40
|
+
c.option '--[no-]drop-audit-table', 'Drop audit table'
|
41
|
+
c.action do |args, options|
|
42
|
+
Mysqlaudit::Actions.new(options.host, options.user, options.pass, options.schema, options.table, options.drop_audit_table).uninstall
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
command :rollback do |c|
|
47
|
+
c.description = 'Rollback transaction cath in audit table'
|
48
|
+
c.syntax = 'audits rollback --host 127.0.0.1 --user root [--pass admin] --schema sakila --table foo --statement INSERT'
|
49
|
+
c.option '--host STRING', String, 'Host'
|
50
|
+
c.option '--user STRING', String, 'User'
|
51
|
+
c.option '--pass STRING', String, 'Password'
|
52
|
+
c.option '--schema STRING', String, 'Schema name'
|
53
|
+
c.option '--table STRING', String, 'Table name'
|
54
|
+
c.option '--statement STRING', String, 'Statement operation, INSERT, UPDATE, or DELETE'
|
55
|
+
c.action do |args, options|
|
56
|
+
Mysqlaudit::Actions.new(options.host, options.user, options.pass, options.schema, options.table, nil, options.statement).rollback
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'mysqlaudit/audit'
|
2
|
+
|
3
|
+
module Mysqlaudit
|
4
|
+
class Actions
|
5
|
+
@audit = nil
|
6
|
+
|
7
|
+
def initialize(host, user, password, schema, table, drop = nil, statement = nil)
|
8
|
+
# def initialize(schema, table, options = {})
|
9
|
+
# options = {host: 'localhost', user: 'root', password: ''}.merge(options)
|
10
|
+
|
11
|
+
$host = host
|
12
|
+
$user = user
|
13
|
+
$password = password
|
14
|
+
$schema = schema
|
15
|
+
$table = table
|
16
|
+
$drop = drop
|
17
|
+
$statement = statement
|
18
|
+
|
19
|
+
@audit = Mysqlaudit::Audit.new($host, $user, $password, $schema)
|
20
|
+
end
|
21
|
+
|
22
|
+
def install()
|
23
|
+
@audit.create_table()
|
24
|
+
|
25
|
+
if !$table
|
26
|
+
tables = @audit.get_tables()
|
27
|
+
tables.each do | table |
|
28
|
+
@audit.create_trigger(table, :insert)
|
29
|
+
@audit.create_trigger(table, :update)
|
30
|
+
@audit.create_trigger(table, :delete)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
@audit.create_trigger($table, :insert)
|
34
|
+
@audit.create_trigger($table, :update)
|
35
|
+
@audit.create_trigger($table, :delete)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def uninstall()
|
40
|
+
if !$table
|
41
|
+
tables = @audit.get_tables()
|
42
|
+
tables.each do | table |
|
43
|
+
@audit.drop_trigger(table, :insert)
|
44
|
+
@audit.drop_trigger(table, :update)
|
45
|
+
@audit.drop_trigger(table, :delete)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
@audit.drop_trigger($table, :insert)
|
49
|
+
@audit.drop_trigger($table, :update)
|
50
|
+
@audit.drop_trigger($table, :delete)
|
51
|
+
end
|
52
|
+
|
53
|
+
if $drop
|
54
|
+
@audit.drop_table()
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def rollback()
|
59
|
+
@audit.rollback($table, $statement.to_sym)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mysql2'
|
3
|
+
|
4
|
+
# @todo Optimize passing params on methods with maps.
|
5
|
+
# @todo Optimize is set params to execute methods.
|
6
|
+
# @todo Passing as parameter the tables names to apply triggers.
|
7
|
+
# @todo Change name for audit table.
|
8
|
+
# @todo If exist trigger then append to existing.
|
9
|
+
# @todo Backup if exist triggers.
|
10
|
+
# @todo Define expiration time for events.
|
11
|
+
|
12
|
+
module Mysqlaudit
|
13
|
+
class Audit
|
14
|
+
def initialize(host, user, password, schema)
|
15
|
+
$host = host
|
16
|
+
$user = user
|
17
|
+
$password = password
|
18
|
+
$schema = schema
|
19
|
+
|
20
|
+
connect
|
21
|
+
end
|
22
|
+
|
23
|
+
def connect()
|
24
|
+
begin
|
25
|
+
@mysql = Mysql2::Client.new(:host => $host,
|
26
|
+
:username => $user,
|
27
|
+
:password => $password,
|
28
|
+
:database => $schema)
|
29
|
+
rescue
|
30
|
+
puts "Can't connect to MySQL Server."
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_table()
|
36
|
+
if !has_table
|
37
|
+
sql = <<SQL
|
38
|
+
CREATE TABLE IF NOT EXISTS audits (
|
39
|
+
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
40
|
+
type enum('I', 'U', 'D') NOT NULL,
|
41
|
+
`table` char(64) NOT NULL,
|
42
|
+
`column` char(64) NOT NULL,
|
43
|
+
`primary_key` int(10) unsigned,
|
44
|
+
`old` TEXT DEFAULT NULL,
|
45
|
+
`new` TEXT DEFAULT NULL,
|
46
|
+
`trigger_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
47
|
+
PRIMARY KEY (id),
|
48
|
+
UNIQUE KEY id_UNIQUE (id)
|
49
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
50
|
+
SQL
|
51
|
+
|
52
|
+
@mysql.query(sql)
|
53
|
+
puts "Created table audits in #{$schema} database."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def has_table()
|
58
|
+
sql = "SELECT true AS has FROM information_schema.tables WHERE table_schema = '#{$schema}' AND table_name = 'audits';"
|
59
|
+
@mysql.query(sql).count == 1
|
60
|
+
end
|
61
|
+
|
62
|
+
def drop_table()
|
63
|
+
return unless has_table()
|
64
|
+
@mysql.query("DROP TABLE IF EXISTS audits;")
|
65
|
+
puts "Delete table audits in #{$schema} database."
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_tables()
|
69
|
+
sql = "SELECT table_name AS name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = '#{$schema}' AND table_name <> 'audits';"
|
70
|
+
sql_result = @mysql.query(sql)
|
71
|
+
sql_result.map { |table| table['name']}
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_primary_key(table)
|
75
|
+
sql = "SELECT column_name AS name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='#{$schema}' AND TABLE_NAME='#{table}' AND column_key = 'PRI';"
|
76
|
+
@mysql.query(sql).first['name']
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_columns(table)
|
80
|
+
sql = "SELECT column_name AS name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='#{$schema}' AND TABLE_NAME='#{table}' AND column_key <> 'PRI';"
|
81
|
+
sql_result = @mysql.query(sql)
|
82
|
+
sql_result.map { |table| table['name']}
|
83
|
+
end
|
84
|
+
|
85
|
+
def create_trigger(table, actionName)
|
86
|
+
if !has_trigger(table, actionName)
|
87
|
+
columns = get_columns(table)
|
88
|
+
key = get_primary_key(table)
|
89
|
+
|
90
|
+
if key
|
91
|
+
sql = "CREATE TRIGGER audit_#{table}_#{actionName.downcase} AFTER #{actionName.upcase} ON #{table}\nFOR EACH ROW BEGIN\n"
|
92
|
+
|
93
|
+
columns.each do | column |
|
94
|
+
case actionName.downcase
|
95
|
+
when :insert
|
96
|
+
sql << "INSERT INTO audits (type, `table`, `column`, primary_key, old, new) VALUES ('#{actionName[0,1].upcase}', '#{table}', '#{column}', NEW.#{key}, NULL, NEW.#{column});\n"
|
97
|
+
when :update
|
98
|
+
sql << "IF OLD.#{column} <> NEW.#{column} THEN\n"
|
99
|
+
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"
|
100
|
+
sql << "END IF;\n"
|
101
|
+
when :delete
|
102
|
+
sql << "INSERT INTO audits (type, `table`, `column`, primary_key, old, new) VALUES ('#{actionName[0,1].upcase}', '#{table}', '#{column}', OLD.#{key}, OLD.#{column}, NULL);\n"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
sql << "END;"
|
107
|
+
|
108
|
+
@mysql.query(sql)
|
109
|
+
puts "Created trigger in #{table} table after #{actionName}."
|
110
|
+
else
|
111
|
+
puts "Impossible to create trigger in #{table}, not have primary key."
|
112
|
+
end
|
113
|
+
else
|
114
|
+
puts "Impossible to create trigger in #{table}, has a trigger."
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def drop_trigger(table, actionName)
|
119
|
+
if has_trigger(table, actionName)
|
120
|
+
sql = "DROP TRIGGER IF EXISTS audit_#{table}_#{actionName};"
|
121
|
+
@mysql.query(sql)
|
122
|
+
puts "Deleted trigger in #{table} table after #{actionName}."
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def has_trigger(table, actionName)
|
127
|
+
sql = "SELECT true AS has FROM information_schema.triggers WHERE trigger_schema = '#{$schema}' AND trigger_name = 'audit_#{table}_#{actionName}';"
|
128
|
+
@mysql.query(sql).count == 1
|
129
|
+
end
|
130
|
+
|
131
|
+
def build_pivot_query(table, statement)
|
132
|
+
columns = get_columns($table)
|
133
|
+
key = get_primary_key($table)
|
134
|
+
|
135
|
+
case statement
|
136
|
+
when :insert
|
137
|
+
sql = <<SQL
|
138
|
+
SELECT CONCAT('/* ', trigger_at, ' */ DELETE FROM #{$table} WHERE id = ', MAX(primary_key),';') AS `row`
|
139
|
+
FROM audits
|
140
|
+
WHERE `type` = 'I'
|
141
|
+
AND `table` = '#{$table}'
|
142
|
+
GROUP BY primary_key
|
143
|
+
ORDER BY trigger_at, primary_key, `column` ASC;
|
144
|
+
SQL
|
145
|
+
when :delete
|
146
|
+
sql = "SELECT CONCAT('/* ', trigger_at, ' */ INSERT INTO #{$table} (#{key}, #{columns.join(', ')}) VALUES (', primary_key, ', ', "
|
147
|
+
columns.each do | column |
|
148
|
+
sql << " QUOTE(MAX(IF(`column` = '#{column}', `old`, NULL))), ', ', "
|
149
|
+
end
|
150
|
+
sql = sql.chomp(" ', ', ")
|
151
|
+
sql << "');'"
|
152
|
+
sql << ") AS `row` FROM audits WHERE `type` = 'D' AND `table` = '#{$table}' GROUP BY primary_key ORDER BY trigger_at, primary_key, `column` ASC;"
|
153
|
+
when :update
|
154
|
+
sql = "SELECT CONCAT('/* ', trigger_at, ' */ UPDATE users SET ', `column`, ' = ', QUOTE(old), ' WHERE id = ', primary_key, ';') AS `row`"
|
155
|
+
sql << "FROM audits WHERE `type` = 'U' AND `table` = '#{$table}' ORDER BY trigger_at, primary_key, `column` ASC;"
|
156
|
+
end
|
157
|
+
|
158
|
+
sql_result = @mysql.query(sql)
|
159
|
+
sql_result.each(:as => :array) do |row|
|
160
|
+
puts row
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def rollback(table, statement)
|
165
|
+
build_pivot_query(table, statement)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/lib/mysqlaudit.rb
ADDED
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mysqlaudit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nicola Strappazzon C.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: MySQL tool for audit all tables with triggers.
|
14
|
+
email: nicola51980@gmail.com
|
15
|
+
executables:
|
16
|
+
- mysqlaudit
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/mysqlaudit
|
21
|
+
- lib/mysqlaudit/actions.rb
|
22
|
+
- lib/mysqlaudit/audit.rb
|
23
|
+
- lib/mysqlaudit/version.rb
|
24
|
+
- lib/mysqlaudit.rb
|
25
|
+
- LICENSE.txt
|
26
|
+
- README.md
|
27
|
+
homepage: https://github.com/nicola51980/mysqlaudit
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.0.5
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: MySQL Audit Tool
|
51
|
+
test_files: []
|