Optimized the setup (not only), shortened to 37s (used to be 120s)

- DBObject::DBInsert(Tracked)NoReload() must be used when it is not required to use the object
- MetaModel::GetObject() has a cache, the operation is 5 times faster
- Changes tracking do not store the initial value, but only value changes
Reworked the CSV import to have it rely on the bulk change API
Bulk change to check the external keys (DB integrity)
Replaced trigger_error (Core only!) by the use of Exceptions (still, some new Exception classes should be defined)
Unit tests do display the call stack in a user friendly format

SVN:code[52]
This commit is contained in:
Romain Quetiez
2009-04-27 07:27:54 +00:00
parent acbb54104e
commit a4663ebed1
23 changed files with 464 additions and 533 deletions

View File

@@ -173,8 +173,8 @@ class UserRightsMatrix extends UserRightsAddOnAPI
$oUser->Set('login', $sAdminUser);
$oUser->Set('password', $sAdminPwd);
$oUser->Set('userid', 1); // one is for root !
$oUser->DBInsert();
$this->SetupUser($oUser, true);
$iUserId = $oUser->DBInsertNoReload();
$this->SetupUser($iUserId, true);
return true;
}
@@ -185,15 +185,13 @@ class UserRightsMatrix extends UserRightsAddOnAPI
$oUserSet = new DBObjectSet(DBObjectSearch::FromSibuSQL("UserRightsMatrixUsers"));
while ($oUser = $oUserSet->Fetch())
{
$this->SetupUser($oUser);
$this->SetupUser($oUser->GetKey());
}
return true;
}
protected function SetupUser($oUser, $bNewUser = false)
protected function SetupUser($iUserId, $bNewUser = false)
{
$iUserId = $oUser->GetKey();
foreach(array('bizmodel', 'application', 'gui', 'core/cmdb') as $sCategory)
{
foreach (MetaModel::GetClasses($sCategory) as $sClass)
@@ -213,11 +211,11 @@ class UserRightsMatrix extends UserRightsAddOnAPI
{
// Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant");
$oMyClassGrant->Set("userid", $oUser->GetKey());
$oMyClassGrant->Set("userid", $iUserId);
$oMyClassGrant->Set("class", $sClass);
$oMyClassGrant->Set("action", $sAction);
$oMyClassGrant->Set("permission", "yes");
$iId = $oMyClassGrant->DBInsert();
$iId = $oMyClassGrant->DBInsertNoReload();
}
}
foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus)
@@ -235,11 +233,11 @@ class UserRightsMatrix extends UserRightsAddOnAPI
{
// Create a new entry
$oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant");
$oMyClassGrant->Set("userid", $oUser->GetKey());
$oMyClassGrant->Set("userid", $iUserId);
$oMyClassGrant->Set("class", $sClass);
$oMyClassGrant->Set("stimulus", $sStimulusCode);
$oMyClassGrant->Set("permission", "yes");
$iId = $oMyClassGrant->DBInsert();
$iId = $oMyClassGrant->DBInsertNoReload();
}
}
foreach (MetaModel::GetAttributesList($sClass) as $sAttCode)
@@ -259,12 +257,12 @@ class UserRightsMatrix extends UserRightsAddOnAPI
{
// Create a new entry
$oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant");
$oMyAttGrant->Set("userid", $oUser->GetKey());
$oMyAttGrant->Set("userid", $iUserId);
$oMyAttGrant->Set("class", $sClass);
$oMyAttGrant->Set("attcode", $sAttCode);
$oMyAttGrant->Set("action", $sAction);
$oMyAttGrant->Set("permission", "yes");
$iId = $oMyAttGrant->DBInsert();
$iId = $oMyAttGrant->DBInsertNoReload();
}
}
}

View File

@@ -122,7 +122,7 @@ class dialogstack
if (self::$m_bCurrPageDeclared)
{
trigger_error("DeclareCaller() must not be called before StartDialog()", E_USER_ERROR);
throw new Exception("DeclareCaller() must not be called before StartDialog()");
}
$aCall = array(
@@ -242,7 +242,7 @@ class dialogstack
}
else
{
trigger_error("Wrong value for button style ($iButtonStyle)", E_USER_ERROR);
throw new Exception("Wrong value for button style ($iButtonStyle)");
}
$sRet .= "<input type=\"hidden\" name=\"dialogstackpop\" value=\"".count($_SESSION['dialogstack_currdlg'])."\">\n";
$sRet .= "</form>\n";

View File

@@ -39,7 +39,7 @@ class utils
self::$m_aConfig = array();
$sConfigContents = self::ReadFromFile(CONFIGFILE);
if (!$sConfigContents) trigger_error("Could not load file ".CONFIGFILE);
if (!$sConfigContents) throw new Exception("Could not load file ".CONFIGFILE);
foreach (explode("\n", $sConfigContents) as $sLine)
{

View File

@@ -310,7 +310,7 @@ class cmdbLiens extends cmdbObjectHomeMade
public static function GetRelationQueries($sRelCode)
{
trigger_error("GetRelationQueries: cmdbLiens");
throw new CoreException("GetRelationQueries: cmdbLiens");
return array("Relies on" => array("sQuery"=>"", "bPropagate"=>true, "iDistance"=>3));
}
}
@@ -357,7 +357,7 @@ class cmdbWorkshop extends cmdbObjectHomeMade
public static function GetRelationQueries($sRelCode)
{
trigger_error("GetRelationQueries: cmdbWorkshop");
throw new CoreException("GetRelationQueries: cmdbWorkshop");
return array("Relies on" => array("sQuery"=>"", "bPropagate"=>true, "iDistance"=>3));
}
}

View File

@@ -42,7 +42,7 @@ class MyHelpers
$sArrayDesc = "{".implode(", ", $aData)."}";
}
// exit!
trigger_error("Wrong value for $sDescription, found '$value' while expecting a value in $sArrayDesc", E_USER_ERROR);
throw new CoreException("Wrong value for $sDescription, found '$value' while expecting a value in $sArrayDesc");
}
// getmicrotime()
@@ -281,10 +281,10 @@ class MyHelpers
///////////////////////////////////////////////////////////////////////////////
public static function make_table_from_assoc_array(&$aData)
{
if (!is_array($aData)) trigger_error("make_table_from_assoc_array: Error - the passed argument is not an array", E_USER_ERROR);
if (!is_array($aData)) throw new CoreException("make_table_from_assoc_array: Error - the passed argument is not an array");
$aFirstRow = reset($aData);
if (count($aData) == 0) return '';
if (!is_array($aFirstRow)) trigger_error("make_table_from_assoc_array: Error - the passed argument is not a bi-dimensional array", E_USER_ERROR);
if (!is_array($aFirstRow)) throw new CoreException("make_table_from_assoc_array: Error - the passed argument is not a bi-dimensional array");
$sOutput = "";
$sOutput .= "<TABLE WIDTH=\"100%\" BORDER=\"0\" CELLSPACING=\"1\" CELLPADDING=\"1\">\n";
@@ -364,7 +364,7 @@ class MyHelpers
///////////////////////////////////////////////////////////////////////////////
public static function beautifulstr($sLongString, $iMaxLen, $bShowLen=false, $bShowTooltip=true)
{
if (!is_string($sLongString)) trigger_error("beautifulstr: expect a string as 1st argument", E_USER_ERROR);
if (!is_string($sLongString)) throw new CoreException("beautifulstr: expect a string as 1st argument");
// Nothing to do if the string is short
if (strlen($sLongString) <= $iMaxLen) return $sLongString;

View File

@@ -53,7 +53,7 @@ abstract class AttributeDefinition
{
if (!array_key_exists($sParam, $this->m_aParams))
{
trigger_error("Unknown attribute definition parameter '$sParam', please select a value in {".implode(", ", $this->m_aParams)."}");
throw new CoreException("Unknown attribute definition parameter '$sParam', please select a value in {".implode(", ", $this->m_aParams)."}");
}
else
{
@@ -90,7 +90,7 @@ abstract class AttributeDefinition
$aBacktrace = debug_backtrace();
$sTargetClass = $aBacktrace[2]["class"];
$sCodeInfo = $aBacktrace[1]["file"]." - ".$aBacktrace[1]["line"];
trigger_error("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)</br>\n", E_USER_ERROR);
throw new Exception("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)");
}
}
}
@@ -390,7 +390,7 @@ class AttributeInteger extends AttributeDBField
return $this->GetSQLExpr()." <= $sQValue";
break;
case 'in':
if (!is_array($value)) trigger_error("Expected an array for argument value (sOpCode='$sOpCode')");
if (!is_array($value)) throw new CoreException("Expected an array for argument value (sOpCode='$sOpCode')");
return $this->GetSQLExpr()." IN ('".implode("', '", $value)."')";
break;
@@ -485,7 +485,7 @@ class AttributeString extends AttributeDBField
return (string)$proposedValue;
// if (!settype($proposedValue, "string"))
// {
// trigger_error("Failed to change the type of '$proposedValue' to a string", E_USER_WARNING);
// throw new CoreException("Failed to change the type of '$proposedValue' to a string");
// }
}
public function RealValueToSQLValue($value)
@@ -692,7 +692,7 @@ class AttributeDate extends AttributeDBField
{
return date("Y-m-d H:i:s", $proposedValue);
}
trigger_error("Invalid type for a date (found ".gettype($proposedValue)." and accepting string/int/DateTime)", E_USER_ERROR);
throw new CoreException("Invalid type for a date (found ".gettype($proposedValue)." and accepting string/int/DateTime)");
return null;
}
public function RealValueToSQLValue($value)
@@ -814,7 +814,7 @@ class AttributeExternalField extends AttributeDefinition
public function GetEditClass() {return "ExtField";}
public function GetDBFieldType()
{
trigger_error("external attribute: does it make any sense to request its type ?", E_USER_WARNING);
// throw new CoreException("external attribute: does it make any sense to request its type ?");
$oExtAttDef = $this->GetExtAttDef();
return $oExtAttDef->GetDBFieldType();
}
@@ -832,7 +832,7 @@ class AttributeExternalField extends AttributeDefinition
return false;
default:
trigger_error("Unexpected value for argument iType: '$iType'", E_USER_ERROR);
throw new CoreException("Unexpected value for argument iType: '$iType'");
}
}
@@ -866,7 +866,7 @@ class AttributeExternalField extends AttributeDefinition
return MetaModel::GetAttributeDef($this->GetHostClass(), $this->Get("extkey_attcode"));
default:
trigger_error("Unexpected value for argument iType: '$iType'", E_USER_ERROR);
throw new CoreException("Unexpected value for argument iType: '$iType'");
}
}

