reworked installation/upgrade process to not use delta-updates any more, as we can now reliable read the schema back from our supported databases:

- makes update scripts a lot easier and saver
- updates are a lot faster now
==> only the needed update-functions get called
This commit is contained in:
Ralf Becker 2004-10-23 15:00:44 +00:00
parent fe6b0728de
commit 630c88d766
5 changed files with 184 additions and 436 deletions

View File

@ -131,6 +131,9 @@ class ADODB2_postgres extends ADODB_DataDict {
list($lines,$pkey) = $this->_GenFields($flds);
$alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
foreach($lines as $v) {
if (($not_null = preg_match('/NOT NULL/i',$v))) {
$v = preg_replace('/NOT NULL/i','',$v);
}
if (preg_match('/^([^ ]+) .*(DEFAULT [^ ]+)/',$v,$matches)) {
list(,$colname,$default) = $matches;
$sql[] = $alter . str_replace($default,'',$v);
@ -138,6 +141,10 @@ class ADODB2_postgres extends ADODB_DataDict {
} else {
$sql[] = $alter . $v;
}
if ($not_null) {
list($colname) = explode(' ',$v);
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET NOT NULL';
}
}
return $sql;
}
@ -194,8 +201,8 @@ class ADODB2_postgres extends ADODB_DataDict {
* @internal
* @param string $tabname table-name
* @param string $dropflds column-names to drop
* @param string $tableflds complete defintion of the new table, eg. for postgres, default ''
* @param array/ $tableoptions options for the new table see CreateTableSQL, default ''
* @param string $tableflds complete defintion of the new table, eg. for postgres
* @param array/string $tableoptions options for the new table see CreateTableSQL, default ''
* @return array with SQL strings
*/
function _recreate_copy_table($tabname,$dropflds,$tableflds,$tableoptions='')
@ -204,7 +211,13 @@ class ADODB2_postgres extends ADODB_DataDict {
$copyflds = array();
foreach($this->MetaColumns($tabname) as $fld) {
if (!$dropflds || !in_array($fld->name,$dropflds)) {
// we need to explicit convert varchar to a number to be able to do an AlterColumn of a char column to a nummeric one
if (preg_match('/'.$fld->name.' (I|I2|I4|I8|N|F)/i',$tableflds,$matches) &&
in_array($fld->type,array('varchar','char','text','bytea'))) {
$copyflds[] = "to_number($fld->name,'S99D99')";
} else {
$copyflds[] = $fld->name;
}
// identify the sequence name and the fld its on
if ($fld->primary_key && $fld->has_default &&
preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) {
@ -222,6 +235,7 @@ class ADODB2_postgres extends ADODB_DataDict {
$aSql = array_merge($aSql,$this->CreateTableSQL($tabname,$tableflds,$tableoptions));
$aSql[] = "INSERT INTO $tabname SELECT $copyflds FROM $tempname";
if ($seq_name && $seq_fld) { // if we have a sequence we need to set it again
$seq_name = $tabname.'_'.$seq_fld.'_seq'; // has to be the name of the new implicit sequence
$aSql[] = "SELECT setval('$seq_name',MAX($seq_fld)) FROM $tabname";
}
$aSql[] = "DROP TABLE $tempname";

View File

@ -27,9 +27,7 @@
class schema_proc
{
var $m_oTranslator;
var $m_oDeltaProc;
var $m_odb;
var $m_aTables; // stores the table-definitions of an application, set by ExecuteScripts
var $m_bDeltaOnly;
var $debug = 0; // 0=Off, 1=some, eg. primary function calls, 2=lots incl. the SQL used
var $max_index_length=array( // if known
@ -43,11 +41,8 @@
*
* @param string $dbms type of the database: 'mysql','pgsql','mssql','sapdb'
*/
function schema_proc($dbms=False,$aTables=False)
function schema_proc($dbms=False)
{
$this->m_aTables = array();
$this->m_bDeltaOnly = False; // Default to false here in case it's just a CreateTable script
$this->m_odb = is_object($GLOBALS['phpgw']->db) ? $GLOBALS['phpgw']->db : $GLOBALS['phpgw_setup']->db;
$this->m_odb->connect();
@ -84,9 +79,6 @@
{
$this->debug_message('schema_proc::CreateTable(%1,%2)',False,$sTableName, $aTableDef);
}
$this->m_aTables[$sTableName] = $aTableDef;
if($this->m_bDeltaOnly) return true;
// creating the table
$aSql = $this->dict->CreateTableSQL($sTableName,$ado_cols = $this->_egw2adodb_columndef($aTableDef));
if (!($retVal = $this->ExecuteSQLArray($aSql,2,'CreateTableSQL(%1,%2) sql=%3',False,$sTableName,$ado_cols,$aSql)))
@ -170,9 +162,6 @@
if ($this->debug) $bOutputHTML = True;
if ($bOutputHTML && !$this->debug) $this->debug = 2;
$this->m_aTables = array();
if($this->m_bDeltaOnly) return true;
foreach($aTables as $sTableName => $aTableDef)
{
if($this->DropTable($sTableName))
@ -198,9 +187,6 @@
*/
function DropTable($sTableName)
{
unset($this->m_aTables[$sTableName]);
if($this->m_bDeltaOnly) return True;
if ($this->sType == 'pgsql') $this->_PostgresTestDropOldSequence($sTableName);
$aSql = $this->dict->DropTableSql($sTableName);
@ -219,10 +205,10 @@
*/
function DropColumn($sTableName, $aTableDef, $sColumnName, $bCopyData = true)
{
unset($this->m_aTables[$sTableName]['fd'][$sColumnName]);
if($this->m_bDeltaOnly) return True;
$table_def = $this->GetTableDefinition($sTableName);
unset($table_def['fd'][$sColumnName]);
$aSql = $this->dict->DropColumnSql($sTableName,$sColumnName,$ado_table=$this->_egw2adodb_columndef($this->m_aTables[$sTableName]));
$aSql = $this->dict->DropColumnSql($sTableName,$sColumnName,$ado_table=$this->_egw2adodb_columndef($table_def));
return $this->ExecuteSQLArray($aSql,2,'DropColumnSQL(%1,%2,%3) sql=%4',False,$sTableName,$sColumnName,$ado_table,$aSql);
}
@ -236,10 +222,6 @@
*/
function RenameTable($sOldTableName, $sNewTableName)
{
$this->m_aTables[$sNewTableName] = $this->m_aTables[$sOldTableName];
unset($this->m_aTables[$sOldTableName]);
if($this->m_bDeltaOnly) return True;
if ($this->sType == 'pgsql') $this->_PostgresTestDropOldSequence($sTableName);
$aSql = $this->dict->RenameTableSQL($sOldTableName, $sNewTableName);
@ -255,13 +237,14 @@
*/
function _PostgresTestDropOldSequence($sTableName)
{
if (!$this->sType == 'pgsql') return;
if ($this->sType != 'pgsql') return;
$seq = $this->adodb->GetOne("SELECT a.attname FROM pg_attribute a, pg_class c, pg_attrdef d WHERE c.relname='$sTableName' AND c.oid=d.adrelid AND d.adsrc LIKE '%seq_$sTableName%' AND a.attrelid=c.oid AND d.adnum=a.attnum");
$seq = $this->adodb->GetOne("SELECT d.adsrc FROM pg_attribute a, pg_class c, pg_attrdef d WHERE c.relname='$sTableName' AND c.oid=d.adrelid AND d.adsrc LIKE '%seq_$sTableName%' AND a.attrelid=c.oid AND d.adnum=a.attnum");
if ($seq)
if ($seq && preg_match('/^nextval\(\'(.*)\'/',$seq,$matches))
{
$this->query("DROP SEQUENCE $seq",__LINE__,__FILE__);
$this->query('DROP SEQUENCE '.$matches[1],__LINE__,__FILE__);
}
}
@ -276,13 +259,13 @@
*/
function AlterColumn($sTableName, $sColumnName, $aColumnDef, $bCopyData=True)
{
$this->m_aTables[$sTableName]['fd'][$sColumnName] = $aColumnDef;
if($this->m_bDeltaOnly) return True;
$table_def = $this->GetTableDefinition($sTableName);
$table_def['fd'][$sColumnName] = $aColumnDef;
$aSql = $this->dict->AlterColumnSQL($sTableName,$ado_col = $this->_egw2adodb_columndef(array(
'fd' => array($sColumnName => $aColumnDef),
'pk' => array(),
)),$ado_table=$this->_egw2adodb_columndef($this->m_aTables[$sTableName]));
)),$ado_table=$this->_egw2adodb_columndef($table_def));
return $this->ExecuteSQLArray($aSql,2,'AlterColumnSQL(%1,%2,%3) sql=%4',False,$sTableName,$ado_col,$ado_table,$aSql);
}
@ -298,33 +281,9 @@
*/
function RenameColumn($sTableName, $sOldColumnName, $sNewColumnName, $bCopyData=True)
{
$this->m_aTables[$sTableName]['fd'][$sNewColumnName] = $this->m_aTables[$sTableName]['fd'][$sOldColumnName];
unset($this->m_aTables[$sTableName]['fd'][$sOldColumnName]);
// check if column is used in an index and evtl. rename the column in the index-definition
if (($key = array_search($sOldColumnName,$this->m_aTables[$sTableName]['pk'])) !== false)
{
$this->m_aTables[$sTableName]['pk'][$key] = $sNewColumnName;
}
foreach(array('ix','uc') as $kind)
{
foreach($this->m_aTables[$sTableName][$kind] as $key => $index)
{
if (!is_array($index))
{
if ($index == $sOldColumnName) $this->m_aTables[$sTableName][$kind][$key] = $sNewColumnName;
}
elseif (($sub_key = array_search($sOldColumnName,$index)) !== false)
{
$this->m_aTables[$sTableName][$kind][$key][$sub_key] = $sNewColumnName;
}
}
}
if($this->m_bDeltaOnly) return True;
// we have to use the new column-name, as m_oDeltaProc has already changed m_aTables
$table_def = $this->GetTableDefinition($sTableName);
$col_def = $this->_egw2adodb_columndef(array(
'fd' => array($sNewColumnName => $this->m_aTables[$sTableName]['fd'][$sNewColumnName]),
'fd' => array($sNewColumnName => $table_def['fd'][strtolower($sOldColumnName)]),
'pk' => array(),
));
@ -343,9 +302,6 @@
*/
function AddColumn($sTableName, $sColumnName, $aColumnDef)
{
$this->m_aTables[$sTableName]['fd'][$sColumnName] = $aColumnDef;
if($this->m_bDeltaOnly) return True;
$aSql = $this->dict->AddColumnSQL($sTableName,$ado_cols = $this->_egw2adodb_columndef(array(
'fd' => array($sColumnName => $aColumnDef),
'pk' => array(),
@ -364,20 +320,18 @@
* @param string $sIdxName='' name of the index, if not given (default) its created automaticaly
* @return int 2: no error, 1: errors, but continued, 0: errors aborted
*/
function CreateIndex($sTableName,$aColumnNames,$type=False,$options='',$sIdxName='')
function CreateIndex($sTableName,$aColumnNames,$bUnique=false,$options='',$sIdxName='')
{
$kind = $bUnique ? 'uc' : 'ix';
$key = !$sIdxName || is_numeric($sIdxName) ? count($this->m_aTables[$sTableName][$kind]) : $sIdxName;
$this->m_aTables[$sTableName][$kind][$key] = $aColumnNames;
if($this->m_bDeltaOnly) return true;
if (!$sIdxName || is_numeric($sIdxName))
{
$sIdxName = $this->_index_name($sTableName,$aColumnNames);
}
$aSql = $this->dict->CreateIndexSQL($name,$sTableName,$aColumnNames,is_array($options) ? $options : array($options));
if (!is_array($options)) $options = $options ? array($options) : array();
if ($bUnique) $options[] = 'UNIQUE';
return $this->ExecuteSQLArray($aSql,2,'CreateIndexSQL(%1,%2,%3) sql=%4',False,$name,$sTableName,$sColumnName, $aColumnDef,$aSql);
$aSql = $this->dict->CreateIndexSQL($name,$sTableName,$aColumnNames,$options);
return $this->ExecuteSQLArray($aSql,2,'CreateIndexSQL(%1,%2,%3,%4) sql=%5',False,$name,$sTableName,$aColumnNames,$options,$aSql);
}
/**
@ -391,20 +345,6 @@
{
if (is_array($aColumnNames))
{
foreach(array('ix','uc') as $kind)
{
foreach($this->m_aTables[$sTableName][$kind] as $idx => $columns)
{
if (!is_array($columns)) $columns = array($columns);
unset($columns['options']);
if (implode(':',$columns) == implode(':',$aColumnNames))
{
unset($this->m_aTables[$sTableName][$kind][$idx]);
break;
}
}
}
$indexes = $this->dict->MetaIndexes($sTableName);
if ($indexes === False)
{
@ -428,7 +368,7 @@
{
$sIdxName = $aColumnNames;
}
if($this->m_bDeltaOnly || !$sIdxName)
if(!$sIdxName)
{
return True;
}
@ -455,7 +395,7 @@
$seq_name = $matches[1];
}
$sql = "SELECT setval('$seq_name',MAX($sColumnName)) FROM $sTableName";
if($GLOBALS['DEBUG']) { echo "<br>Updating sequence '$seq_name using: $sql"; }
if($this->debug) { echo "<br>Updating sequence '$seq_name using: $sql"; }
return $this->query($sql,__LINE__,__FILE__);
}
return True;
@ -475,11 +415,9 @@
*/
function RefreshTable($sTableName, $aTableDef, $aDefaults=False)
{
if($GLOBALS['DEBUG']) { echo "<p>schema_proc::RefreshTable('$sTableName',"._debug_array($aTableDef,False).")<p>m_aTables[$sTableName]="._debug_array($this->m_aTables[$sTableName],False)."\n"; }
$old_fd = $this->m_aTables[$sTableName]['fd'];
if($this->debug) { echo "<p>schema_proc::RefreshTable('$sTableName',"._debug_array($aTableDef,False).")<p>$sTableName="._debug_array($old_table_def,False)."\n"; }
$this->m_aTables[$sTableName] = $aTableDef;
if($this->m_bDeltaOnly) return true;
$old_table_def = $this->GetTableDefinition($sTableName);
$tmp_name = 'tmp_'.$sTableName;
$this->m_odb->transaction_begin();
@ -492,9 +430,16 @@
{
$value = $aDefaults[$name];
}
elseif (isset($old_fd[$name])) // existing column, use its value => column-name in query
elseif (isset($old_table_def['fd'][$name])) // existing column, use its value => column-name in query
{
$value = $name;
// this is eg. necessary to change a varchar into an int column under postgres
if ($this->sType == 'pgsql' &&
in_array($old_table_def['fd'][$name]['type'],array('char','varchar','text','blob')) &&
in_array($data['type'],array('int','decimal')))
{
$value = "to_number($name,'S99D99')";
}
}
else // new column => use default value or NULL
{
@ -505,14 +450,16 @@
else
{
$value = $this->m_odb->quote(isset($data['default']) ? $data['default'] : '',$data['type']);
// fix for postgres error "no '<' operator for type 'unknown'"
if ($this->sType == 'pgsql')
{
$type_translated = $this->m_oTranslator->TranslateType($data['type']);
// fix for postgres error "no '<' operator for type 'unknown'"
if(($type_translated = $this->TranslateType($data['type'])))
{
$value = "CAST($value AS $type_translated)";
}
}
}
}
$blob_column_included = $blob_column_included || in_array($data['type'],array('blob','text','longtext'));
$auto_column_included = $auto_column_included || $data['type'] == 'auto';
$select[] = $value;
@ -529,10 +476,10 @@
break;
}
// because of all the trouble with sequences and indexes in the global namespace,
// we use an additional temp. table for postgres and not rename the existing on, but drop it.
// we use an additional temp. table for postgres and not rename the existing one, but drop it.
if ($this->sType == 'pgsql')
{
$Ok = $this->m_odb->query("SELECT * INTO TEMPORARY TABLE $tmp_name FROM $sTableName",__LINE__,__FILE__) &&
$Ok = $this->m_odb->query("SELEcT * INTO TEMPORARY TABLE $tmp_name FROM $sTableName",__LINE__,__FILE__) &&
$this->DropTable($sTableName);
}
else
@ -542,7 +489,7 @@
$Ok = $Ok && $this->CreateTable($sTableName,$aTableDef) &&
$this->m_odb->query("$extra INSERT INTO $sTableName (".
implode(',',array_keys($aTableDef['fd'])).
") SELECT $distinct $select FROM $tmp_name",__LINE__,__FILE__) &&
") SELEcT $distinct $select FROM $tmp_name",__LINE__,__FILE__) &&
$this->DropTable($tmp_name);
if (!$Ok)
@ -555,7 +502,6 @@
{
$this->UpdateSequence($sTableName,$aTableDef['pk'][0]);
}
$this->DropTable($tmp_name);
$this->m_odb->transaction_commit();
return True;
@ -587,8 +533,6 @@
if ($this->debug) $bOutputHTML = True;
if ($bOutputHTML && !$this->debug) $this->debug = 2;
$this->m_aTables = array();
foreach($aTables as $sTableName => $aTableDef)
{
if($this->CreateTable($sTableName, $aTableDef))
@ -620,11 +564,6 @@
*/
function f($value,$strip_slashes=False)
{
if($this->m_bDeltaOnly)
{
// Don't care, since we are processing deltas only
return False;
}
return $this->m_odb->f($value,$strip_slashes);
}
@ -635,11 +574,6 @@
*/
function num_rows()
{
if($this->m_bDeltaOnly)
{
// If not False, we will cause while loops calling us to hang
return False;
}
return $this->m_odb->num_rows();
}
@ -650,11 +584,6 @@
*/
function next_record()
{
if($this->m_bDeltaOnly)
{
// If not False, we will cause while loops calling us to hang
return False;
}
return $this->m_odb->next_record();
}
@ -670,11 +599,6 @@
*/
function query($sQuery, $line='', $file='')
{
if($this->m_bDeltaOnly)
{
// Don't run this query, since we are processing deltas only
return True;
}
return $this->m_odb->query($sQuery, $line, $file);
}
@ -692,11 +616,6 @@
*/
function insert($table,$data,$where,$line,$file,$app)
{
if($this->m_bDeltaOnly)
{
// Don't run this query, since we are processing deltas only
return True;
}
return $this->m_odb->insert($table,$data,$where,$line,$file,$app);
}
@ -934,7 +853,7 @@
}
if (!$ado_col)
{
$this->error("Ignoring unknown column-type '$col_data[type]($col_data[precision])' !!!");
$this->error("Ignoring unknown column-type '$col_data[type]($col_data[precision])' !!!<br>".function_backtrace());
continue;
}
if (isset($col_data['nullable']) && !$col_data['nullable'])
@ -955,6 +874,21 @@
return implode(",\n",$ado_defs);
}
/**
* Translates an eGW type into the DB's native type
*
* @param string $egw_type eGW name of type
* @param string/boolean DB's name of the type or false if the type could not be identified (should not happen)
*/
function TranslateType($egw_type)
{
$ado_col = $this->_egw2adodb_columndef(array(
'fd' => array('test' => array('type' => $egw_type)),
'pk' => array(),
));
return preg_match('/test ([A-Z0-9]+)/i',$ado_col,$matches) ? $this->dict->ActualType($matches[1]) : false;
}
/**
* Read the table-definition direct from the database
*
@ -1140,7 +1074,7 @@
}
/**
* Get actual columnnames as a comma-separated string in$sColumns and set table-definition in class-vars
* Get actual columnnames as a comma-separated string in $sColumns and set indices as class-vars pk,fk,ix,uc
*
* old translator function, use GetTableDefition() instead
* @depricated

View File

@ -6,6 +6,8 @@
* This file written by Miles Lott <milos@groupwhere.org> *
* Originally written for phpGroupWare. *
* (C) 2001-2004 Miles Lott *
* Upgrade process rewritten by <RalfBecker@outdoor-training.de> to no *
* longer require tables_baseline files and delta-upgrades *
* -------------------------------------------- *
* 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 *
@ -43,17 +45,7 @@
*/
function init_process()
{
$ConfigDomain = get_var('ConfigDomain',array('COOKIE','POST'));
$phpgw_domain = $GLOBALS['phpgw_domain'];
$GLOBALS['phpgw_setup']->oProc = CreateObject('phpgwapi.schema_proc',$phpgw_domain[$ConfigDomain]['db_type']);
$GLOBALS['phpgw_setup']->oProc->m_odb = $GLOBALS['phpgw_setup']->db;
$GLOBALS['phpgw_setup']->oProc->m_odb->Host = $phpgw_domain[$ConfigDomain]['db_host'];
$GLOBALS['phpgw_setup']->oProc->m_odb->Database = $phpgw_domain[$ConfigDomain]['db_name'];
$GLOBALS['phpgw_setup']->oProc->m_odb->User = $phpgw_domain[$ConfigDomain]['db_user'];
$GLOBALS['phpgw_setup']->oProc->m_odb->Password = $phpgw_domain[$ConfigDomain]['db_pass'];
$GLOBALS['phpgw_setup']->oProc->m_odb->Halt_On_Error = 'report';
$GLOBALS['phpgw_setup']->oProc->m_odb->connect();
$GLOBALS['phpgw_setup']->oProc = CreateObject('phpgwapi.schema_proc');
}
/*!
@ -64,7 +56,7 @@
@param $DEBUG optional, print debugging info
@param $force_en optional, install english language files
*/
function pass($setup_info,$method='new',$DEBUG=False,$force_en=False)
function pass($setup_info,$method='new',$DEBUG=False,$force_en=False,$system_charset=false)
{
if(!$method)
{
@ -83,6 +75,7 @@
$passing = array();
$pass_string = implode (':', $pass);
$passing_string = implode (':', $passing);
$do_langs = false;
while($pass_string != $passing_string)
{
$passing = array();
@ -124,14 +117,14 @@
case 'new':
/* Create tables and insert new records for each app in this list */
$passing = $this->current($pass,$DEBUG);
$this->save_minimal_config($system_charset);
$passing = $this->default_records($passing,$DEBUG);
$passing = $this->add_langs($passing,$DEBUG,array(get_var('ConfigLang',Array('POST','COOKIE')),'en'));
$this->save_minimal_config();
$do_langs = true; // just do it once at the end of all passes
break;
case 'upgrade':
/* Run upgrade scripts on each app in the list */
$passing = $this->upgrade($pass,$DEBUG);
$passing = $this->upgrade_langs($passing,$DEBUG);
$do_langs = true; // just do it once at the end of all passes
//_debug_array($pass);exit;
break;
default:
@ -179,22 +172,25 @@
$pass_string = implode (':', $pass);
$passing_string = implode (':', $passing);
}
/* now return the list */
@reset($passed);
while(list($key,$value) = @each($passed))
if ($do_langs) // just do it once at the end of all passes
{
$setup_info[$value['name']] = $passed[$value['name']];
$langs = false;
if ($method == 'new')
{
$langs[] = ($own_lang = get_var('ConfigLang',Array('POST','COOKIE')));
if ($own_lang != 'en') $langs[] = 'en';
}
return ($setup_info);
$this->translation->drop_add_all_langs($langs);
}
/* now return the list */
return $setup_info = array_merge($setup_info,$passed);
}
/*!
@function save_minimal_config
@abstract saves a minimal default config, so you get a running install without entering and saveing Step #2 config
*/
function save_minimal_config()
function save_minimal_config($system_charset)
{
$GLOBALS['current_config']['site_title'] = 'eGroupWare';
$GLOBALS['current_config']['hostname'] = $_SERVER['HTTP_HOST'];
@ -226,6 +222,15 @@
// RalfBecker: php.net recommend this for security reasons, it should be our default too
$GLOBALS['current_config']['usecookies'] = 'True';
if ($system_charset)
{
$GLOBALS['current_config']['system_charset'] = $system_charset;
if (is_object($GLOBALS['phpgw_setup']->translation->sql))
{
$GLOBALS['phpgw_setup']->translation->sql->system_charset = $system_charset;
}
}
foreach($GLOBALS['current_config'] as $setting => $value)
{
$setting = $GLOBALS['phpgw_setup']->db->db_addslashes($setting);
@ -246,8 +251,6 @@
{
$this->init_process();
}
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
/* The following is built so below we won't try to drop a table that isn't there. */
$tablenames = $GLOBALS['phpgw_setup']->db->table_names();
if (!is_array($setup_info) || !is_array($tablenames))
@ -298,8 +301,6 @@
{
$this->init_process();
}
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
@reset($setup_info);
while(list($key,$null) = @each($setup_info))
{
@ -380,9 +381,6 @@
{
$this->init_process();
}
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
// $oProc = $GLOBALS['phpgw_setup']->oProc;
@reset($setup_info);
while(list($key,$null) = @each($setup_info))
{
@ -407,75 +405,6 @@
return ($setup_info);
}
/*!
@function add_langs
@abstract process application lang files and uninstall
@param $setup_info array of application info from setup.inc.php files, etc.
*/
function add_langs($setup_info,$DEBUG=False,$force_langs=False)
{
@reset($setup_info);
while(list($key,$null) = @each($setup_info))
{
$appname = $setup_info[$key]['name'];
$this->translation->add_langs($appname,$DEBUG,$force_langs);
if($DEBUG)
{
echo '<br>process->add_langs(): Translations added for ' . $appname . "\n";
}
}
/* Done, return current status */
return ($setup_info);
}
/*!
@function drop_langs
@abstract process application lang files and install
@param $setup_info array of application info from setup.inc.php files, etc.
*/
function drop_langs($setup_info,$DEBUG=False)
{
@reset($setup_info);
while(list($key,$null) = @each($setup_info))
{
$appname = $setup_info[$key]['name'];
$this->translation->drop_langs($appname,$DEBUG);
if($DEBUG)
{
echo '<br>process->drop_langs(): Translations removed for ' . $appname . "\n";
}
}
/* Done, return current status */
return ($setup_info);
}
/*!
@function upgrade_langs
@abstract process application lang files and reinstall
@param $setup_info array of application info from setup.inc.php files, etc.
*/
function upgrade_langs($setup_info,$DEBUG=False)
{
@reset($setup_info);
while(list($key,$null) = @each($setup_info))
{
/* Don't upgrade lang files in the middle of an upgrade */
if($setup_info[$key]['status'] == 'R')
{
continue;
}
$appname = $setup_info[$key]['name'];
$this->translation->drop_langs($appname,$DEBUG);
$this->translation->add_langs($appname,$DEBUG);
if($DEBUG)
{
echo '<br>process->upgrade_langs(): Translations reinstalled for ' . $appname . "\n";
}
}
/* Done, return current status */
return ($setup_info);
}
/*!
@function test_data
@abstract process test_data.inc.php in each application/setup dir for developer tests
@ -488,9 +417,6 @@
{
$this->init_process();
}
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
// $oProc = $GLOBALS['phpgw_setup']->oProc;
@reset($setup_info);
while(list($key,$null) = @each($setup_info))
{
@ -569,217 +495,91 @@
{
$this->init_process();
}
$GLOBALS['phpgw_setup']->oProc->m_odb->HaltOnError = 'no';
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = True;
$GLOBALS['phpgw_setup']->oProc->m_odb->HaltOnError = 'yes';
@reset($setup_info);
while(list($key,$null) = @each($setup_info))
foreach($setup_info as $key => $appdata)
{
$appname = $appdata['name'];
/* Don't try to upgrade an app that is not installed */
if(!$GLOBALS['phpgw_setup']->app_registered($setup_info[$key]['name']))
if(!$GLOBALS['phpgw_setup']->app_registered($appname))
{
if($DEBUG)
{
echo '<br>process->upgrade(): Application not installed: ' . $appname . "\n";
echo "<p>process->upgrade(): Application not installed: $appname</p>\n";
}
unset($setup_info[$key]);
unset($setup_info[$appname]);
continue;
}
/* if upgrade required, or if we are running again after an upgrade or dependency failure */
if($DEBUG) { echo '<br>process->upgrade(): Incoming : appname: '.$setup_info[$key]['name'] . ' status: ' . $setup_info[$key]['status']; }
if($setup_info[$key]['status'] == 'U' ||
$setup_info[$key]['status'] == 'D' ||
$setup_info[$key]['status'] == 'V' ||
$setup_info[$key]['status'] == '') // TODO this is not getting set for api upgrade, sometimes ???
if($DEBUG)
{
$appname = $setup_info[$key]['name'];
$apptitle = $setup_info[$key]['title'];
$currentver = $setup_info[$key]['currentver'];
$targetver = $setup_info[$key]['version']; // The version we need to match when done
echo '<div style="text-align: left; border: thin dashed black; margin-top: 5px;">'."process->upgrade(): Incoming : appname: $appname, version: $appdata[currentver], status: $appdata[status]\n";
}
if($appdata['status'] == 'U' || $appdata['status'] == 'D' ||$appdata['status'] == 'V' || $appdata['status'] == '') // TODO this is not getting set for api upgrade, sometimes ???
{
$currentver = $appdata['currentver'];
$targetver = $appdata['version']; // The version we need to match when done
$appdir = PHPGW_SERVER_ROOT . SEP . $appname . SEP . 'setup' . SEP;
$test = array();
$GLOBALS['phpgw_setup']->oProc->m_aTables = $phpgw_baseline = array();
/*
$phpgw_baseline = array();
$tmpapp = array();
$tmpapp[] = $setup_info[$key];
$this->baseline($tmpapp,$DEBUG);
$GLOBALS['phpgw_setup']->oProc->m_aTables = $phpgw_baseline;
// So far, including the baseline file is not helping.
// Only AlterColumn/RenameColumn seem to be failing silently.
// This is because we are not keeping up with table changes, so a table in baseline
// either does not exist anymore, or the baseline is being lost.
// 10-18-2003 milosch - The baseline file is definitely needed for any app with and update file.
*/
if($setup_info[$key]['tables'] && file_exists($appdir.'tables_baseline.inc.php'))
{
if($DEBUG)
{
echo '<br>process->baseline(): Including baseline tables for ' . $appname . "\n";
}
include ($appdir.'tables_baseline.inc.php');
$GLOBALS['phpgw_setup']->oProc->m_aTables = $phpgw_baseline;
/* $GLOBALS['phpgw_setup']->oProc->GenerateScripts($phpgw_baseline, $DEBUG); */
}
else
{
if($DEBUG)
{
echo '<br>process->baseline(): No baseline tables for ' . $appname . "\n";
}
/* This should be a break with a status setting, or not at all
break;
*/
}
if(file_exists($appdir . 'tables_update.inc.php') && !@$this->updateincluded[$appname])
{
include ($appdir . 'tables_update.inc.php');
$this->updateincluded[$appname] = True;
/* $test array comes from update file. It is a list of available upgrade functions */
@reset($test);
while(list($x,$value) = @each($test))
while ($currentver && $currentver != $targetver &&
function_exists($function = $appname . '_upgrade' . str_replace('.','_',$currentver)))
{
$this->currentversion = $currentver = $setup_info[$key]['currentver'];
/* build upgrade function name */
$function = $appname . '_upgrade' . str_replace(".", '_', $value);
if($DEBUG)
{
echo '<br>process->upgrade(): appname: ' . $appname;
echo '<br>process->upgrade(): currentver: ' . $currentver;
echo '<br>process->upgrade(): targetver: ' . $targetver;
echo '<br>process->upgrade(): status: ' . $setup_info[$key]['status'];
echo '<br>process->upgrade(): checking: ' . $value;
echo '<br>process->upgrade(): function: ' . $function;
echo "<br>process->upgrade(): $appname($currentver --> $targetver): running $function()\n";
}
if($value == $targetver)
if (!($currentver = $function()))
{
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
/* Done upgrading */
if($DEBUG)
{
echo '<br>process->upgrade(): Upgrade of ' . $appname . ' to ' . $targetver . ' is completed.' . "\n";
echo "<b>failed!!!</b>\n";
}
$appstatus = 'F';
}
else
{
if($DEBUG)
{
echo "--> $currentver\n";
}
}
}
if ($currentver == $targetver) // upgrades succesful
{
if($DEBUG)
{
echo "<br>process->upgrade(): Upgrade of $appname to $targetver is completed.\n";
}
$appstatus = 'C';
$setup_info[$key]['status'] = $appstatus;
}
elseif ($currentver)
{
if($DEBUG)
{
echo "<br><b>process->upgrade(): No table upgrade available for appname: $appname, version: $currentver</b>\n";
}
$setup_info[$key]['currentver'] = $targetver;
if($GLOBALS['phpgw_setup']->app_registered($appname))
{
$GLOBALS['phpgw_setup']->update_app($appname);
$GLOBALS['phpgw_setup']->update_hooks($appname);
}
else
{
$GLOBALS['phpgw_setup']->register_app($appname);
$GLOBALS['phpgw_setup']->register_hooks($appname);
}
//break;
}
elseif(($value == $currentver) || !$currentver)
{
/* start upgrading db in addition to baseline */
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
if($DEBUG) { echo '<br>process->upgrade(): running ' . $function; }
/* run upgrade function */
$success = $function();
if($success != False)
{
$setup_info[$key]['currentver'] = $success;
if($DEBUG)
{
echo '<br>process->upgrade(): Upgrade of ' . $appname
. ' from ' . $value
. ' to ' . $setup_info[$key]['currentver']
. ' is completed.' . "\n";
}
$appstatus = 'R';
$setup_info[$key]['status'] = $appstatus;
if($GLOBALS['phpgw_setup']->app_registered($appname))
{
if($DEBUG)
{
echo '<br>process->upgrade(): Updating registration of ' . $appname . ', new version: ' . $setup_info[$key]['currentver'];
}
$GLOBALS['phpgw_setup']->update_app($appname);
$GLOBALS['phpgw_setup']->update_hooks($appname);
}
else
{
if($DEBUG)
{
echo '<br>process->upgrade(): Registering ' . $appname . ', version: ' . $setup_info[$key]['currentver'];
}
$GLOBALS['phpgw_setup']->register_app($appname);
$GLOBALS['phpgw_setup']->register_hooks($appname);
}
// is the next update the one we need?
if ($success && $test[$x+1] != $success &&
($num = array_search($success,$test)) !== False)
{
// do we have the needed update somewhere else in the row?
// if yes, position the array-pointer just before that update and continue
reset($test);
while((list($x,$value) = each($test)) && $x < $num-1);
continue;
}
}
else
{
if($DEBUG)
{
echo '<br>process->upgrade(): Upgrade of ' . $appname
. ' from ' . $currentver
. ' to ' . $value
. ' failed!!!' . "\n";
}
$appstatus = 'F';
break;
}
}
elseif ($GLOBALS['phpgw_setup']->alessthanb($value,$currentver))
{
if($DEBUG) { echo '<br>process->upgrade(): running baseline delta only: ' . $function . '...'; }
$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = True;
$success = $function();
// is the next update the one we need?
if ($success && $test[$x+1] != $success &&
($num = array_search($success,$test)) !== False)
{
// do we have the needed update somewhere else in the row?
// if yes, position the array-pointer just before that update and continue
reset($test);
while((list($x,$value) = each($test)) && $x < $num-1);
continue;
}
}
else
{
break;
}
}
}
else
{
if($setup_info[$appname]['tables'])
{
$appstatus = 'F';
if($DEBUG)
{
echo '<br>process->upgrade(): No table upgrade available for ' . $appname . "\n";
echo "<br>process->upgrade(): No table upgrade required/availible for $appname\n";
}
}
else
{
$setup_info[$key]['currentver'] == $targetver;
$appstatus = 'C';
}
if ($appstatus == 'C') // update successful completed
{
$setup_info[$key]['currentver'] = $targetver;
if($GLOBALS['phpgw_setup']->app_registered($appname))
{
$GLOBALS['phpgw_setup']->update_app($appname);
@ -790,29 +590,23 @@
$GLOBALS['phpgw_setup']->register_app($appname);
$GLOBALS['phpgw_setup']->register_hooks($appname);
}
}
if($DEBUG)
{
echo '<br>process->upgrade(): No table upgrade required for ' . $appname . "\n";
}
}
}
}
else
{
$appstatus = 'C';
if($DEBUG)
{
echo '<br>process->upgrade(): No upgrade required for ' . $appname . "\n";
echo "<br>process->upgrade(): No upgrade required for $appname\n";
}
$appstatus = 'C';
}
/* Done with this app, update status */
$setup_info[$key]['status'] = $appstatus;
if($DEBUG)
{
echo '<br>process->upgrade(): Outgoing : appname: '.$setup_info[$key]['name'] . ' status: ' . $setup_info[$key]['status'];
echo "<br>process->upgrade(): Outgoing : appname: $appname, status: $appstatus</div>\n";
}
$setup_info[$key]['status'] = $appstatus;
}
/* Done, return current status */

View File

@ -120,5 +120,16 @@
$this->setup_translation_sql();
return $this->sql->add_langs($appname,$DEBUG,$force_langs);
}
function drop_add_all_langs($langs=False)
{
$this->setup_translation_sql();
if (!$langs && !count($langs = $this->sql->get_langs()))
{
$langs[] = 'en';
}
return $this->sql->install_langs($langs,'dumpold');
}
}
?>

View File

@ -124,6 +124,8 @@
$install = get_var('install',Array('POST'));
$upgrade = get_var('upgrade',Array('POST'));
$do_langs = false;
if(!empty($remove) && is_array($remove))
{
$historylog = CreateObject('phpgwapi.historylog');
@ -148,9 +150,7 @@
$GLOBALS['phpgw_setup']->deregister_hooks($setup_info[$appname]['name']);
echo '<br>' . $setup_info[$appname]['title'] . ' ' . lang('hooks deregistered') . '.';
}
$terror = $GLOBALS['phpgw_setup']->process->drop_langs($terror,$DEBUG);
echo '<br>' . $setup_info[$appname]['title'] . ' ' . lang('Translations removed') . '.';
$do_langs = true;
if ($historylog->delete($appname))
{
@ -195,13 +195,7 @@
echo '<br>' . $setup_info[$appname]['title'] . ' ' . lang('hooks registered') . '.';
}
}
$force_en = False;
if($appname == 'phpgwapi')
{
$force_en = True;
}
$terror = $GLOBALS['phpgw_setup']->process->add_langs($terror,$DEBUG,$force_en);
echo '<br>' . $setup_info[$appname]['title'] . ' ' . lang('Translations added') . '.';
$do_langs = true;
}
}
@ -222,12 +216,13 @@
{
echo '<br>' . $setup_info[$appname]['title'] . ' ' . lang('upgraded') . '.';
}
$terror = $GLOBALS['phpgw_setup']->process->upgrade_langs($terror,$DEBUG);
echo '<br>' . $setup_info[$appname]['title'] . ' ' . lang('Translations upgraded') . '.';
$do_langs = true;
}
}
if ($do_langs)
{
$GLOBALS['phpgw_setup']->process->translation->drop_add_all_langs();
}
//$setup_tpl->set_var('goback',
echo '<br><a href="applications.php?debug='.$DEBUG.'">' . lang('Go back') . '</a>';
//$setup_tpl->pparse('out','submit');