Upgrade/toolkit: improved the data sources update procedure (no need to create "direct" linkset attributes, remove old attributes, more verbose)

SVN:trunk[1532]
This commit is contained in:
Romain Quetiez
2011-08-29 13:23:57 +00:00
parent dde3efc0c7
commit 37ec8b12f3

View File

@@ -696,10 +696,10 @@ EOF
$aColumns = $this->GetSQLColumns(); $aColumns = $this->GetSQLColumns();
$aResult = array(); $aResult = array();
$sTriggerInsert = "CREATE TRIGGER `{$sTable}_bi` BEFORE INSERT ON $sTable"; $sTriggerInsert = "CREATE TRIGGER `{$sTable}_bi` BEFORE INSERT ON `$sTable`";
$sTriggerInsert .= " FOR EACH ROW"; $sTriggerInsert .= " FOR EACH ROW";
$sTriggerInsert .= " BEGIN"; $sTriggerInsert .= " BEGIN";
$sTriggerInsert .= " INSERT INTO {$sReplicaTable} (sync_source_id, status_last_seen, `status`) VALUES ({$this->GetKey()}, NOW(), 'new');"; $sTriggerInsert .= " INSERT INTO `{$sReplicaTable}` (`sync_source_id`, `status_last_seen`, `status`) VALUES ({$this->GetKey()}, NOW(), 'new');";
$sTriggerInsert .= " SET NEW.id = LAST_INSERT_ID();"; $sTriggerInsert .= " SET NEW.id = LAST_INSERT_ID();";
$sTriggerInsert .= " END;"; $sTriggerInsert .= " END;";
$aResult['bi'] = $sTriggerInsert; $aResult['bi'] = $sTriggerInsert;
@@ -717,20 +717,20 @@ EOF
// status is forced to "new" if the replica was obsoleted directly from the state "new" (dest_id = null) // status is forced to "new" if the replica was obsoleted directly from the state "new" (dest_id = null)
// otherwise, if status was either 'obsolete' or 'synchronized' it is turned into 'modified' or 'synchronized' depending on the changes // otherwise, if status was either 'obsolete' or 'synchronized' it is turned into 'modified' or 'synchronized' depending on the changes
// otherwise, the status is left as is // otherwise, the status is left as is
$sTriggerUpdate = "CREATE TRIGGER `{$sTable}_bu` BEFORE UPDATE ON $sTable"; $sTriggerUpdate = "CREATE TRIGGER `{$sTable}_bu` BEFORE UPDATE ON `$sTable`";
$sTriggerUpdate .= " FOR EACH ROW"; $sTriggerUpdate .= " FOR EACH ROW";
$sTriggerUpdate .= " BEGIN"; $sTriggerUpdate .= " BEGIN";
$sTriggerUpdate .= " IF @itopuser is null THEN"; $sTriggerUpdate .= " IF @itopuser is null THEN";
$sTriggerUpdate .= " UPDATE {$sReplicaTable} SET status_last_seen = NOW(), `status` = IF(`status` = 'obsolete', IF(`dest_id` IS NULL, 'new', 'modified'), IF(`status` IN ('synchronized') AND ($sIsModified), 'modified', `status`)) WHERE sync_source_id = {$this->GetKey()} AND id = OLD.id;"; $sTriggerUpdate .= " UPDATE `{$sReplicaTable}` SET status_last_seen = NOW(), `status` = IF(`status` = 'obsolete', IF(`dest_id` IS NULL, 'new', 'modified'), IF(`status` IN ('synchronized') AND ($sIsModified), 'modified', `status`)) WHERE sync_source_id = {$this->GetKey()} AND id = OLD.id;";
$sTriggerUpdate .= " SET NEW.id = OLD.id;"; // make sure this id won't change $sTriggerUpdate .= " SET NEW.id = OLD.id;"; // make sure this id won't change
$sTriggerUpdate .= " END IF;"; $sTriggerUpdate .= " END IF;";
$sTriggerUpdate .= " END;"; $sTriggerUpdate .= " END;";
$aResult['bu'] = $sTriggerUpdate; $aResult['bu'] = $sTriggerUpdate;
$sTriggerDelete = "CREATE TRIGGER `{$sTable}_ad` AFTER DELETE ON $sTable"; $sTriggerDelete = "CREATE TRIGGER `{$sTable}_ad` AFTER DELETE ON `$sTable`";
$sTriggerDelete .= " FOR EACH ROW"; $sTriggerDelete .= " FOR EACH ROW";
$sTriggerDelete .= " BEGIN"; $sTriggerDelete .= " BEGIN";
$sTriggerDelete .= " DELETE FROM {$sReplicaTable} WHERE id = OLD.id;"; $sTriggerDelete .= " DELETE FROM `{$sReplicaTable}` WHERE id = OLD.id;";
$sTriggerDelete .= " END;"; $sTriggerDelete .= " END;";
$aResult['ad'] = $sTriggerDelete; $aResult['ad'] = $sTriggerDelete;
return $aResult; return $aResult;
@@ -762,27 +762,48 @@ EOF
while($oAttribute = $oAttributeSet->Fetch()) while($oAttribute = $oAttributeSet->Fetch())
{ {
$aAttributes[$oAttribute->Get('attcode')] = $oAttribute; $sAttCode = $oAttribute->Get('attcode');
if (MetaModel::IsValidAttCode($this->GetTargetClass(), $sAttCode))
{
$aAttributes[$sAttCode] = $oAttribute;
}
else
{
// Old field remaining
if ($bVerbose)
{
echo "Irrelevant field description for the field '$sAttCode', for the data synchro task ".$this->GetName()." (".$this->GetKey()."), will be removed.\n";
}
$bFixNeeded = true;
if (!$bDiagnostics)
{
if ($oChange == null)
{
$oChange = MetaModel::NewObject("CMDBChange");
$oChange->Set("date", time());
$sUserString = CMDBChange::GetCurrentUserName();
$oChange->Set("userinfo", $sUserString);
$oChange->DBInsert();
}
// Fix the issue
$oAttribute->DBDeleteTracked($oChange);
}
} }
foreach(MetaModel::ListAttributeDefs($this->GetTargetClass()) as $sAttCode=>$oAttDef) }
{
if ($oAttDef->IsWritable()) foreach($this->ListTargetAttributes() as $sAttCode=>$oAttDef)
{ {
if (!isset($aAttributes[$sAttCode])) if (!isset($aAttributes[$sAttCode]))
{ {
$bFixNeeded = true; $bFixNeeded = true;
$aMissingFields[] = $sAttCode; $aMissingFields[] = $sAttCode;
// New field missing... // New field missing...
if ($bDiagnostics)
{
// Report the issue
if ($bVerbose) if ($bVerbose)
{ {
echo "Missing field description for the field '$sAttCode', for the data synchro task ".$this->GetName()." (".$this->GetKey()."), will be created with default values.\n"; echo "Missing field description for the field '$sAttCode', for the data synchro task ".$this->GetName()." (".$this->GetKey()."), will be created with default values.\n";
} }
} if (!$bDiagnostics)
else
{ {
if ($oChange == null) if ($oChange == null)
{ {
@@ -798,28 +819,34 @@ EOF
} }
} }
} }
}
$sTable = $this->GetDataTable(); $sTable = $this->GetDataTable();
if ($bFixNeeded) if ($bFixNeeded && (count($aMissingFields) > 0))
{ {
$aRepairQueries = array();
// The structure of the table needs adjusting // The structure of the table needs adjusting
$aColumns = $this->GetSQLColumns($aMissingFields); $aColumns = $this->GetSQLColumns($aMissingFields);
$aFieldDefs = array(); $aFieldDefs = array();
foreach($aColumns as $sAttCode => $sColumnDef) foreach($aColumns as $sAttCode => $sColumnDef)
{ {
$aFieldDefs[] = "$sAttCode $sColumnDef"; if (CMDBSource::IsField($sTable, $sAttCode))
{
$aRepairQueries[] = "ALTER TABLE `$sTable` DROP COLUMN `$sAttCode`;";
} }
$sAlterTable = "ALTER TABLE `$sTable` ADD (".implode(',', $aFieldDefs).");";
$aFieldDefs[] = "`$sAttCode` $sColumnDef";
}
$aRepairQueries[] = "ALTER TABLE `$sTable` ADD (".implode(',', $aFieldDefs).");";
// The triggers as well must be adjusted // The triggers as well must be adjusted
$aTriggers = array();
$aTriggersDefs = $this->GetTriggersDefinition(); $aTriggersDefs = $this->GetTriggersDefinition();
$aTriggers[] = "DROP TRIGGER IF EXISTS {$sTable}_bi;"; $aRepairQueries[] = "DROP TRIGGER IF EXISTS `{$sTable}_bi`;";
$aTriggers[] = $aTriggersDefs['bi']; $aRepairQueries[] = $aTriggersDefs['bi'];
$aTriggers[] = "DROP TRIGGER IF EXISTS {$sTable}_bu;"; $aRepairQueries[] = "DROP TRIGGER IF EXISTS `{$sTable}_bu`;";
$aTriggers[] = $aTriggersDefs['bu']; $aRepairQueries[] = $aTriggersDefs['bu'];
$aTriggers[] = "DROP TRIGGER IF EXISTS {$sTable}_ad;"; $aRepairQueries[] = "DROP TRIGGER IF EXISTS `{$sTable}_ad`;";
$aTriggers[] = $aTriggersDefs['ad']; $aRepairQueries[] = $aTriggersDefs['ad'];
if ($bDiagnostics) if ($bDiagnostics)
{ {
@@ -827,21 +854,14 @@ EOF
{ {
// Report the issue // Report the issue
echo "The structure of the table $sTable for the data synchro task ".$this->GetName()." (".$this->GetKey().") must be altered (missing fields: ".implode(',', $aMissingFields).").\n"; echo "The structure of the table $sTable for the data synchro task ".$this->GetName()." (".$this->GetKey().") must be altered (missing fields: ".implode(',', $aMissingFields).").\n";
echo "$sAlterTable\n";
echo "The trigger {$sTable}_bi, {$sTable}_bu, {$sTable}_ad for the data synchro task ".$this->GetName()." (".$this->GetKey().") must be re-created.\n"; echo "The trigger {$sTable}_bi, {$sTable}_bu, {$sTable}_ad for the data synchro task ".$this->GetName()." (".$this->GetKey().") must be re-created.\n";
echo implode("\n", $aTriggers)."\n"; echo implode("\n", $aRepairQueries)."\n";
} }
} }
else else
{ {
// Fix the issue // Fix the issue
CMDBSource::Query($sAlterTable); foreach($aRepairQueries as $sSQL)
if ($bVerbose)
{
echo "$sAlterTable\n";
}
foreach($aTriggers as $sSQL)
{ {
CMDBSource::Query($sSQL); CMDBSource::Query($sSQL);
if ($bVerbose) if ($bVerbose)
@@ -1194,6 +1214,24 @@ EOF
} }
} }
/**
* Get the list of attributes eligible to the synchronization
*/
public function ListTargetAttributes()
{
$aRet = array();
foreach(MetaModel::ListAttributeDefs($this->GetTargetClass()) as $sAttCode => $oAttDef)
{
if ($sAttCode == 'finalclass') continue;
if (!$oAttDef->IsWritable()) continue;
if ($oAttDef->IsLinkSet() && !$oAttDef->IsIndirect()) continue;
$aRet[$sAttCode] = $oAttDef;
}
return $aRet;
}
/** /**
* Get the list of SQL columns corresponding to a particular list of attribute codes * Get the list of SQL columns corresponding to a particular list of attribute codes
* Defaults to the whole list of columns for the current class * Defaults to the whole list of columns for the current class
@@ -1206,9 +1244,8 @@ EOF
if (is_null($aAttributeCodes)) if (is_null($aAttributeCodes))
{ {
$aAttributeCodes = array(); $aAttributeCodes = array();
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) foreach($this->ListTargetAttributes() as $sAttCode => $oAttDef)
{ {
if ($sAttCode == 'finalclass') continue;
$aAttributeCodes[] = $sAttCode; $aAttributeCodes[] = $sAttCode;
} }
} }