From 7c007d564ad605bbc306eeabe454c16d23a826f0 Mon Sep 17 00:00:00 2001 From: following Date: Thu, 27 Jun 2013 21:59:38 +0200 Subject: [PATCH] improved trigger/sp handling of database versioning - skip dbsv-update if triggers/sp are not installed (yet) - added safeguard against downgrading to old trigger/sp versions --- bin/dbsv-update.php | 65 +++++++++++++++---- .../doc/sql/stored-proc/maintain-113.inc.php | 9 +++ .../doc/sql/stored-proc/maintain-114.inc.php | 19 ++++++ .../sql/stored-proc/maintain-current.inc.php | 12 +++- htdocs/lib2/db.inc.php | 55 +++++++++++----- 5 files changed, 131 insertions(+), 29 deletions(-) create mode 100644 htdocs/doc/sql/stored-proc/maintain-114.inc.php diff --git a/bin/dbsv-update.php b/bin/dbsv-update.php index 5413582f..aa02ac45 100644 --- a/bin/dbsv-update.php +++ b/bin/dbsv-update.php @@ -22,10 +22,24 @@ require_once($opt['rootpath'] . 'lib2/cli.inc.php'); if (!sql_field_exists('cache_attrib','gc_id')) - die("\n - ERROR: Database structure too old. You must first do a manual update - up to commit 467aae4 (March 27, 2013) to enable automatic updates. - See htdocs/doc/sql/db-changes.txt.\n"); + { + die( + " ERROR: Database structure too old. You must first do a manual update\n" . + " up to commit 467aae4 (March 27, 2013) to enable automatic updates.\n" . + " See htdocs/doc/sql/db-changes.txt.\n"); + // Do not continue with dbupdate.php, because the current data.sql and + // maintain.php will not fit either. + } + + if (!sql_function_exists('distance') || !sql_procedure_exists('sp_touch_cache')) + { + // We need a consistent starting point including triggers & functions, and it's + // safer not to decide HERE which trigger version to install. + echo "Triggers / DB functions are not installed (yet) - skipping DB versioning.\n"; + exit; + // continue with dbupdate.php if called from there and let's hope + // maintain.php matches the installed tables' DB version ... + } $db_version = max(99, sql_value("SELECT `value` FROM `sysconfig` WHERE `name`='db_version'",99)); @@ -59,15 +73,27 @@ { global $opt, $db_version; - $syncfile = $opt['rootpath'] . 'cache2/dbsv-running'; - file_put_contents($syncfile,'dbsv is running'); + // For the case we re-run an old mutation for some accident, we must make + // sure that we are not downgrading to an old trigger version (which may be + // incompatible with the current database structures. + if (sql_function_exists('dbsvTriggerVersion')) + $trigger_version = sql_value('SELECT dbsvTriggerVersion()',0); + else + $trigger_version = 0; - system('php ' . $opt['rootpath'] . 'doc/sql/stored-proc/maintain.php --dbsv '.$db_version.' --flush'); - - if (file_exists($syncfile)) + if ($trigger_version < $db_version) { - die("\nmaintain.php was not properly executed\n"); - unlink($syncfile); + $syncfile = $opt['rootpath'] . 'cache2/dbsv-running'; + file_put_contents($syncfile,'dbsv is running'); + + system('php ' . $opt['rootpath'] . 'doc/sql/stored-proc/maintain.php --dbsv '.$db_version.' --flush'); + // This will also update dbsvTriggerVersion. + + if (file_exists($syncfile)) + { + die("\nmaintain.php was not properly executed\n"); + unlink($syncfile); + } } } @@ -274,8 +300,23 @@ sql("ALTER TABLE `caches` ADD INDEX `wp_gc_maintained` (`wp_gc_maintained`)"); } - function dbv_113() // preventive trigger update + function dbv_113() // preventive, initial trigger update { + // The if-condition ensures that we will not downgrade to an old trigger + // version for the case this function is re-run by some accident. + // For future trigger updates, this will be ensured by the version + // number returned by dbsvTriggerVersion(). + + if (!sql_function_exists('dbsvTriggerVersion')) + update_triggers(); + } + + function dbv_114() // add dbsvTriggerVersion + { + // dbsvTriggerVersion was introduced AFTER defining mutation #113 (it was + // inserted there later). So we need to additionally install it on installations + // which already updated to v113: + update_triggers(); } diff --git a/htdocs/doc/sql/stored-proc/maintain-113.inc.php b/htdocs/doc/sql/stored-proc/maintain-113.inc.php index b4598760..b4a260a1 100644 --- a/htdocs/doc/sql/stored-proc/maintain-113.inc.php +++ b/htdocs/doc/sql/stored-proc/maintain-113.inc.php @@ -1745,4 +1745,13 @@ UPDATE caches SET meta_last_modified=NOW() WHERE caches.wp_oc=OLD.wp; END;"); + // Update trigger version. + // Keep this at the end of this file. + sql_dropFunction('dbsvTriggerVersion'); + $db_version = sqlValue("SELECT `value` FROM `sysconfig` WHERE `name`='db_version'", 0); + sql(" + CREATE FUNCTION `dbsvTriggerVersion` () RETURNS INT + RETURN '&1'", + $db_version); + ?> \ No newline at end of file diff --git a/htdocs/doc/sql/stored-proc/maintain-114.inc.php b/htdocs/doc/sql/stored-proc/maintain-114.inc.php new file mode 100644 index 00000000..347ca9c7 --- /dev/null +++ b/htdocs/doc/sql/stored-proc/maintain-114.inc.php @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/htdocs/doc/sql/stored-proc/maintain-current.inc.php b/htdocs/doc/sql/stored-proc/maintain-current.inc.php index 2e2a09c6..e5d7b066 100644 --- a/htdocs/doc/sql/stored-proc/maintain-current.inc.php +++ b/htdocs/doc/sql/stored-proc/maintain-current.inc.php @@ -1739,4 +1739,14 @@ UPDATE caches SET meta_last_modified=NOW() WHERE caches.wp_oc=OLD.wp; END;"); -?> \ No newline at end of file + + // Update trigger version function. + // Keep this at the end of this file. + sql_dropFunction('dbsvTriggerVersion'); + $db_version = sqlValue("SELECT `value` FROM `sysconfig` WHERE `name`='db_version'", 0); + sql(" + CREATE FUNCTION `dbsvTriggerVersion` () RETURNS INT + RETURN '&1'", + $db_version); + +?> diff --git a/htdocs/lib2/db.inc.php b/htdocs/lib2/db.inc.php index 37c7c24b..24b92395 100644 --- a/htdocs/lib2/db.inc.php +++ b/htdocs/lib2/db.inc.php @@ -1089,22 +1089,6 @@ fclose($f); } - function sql_dropFunction($name) - { - global $dbname; - - $rs = sql("SHOW FUNCTION STATUS LIKE '&1'", $name); - while ($r = sql_fetch_assoc($rs)) - { - if ($r['Db'] == $dbname && $r['Name'] == $name && $r['Type'] == 'FUNCTION') - { - sql('DROP FUNCTION `&1`', $name); - return; - } - } - sql_free_result($rs); - } - // test if a database table exists function sql_table_exists($table) { @@ -1150,4 +1134,43 @@ 0, $opt['db']['placeholder']['db'], $table, $index) > 0; } + // test if a function or procedure exists + function sql_fp_exists($type, $name) + { + global $opt; + + $rs = sql("SHOW $type STATUS LIKE '&1'", $name); + $r = sql_fetch_assoc($rs); + sql_free_result($rs); + + return ($r && + $r['Db'] == $opt['db']['placeholder']['db'] && + $r['Name'] == $name && + $r['Type'] == $type); + } + + // test if a function exists + function sql_function_exists($name) + { + return sql_fp_exists('FUNCTION',$name); + } + + // delete a function + function sql_dropFunction($name) + { + sql('DROP FUNCTION IF EXISTS `&1`', $name); + } + + // test if a procedure exists + function sql_procedure_exists($name) + { + return sql_fp_exists('PROCEDURE',$name); + } + + // delete a procedure + function sql_dropProcedure($name) + { + sql('DROP PROCEDURE IF EXISTS `&1`', $name); + } + ?> \ No newline at end of file