New: Can fix some fatal errors with a repair script.

This commit is contained in:
Laurent Destailleur 2009-06-15 18:16:22 +00:00
parent b96f501799
commit 70c4f0bd93
4 changed files with 167 additions and 128 deletions

View File

@ -42,6 +42,7 @@ For developers:
- Updated wiki documentation.
- Better W3C standard.
- Can add data provided with a module.
- Can fix some corruptions in database by calling the update page with action=repair
***** Changelog for 2.6 compared to 2.5 *****

View File

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2008 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004-2009 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2009 Regis Houssin <regis@dolibarr.fr>
*
* This program is free software; you can redistribute it and/or modify
@ -19,10 +19,11 @@
*/
/**
\file htdocs/install/upgrade.php
\brief Run migration script
\version $Id$
*/
* \file htdocs/install/upgrade.php
* \brief Run migration script
* \version $Id$
* \remarks Can be also called directly with http://mydolibarr/install/upgrade.php?action=repair
*/
include_once("./inc.php");
if (file_exists($conffile)) include_once($conffile);
@ -60,14 +61,22 @@ dolibarr_install_syslog("upgrade: Entering upgrade.php page");
if (! is_object($conf)) dolibarr_install_syslog("upgrade2: conf file not initialized",LOG_ERR);
/*
* View
*/
pHeader($langs->trans("DatabaseMigration"),"upgrade2","upgrade");
$actiondone=0;
if (! isset($_GET["action"]) || $_GET["action"] == "upgrade")
// Action to launch the repair or migrate script
if (! isset($_GET["action"]) || $_GET["action"] == "upgrade" || $_GET["action"] == "repair")
{
$actiondone=1;
print '<h3>'.$langs->trans("DatabaseMigration").'<h3>';
if (! $versionfrom && ! $versionto)
if ($_GET["action"] != "repair" && ! $versionfrom && ! $versionto)
{
print '<div class="error">Parameter versionfrom or version to missing.</div>';
exit;
@ -138,131 +147,137 @@ if (! isset($_GET["action"]) || $_GET["action"] == "upgrade")
print '<tr><td colspan="2">'.$langs->trans("PleaseBePatient").'</td></tr>';
flush();
// Delete duplicates in table categorie_association
$couples=array();
$filles=array();
$sql = "SELECT fk_categorie_mere, fk_categorie_fille";
$sql.= " FROM ".MAIN_DB_PREFIX."categorie_association";
dolibarr_install_syslog("upgrade: search duplicate sql=".$sql);
$resql = $db->query($sql);
if ($resql)
if ($_GET["action"] != "repair")
{
$num=$db->num_rows($resql);
while ($obj=$db->fetch_object($resql))
/*
* Delete duplicates in table categorie_association
*/
$couples=array();
$filles=array();
$sql = "SELECT fk_categorie_mere, fk_categorie_fille";
$sql.= " FROM ".MAIN_DB_PREFIX."categorie_association";
dolibarr_install_syslog("upgrade: search duplicate sql=".$sql);
$resql = $db->query($sql);
if ($resql)
{
if (! isset($filles[$obj->fk_categorie_fille])) // Only one record as child (a child has only on parent).
$num=$db->num_rows($resql);
while ($obj=$db->fetch_object($resql))
{
if ($obj->fk_categorie_mere != $obj->fk_categorie_fille)
if (! isset($filles[$obj->fk_categorie_fille])) // Only one record as child (a child has only on parent).
{
$filles[$obj->fk_categorie_fille]=1; // Set record for this child
$couples[$obj->fk_categorie_mere.'_'.$obj->fk_categorie_fille]=array('mere'=>$obj->fk_categorie_mere, 'fille'=>$obj->fk_categorie_fille);
}
}
}
dolibarr_install_syslog("upgrade: result is num=".$num." sizeof(couples)=".sizeof($couples));
// If there is duplicates couples or child with two parents
if (sizeof($couples) > 0 && $num > sizeof($couples))
{
$error=0;
$db->begin();
$sql="DELETE FROM ".MAIN_DB_PREFIX."categorie_association";
dolibarr_install_syslog("upgrade: delete association sql=".$sql);
$resqld=$db->query($sql);
if ($resqld)
{
foreach($couples as $key => $val)
{
$sql ="INSERT INTO ".MAIN_DB_PREFIX."categorie_association(fk_categorie_mere,fk_categorie_fille)";
$sql.=" VALUES(".$val['mere'].", ".$val['fille'].")";
dolibarr_install_syslog("upgrade: insert association sql=".$sql);
$resqli=$db->query($sql);
if (! $resqli) $error++;
}
}
if (! $error)
{
print '<tr><td>'.$langs->trans("RemoveDuplicates").'</td>';
print '<td align="right">'.$langs->trans("Success").' ('.$num.'=>'.sizeof($couples).')</td></tr>';
$db->commit();
}
else
{
print '<tr><td>'.$langs->trans("RemoveDuplicates").'</td>';
print '<td align="right">'.$langs->trans("Failed").'</td></tr>';
$db->rollback();
}
}
}
else
{
print '<div class="error">'.$langs->trans("Error").'</div>';
}
if ($ok)
{
$versioncommande=split('\.','4.0');
if (sizeof($versioncommande) && sizeof($versionarray)
&& versioncompare($versioncommande,$versionarray) <= 0) // Si mysql >= 4.0
{
// Suppression vieilles contraintes sans noms et en doubles
// Les contraintes indesirables ont un nom qui commence par 0_ ou se termine par ibfk_999
/* $listtables=array( 'llx_product_fournisseur_price',
'llx_fichinter',
'llx_facture_fourn',
'llx_propal',
'llx_socpeople',
'llx_telephonie_adsl_fournisseur',
'llx_telephonie_client_stats',
'llx_telephonie_contact_facture',
'llx_telephonie_societe_ligne',
'llx_telephonie_tarif_client');
*/
$listtables = $db->DDLListTables($conf->db->name,'');
foreach ($listtables as $val)
{
//print "x".$val."<br>";
$sql = "SHOW CREATE TABLE ".$val;
$resql = $db->query($sql);
if ($resql)
{
$values=$db->fetch_array($resql);
$i=0;
$createsql=$values[1];
while (eregi('CONSTRAINT `(0_[0-9a-zA-Z]+|[_0-9a-zA-Z]+_ibfk_[0-9]+)`',$createsql,$reg) && $i < 100)
if ($obj->fk_categorie_mere != $obj->fk_categorie_fille)
{
$sqldrop="ALTER TABLE ".$val." DROP FOREIGN KEY ".$reg[1];
$resqldrop = $db->query($sqldrop);
if ($resqldrop)
{
print '<tr><td colspan="2">'.$sqldrop.";</td></tr>\n";
}
$createsql=eregi_replace('CONSTRAINT `'.$reg[1].'`','XXX',$createsql);
$i++;
$filles[$obj->fk_categorie_fille]=1; // Set record for this child
$couples[$obj->fk_categorie_mere.'_'.$obj->fk_categorie_fille]=array('mere'=>$obj->fk_categorie_mere, 'fille'=>$obj->fk_categorie_fille);
}
$db->free($resql);
}
}
dolibarr_install_syslog("upgrade: result is num=".$num." sizeof(couples)=".sizeof($couples));
// If there is duplicates couples or child with two parents
if (sizeof($couples) > 0 && $num > sizeof($couples))
{
$error=0;
$db->begin();
$sql="DELETE FROM ".MAIN_DB_PREFIX."categorie_association";
dolibarr_install_syslog("upgrade: delete association sql=".$sql);
$resqld=$db->query($sql);
if ($resqld)
{
foreach($couples as $key => $val)
{
$sql ="INSERT INTO ".MAIN_DB_PREFIX."categorie_association(fk_categorie_mere,fk_categorie_fille)";
$sql.=" VALUES(".$val['mere'].", ".$val['fille'].")";
dolibarr_install_syslog("upgrade: insert association sql=".$sql);
$resqli=$db->query($sql);
if (! $resqli) $error++;
}
}
if (! $error)
{
print '<tr><td>'.$langs->trans("RemoveDuplicates").'</td>';
print '<td align="right">'.$langs->trans("Success").' ('.$num.'=>'.sizeof($couples).')</td></tr>';
$db->commit();
}
else
{
if ($db->lasterrno() != 'DB_ERROR_NOSUCHTABLE')
print '<tr><td>'.$langs->trans("RemoveDuplicates").'</td>';
print '<td align="right">'.$langs->trans("Failed").'</td></tr>';
$db->rollback();
}
}
}
else
{
print '<div class="error">'.$langs->trans("Error").'</div>';
}
/*
* Remove deprecated indexes and constraints
*/
if ($ok)
{
$versioncommande=split('\.','4.0');
if (sizeof($versioncommande) && sizeof($versionarray)
&& versioncompare($versioncommande,$versionarray) <= 0) // Si mysql >= 4.0
{
// Suppression vieilles contraintes sans noms et en doubles
// Les contraintes indesirables ont un nom qui commence par 0_ ou se termine par ibfk_999
/* $listtables=array( 'llx_product_fournisseur_price',
'llx_fichinter',
'llx_facture_fourn',
'llx_propal',
'llx_socpeople',
'llx_telephonie_adsl_fournisseur',
'llx_telephonie_client_stats',
'llx_telephonie_contact_facture',
'llx_telephonie_societe_ligne',
'llx_telephonie_tarif_client');
*/
$listtables = $db->DDLListTables($conf->db->name,'');
foreach ($listtables as $val)
{
//print "x".$val."<br>";
$sql = "SHOW CREATE TABLE ".$val;
$resql = $db->query($sql);
if ($resql)
{
print '<tr><td colspan="2"><font class="error">'.$sql.' : '.$db->lasterror()."</font></td></tr>\n";
$values=$db->fetch_array($resql);
$i=0;
$createsql=$values[1];
while (eregi('CONSTRAINT `(0_[0-9a-zA-Z]+|[_0-9a-zA-Z]+_ibfk_[0-9]+)`',$createsql,$reg) && $i < 100)
{
$sqldrop="ALTER TABLE ".$val." DROP FOREIGN KEY ".$reg[1];
$resqldrop = $db->query($sqldrop);
if ($resqldrop)
{
print '<tr><td colspan="2">'.$sqldrop.";</td></tr>\n";
}
$createsql=eregi_replace('CONSTRAINT `'.$reg[1].'`','XXX',$createsql);
$i++;
}
$db->free($resql);
}
else
{
if ($db->lasterrno() != 'DB_ERROR_NOSUCHTABLE')
{
print '<tr><td colspan="2"><font class="error">'.$sql.' : '.$db->lasterror()."</font></td></tr>\n";
}
}
}
}
}
}
/***************************************************************************************
*
* Chargement fichiers dans migration
*
***************************************************************************************/
/*
* Load sql files
*/
if ($ok)
{
if ($choix==1) $dir = "../../mysql/migration/";
@ -284,16 +299,29 @@ if (! isset($_GET["action"]) || $_GET["action"] == "upgrade")
}
sort($filesindir);
# Determine les fichiers sql a passer
foreach($filesindir as $file)
# Define which file to run
if ($_GET["action"] != "repair")
{
if (eregi($from,$file))
foreach($filesindir as $file)
{
$filelist[]=$file;
if (eregi($from,$file))
{
$filelist[]=$file;
}
else if (eregi($to,$file)) // First test may be false if we migrate from x.y.* to x.y.*
{
$filelist[]=$file;
}
}
else if (eregi($to,$file)) // First test may be false if we migrate from x.y.* to x.y.*
}
else
{
foreach($filesindir as $file)
{
$filelist[]=$file;
if (eregi('repair',$file))
{
$filelist[]=$file;
}
}
}
@ -314,7 +342,9 @@ if (! isset($_GET["action"]) || $_GET["action"] == "upgrade")
if ($db->connected) $db->close();
}
else
if (empty($actiondone))
{
print '<div class="error">'.$langs->trans("ErrorWrongParameters").'</div>';
}

View File

@ -172,8 +172,3 @@ alter table llx_commande_fournisseur add column ref_supplier varchar(30
alter table llx_mailing add column bgcolor varchar(8) after body;
alter table llx_mailing add column bgimage varchar(255) after bgcolor;
-- Request to clean corrupted database
delete from llx_facture where facnumber = '(PROV)';
delete from llx_commande where ref = '(PROV)';
delete from llx_propal where ref = '(PROV)';

View File

@ -0,0 +1,13 @@
--
-- $Id$
--
-- Script to repair some fatal errors due to database corruption
--
-- when current version is 2.6.0 or higher.
--
-- Request to clean corrupted database
delete from llx_facture where facnumber = '(PROV)';
delete from llx_commande where ref = '(PROV)';
delete from llx_propal where ref = '(PROV)';