Explorar o código

#783, #233 and #466 The recent revision (2921 for ticket #783) introduced a significant slow down when performing CSV import (but not only). This new revision does suppress the regression, and even speeds up bulk updates in general. This revision is candidate for retrofit into branch 2.0.1 (along with 2921)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@2948 a333f486-631f-4898-b8df-5754b55c2be0
romainq %!s(int64=11) %!d(string=hai) anos
pai
achega
46363e170f
Modificáronse 4 ficheiros con 58 adicións e 20 borrados
  1. 21 15
      core/dbobject.class.php
  2. 11 2
      core/dbobjectset.class.php
  3. 16 1
      core/expression.class.inc.php
  4. 10 2
      core/metamodel.class.php

+ 21 - 15
core/dbobject.class.php

@@ -936,7 +936,7 @@ abstract class DBObject
 		}
 		elseif ($oAtt->IsScalar())
 		{
-			$aValues = $oAtt->GetAllowedValues($this->ToArgs());
+			$aValues = $oAtt->GetAllowedValues($this->ToArgsForQuery());
 			if (count($aValues) > 0)
 			{
 				if (!array_key_exists($toCheck, $aValues))
@@ -1901,20 +1901,31 @@ abstract class DBObject
 		$this->Set($sAttCode, $oSW);
 	}	 	
 
-	// Make standard context arguments
-	// Note: Needs to be reviewed because it is currently called once per attribute when an object is written (CheckToWrite / CheckValue)
-	//       Several options here:
-	//       1) cache the result
-	//       2) set only the object ref and resolve the values iif needed from contextual templates and queries (easy for the queries, not for the templates)
+	/*
+	* Create query parameters (SELECT ... WHERE service = :this->service_id)
+	* to be used with the APIs DBObjectSearch/DBObjectSet
+	* 		
+	* Starting 2.0.2 the parameters are computed on demand, at the lowest level,
+	* in VariableExpression::Render()		
+	*/	
+	public function ToArgsForQuery($sArgName = 'this')
+	{
+		return array($sArgName.'->object()' => $this);
+	}
+
+	/*
+	* Create template placeholders
+	* An improvement could be to compute the values on demand
+	* (i.e. interpret the template to determine the placeholders)		
+	*/
 	public function ToArgs($sArgName = 'this')
 	{
 		if (is_null($this->m_aAsArgs))
 		{
 			$oKPI = new ExecutionKPI();
-			$aScalarArgs = array();
+			$aScalarArgs = $this->ToArgsForQuery($sArgName);
 			$aScalarArgs[$sArgName] = $this->GetKey();
 			$aScalarArgs[$sArgName.'->id'] = $this->GetKey();
-			$aScalarArgs[$sArgName.'->object()'] = $this;
 			$aScalarArgs[$sArgName.'->hyperlink()'] = $this->GetHyperlink('iTopStandardURLMaker', false);
 			$aScalarArgs[$sArgName.'->hyperlink(portal)'] = $this->GetHyperlink('PortalURLMaker', false);
 			$aScalarArgs[$sArgName.'->name()'] = $this->GetName();
@@ -1940,12 +1951,7 @@ abstract class DBObject
 				{
 					$sRemoteName = $oAttDef->IsIndirect() ? $oAttDef->GetExtKeyToRemote().'_friendlyname' : 'friendlyname';
 
-					// Since we want to limit the number of item, it is not feasible to simply rely on Get() to build the link set
-					// $oLinkSet = $this->Get($sAttCode);
-					$sLinkedClass = $oAttDef->GetLinkedClass();
-					$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
-					$oSearch = DBObjectSearch::FromOQL("SELECT $sLinkedClass WHERE $sExtKeyToMe = :this");
-					$oLinkSet = new DBObjectSet($oSearch, array(), array('this' => $this->GetKey()));
+					$oLinkSet = $this->Get($sAttCode);
 					$iLimit = MetaModel::GetConfig()->Get('max_linkset_output');
 					if ($iLimit > 0)
 					{
@@ -2165,7 +2171,7 @@ abstract class DBObject
 			$iDepth = $bPropagate ? $iMaxDepth - 1 : 0;
 
 			$oFlt = DBObjectSearch::FromOQL($sQuery);
-			$oObjSet = new DBObjectSet($oFlt, array(), $this->ToArgs());
+			$oObjSet = new DBObjectSet($oFlt, array(), $this->ToArgsForQuery());
 			while ($oObj = $oObjSet->Fetch())
 			{
 				$sRootClass = MetaModel::GetRootClass(get_class($oObj));

+ 11 - 2
core/dbobjectset.class.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -758,7 +758,16 @@ class DBObjectSet
 		{
 			if (MetaModel::IsValidObject($value))
 			{
-				$aScalarArgs = array_merge($aScalarArgs, $value->ToArgs($sArgName));
+				if (strpos($sArgName, '->object()') === false)
+				{
+					// Lazy syntax - develop the object contextual parameters
+					$aScalarArgs = array_merge($aScalarArgs, $value->ToArgsForQuery($sArgName));
+				}
+				else
+				{
+					// Leave as is
+					$aScalarArgs[$sArgName] = $value;
+				}
 			}
 			else
 			{

+ 16 - 1
core/expression.class.inc.php

@@ -611,7 +611,22 @@ class VariableExpression extends UnaryExpression
 		{
 			return CMDBSource::Quote($aArgs[$this->m_sName]);
 		}
-		elseif ($bRetrofitParams)
+		elseif (($iPos = strpos($this->m_sName, '->')) !== false)
+		{
+			$sParamName = substr($this->m_sName, 0, $iPos);
+			if (array_key_exists($sParamName.'->object()', $aArgs))
+			{
+				$sAttCode = substr($this->m_sName, $iPos + 2);
+				$oObj = $aArgs[$sParamName.'->object()'];
+				if ($sAttCode == 'id')
+				{
+					return CMDBSource::Quote($oObj->GetKey());
+				}
+				return CMDBSource::Quote($oObj->Get($sAttCode));
+			}
+		}
+
+		if ($bRetrofitParams)
 		{
 			$aArgs[$this->m_sName] = null;
 			return ':'.$this->m_sName;

+ 10 - 2
core/metamodel.class.php

@@ -2093,7 +2093,16 @@ abstract class MetaModel
 		{
 			if (self::IsValidObject($value))
 			{
-				$aScalarArgs = array_merge($aScalarArgs, $value->ToArgs($sArgName));
+				if (strpos($sArgName, '->object()') === false)
+				{
+					// Lazy syntax - develop the object contextual parameters
+					$aScalarArgs = array_merge($aScalarArgs, $value->ToArgsForQuery($sArgName));
+				}
+				else
+				{
+					// Leave as is
+					$aScalarArgs[$sArgName] = $value;
+				}
 			}
 			else
 			{
@@ -2103,7 +2112,6 @@ abstract class MetaModel
 		// Add standard contextual arguments
 		//
 		$aScalarArgs['current_contact_id'] = UserRights::GetContactId();
-		
 		return $aScalarArgs;
 	}