* Backup: backup could contain rows multiple times (which caused restore to fail)

This commit is contained in:
Ralf Becker 2014-07-11 17:36:27 +00:00
parent 80f1abf3a2
commit 597b0ff2e2

View File

@ -7,7 +7,7 @@
* @package api * @package api
* @subpackage db * @subpackage db
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2003-12 by Ralf Becker <RalfBecker-AT-outdoor-training.de> * @copyright (c) 2003-14 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @version $Id$ * @version $Id$
*/ */
@ -79,6 +79,12 @@ class db_backup
* @var boolean * @var boolean
*/ */
var $backup_files = false ; var $backup_files = false ;
/**
* Reference to schema_proc's egw_db object
*
* @var egw_db
*/
var $db;
/** /**
* Constructor * Constructor
@ -278,7 +284,7 @@ class db_backup
/* Sort the files by ctime. */ /* Sort the files by ctime. */
krsort($files); krsort($files);
$count = 0; $count = 0;
foreach($files as $ctime => $file) foreach($files as $file)
{ {
if ($count >= $this->backup_mincount)// if ($count >= $this->backup_mincount)//
{ {
@ -411,6 +417,7 @@ class db_backup
} }
$table = False; $table = False;
$n = 0; $n = 0;
$rows = array();
while(!feof($f)) while(!feof($f))
{ {
$line = trim(fgets($f)); ++$n; $line = trim(fgets($f)); ++$n;
@ -620,7 +627,6 @@ class db_backup
if($type == 'zip') if($type == 'zip')
{ {
fclose($f); fclose($f);
$f = $save_f;
unlink($name); unlink($name);
rmdir($dir.'/database_backup'); rmdir($dir.'/database_backup');
} }
@ -723,7 +729,7 @@ class db_backup
$str_pending = False; $str_pending = False;
$n = 0; $n = 0;
foreach($fields as $i => $field) foreach($fields as $field)
{ {
if ($str_pending !== False) if ($str_pending !== False)
{ {
@ -839,12 +845,24 @@ class db_backup
{ {
if (in_array($table,$this->exclude_tables)) continue; // dont backup if (in_array($table,$this->exclude_tables)) continue; // dont backup
$total = 0; // do we have a primary key?
// --> use it to order and limit rows, to kope with rows being added during backup
// otherwise new rows can cause rows being backed up twice and
// backups don't restore because of doublicate keys
$pk = $schema['pk'] && count($schema['pk']) == 1 ? $schema['pk'][0] : null;
$total = $max = 0;
do { do {
$num_rows = 0; $num_rows = 0;
// querying only chunks for 100 rows, to not run into memory limit on huge tables // querying only chunks for 10000 rows, to not run into memory limit on huge tables
foreach($this->db->select($table, '*', false, __LINE__, __FILE__, $total, '', false, self::ROW_CHUNK) as $row) foreach($this->db->select($table, '*',
empty($pk) ? false : $pk.' > '.$max, // limit by maximum primary key already received
__LINE__, __FILE__,
empty($pk) ? $total : 0, // if no primary limit by number of received rows
empty($pk) ? '' : 'ORDER BY '.$pk.' ASC', // order by primary key
false, self::ROW_CHUNK) as $row)
{ {
if (!empty($pk)) $max = $row[$pk];
if ($total === 0) fwrite($f,"\ntable: $table\n".implode(',',array_keys($row))."\n"); if ($total === 0) fwrite($f,"\ntable: $table\n".implode(',',array_keys($row))."\n");
array_walk($row,array('db_backup','escape_data'),$schema['fd']); array_walk($row,array('db_backup','escape_data'),$schema['fd']);
@ -870,14 +888,14 @@ class db_backup
//echo $name.'<br>'; //echo $name.'<br>';
$zip->addFile($name, 'database_backup/'.basename($name)); $zip->addFile($name, 'database_backup/'.basename($name));
$count = 1; $count = 1;
foreach($file_list as $num => $file) foreach($file_list as $file)
{ {
//echo substr($file,strlen($dir)+1).'<br>'; //echo substr($file,strlen($dir)+1).'<br>';
//echo $file.'<br>'; //echo $file.'<br>';
$zip->addFile($file,substr($file,strlen($dir)+1));//,substr($file); $zip->addFile($file,substr($file,strlen($dir)+1));//,substr($file);
if(($count++) == 100) { // the file descriptor limit if(($count++) == 100) { // the file descriptor limit
$zip->close(); $zip->close();
if($zip = new ZipArchive()) { if(($zip = new ZipArchive())) {
$zip->open($filename); $zip->open($filename);
$count =0; $count =0;
} }
@ -1009,7 +1027,7 @@ class db_backup
} }
else else
{ {
if (!$only_vals && $key === 'nullable') if ($key === 'nullable')
{ {
$def .= $val ? 'True' : 'False'; $def .= $val ? 'True' : 'False';
} }