View File

@@ -62,6 +62,14 @@ class CellChangeSpec_Unchanged extends CellChangeSpec
}
}
class CellChangeSpec_Init extends CellChangeSpec
{
public function GetDescription()
{
return $this->GetValue();
}
}
class CellChangeSpec_Modify extends CellChangeSpec
{
protected $m_previousValue;
@@ -94,7 +102,7 @@ class CellChangeSpec_Issue extends CellChangeSpec_Modify
{
return 'Could not be changed - reason: '.$this->m_sReason;
}
return 'Could not be changed to "'.$this->GetValue().' - reason:'.$this->m_sReason.' (previous: '.$this->m_previousValue.')';
return 'Could not be changed to "'.$this->GetValue().'" - reason: '.$this->m_sReason.' (previous: '.$this->m_previousValue.')';
}
}
@@ -168,7 +176,7 @@ class RowStatus_Issue extends RowStatus
{
protected $m_sReason;
public function __construct($proposedValue, $previousValue, $sReason)
public function __construct($sReason)
{
$this->m_sReason = $sReason;
}
@@ -240,10 +248,17 @@ class BulkChange
$oTargetObj->Set($sAttCode, $oForeignObj->GetKey());
// Report it
if (array_key_exists($sAttCode, $oTargetObj->ListChanges(false)))
if (array_key_exists($sAttCode, $oTargetObj->ListChanges()))
{
if ($oTargetObj->IsNew())
{
$aResults[$sAttCode]= new CellChangeSpec_Init($oForeignObj->GetKey(), $oTargetObj->Get($sAttCode), $oTargetObj->GetOriginal($sAttCode));
}
else
{
$aResults[$sAttCode]= new CellChangeSpec_Modify($oForeignObj->GetKey(), $oTargetObj->Get($sAttCode), $oTargetObj->GetOriginal($sAttCode));
}
}
else
{
$aResults[$sAttCode]= new CellChangeSpec_Unchanged($oTargetObj->Get($sAttCode));
@@ -258,9 +273,16 @@ class BulkChange
// Set the object attributes
//
foreach ($this->m_aAttList as $sAttCode => $iCol)
{
if (!$oTargetObj->CheckValue($sAttCode, $aRowData[$iCol]))
{
$aErrors[$sAttCode] = "Unexpected value";
}
else
{
$oTargetObj->Set($sAttCode, $aRowData[$iCol]);
}
}
// Reporting on fields
//
@@ -269,11 +291,19 @@ class BulkChange
{
if (isset($aErrors[$sAttCode]))
{
$aResults["col$iCol"]= new CellChangeSpec_Issue($aRowData[$iCol], $previousValue, $sReason);
$aResults["col$iCol"]= new CellChangeSpec_Issue($aRowData[$iCol], $oTargetObj->Get($sAttCode), $aErrors[$sAttCode]);
}
elseif (array_key_exists($sAttCode, $aChangedFields))
{
$aResults["col$iCol"]= new CellChangeSpec_Modify($aRowData[$iCol], $oTargetObj->Get($sAttCode), $oTargetObj->GetOriginal($sAttCode));
$originalValue = $oTargetObj->GetOriginal($sAttCode);
if ($oTargetObj->IsNew())
{
$aResults["col$iCol"]= new CellChangeSpec_Init($aRowData[$iCol], $oTargetObj->Get($sAttCode), $originalValue);
}
else
{
$aResults["col$iCol"]= new CellChangeSpec_Modify($aRowData[$iCol], $oTargetObj->Get($sAttCode), $originalValue);
}
}
else
{
@@ -315,7 +345,7 @@ class BulkChange
//
if ($oChange)
{
$newID = $oTargetObj->DBInsertTracked($oChange);
$newID = $oTargetObj->DBInsertTrackedNoReload($oChange);
$aResult[$iRow]["__STATUS__"] = new RowStatus_NewObj($newID);
}
else

View File

@@ -150,15 +150,17 @@ class CMDBChangeOpSetAttribute extends CMDBChangeOp
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("label"=>"Attribute", "description"=>"code of the modified property", "allowed_values"=>null, "sql"=>"attcode", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("oldvalue", array("label"=>"Previous value", "description"=>"previous value of the attribute", "allowed_values"=>null, "sql"=>"oldvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("newvalue", array("label"=>"New value", "description"=>"new value of the attribute", "allowed_values"=>null, "sql"=>"newvalue", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("attcode");
MetaModel::Init_AddFilterFromAttribute("oldvalue");
MetaModel::Init_AddFilterFromAttribute("newvalue");
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'newvalue')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'newvalue')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode', 'oldvalue', 'newvalue')); // Attributes to be displayed for a list
}
}

View File

@@ -144,7 +144,7 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$iId = $oMyChangeOp->DBInsert();
$iId = $oMyChangeOp->DBInsertNoReload();
}
private function RecordObjDeletion(CMDBChange $oChange, $objkey)
{
@@ -152,22 +152,12 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $objkey);
$iId = $oMyChangeOp->DBInsert();
$iId = $oMyChangeOp->DBInsertNoReload();
}
private function RecordAttChanges(CMDBChange $oChange, array $aValues = array())
private function RecordAttChanges(CMDBChange $oChange, array $aValues)
{
// $aValues is an array of $sAttCode => $value
// ... some values...
//
if (empty($aValues))
{
// ... or every object values
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if ($oAttDef->IsLinkSet()) continue; // #@# temporary
$aValues[$sAttCode] = $this->Get($sAttCode);
}
}
foreach ($aValues as $sAttCode=> $value)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
@@ -177,8 +167,9 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
$oMyChangeOp->Set("oldvalue", $this->GetOriginal($sAttCode));
$oMyChangeOp->Set("newvalue", $value);
$iId = $oMyChangeOp->DBInsert();
$iId = $oMyChangeOp->DBInsertNoReload();
}
}
@@ -186,7 +177,7 @@ abstract class CMDBObject extends DBObject
{
if(!is_object(self::$m_oCurrChange))
{
trigger_error("DBInsert() could not be used here, please use DBInsertTracked() instead", E_USER_ERROR);
throw new CoreException("DBInsert() could not be used here, please use DBInsertTracked() instead");
}
return $this->DBInsertTracked_Internal();
}
@@ -199,11 +190,25 @@ abstract class CMDBObject extends DBObject
return $ret;
}
protected function DBInsertTracked_Internal()
public function DBInsertTrackedNoReload(CMDBChange $oChange)
{
self::$m_oCurrChange = $oChange;
$ret = $this->DBInsertTracked_Internal(true);
self::$m_oCurrChange = null;
return $ret;
}
protected function DBInsertTracked_Internal($bDoNotReload = false)
{
if ($bDoNotReload)
{
$ret = parent::DBInsertNoReload();
}
else
{
$ret = parent::DBInsert();
}
$this->RecordObjCreation(self::$m_oCurrChange);
$this->RecordAttChanges(self::$m_oCurrChange);
return $ret;
}
@@ -211,7 +216,7 @@ abstract class CMDBObject extends DBObject
{
if(!self::$m_oCurrChange)
{
trigger_error("DBClone() could not be used here, please use DBCloneTracked() instead", E_USER_ERROR);
throw new CoreException("DBClone() could not be used here, please use DBCloneTracked() instead");
}
return $this->DBCloneTracked_Internal();
}
@@ -229,7 +234,6 @@ abstract class CMDBObject extends DBObject
$oClone = MetaModel::GetObject(get_class($this), $newKey);
$oClone->RecordObjCreation(self::$m_oCurrChange);
$oClone->RecordAttChanges(self::$m_oCurrChange);
return $newKey;
}
@@ -237,7 +241,7 @@ abstract class CMDBObject extends DBObject
{
if(!self::$m_oCurrChange)
{
trigger_error("DBUpdate() could not be used here, please use DBUpdateTracked() instead", E_USER_ERROR);
throw new CoreException("DBUpdate() could not be used here, please use DBUpdateTracked() instead");
}
return $this->DBUpdateTracked_internal();
}
@@ -255,7 +259,7 @@ abstract class CMDBObject extends DBObject
$aChanges = $this->ListChanges();
if (count($aChanges) == 0)
{
trigger_error("Attempting to update an unchanged object", E_USER_NOTICE);
throw new CoreWarning("Attempting to update an unchanged object");
return;
}
@@ -268,7 +272,7 @@ abstract class CMDBObject extends DBObject
{
if(!self::$m_oCurrChange)
{
trigger_error("DBDelete() could not be used here, please use DBDeleteTracked() instead", E_USER_ERROR);
throw new CoreException("DBDelete() could not be used here, please use DBDeleteTracked() instead");
}
return $this->DBDeleteTracked_Internal();
}
@@ -292,7 +296,7 @@ abstract class CMDBObject extends DBObject
{
if(!self::$m_oCurrChange)
{
trigger_error("BulkDelete() could not be used here, please use BulkDeleteTracked() instead", E_USER_ERROR);
throw new CoreException("BulkDelete() could not be used here, please use BulkDeleteTracked() instead");
}
return $this->BulkDeleteTracked_Internal($oFilter);
}
@@ -306,7 +310,7 @@ abstract class CMDBObject extends DBObject
protected static function BulkDeleteTracked_Internal(DBObjectSearch $oFilter)
{
trigger_error("Change tracking not tested for bulk operations", E_USER_WARNING);
throw new CoreWarning("Change tracking not tested for bulk operations");
// Get the list of objects to delete (and record data before deleting the DB records)
$oObjSet = new CMDBObjectSet($oFilter);
@@ -331,7 +335,7 @@ abstract class CMDBObject extends DBObject
{
if(!self::$m_oCurrChange)
{
trigger_error("BulkUpdate() could not be used here, please use BulkUpdateTracked() instead", E_USER_ERROR);
throw new CoreException("BulkUpdate() could not be used here, please use BulkUpdateTracked() instead");
}
return $this->BulkUpdateTracked_Internal($oFilter, $aValues);
}

View File

@@ -47,6 +47,17 @@ class CoreException extends Exception
{
return $this->getMessage();
}
public function getTraceAsHtml()
{
$aBackTrace = $this->getTrace();
return MyHelpers::get_callstack_html(0, $this->getTrace());
// return "<pre>\n".$this->getTraceAsString()."</pre>\n";
}
}
class CoreWarning extends CoreException
{
}
?>

