Ich habe mich in letzter Zeit etwas mehr mit SQL an sich beschäftigt und bin dabei auf einige intressante Features gestossen, die nirgendwo in LoGD verwendet werden aber durchaus nützlich sein können. Und zwar sind das die sogenannten Trigger - Datenbankevents, die bei bestimmten Momenten ausgelöst werden und SQL-Code ausführt.
Man kann so die ganzen Account-Lösch-Aufräumarbeiten in die Datenbank auslagern. Die Vorteile liegen auf der Hand: Da die Latenz PHP<=>MySQL wegfällt sparrt man damit Zeit. Und man kann sich darauf verlassen, dass die Datenintegrität immer gegeben ist - wenn man zwei verschiedene PHP-Löschroutinen hat und die nicht synchron hält, können durchaus noch Reste übrig bleiben.
Leider hat das ganze auch einige Nachteile: Zuerst einmal braucht man für Trigger mindestens MySQL in der Version 5. Und dann ist es auch nicht garantiert, dass das Trigger-Erstellen mit jeder PHP-Version funktioniert (mysql_query funktioniert mit PHP 5.2.6, vermutlich nicht mit PHP < 5.). Das heisst, ich empfehle das, was ich hier vorstelle nur Leuten, die auch wissen, was sie tun.
Die Triggerfactory, die ich hier vorstelle und aus YaGD portiert wurde, kümmert sich um das erstellen der Trigger und das löschen der selben, um das aktualisieren. Die Informationen werden systematisch in einer Tabelle gespeichert. Der Vorteil der ganzen Geschichte ist, dass die Triggerfactory theoretisch Module unterstützt.
$this->bbcode_second_pass_code('', 'CREATE TABLE IF NOT EXISTS `triggers` (
triggertable varchar(128) NOT NULL,
triggertype varchar(7) NOT NULL,
triggerposition varchar(6) NOT NULL,
triggeridentifier varchar(64) NOT NULL,
triggercode text NOT NULL,
PRIMARY KEY (triggertable,triggertype,triggerposition,triggeridentifier)
);')
$this->bbcode_second_pass_code('', '/*
* Trigger: A factory which builds mysql triggers automaticly.
*
* Dependencies:
* - LoGD-0.9.7+jt ext GER 3
* - function db_query_secure()
*
* Copyright 2009 Basilius Sauter <basilius.sauter@hispeed.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
class Trigger {
protected $type = array(
'INSERT' => 'INSERT',
'UPDATE' => 'UPDATE',
'DELETE' => 'DELETE'
);
protected $position = array(
'AFTER' => 'AFTER',
'BEFORE' => 'BEFORE',
);
# creates a trigger-event.
# $id: A Identifier, like a modulename. Must be Unique with $table, $position and $type.
# $table: The table that should be surveilled by MySQL.
# $position: AFTER or BEFORE an Event.
# $type: INSERT, UPDATE or DELETE. Not the same as the MySQL-Commands INSERT INTO, UPDATE or DELETE FROM.
# $code: MySQL-Code which should be executed. Can contents multiple queries.
public static function add($id, $table, $position, $type, $code) {
$position = strToUpper($position);
$type = strToUpper($type);
$sql = 'INSERT INTO triggers (triggertable, triggertype, triggerposition, triggeridentifier, triggercode)
VALUES (?,?,?,?,?)
ON DUPLICATE KEY UPDATE triggercode = VALUES(triggercode)';
$args = array($table, $type, $position, $id, $code);
db_query_secure($sql, $args);
self::rebuildTrigger($table, $position, $type);
}
# Drops a trigger-event
# $id: A Identifier, like a modulename. Must be Unique with $table, $position and $type.
# $table: The table that should be surveilled by MySQL.
# $position: AFTER or BEFORE an Event.
# $type: INSERT, UPDATE or DELETE. Not the same as the MySQL-Commands INSERT INTO, UPDATE or DELETE FROM.
public static function drop($id, $table, $position, $type) {
$position = strToUpper($position);
$type = strToUpper($type);
$sql = 'DELETE FROM triggers WHERE triggertable = ? AND triggerposition = ? AND triggertype = ? AND triggeridentifier = ?';
$args = array($table, $position, $type, $id);
db_query_secure($sql, $args);
self::rebuildTrigger($table, $position, $type);
}
# Rebuilds the triggers $table-$position-$type.
protected static function rebuildTrigger($table, $position, $type) {
$triggername = self::getTriggerName($table, $position, $type);
$sql = 'SELECT triggercode FROM triggers WHERE triggertable = ? AND triggerposition = ? AND triggertype = ?';
$args = array($table, $position, $type);
$res= db_query_secure($sql, $args);
if(db_num_rows($res) > 0) {
// Killing Trigger
$triggerSQL = sprintf('DROP TRIGGER IF EXISTS %s', $triggername);
db_query($triggerSQL);
unset($triggerSQL);
$code = array();
# Fix by Harthas. Replaces YaGD-Code.
while( $row = db_fetch_assoc( $res ) ) {
array_push($code, $row['triggercode']);
unset($row);
}
$triggerSQL = sprintf('CREATE TRIGGER %s
%s %s ON %s
FOR EACH ROW
BEGIN
%s
END;
', $triggername, $position, $type, $table, implode("\n", $code));
}
else {
$triggerSQL = sprintf('DROP TRIGGER IF EXISTS %s', $triggername);
}
db_query($triggerSQL);
}
# Returns the systematic trigger name from $table, $position and $type.
protected static function getTriggerName($table, $position, $type) {
return strtolower(sprintf('%s_%s_%s', $table, $position, $type));
}
}')