diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php index e69fc6c1b..a6d384fab 100644 --- a/core/dbobjectsearch.class.php +++ b/core/dbobjectsearch.class.php @@ -1,9 +1,9 @@ - - -/** - * Define filters for a given class of objects (formerly named "filter") - * - * @copyright Copyright (C) 2010-2017 Combodo SARL - * @license http://opensource.org/licenses/AGPL-3.0 - */ +// // Dev hack for disabling the some query build optimizations (Folding/Merging) define('ENABLE_OPT', true); @@ -1623,9 +1616,9 @@ class DBObjectSearch extends DBSearch $bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses()); - self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY")); + //self::DbgTrace("Entering: ".$this->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY")); - $sRootClass = MetaModel::GetRootClass($sClass); + //$sRootClass = MetaModel::GetRootClass($sClass); $sKeyField = MetaModel::DBGetKey($sClass); if ($bIsOnQueriedClass) @@ -1679,9 +1672,9 @@ class DBObjectSearch extends DBSearch } } } -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; + //echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; $aExpectedAtts = array(); // array of (attcode => fieldexpression) -//echo "

".__LINE__.": GetUnresolvedFields($sClassAlias, ...)

\n"; + //echo "

".__LINE__.": GetUnresolvedFields($sClassAlias, ...)

\n"; $oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts); // Compute a clear view of required joins (from the current class) @@ -2159,8 +2152,14 @@ class DBObjectSearch extends DBSearch * Get the expression for the class and its subclasses (if finalclass = 'subclass' ...) * Simplifies the final expression by grouping classes having the same expression */ - static protected function GetPolymorphicExpression($sClass, $sAttCode) + static public function GetPolymorphicExpression($sClass, $sAttCode) { + $oExpression = ExpressionCache::GetCachedExpression($sClass, $sAttCode); + if (!empty($oExpression)) + { + return $oExpression; + } + // 1st step - get all of the required expressions (instantiable classes) // and group them using their OQL representation // diff --git a/core/expressioncache.class.inc.php b/core/expressioncache.class.inc.php new file mode 100644 index 000000000..16731391f --- /dev/null +++ b/core/expressioncache.class.inc.php @@ -0,0 +1,110 @@ + +// + +class ExpressionCache +{ + static private $aCache = array(); + + static public function GetCachedExpression($sClass, $sAttCode) + { + // read current cache + @include_once (static::GetCacheFileName()); + + $oExpr = null; + $sKey = static::GetKey($sClass, $sAttCode); + if (array_key_exists($sKey, static::$aCache)) + { + $oExpr = static::$aCache[$sKey]; + } + else + { + if (class_exists('ExpressionCacheData')) + { + if (array_key_exists($sKey, ExpressionCacheData::$aCache)) + { + $sVal = ExpressionCacheData::$aCache[$sKey]; + $oExpr = unserialize($sVal); + static::$aCache[$sKey] = $oExpr; + } + } + } + return $oExpr; + } + + + static public function Warmup() + { + $sFilePath = static::GetCacheFileName(); + + if (!is_file($sFilePath)) + { + $content = << '".serialize($oExpr)."',\n"; + } + + /** + * @param $sClass + * @param $sAttCode + * @return string + */ + static private function GetKey($sClass, $sAttCode) + { + return $sClass.'::'.$sAttCode; + } + + public static function GetCacheFileName() + { + return utils::GetCachePath().'expressioncache.php'; + } + +} + + + diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 75b1a3934..42a4f3ffe 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -1,9 +1,9 @@ +// require_once(APPROOT.'core/modulehandler.class.inc.php'); require_once(APPROOT.'core/querybuildercontext.class.inc.php'); @@ -23,6 +24,7 @@ require_once(APPROOT.'core/metamodelmodifier.inc.php'); require_once(APPROOT.'core/computing.inc.php'); require_once(APPROOT.'core/relationgraph.class.inc.php'); require_once(APPROOT.'core/apc-compat.php'); +require_once(APPROOT.'core/expressioncache.class.inc.php'); /** * Metamodel @@ -331,9 +333,16 @@ abstract class MetaModel } final static public function GetObsolescenceExpression($sClass) { - self::_check_subclass($sClass); - $sOql = self::$m_aClassParams[$sClass]['obsolescence_expression']; - $oRet = Expression::FromOQL("COALESCE($sOql, 0)"); + if (self::IsObsoletable($sClass)) + { + self::_check_subclass($sClass); + $sOql = self::$m_aClassParams[$sClass]['obsolescence_expression']; + $oRet = Expression::FromOQL("COALESCE($sOql, 0)"); + } + else + { + $oRet = Expression::FromOQL("0"); + } return $oRet; } final static public function GetNameSpec($sClass) @@ -4394,6 +4403,8 @@ abstract class MetaModel echo "Debug
\n"; self::static_var_dump(); } + + ExpressionCache::Warmup(); } public static function LoadConfig($oConfiguration, $bAllowCache = false) diff --git a/core/oql/expression.class.inc.php b/core/oql/expression.class.inc.php index 20a11173d..1863fd6d1 100644 --- a/core/oql/expression.class.inc.php +++ b/core/oql/expression.class.inc.php @@ -1,9 +1,9 @@ +// - -/** - * General definition of an expression tree (could be OQL, SQL or whatever) - * - * @copyright Copyright (C) 2010-2017 Combodo SARL - * @license http://opensource.org/licenses/AGPL-3.0 - */ - -class MissingQueryArgument extends CoreException +lass MissingQueryArgument extends CoreException { } @@ -89,9 +82,15 @@ abstract class Expression */ static public function FromOQL($sConditionExpr) { + static $aCache = array(); + if (array_key_exists($sConditionExpr, $aCache)) + { + return $aCache[$sConditionExpr]; + } $oOql = new OqlInterpreter($sConditionExpr); $oExpression = $oOql->ParseExpression(); - + $aCache[$sConditionExpr] = $oExpression; + return $oExpression; }