View File

@@ -57,8 +57,23 @@ abstract class DBObject
{
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
$this->m_aOrigValues[$sAttCode] = null;
// ??? $this->m_aLoadedAtt[$sAttCode] = true;
if ($oAttDef->IsExternalField())
{
// This field has to be read from the DB
$this->m_aLoadedAtt[$sAttCode] = false;
}
else
{
// No need to trigger a reload for that attribute
// Let's consider it as being already fully loaded
$this->m_aLoadedAtt[$sAttCode] = true;
}
}
}
public function IsNew()
{
return (!$this->m_bIsInDB);
}
// Returns an Id for memory objects
@@ -113,7 +128,7 @@ abstract class DBObject
$aRow = MetaModel::MakeSingleRow(get_class($this), $this->m_iKey);
if (empty($aRow))
{
trigger_error("Failed to reload object of class '".get_class($this)."', id = ".$this->m_iKey, E_USER_ERROR);
throw new CoreException("Failed to reload object of class '".get_class($this)."', id = ".$this->m_iKey);
}
$this->FromRow($aRow);
@@ -161,14 +176,14 @@ abstract class DBObject
if (!array_key_exists($sKeyField, $aRow))
{
// #@# Bug ?
trigger_error("Missing key for class '".get_class($this)."'", E_USER_ERROR);
throw new CoreException("Missing key for class '".get_class($this)."'");
}
else
{
$iPKey = $aRow[$sKeyField];
if (!self::IsValidPKey($iPKey))
{
trigger_error("An object id must be an integer value ($iPKey)", E_USER_NOTICE);
throw new CoreWarning("An object id must be an integer value ($iPKey)");
}
$this->m_iKey = $iPKey;
}
@@ -204,7 +219,7 @@ abstract class DBObject
{
if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
{
trigger_error("Unknown attribute code '$sAttCode' for the class ".get_class($this), E_USER_ERROR);
throw new CoreException("Unknown attribute code '$sAttCode' for the class ".get_class($this));
}
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($this->m_bIsInDB && !$this->m_bFullyLoaded)
@@ -216,7 +231,7 @@ abstract class DBObject
}
if($oAttDef->IsScalar() && !$oAttDef->IsNullAllowed() && is_null($value))
{
trigger_error("null not allowed for attribute '$sAttCode', setting default value", E_USER_NOTICE);
throw new CoreWarning("null not allowed for attribute '$sAttCode', setting default value");
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
@@ -227,7 +242,7 @@ abstract class DBObject
// (useful when building objects in memory and not from a query)
if ( (get_class($value) != $oAttDef->GetTargetClass()) && (!is_subclass_of($value, $oAttDef->GetTargetClass())))
{
trigger_error("Trying to set the value of '$sAttCode', to an object of class '".get_class($value)."', whereas it's an ExtKey to '".$oAttDef->GetTargetClass()."'. Ignored", E_USER_NOTICE);
throw new CoreWarning("Trying to set the value of '$sAttCode', to an object of class '".get_class($value)."', whereas it's an ExtKey to '".$oAttDef->GetTargetClass()."'. Ignored");
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
}
else
@@ -245,7 +260,7 @@ abstract class DBObject
}
if(!$oAttDef->IsScalar() && !is_object($value))
{
trigger_error("scalar not allowed for attribute '$sAttCode', setting default value (empty list)", E_USER_NOTICE);
throw new CoreWarning("scalar not allowed for attribute '$sAttCode', setting default value (empty list)");
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
@@ -253,7 +268,7 @@ abstract class DBObject
{
if((get_class($value) != 'DBObjectSet') && !is_subclass_of($value, 'DBObjectSet'))
{
trigger_error("expecting a set of persistent objects (found a '".get_class($value)."'), setting default value (empty list)", E_USER_NOTICE);
throw new CoreWarning("expecting a set of persistent objects (found a '".get_class($value)."'), setting default value (empty list)");
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
@@ -264,7 +279,7 @@ abstract class DBObject
// not working fine :-( if (!is_subclass_of($sSetClass, $sLinkClass))
if ($sSetClass != $sLinkClass)
{
trigger_error("expecting a set of '$sLinkClass' objects (found a set of '$sSetClass'), setting default value (empty list)", E_USER_NOTICE);
throw new CoreWarning("expecting a set of '$sLinkClass' objects (found a set of '$sSetClass'), setting default value (empty list)");
$this->m_aCurrValues[$sAttCode] = $oAttDef->GetDefaultValue();
return;
}
@@ -276,7 +291,7 @@ abstract class DBObject
{
if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
{
trigger_error("Unknown attribute code '$sAttCode' for the class ".get_class($this), E_USER_ERROR);
throw new CoreException("Unknown attribute code '$sAttCode' for the class ".get_class($this));
}
if ($this->m_bIsInDB && !$this->m_aLoadedAtt[$sAttCode])
{
@@ -291,7 +306,7 @@ abstract class DBObject
{
if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
{
trigger_error("Unknown attribute code '$sAttCode' for the class ".get_class($this), E_USER_ERROR);
throw new CoreException("Unknown attribute code '$sAttCode' for the class ".get_class($this));
}
return $this->m_aOrigValues[$sAttCode];
}
@@ -374,12 +389,12 @@ abstract class DBObject
{
if (!self::IsValidPKey($iNewKey))
{
trigger_error("An object id must be an integer value ($iNewKey)", E_USER_ERROR);
throw new CoreException("An object id must be an integer value ($iNewKey)");
}
if ($this->m_bIsInDB && !empty($this->m_iKey) && ($this->m_iKey != $iNewKey))
{
trigger_error("Changing the key ({$this->m_iKey} to $iNewKey) on an object (class {".get_class($this).") wich already exists in the Database", E_USER_NOTICE);
throw new CoreException("Changing the key ({$this->m_iKey} to $iNewKey) on an object (class {".get_class($this).") wich already exists in the Database");
}
$this->m_iKey = $iNewKey;
}
@@ -431,15 +446,27 @@ abstract class DBObject
// check if the given (or current) value is suitable for the attribute
public function CheckValue($sAttCode, $value = null)
{
if (!is_null($value))
{
$toCheck = $value;
}
else
{
$toCheck = $this->Get($sAttCode);
}
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if ($oAtt->IsExternalKey())
{
if (!$oAtt->IsNullAllowed() || ($this->Get($sAttCode) != 0) )
if (!$oAtt->IsNullAllowed() || ($toCheck != 0) )
{
$oTargetObj = MetaModel::GetObject($oAtt->GetTargetClass(), $this->Get($sAttCode));
if (!$oTargetObj)
try
{
$oTargetObj = MetaModel::GetObject($oAtt->GetTargetClass(), $toCheck);
return true;
}
catch (CoreException $e)
{
echo "Invalid value (".$this->Get($sAttCode).") for ExtKey $sAttCode.";
return false;
}
}
@@ -580,11 +607,11 @@ abstract class DBObject
// Insert of record for the new object into the database
// Returns the key of the newly created object
public function DBInsert()
public function DBInsertNoReload()
{
if ($this->m_bIsInDB)
{
trigger_error("The object already exists into the Database, you may want to use the clone function", E_USER_ERROR);
throw new CoreException("The object already exists into the Database, you may want to use the clone function");
}
$sClass = get_class($this);
@@ -604,7 +631,7 @@ abstract class DBObject
{
if (empty($this->m_iKey))
{
trigger_error("Missing key for the object to write - This class is supposed to have a user defined key, not an autonumber", E_USER_NOTICE);
throw new CoreWarning("Missing key for the object to write - This class is supposed to have a user defined key, not an autonumber");
}
}
@@ -629,6 +656,12 @@ abstract class DBObject
// Reload to update the external attributes
$this->m_bIsInDB = true;
return $this->m_iKey;
}
public function DBInsert()
{
$this->DBInsertNoReload();
$this->Reload();
return $this->m_iKey;
}
@@ -647,12 +680,12 @@ abstract class DBObject
{
if (!$this->m_bIsInDB)
{
trigger_error("DBUpdate: could not update a newly created object, please call DBInsert instead", E_USER_ERROR);
throw new CoreException("DBUpdate: could not update a newly created object, please call DBInsert instead");
}
$aChanges = $this->ListChanges();
if (count($aChanges) == 0)
{
trigger_error("Attempting to update an unchanged object", E_USER_NOTICE);
throw new CoreWarning("Attempting to update an unchanged object");
return;
}
$bHasANewExternalKeyValue = false;
@@ -741,7 +774,7 @@ abstract class DBObject
if (!is_callable($aActionCallSpec))
{
trigger_error("Unable to call action: ".get_class($this)."::$sActionHandler", E_USER_ERROR);
throw new CoreException("Unable to call action: ".get_class($this)."::$sActionHandler");
return;
}
$bRet = call_user_func($aActionCallSpec, $sStimulusCode);

View File

@@ -309,12 +309,12 @@ class DBObjectSearch
{
if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode))
{
trigger_error("The attribute code '$sExtKeyAttCode' is not an external key of the class '{$this->GetClass()}' - the condition will be ignored", E_USER_WARNING);
throw new CoreWarning("The attribute code '$sExtKeyAttCode' is not an external key of the class '{$this->GetClass()}' - the condition will be ignored");
}
$oAttExtKey = MetaModel::GetAttributeDef($this->GetClass(), $sExtKeyAttCode);
if(!MetaModel::IsSameFamilyBranch($oFilter->GetClass(), $oAttExtKey->GetTargetClass()))
{
trigger_error("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}", E_USER_ERROR);
throw new CoreException("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
}
if (array_key_exists($sExtKeyAttCode, $this->m_aPointingTo))
@@ -347,12 +347,12 @@ class DBObjectSearch
$sForeignClassAlias = $oFilter->GetClassAlias();
if (!MetaModel::IsValidKeyAttCode($sForeignClass, $sForeignExtKeyAttCode))
{
trigger_error("The attribute code '$sForeignExtKeyAttCode' is not an external key of the class '{$sForeignClass}' - the condition will be ignored", E_USER_WARNING);
throw new CoreException("The attribute code '$sForeignExtKeyAttCode' is not an external key of the class '{$sForeignClass}' - the condition will be ignored");
}
$oAttExtKey = MetaModel::GetAttributeDef($sForeignClass, $sForeignExtKeyAttCode);
if(!MetaModel::IsSameFamilyBranch($this->GetClass(), $oAttExtKey->GetTargetClass()))
{
trigger_error("The specified filter (objects referencing an object of class {$this->GetClass()}) is not compatible with the key '{$sForeignClass}::$sForeignExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}", E_USER_ERROR);
throw new CoreException("The specified filter (objects referencing an object of class {$this->GetClass()}) is not compatible with the key '{$sForeignClass}::$sForeignExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
}
if (array_key_exists($sForeignClass, $this->m_aReferencedBy) && array_key_exists($sForeignExtKeyAttCode, $this->m_aReferencedBy[$sForeignClass]))
{
@@ -396,7 +396,7 @@ class DBObjectSearch
{
if ($this->GetClass() != $oFilter->GetClass())
{
trigger_error("Attempting to merge a filter of class '{$this->GetClass()}' with a filter of class '{$oFilter->GetClass()}'", E_USER_ERROR);
throw new CoreException("Attempting to merge a filter of class '{$this->GetClass()}' with a filter of class '{$oFilter->GetClass()}'");
}
// Translate search condition into our aliasing scheme
@@ -546,7 +546,7 @@ class DBObjectSearch
$iMaxDepth = $aCondition[3];
$oFilter->AddCondition_RelatedTo($oSubFilter, $sRelCode, $iMaxDepth);
default:
trigger_error("invalid filter definition (cannot unserialize the data, clear text = '$sClearText')", E_USER_ERROR);
throw new CoreException("invalid filter definition (cannot unserialize the data, clear text = '$sClearText')");
}
}
return $oFilter;
@@ -662,7 +662,7 @@ class DBObjectSearch
}
if (count($aParams) > 0)
{
trigger_error("Unused parameter(s) for this SibusQL expression: (".implode(', ', array_keys($aParams)).")");
throw new CoreException("Unused parameter(s) for this SibusQL expression: (".implode(', ', array_keys($aParams)).")");
}
return $sQuery;
}
@@ -931,7 +931,7 @@ class DBObjectSearch
}
else
{
trigger_error("Wrong format for filter definition: '$sQuery'");
throw new CoreException("Wrong format for filter definition: '$sQuery'");
}
}
}

View File

@@ -170,11 +170,6 @@ class DBObjectSet
$this->m_aId2Row[$oObject->GetKey()] = $iNextPos;
}
public function RemoveObject($iRow)
{
trigger_error("#@# not implemented! ca sert a quoi ?");
}
public function AddObjectArray($aObjects)
{
foreach ($aObjects as $oObj)
@@ -187,7 +182,7 @@ class DBObjectSet
{
if ($this->GetRootClass() != $oObjectSet->GetRootClass())
{
trigger_error("Could not merge two objects sets if they don't have the same root class");
throw new CoreException("Could not merge two objects sets if they don't have the same root class");
}
if (!$this->m_bLoaded) $this->Load();
@@ -202,7 +197,7 @@ class DBObjectSet
{
if ($this->GetRootClass() != $oObjectSet->GetRootClass())
{
trigger_error("Could not 'intersect' two objects sets if they don't have the same root class");
throw new CoreException("Could not 'intersect' two objects sets if they don't have the same root class");
}
if (!$this->m_bLoaded) $this->Load();
@@ -223,7 +218,7 @@ class DBObjectSet
{
if ($this->GetRootClass() != $oObjectSet->GetRootClass())
{
trigger_error("Could not 'delta' two objects sets if they don't have the same root class");
throw new CoreException("Could not 'delta' two objects sets if they don't have the same root class");
}
if (!$this->m_bLoaded) $this->Load();

View File

@@ -37,7 +37,7 @@ abstract class FilterDefinition
{
if (!array_key_exists($sParam, $this->m_aParams))
{
trigger_error("Unknown attribute definition parameter '$sParam', please select a value in {".implode(", ", $this->m_aParams)."}");
throw new CoreException("Unknown attribute definition parameter '$sParam', please select a value in {".implode(", ", $this->m_aParams)."}");
}
else
{
@@ -64,7 +64,7 @@ abstract class FilterDefinition
$aBacktrace = debug_backtrace();
$sTargetClass = $aBacktrace[2]["class"];
$sCodeInfo = $aBacktrace[1]["file"]." - ".$aBacktrace[1]["line"];
trigger_error("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)</br>\n", E_USER_ERROR);
throw new CoreException("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)");
}
}
}
@@ -86,7 +86,7 @@ abstract class FilterDefinition
$aOperators = $this->GetOperators();
if (!array_key_exists($sOpCode, $aOperators))
{
trigger_error("Unknown operator '$sOpCode'", E_USER_ERROR);
throw new CoreException("Unknown operator '$sOpCode'");
}
return $aOperators[$sOpCode];
@@ -145,11 +145,11 @@ class FilterPrivateKey extends FilterDefinition
switch($sOpCode)
{
case "IN":
if (!is_array($sQValue)) trigger_error("Expected an array for argument value (sOpCode='$sOpCode')");
if (!is_array($sQValue)) throw new CoreException("Expected an array for argument value (sOpCode='$sOpCode')");
return "$sFieldName IN (".implode(", ", $sQValue).")";
case "NOTIN":
if (!is_array($sQValue)) trigger_error("Expected an array for argument value (sOpCode='$sOpCode')");
if (!is_array($sQValue)) throw new CoreException("Expected an array for argument value (sOpCode='$sOpCode')");
return "$sFieldName NOT IN (".implode(", ", $sQValue).")";
case "!=":

View File

@@ -108,7 +108,7 @@ abstract class MetaModel
// (it is not possible to guess it when called as myderived::...)
if (!array_key_exists($sClass, self::$m_aClassParams))
{
trigger_error("Unknown class '$sClass', expected a value in {".implode(', ', array_keys(self::$m_aClassParams))."}", E_USER_ERROR);
throw new CoreException("Unknown class '$sClass', expected a value in {".implode(', ', array_keys(self::$m_aClassParams))."}");
}
}
@@ -685,7 +685,7 @@ abstract class MetaModel
{
if (!array_key_exists($sParamName, $aListInfo))
{
trigger_error("Declaration of list $sListCode - missing parameter $sParamName", E_USER_ERROR);
throw new CoreException("Declaration of list $sListCode - missing parameter $sParamName");
}
}
@@ -704,7 +704,7 @@ abstract class MetaModel
{
if (!array_key_exists($sParamName, $aRelationInfo))
{
trigger_error("Declaration of relation $sRelCode - missing parameter $sParamName", E_USER_ERROR);
throw new CoreException("Declaration of relation $sRelCode - missing parameter $sParamName");
}
}
@@ -716,7 +716,7 @@ abstract class MetaModel
{
if (count(self::GetClasses()) > 0)
{
trigger_error("InitClasses should not be called more than once -skipped");
throw new CoreException("InitClasses should not be called more than once -skipped");
return;
}
@@ -769,11 +769,11 @@ abstract class MetaModel
//
if (array_key_exists('id', self::$m_aAttribDefs[$sClass]))
{
trigger_error("Class $sClass, 'id' is a reserved keyword, it cannot be used as an attribute code", E_USER_ERROR);
throw new CoreException("Class $sClass, 'id' is a reserved keyword, it cannot be used as an attribute code");
}
if (array_key_exists('id', self::$m_aFilterDefs[$sClass]))
{
trigger_error("Class $sClass, 'id' is a reserved keyword, it cannot be used as a filter code", E_USER_ERROR);
throw new CoreException("Class $sClass, 'id' is a reserved keyword, it cannot be used as a filter code");
}
$oFilter = new FilterPrivateKey('id', array('id_field' => self::DBGetKey($sClass)));
self::$m_aFilterDefs[$sClass]['id'] = $oFilter;
@@ -785,11 +785,11 @@ abstract class MetaModel
{
if (array_key_exists('finalclass', self::$m_aAttribDefs[$sClass]))
{
trigger_error("Class $sClass, 'finalclass' is a reserved keyword, it cannot be used as an attribute code", E_USER_ERROR);
throw new CoreException("Class $sClass, 'finalclass' is a reserved keyword, it cannot be used as an attribute code");
}
if (array_key_exists('finalclass', self::$m_aFilterDefs[$sClass]))
{
trigger_error("Class $sClass, 'finalclass' is a reserved keyword, it cannot be used as a filter code", E_USER_ERROR);
throw new CoreException("Class $sClass, 'finalclass' is a reserved keyword, it cannot be used as a filter code");
}
$sClassAttCode = 'finalclass';
$sRootClass = self::GetRootClass($sClass);
@@ -846,14 +846,14 @@ abstract class MetaModel
$sClass = self::GetCallersPHPClass("Init");
if (!array_key_exists("name", $aParams))
{
trigger_error("Declaration of class $sClass: missing name ({$aMandatParams["name"]})", E_USER_ERROR);
throw new CoreException("Declaration of class $sClass: missing name ({$aMandatParams["name"]})");
}
foreach($aMandatParams as $sParamName=>$sParamDesc)
{
if (!array_key_exists($sParamName, $aParams))
{
trigger_error("Declaration of class $sClass - missing parameter $sParamName", E_USER_ERROR);
throw new CoreException("Declaration of class $sClass - missing parameter $sParamName");
}
}
@@ -938,7 +938,7 @@ abstract class MetaModel
if (!self::IsValidAttCode($sTargetClass, $sAttCode))
{
trigger_error("Could not overload '$sAttCode', expecting a code from {".implode(", ", self::GetAttributesList($sTargetClass))."}");
throw new CoreException("Could not overload '$sAttCode', expecting a code from {".implode(", ", self::GetAttributesList($sTargetClass))."}");
}
self::$m_aAttribDefs[$sTargetClass][$sAttCode]->OverloadParams($aParams);
}
@@ -1000,7 +1000,7 @@ abstract class MetaModel
if (!self::IsValidFilterCode($sTargetClass, $sFltCode))
{
trigger_error("Could not overload '$sFltCode', expecting a code from {".implode(", ", self::GetFiltersList($sTargetClass))."}");
throw new CoreException("Could not overload '$sFltCode', expecting a code from {".implode(", ", self::GetFiltersList($sTargetClass))."}");
}
self::$m_aFilterDefs[$sTargetClass][$sFltCode]->OverloadParams($aParams);
}
@@ -1150,7 +1150,7 @@ abstract class MetaModel
if (count(self::$m_Category2Class) > 0)
{
trigger_error("unkown class category '$sCategory', expecting a value in {".implode(', ', array_keys(self::$m_Category2Class))."}");
throw new CoreException("unkown class category '$sCategory', expecting a value in {".implode(', ', array_keys(self::$m_Category2Class))."}");
}
return array();
}
@@ -1175,7 +1175,7 @@ abstract class MetaModel
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sFieldAlias, self::GetAttributesList($oFilter->GetClass()));
if (!is_bool($bAscending))
{
trigger_error("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
throw new CoreException("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
}
}
if (empty($aOrderBy))
@@ -1565,8 +1565,7 @@ abstract class MetaModel
{
if (count(self::GetClasses()) == 0)
{
trigger_error("MetaModel::InitClasses() has not been called, or no class has been declared ?!?!");
exit;
throw new CoreException("MetaModel::InitClasses() has not been called, or no class has been declared ?!?!");
}
$aErrors = array();
@@ -2229,7 +2228,7 @@ abstract class MetaModel
}
if ($iPlannedDel > $iMaxDel)
{
trigger_error("DB Integrity Check safety net - Exceeding the limit of $iMaxDel planned record deletion", E_USER_WARNING);
throw new CoreWarning("DB Integrity Check safety net - Exceeding the limit of $iMaxDel planned record deletion");
break;
}
// Safety net #2 - limit the iterations
@@ -2238,7 +2237,7 @@ abstract class MetaModel
$iMaxLoops = 10;
if ($iLoopCount > $iMaxLoops)
{
trigger_error("DB Integrity Check safety net - Reached the limit of $iMaxLoops loops", E_USER_WARNING);
throw new CoreWarning("DB Integrity Check safety net - Reached the limit of $iMaxLoops loops");
break;
}
}
@@ -2410,21 +2409,50 @@ abstract class MetaModel
// Building an object
//
//
private static $aQueryCacheGetObject = array();
private static $aQueryCacheGetObjectHits = array();
public static function GetQueryCacheStatus()
{
$aRes = array();
$iTotalHits = 0;
foreach(self::$aQueryCacheGetObjectHits as $sClass => $iHits)
{
$aRes[] = "$sClass: $iHits";
$iTotalHits += $iHits;
}
return $iTotalHits.' ('.implode(', ', $aRes).')';
}
public static function MakeSingleRow($sClass, $iKey)
{
if (!array_key_exists($sClass, self::$aQueryCacheGetObject))
{
// NOTE: Quick and VERY dirty caching mechanism which relies on
// the fact that the string '987654321' will never appear in the
// standard query
// This will be replaced for sure with a prepared statement
// or a view... next optimization to come!
$oFilter = new DBObjectSearch($sClass);
$oFilter->AddCondition('id', $iKey, '=');
$oFilter->AddCondition('id', 987654321, '=');
$sSQL = self::MakeSelectQuery($oFilter);
//echo "$sSQL</br>\n";
self::$aQueryCacheGetObject[$sClass] = $sSQL;
self::$aQueryCacheGetObjectHits[$sClass] = 0;
}
else
{
$sSQL = self::$aQueryCacheGetObject[$sClass];
self::$aQueryCacheGetObjectHits[$sClass] += 1;
// echo " -load $sClass/$iKey- ".self::$aQueryCacheGetObjectHits[$sClass]."<br/>\n";
}
$sSQL = str_replace('987654321', CMDBSource::Quote($iKey), $sSQL);
$res = CMDBSource::Query($sSQL);
$aRow = CMDBSource::FetchArray($res);
CMDBSource::FreeResult($res);
if (empty($aRow))
{
trigger_error("No result for the single row query: '$sSQL'");
throw new CoreException("No result for the single row query: '$sSQL'");
}
return $aRow;
}
@@ -2446,7 +2474,7 @@ abstract class MetaModel
// @#@ possible improvement: check that the class is valid !
$sRootClass = self::GetRootClass($sClass);
$sFinalClassField = self::DBGetClassField($sRootClass);
trigger_error("Empty class name for object $sClass::{$aRow["id"]} (root class '$sRootClass', field '{$sFinalClassField}' is empty)", E_USER_ERROR);
throw new CoreException("Empty class name for object $sClass::{$aRow["id"]} (root class '$sRootClass', field '{$sFinalClassField}' is empty)");
}
else
{
@@ -2462,7 +2490,6 @@ abstract class MetaModel
$aRow = self::MakeSingleRow($sClass, $iKey);
if (empty($aRow))
{
// #@# exception ?
return null;
}
return self::GetObjectByRow($sClass, $aRow);

View File

@@ -46,7 +46,7 @@ class SQLQuery
{
if (!CMDBSource::IsTable($sTable))
{
trigger_error("Unknown table '$sTable'", E_USER_ERROR);
throw new CoreException("Unknown table '$sTable'");
}
// $aFields must be an array of "alias"=>"expr"
// $oConditionExpr must be a condition tree
@@ -137,7 +137,7 @@ class SQLQuery
assert((get_class($oSQLQuery) == __CLASS__) || is_subclass_of($oSQLQuery, __CLASS__));
if (!CMDBSource::IsField($this->m_sTable, $sLeftField))
{
trigger_error("Unknown field '$sLeftField' in table '".$this->m_sTable, E_USER_ERROR);
throw new CoreException("Unknown field '$sLeftField' in table '".$this->m_sTable);
}
if (empty($sRightTableAlias))
{
@@ -147,7 +147,7 @@ class SQLQuery
//
// if (!CMDBSource::IsField($sRightTable, $sRightField))
// {
// trigger_error("Unknown field '$sRightField' in table '".$sRightTable."'", E_USER_ERROR);
// throw new CoreException("Unknown field '$sRightField' in table '".$sRightTable."'");
// }
$this->m_aJoinSelects[] = array(
@@ -187,7 +187,7 @@ class SQLQuery
if ($this->m_oConditionExpr->IsAny())
-- if (count($aConditions) == 0) --
{
trigger_error("Building a request wich will delete every object of a given table -looks suspicious- please use truncate instead...", E_USER_ERROR);
throw new CoreException("Building a request wich will delete every object of a given table -looks suspicious- please use truncate instead...");
}
*/
$sWhere = self::ClauseWhere($oCondition);
@@ -277,7 +277,7 @@ class SQLQuery
$sFrom .= ") ON ".$aJoinInfo["joincondition"];
break;
default:
trigger_error("Unknown jointype: '".$aJoinInfo["jointype"]."'");
throw new CoreException("Unknown jointype: '".$aJoinInfo["jointype"]."'");
}
}
return $sFrom;

View File

@@ -44,7 +44,7 @@ class ObjectStimulus
$aBacktrace = debug_backtrace();
$sTargetClass = $aBacktrace[2]["class"];
$sCodeInfo = $aBacktrace[1]["file"]." - ".$aBacktrace[1]["line"];
trigger_error("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)</br>\n", E_USER_ERROR);
throw new CoreException("missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)");
}
}
}

View File

@@ -150,11 +150,17 @@ abstract class TestHandler
{
$this->ReportError($e->getMessage().' - '.$e->getTraceAsHtml());
}
catch (CoreException $e)
{
//$this->ReportError($e->getMessage());
//$this->ReportError($e->__tostring());
$this->ReportError($e->getMessage().' - '.$e->getTraceAsHtml());
}
catch (Exception $e)
{
//$this->ReportError($e->getMessage());
//$this->ReportError($e->__tostring());
$this->ReportError($e->getMessage().' - '.$e->getTraceAsString());
$this->ReportError('class '.get_class($e).' --- '.$e->getMessage().' - '.$e->getTraceAsString());
}
restore_error_handler();
$this->m_sOutput = ob_get_clean();

View File

@@ -77,12 +77,12 @@ class UserRights
{
if (!class_exists($sModuleName))
{
trigger_error("Could not select this module, '$sModuleName' in not a valid class name", E_USER_ERROR);
throw new CoreException("Could not select this module, '$sModuleName' in not a valid class name");
return;
}
if (!is_subclass_of($sModuleName, 'UserRightsAddOnAPI'))
{
trigger_error("Could not select this module, the class '$sModuleName' is not derived from UserRightsAddOnAPI", E_USER_ERROR);
throw new CoreException("Could not select this module, the class '$sModuleName' is not derived from UserRightsAddOnAPI");
return;
}
self::$m_oAddOn = new $sModuleName;

View File

@@ -17,165 +17,6 @@ $oPage = new iTopWebPage("iTop - Bulk import", $currentOrganization);
define ('EXTKEY_SEP', '::::');
define ('EXTKEY_LABELSEP', ' -> ');
class CSVParser
{
private $m_sCSVData;
private $m_sSep;
private $m_iSkip;
public function __construct($sTxt)
{
$this->m_sCSVData = $sTxt;
}
public function SetSeparator($sSep)
{
$this->m_sSep = $sSep;
}
public function GetSeparator()
{
return $this->m_sSep;
}
public function SetSkipLines($iSkip)
{
$this->m_iSkip = $iSkip;
}
public function GetSkipLines()
{
return $this->m_iSkip;
}
public function GuessSeparator()
{
// Note: skip the first line anyway
$aKnownSeps = array(';', ',', "\t"); // Use double quote for special chars!!!
$aStatsBySeparator = array();
foreach ($aKnownSeps as $sSep)
{
$aStatsBySeparator[$sSep] = array();
}
foreach(split("\n", $this->m_sCSVData) as $sLine)
{
$sLine = trim($sLine);
if (substr($sLine, 0, 1) == '#') continue;
if (empty($sLine)) continue;
$aLineCharsCount = count_chars($sLine, 0);
foreach ($aKnownSeps as $sSep)
{
$aStatsBySeparator[$sSep][] = $aLineCharsCount[ord($sSep)];
}
}
// Default to ','
$this->SetSeparator(",");
foreach ($aKnownSeps as $sSep)
{
// Note: this function is NOT available :-(
// stats_variance($aStatsBySeparator[$sSep]);
$iMin = min($aStatsBySeparator[$sSep]);
$iMax = max($aStatsBySeparator[$sSep]);
if (($iMin == $iMax) && ($iMax > 0))
{
$this->SetSeparator($sSep);
break;
}
}
return $this->GetSeparator();
}
public function GuessSkipLines()
{
// Take the FIRST -valuable- LINE ONLY
// If there is a number, then for sure this is not a header line
// Otherwise, we may consider that there is one line to skip
foreach(split("\n", $this->m_sCSVData) as $sLine)
{
$sLine = trim($sLine);
if (substr($sLine, 0, 1) == '#') continue;
if (empty($sLine)) continue;
foreach (split($this->m_sSep, $sLine) as $value)
{
if (is_numeric($value))
{
$this->SetSkipLines(0);
return 0;
}
}
$this->SetSkipLines(1);
return 1;
}
}
function ToArray($aFieldMap, $iMax = 0)
{
// $aFieldMap is an array of col_index=>col_name
// $iMax is a limit
$aRes = array();
$iCount = 0;
$iSkipped = 0;
foreach(split("\n", $this->m_sCSVData) as $sLine)
{
$sLine = trim($sLine);
if (substr($sLine, 0, 1) == '#') continue;
if (empty($sLine)) continue;
if ($iSkipped < $this->m_iSkip)
{
$iSkipped++;
continue;
}
foreach (split($this->m_sSep, $sLine) as $iCol=>$sValue)
{
if (is_array($aFieldMap)) $sColRef = $aFieldMap[$iCol];
else $sColRef = "field$iCol";
$aRes[$iCount][$sColRef] = $sValue;
}
$iCount++;
if (($iMax > 0) && ($iCount >= $iMax)) break;
}
return $aRes;
}
public function ListFields()
{
// Take the first valuable line
foreach(split("\n", $this->m_sCSVData) as $sLine)
{
$sLine = trim($sLine);
if (substr($sLine, 0, 1) == '#') continue;
if (empty($sLine)) continue;
// We've got the first valuable line, that's it!
break;
}
$aRet = array();
foreach (split($this->m_sSep, $sLine) as $iCol=>$value)
{
if ($this->m_iSkip == 0)
{
// No header to help us
$sLabel = "field $iCol";
}
else
{
$sLabel = "$value";
}
$aRet[] = $sLabel;
}
return $aRet;
}
}
///////////////////////////////////////////////////////////////////////////////
// External key/field naming conventions (sharing the naming space with std attributes
///////////////////////////////////////////////////////////////////////////////
@@ -291,176 +132,11 @@ function ShowTableForm($oPage, $oCSVParser, $sClass)
$sSelField .= "&nbsp;<input type=\"checkbox\" name=\"iskey[field$iFieldIndex]\" value=\"yes\" $sCHECKED>";
$aFields["field$iFieldIndex"]["label"] = $sSelField;
$aFields["field$iFieldIndex"]["value"] = $aColToRow["field$iFieldIndex"];
$aFields["field$iFieldIndex"]["value"] = $aColToRow[$iFieldIndex];
}
$oPage->details($aFields);
}
function PrepareObject(&$oTargetObj, $aRowData, $aAttList, $aExtKeys, &$aWarnings, &$aErrors)
{
$aResults = array();
$aWarnings = array();
$aErrors = array();
// External keys reconciliation
//
foreach($aExtKeys as $sAttCode=>$aKeyConfig)
{
$oExtKey = MetaModel::GetAttributeDef(get_class($oTargetObj), $sAttCode);
$oReconFilter = new CMDBSearchFilter($oExtKey->GetTargetClass());
foreach ($aKeyConfig as $iCol => $sForeignAttCode)
{
// The foreign attribute is one of our reconciliation key
$sFieldId = MakeExtFieldSelectValue($sAttCode, $sForeignAttCode);
$oReconFilter->AddCondition($sForeignAttCode, $aRowData[$sFieldId], '=');
$aResults["col$iCol"]= "<div class=\"csvimport_extreconkey\">".$aRowData[$sFieldId]."</div>";
}
$oExtObjects = new CMDBObjectSet($oReconFilter);
switch($oExtObjects->Count())
{
case 0:
$aErrors[$sAttCode] = "Object not found";
$aResults[$sAttCode]= "<div class=\"csvimport_error\">".$aErrors[$sAttCode]."</div>";
break;
case 1:
// Do change the external key attribute
$oForeignObj = $oExtObjects->Fetch();
$oTargetObj->Set($sAttCode, $oForeignObj->GetKey());
// Report it
if (array_key_exists($sAttCode, $oTargetObj->ListChanges()))
{
$aResults[$sAttCode]= "<div class=\"csvimport_ok\">".$oForeignObj->GetHyperLink()."</div>";
}
else
{
$aResults[$sAttCode]= "<div class=\"\">".$oForeignObj->GetHyperLink()."</div>";
}
break;
default:
$aErrors[$sAttCode] = "Found ".$oExtObjects->Count()." matches";
$aResults[$sAttCode]= "<div class=\"csvimport_error\">".$aErrors[$sAttCode]."</div>";
}
}
// Set the object attributes
//
foreach ($aAttList as $iCol => $sAttCode)
{
$oTargetObj->Set($sAttCode, $aRowData[$sAttCode]);
}
// Reporting on fields
//
$aChangedFields = $oTargetObj->ListChanges();
foreach ($aAttList as $iCol => $sAttCode)
{
// By default... nothing happens
$sClass = "";
$sMoreInfo = "";
// Override if the attribute has changed
if (array_key_exists($sAttCode, $aChangedFields))
{
$sClass = "csvimport_ok";
}
// Override if a warning is found
if (isset($aWarnings[$sAttCode]))
{
$sClass = "csvimport_warning";
$sMoreInfo .= ", ".$aWarnings[$sAttCode];
}
// Override if an error is found
if (isset($aErrors[$sAttCode]))
{
$sClass = "csvimport_error";
$sMoreInfo = ", ".$aErrors[$sAttCode];
}
$aResults["col$iCol"]= "<div class=\"$sClass\">".$aRowData[$sAttCode].$sMoreInfo."</div>";
}
// Checks
//
if (!$oTargetObj->CheckConsistency())
{
$aErrors["GLOBAL"] = "Attributes not consistent with each others";
}
return $aResults;
}
function CreateObject(&$aResult, $iRow, $sClass, $aRowData, $aAttList, $aExtKeys, CMDBChange $oChange = null)
{
$oTargetObj = MetaModel::NewObject($sClass);
$aResult[$iRow] = PrepareObject($oTargetObj, $aRowData, $aAttList, $aExtKeys, $aWarnings, $aErrors);
if (count($aErrors) > 0)
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = "Unexpected attribute value(s)";
return;
}
// Check that any external key will have a value proposed
// Could be said once for all rows !!!
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAtt)
{
if (!$oAtt->IsExternalKey()) continue;
//if (!in_array($sAttCode, $aAttList))
//{
// $aResult[$iRow]["__STATUS__"] = "Could not be created - Missing external key (".$oAtt->GetLabel().")";
// return;
//}
}
// Optionaly record the results
//
if ($oChange)
{
$newID = $oTargetObj->DBInsertTracked($oChange);
$aResult[$iRow]["__STATUS__"] = "Created: ".$oTargetObj->GetHyperLink($newID);
}
else
{
$aResult[$iRow]["__STATUS__"] = "Create";
}
}
function UpdateObject(&$aResult, $iRow, $oTargetObj, $aRowData, $aAttList, $aExtKeys, CMDBChange $oChange = null)
{
$aResult[$iRow] = PrepareObject($oTargetObj, $aRowData, $aAttList, $aExtKeys, $aWarnings, $aErrors);
// Reporting
//
if (count($aErrors) > 0)
{
$sErrors = implode(', ', $aErrors);
$aResult[$iRow]["__STATUS__"] = "Unexpected attribute value(s)";
return;
}
$aChangedFields = $oTargetObj->ListChanges();
if (count($aChangedFields) > 0)
{
$sVerb = $oChange ? "Updated" : "Update";
$aResult[$iRow]["__STATUS__"] = "$sVerb ".count($aChangedFields)." cols";
// Optionaly record the results
//
if ($oChange)
{
$oTargetObj->DBUpdateTracked($oChange);
}
}
else
{
$aResult[$iRow]["__STATUS__"] = "No change";
}
}
function ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, CMDBChange $oChange = null)
{
@@ -487,18 +163,18 @@ function ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, CM
elseif (IsExtKeyField($sColDesc))
{
list($sExtKeyAttCode, $sExtReconcKeyAttCode) = GetExtKeyFieldCodes($sColDesc);
$aExtKeys[$sExtKeyAttCode][$iFieldId] = $sExtReconcKeyAttCode;
$aExtKeys[$sExtKeyAttCode][$sExtReconcKeyAttCode] = $iFieldId;
}
elseif (array_key_exists($sFieldId, $aIsReconcKey))
{
$aReconcilKeys[$iFieldId] = $sColDesc;
$aAttList[$iFieldId] = $sColDesc; // A reconciliation key is also a field
$aReconcilKeys[$sColDesc] = $iFieldId;
$aAttList[$sColDesc] = $iFieldId; // A reconciliation key is also a field
}
else
{
// $sColDesc is an attribute code
//
$aAttList[$iFieldId] = $sColDesc;
$aAttList[$sColDesc] = $iFieldId;
}
}
@@ -511,7 +187,7 @@ function ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, CM
{
$aDisplayConfig["col$iPKeyId"] = array("label"=>"<strong>pkey</strong>", "description"=>"");
}
foreach($aReconcilKeys as $iCol=>$sAttCode)
foreach($aReconcilKeys as $sAttCode => $iCol)
{
$sLabel = MetaModel::GetAttributeDef($sClass, $sAttCode)->GetLabel();
$aDisplayConfig["col$iCol"] = array("label"=>"$sLabel", "description"=>"");
@@ -521,7 +197,7 @@ function ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, CM
$oExtKeyAtt = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sLabel = $oExtKeyAtt->GetLabel();
$aDisplayConfig[$sAttCode] = array("label"=>"$sLabel", "description"=>"");
foreach ($aKeyConfig as $iCol => $sForeignAttCode)
foreach ($aKeyConfig as $sForeignAttCode => $iCol)
{
// The foreign attribute is one of our reconciliation key
@@ -529,7 +205,7 @@ function ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, CM
$aDisplayConfig["col$iCol"] = array("label"=>"$sLabel", "description"=>"");
}
}
foreach ($aAttList as $iCol => $sAttCode)
foreach ($aAttList as $sAttCode => $iCol)
{
$sLabel = MetaModel::GetAttributeDef($sClass, $sAttCode)->GetLabel();
$aDisplayConfig["col$iCol"] = array("label"=>"$sLabel", "description"=>"");
@@ -537,53 +213,58 @@ function ProcessData($oPage, $sClass, $oCSVParser, $aFieldMap, $aIsReconcKey, CM
// Compute the results
//
$aResult = array();
foreach($oCSVParser->ToArray(array_values($aFieldMap)) as $iRow => $aRowData)
{
$oReconciliationFilter = new CMDBSearchFilter($sClass);
if (isset($iPKeyId))
{
$oReconciliationFilter->AddCondition("pkey", $aRowData["pkey"], '=');
}
foreach($aReconcilKeys as $iCol=>$sAttCode)
{
$sSearchAttCode = $aFieldMap['field'.$iCol];
$oReconciliationFilter->AddCondition($sSearchAttCode, $aRowData[$sSearchAttCode], '=');
}
$oReconciliationSet = new CMDBObjectSet($oReconciliationFilter);
switch($oReconciliationSet->Count())
{
case 0:
CreateObject($aResult, $iRow, $sClass, $aRowData, $aAttList, $aExtKeys, $oChange);
// $aResult[$iRow]["__STATUS__"]=> set in CreateObject
$aResult[$iRow]["__RECONCILIATION__"] = "Object not found";
break;
case 1:
$oTargetObj = $oReconciliationSet->Fetch();
UpdateObject($aResult, $iRow, $oTargetObj, $aRowData, $aAttList, $aExtKeys, $oChange);
$aResult[$iRow]["__RECONCILIATION__"] = "Found a ".$oTargetObj->GetHyperLink("match");
// $aResult[$iRow]["__STATUS__"]=> set in UpdateObject
break;
default:
foreach ($aAttList as $iCol => $sAttCode)
{
$aResult[$iRow]["col$iCol"]= $aRowData[$sAttCode];
}
$aResult[$iRow]["__RECONCILIATION__"] = "Found ".$oReconciliationSet->Count()." matches";
$aResult[$iRow]["__STATUS__"]= "skipped";
}
$aData = $oCSVParser->ToArray();
// Whatever happened, do report the reconciliation values
if (isset($iPKeyId))
$oBulk = new BulkChange(
$sClass,
$aData,
$aAttList,
array_keys($aReconcilKeys),
$aExtKeys
);
$aRes = $oBulk->Process($oChange);
$aResultDisp = array(); // to be displayed
foreach($aRes as $iRow => $aRowData)
{
$aResult[$iRow]["col$iPKeyId"] = "<div class=\"csvimport_reconkey\">".$aRowData["pkey"]."</div>";
}
foreach($aReconcilKeys as $iCol=>$sAttCode)
$aRowDisp = array();
$aRowDisp["__RECONCILIATION__"] = $aRowData["__RECONCILIATION__"];
$aRowDisp["__STATUS__"] = $aRowData["__STATUS__"]->GetDescription();
foreach($aRowData as $sKey => $value)
{
$aResult[$iRow]["col$iCol"] = "<div class=\"csvimport_reconkey\">".$aRowData[$sAttCode]."</div>";
if ($sKey == '__RECONCILIATION__') continue;
if ($sKey == '__STATUS__') continue;
switch (get_class($value))
{
case 'CellChangeSpec_Void':
$sClass = '';
break;
case 'CellChangeSpec_Unchanged':
$sClass = '';
break;
case 'CellChangeSpec_Modify':
$sClass = 'csvimport_ok';
break;
case 'CellChangeSpec_Init':
$sClass = 'csvimport_init';
break;
case 'CellChangeSpec_Issue':
$sClass = 'csvimport_error';
break;
}
if (empty($sClass))
{
$aRowDisp[$sKey] = $value->GetDescription();
}
else
{
$aRowDisp[$sKey] = "<div class=\"$sClass\">".$value->GetDescription()."</div>";
}
}
$oPage->table($aDisplayConfig, $aResult);
$aResultDisp[$iRow] = $aRowDisp;
}
$oPage->table($aDisplayConfig, $aResultDisp);
}
///////////////////////////////////////////////////////////////////////////////
@@ -710,7 +391,7 @@ function DoProcessOrVerify($oPage, $sClass, CMDBChange $oChange = null)
$oPage->p("<h2>Goal summary</h2>");
$oPage->p("Target: $iTarget rows");
$aSampleData = $oCSVParser->ToArray(null, 5);
$aSampleData = $oCSVParser->ToArray(array_keys($aFieldMap), 5);
$aDisplayConfig = array();
foreach ($aFieldMap as $sFieldId=>$sColDesc)
{

View File

@@ -612,8 +612,23 @@ class TestQueriesOnFarm extends TestBizModel
MetaModel::DBCheckIntegrity();
}
protected $m_oChange;
protected function ObjectToDB(CMDBObject $oNew)
{
if (!isset($this->m_oChange))
{
new CMDBChange();
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$oMyChange->Set("userinfo", "Administrator");
$iChangeId = $oMyChange->DBInsertNoReload();
$this->m_oChange = $oMyChange;
}
$iId = $oNew->DBInsertTrackedNoReload($this->m_oChange);
return $iId;
}
private function InsertMammal($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $sName, $iHeight, $sBirth)
protected function InsertMammal($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $sName, $iHeight, $sBirth)
{
$oNew = MetaModel::NewObject('Mammal');
$oNew->Set('species', $sSpecies);
@@ -624,11 +639,10 @@ class TestQueriesOnFarm extends TestBizModel
$oNew->Set('name', $sName);
$oNew->Set('height', $iHeight);
$oNew->Set('birth', $sBirth);
$iId = $oNew->DBInsert();
return $iId;
return $this->ObjectToDB($oNew);
}
private function InsertBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId)
protected function InsertBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId)
{
$oNew = MetaModel::NewObject('Bird');
$oNew->Set('species', $sSpecies);
@@ -636,11 +650,10 @@ class TestQueriesOnFarm extends TestBizModel
$oNew->Set('speed', $iSpeed);
$oNew->Set('mother', $iMotherid);
$oNew->Set('father', $iFatherId);
$iId = $oNew->DBInsert();
return $iId;
return $this->ObjectToDB($oNew);
}
private function InsertFlyingBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $iFlyingSpeed)
protected function InsertFlyingBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $iFlyingSpeed)
{
$oNew = MetaModel::NewObject('FlyingBird');
$oNew->Set('species', $sSpecies);
@@ -649,8 +662,7 @@ class TestQueriesOnFarm extends TestBizModel
$oNew->Set('mother', $iMotherid);
$oNew->Set('father', $iFatherId);
$oNew->Set('flyingspeed', $iFlyingSpeed);
$iId = $oNew->DBInsert();
return $iId;
return $this->ObjectToDB($oNew);
}
private function InsertGroup($sName, $iLeaderId)
@@ -658,7 +670,7 @@ class TestQueriesOnFarm extends TestBizModel
$oNew = MetaModel::NewObject('Group');
$oNew->Set('name', $sName);
$oNew->Set('leader', $iLeaderId);
$iId = $oNew->DBInsert();
$iId = $oNew->DBInsertNoReload();
return $iId;
}
@@ -926,6 +938,131 @@ class TestBulkChangeOnFarm extends TestBizModel
}
}
///////////////////////////////////////////////////////////////////////////
// Benchmark queries
///////////////////////////////////////////////////////////////////////////
class TestItopEfficiency extends TestBizModel
{
static public function GetName()
{
return 'Itop - benchmark';
}
static public function GetDescription()
{
return 'Measure time to perform the queries';
}
static public function GetConfigFile() {return '../config-itop.php';}
protected function DoBenchmark($sOqlQuery)
{
echo "<h3>Testing query: $sOqlQuery</h3>";
$fStart = MyHelpers::getmicrotime();
for($i=0 ; $i < COUNT_BENCHMARK ; $i++)
{
$oFilter = DBObjectSearch::FromOQL($sOqlQuery);
}
$fDuration = MyHelpers::getmicrotime() - $fStart;
$fParsingDuration = $fDuration / COUNT_BENCHMARK;
$fStart = MyHelpers::getmicrotime();
for($i=0 ; $i < COUNT_BENCHMARK ; $i++)
{
$sSQL = MetaModel::MakeSelectQuery($oFilter);
}
$fDuration = MyHelpers::getmicrotime() - $fStart;
$fBuildDuration = $fDuration / COUNT_BENCHMARK;
$fStart = MyHelpers::getmicrotime();
for($i=0 ; $i < COUNT_BENCHMARK ; $i++)
{
$res = CMDBSource::Query($sSQL);
}
$fDuration = MyHelpers::getmicrotime() - $fStart;
$fQueryDuration = $fDuration / COUNT_BENCHMARK;
// The fetch could not be repeated with the same results
// But we've seen so far that is was very very quick to exec
// So it makes sense to benchmark it a single time
$fStart = MyHelpers::getmicrotime();
$aRow = CMDBSource::FetchArray($res);
$fDuration = MyHelpers::getmicrotime() - $fStart;
$fFetchDuration = $fDuration;
$fStart = MyHelpers::getmicrotime();
for($i=0 ; $i < COUNT_BENCHMARK ; $i++)
{
$sOql = $oFilter->ToOQL();
}
$fDuration = MyHelpers::getmicrotime() - $fStart;
$fToOqlDuration = $fDuration / COUNT_BENCHMARK;
echo "<ul>\n";
echo "<li>Parsing: $fParsingDuration</li>\n";
echo "<li>Build: $fBuildDuration</li>\n";
echo "<li>Query: $fQueryDuration</li>\n";
echo "<li>Fetch: $fFetchDuration</li>\n";
echo "<li>ToOql: $fToOqlDuration</li>\n";
echo "</ul>\n";
// Everything but the ToOQL (wich is interesting, anyhow)
$fTotal = $fParsingDuration + $fBuildDuration + $fQueryDuration + $fFetchDuration;
return array(
'rows' => CMDBSource::NbRows($res),
'duration (s)' => round($fTotal, 4),
'parsing (%)' => round(100 * $fParsingDuration / $fTotal, 1),
'build SQL (%)' => round(100 * $fBuildDuration / $fTotal, 1),
'query exec (%)' => round(100 * $fQueryDuration / $fTotal, 1),
'fetch (%)' => round(100 * $fFetchDuration / $fTotal, 1),
'to OQL (%)' => round(100 * $fToOqlDuration / $fTotal, 1),
'parsing+build (%)' => round(100 * ($fParsingDuration + $fBuildDuration) / $fTotal, 1),
);
}
protected function DoExecute()
{
define ('COUNT_BENCHMARK', 3);
echo "<p>The test will be repeated ".COUNT_BENCHMARK." times</p>";
$aQueries = array(
'SELECT CMDBChangeOpSetAttribute',
'SELECT CMDBChangeOpSetAttribute WHERE id=10',
'SELECT CMDBChangeOpSetAttribute WHERE id=123456789',
'SELECT CMDBChangeOpSetAttribute WHERE CMDBChangeOpSetAttribute.id=10',
'SELECT bizIncidentTicket',
'SELECT bizIncidentTicket WHERE id=1',
'SELECT bizPerson',
'SELECT bizPerson WHERE id=1',
'SELECT bizIncidentTicket JOIN bizPerson ON bizIncidentTicket.agent_id = bizPerson.id WHERE bizPerson.id = 5',
);
$aStats = array();
foreach ($aQueries as $sOQL)
{
$aStats[$sOQL] = $this->DoBenchmark($sOQL);
}
$aData = array();
foreach ($aStats as $sOQL => $aResults)
{
$aValues = array();
$aValues['OQL'] = htmlentities($sOQL);
foreach($aResults as $sDesc => $sInfo)
{
$aValues[$sDesc] = htmlentities($sInfo);
}
$aData[] = $aValues;
}
echo MyHelpers::make_table_from_assoc_array($aData);
return true;
}
}
///////////////////////////////////////////////////////////////////////////
// Test data load
///////////////////////////////////////////////////////////////////////////

View File

@@ -163,10 +163,14 @@ class XMLDataLoader
{
$iExtKey = -$iDstObj; // Convention: Unresolved keys are stored as negative !
}
// tested by Romain, little impact on perf (not significant on the intial setup)
//$oTargetObj->CheckValue($sAttCode, $iExtKey);
$oTargetObj->Set($sAttCode, $iExtKey);
}
else
{
// tested by Romain, little impact on perf (not significant on the intial setup)
//$oTargetObj->CheckValue($sAttCode, (string)$oXmlObj->$sAttCode);
$oTargetObj->Set($sAttCode, (string)$oXmlObj->$sAttCode);
}
}
@@ -200,11 +204,11 @@ class XMLDataLoader
{
if (is_subclass_of($oTargetObj, 'CMDBObject'))
{
$iObjId = $oTargetObj->DBInsertTracked($this->m_oChange);
$iObjId = $oTargetObj->DBInsertTrackedNoReload($this->m_oChange);
}
else
{
$iObjId = $oTargetObj->DBInsert();
$iObjId = $oTargetObj->DBInsertNoReload();
}
}

View File

@@ -138,6 +138,9 @@ try
case 'CellChangeSpec_Modify':
$sClass = 'csvimport_ok';
break;
case 'CellChangeSpec_Init':
$sClass = 'csvimport_init';
break;
case 'CellChangeSpec_Issue':
$sClass = 'csvimport_error';
break;