Skip to content

Instantly share code, notes, and snippets.

@jstroem
Last active November 25, 2015 08:09
Show Gist options
  • Save jstroem/a8fdc5ff89cbc820783c to your computer and use it in GitHub Desktop.
Save jstroem/a8fdc5ff89cbc820783c to your computer and use it in GitHub Desktop.
A simple way to get a history log on a complete table without getting hurt on the SELECT performance.
//Replace `TABLE_NAME` with the name of the table
//Replace `DB_NAME` with the database name.
//Replace `PRIMARY_KEY` with the primary key of the `TABLE_NAME`
CREATE TABLE DB_NAME.TABLE_NAME_history LIKE DB_NAME.TABLE_NAME;
ALTER TABLE DB_NAME.TABLE_NAME_history MODIFY COLUMN PRIMARY_KEY int(11) NOT NULL,
DROP PRIMARY KEY, ENGINE = MyISAM, ADD action VARCHAR(8) DEFAULT 'insert' FIRST,
ADD revision INT(6) NOT NULL AUTO_INCREMENT AFTER action,
ADD dt_datetime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER revision,
ADD PRIMARY KEY (PRIMARY_KEY, revision);
DROP TRIGGER IF EXISTS DB_NAME.TABLE_NAME__ai;
DROP TRIGGER IF EXISTS DB_NAME.TABLE_NAME__au;
DROP TRIGGER IF EXISTS DB_NAME.TABLE_NAME__bd;
CREATE TRIGGER DB_NAME.TABLE_NAME__ai AFTER INSERT ON DB_NAME.TABLE_NAME FOR EACH ROW
INSERT INTO DB_NAME.TABLE_NAME_history SELECT 'insert', NULL, NOW(), d.*
FROM DB_NAME.TABLE_NAME AS d WHERE d.PRIMARY_KEY = NEW.PRIMARY_KEY;
CREATE TRIGGER DB_NAME.TABLE_NAME__au AFTER UPDATE ON DB_NAME.TABLE_NAME FOR EACH ROW
INSERT INTO DB_NAME.TABLE_NAME_history SELECT 'update', NULL, NOW(), d.*
FROM DB_NAME.TABLE_NAME AS d WHERE d.PRIMARY_KEY = NEW.PRIMARY_KEY;
CREATE TRIGGER DB_NAME.TABLE_NAME__bd BEFORE DELETE ON DB_NAME.TABLE_NAME FOR EACH ROW
INSERT INTO DB_NAME.TABLE_NAME_history SELECT 'delete', NULL, NOW(), d.*
FROM DB_NAME.TABLE_NAME AS d WHERE d.PRIMARY_KEY = OLD.PRIMARY_KEY;
private $history_table_name = "???";
private $history_primary_key = 'id';
public function up()
{
$this->execute('CREATE TABLE '.$this->history_table_name.'_history LIKE '.$this->history_table_name.'');
$table = $this->table($this->history_table_name.'_history');
$table->changeColumn($this->history_primary_key, 'integer', array('null' => false));
$table->addColumn('action', 'string', array('limit' => 8, 'default' => 'insert'));
$table->addColumn('revision_at', 'datetime', array('default' => null, 'null' => true));
$table->update();
$this->execute('ALTER TABLE '.$this->history_table_name.'_history DROP PRIMARY KEY, ENGINE = MyISAM, ADD revisionid INT(11) NOT NULL AUTO_INCREMENT AFTER action, ADD PRIMARY KEY ('.$this->history_primary_key.', revisionid)');
$this->execute("CREATE TRIGGER ".$this->history_table_name."__ai AFTER INSERT ON ".$this->history_table_name." FOR EACH ROW ".
"INSERT INTO ".$this->history_table_name."_history SELECT d.*, 'insert', NULL, NOW() ".
"FROM ".$this->history_table_name." AS d WHERE d.".$this->history_primary_key." = NEW.".$this->history_primary_key.";");
$this->execute(
"CREATE TRIGGER ".$this->history_table_name."__au AFTER UPDATE ON ".$this->history_table_name." FOR EACH ROW ".
"INSERT INTO ".$this->history_table_name."_history SELECT d.*, 'update', NULL, NOW() ".
"FROM ".$this->history_table_name." AS d WHERE d.".$this->history_primary_key." = NEW.".$this->history_primary_key.";");
$this->execute(
"CREATE TRIGGER ".$this->history_table_name."__bd BEFORE DELETE ON ".$this->history_table_name." FOR EACH ROW ".
"INSERT INTO ".$this->history_table_name."_history SELECT d.*, 'delete', NULL, NOW() ".
"FROM ".$this->history_table_name." AS d WHERE d.".$this->history_primary_key." = OLD.".$this->history_primary_key.";");
}
public function down(){
$this->dropTable($this->history_table_name.'_history');
$this->execute('DROP TRIGGER IF EXISTS '.$this->history_table_name.'__ai;');
$this->execute('DROP TRIGGER IF EXISTS '.$this->history_table_name.'__au;');
$this->execute('DROP TRIGGER IF EXISTS '.$this->history_table_name.'__bd;');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment