diff --git a/core/MyHelpers.class.inc.php b/core/MyHelpers.class.inc.php
index 532ca87c6..59ba892d0 100644
--- a/core/MyHelpers.class.inc.php
+++ b/core/MyHelpers.class.inc.php
@@ -94,6 +94,113 @@ class MyHelpers
echo "\n\n";
}
+ public static function var_dump_string($var)
+ {
+ ob_start();
+ print_r($var);
+ $sRet = ob_get_clean();
+ return $sRet;
+ }
+
+ protected static function first_diff_line($s1, $s2)
+ {
+ $aLines1 = explode("\n", $s1);
+ $aLines2 = explode("\n", $s2);
+ for ($i = 0 ; $i < min(count($aLines1), count($aLines2)) ; $i++)
+ {
+ if ($aLines1[$i] != $aLines2[$i]) return $i;
+ }
+ return false;
+ }
+
+ protected static function highlight_line($sMultiline, $iLine, $sHighlightStart = '', $sHightlightEnd = '')
+ {
+ $aLines = explode("\n", $sMultiline);
+ $aLines[$iLine] = $sHighlightStart.$aLines[$iLine].$sHightlightEnd;
+ return implode("\n", $aLines);
+ }
+
+ protected static function first_diff($s1, $s2)
+ {
+ // do not work fine with multiline strings
+ $iLen1 = strlen($s1);
+ $iLen2 = strlen($s2);
+ for ($i = 0 ; $i < min($iLen1, $iLen2) ; $i++)
+ {
+ if ($s1[$i] !== $s2[$i]) return $i;
+ }
+ return false;
+ }
+
+ protected static function last_diff($s1, $s2)
+ {
+ // do not work fine with multiline strings
+ $iLen1 = strlen($s1);
+ $iLen2 = strlen($s2);
+ for ($i = 0 ; $i < min(strlen($s1), strlen($s2)) ; $i++)
+ {
+ if ($s1[$iLen1 - $i - 1] !== $s2[$iLen2 - $i - 1]) return array($iLen1 - $i, $iLen2 - $i);
+ }
+ return false;
+ }
+
+ protected static function text_cmp_html($sText1, $sText2, $sHighlight)
+ {
+ $iDiffPos = self::first_diff_line($sText1, $sText2);
+ $sDisp1 = self::highlight_line($sText1, $iDiffPos, '
', '
');
+ $sDisp2 = self::highlight_line($sText2, $iDiffPos, '', '
');
+ echo "\n";
+ echo "\n";
+ echo "$sDisp1 | \n";
+ echo "$sDisp2 | \n";
+ echo "
\n";
+ echo "
\n";
+ }
+
+ protected static function string_cmp_html($s1, $s2, $sHighlight)
+ {
+ $iDiffPos = self::first_diff($s1, $s2);
+ if ($iDiffPos === false)
+ {
+ echo "strings are identical";
+ return;
+ }
+ $sStart = substr($s1, 0, $iDiffPos);
+
+ $aLastDiff = self::last_diff($s1, $s2);
+ $sEnd = substr($s1, $aLastDiff[0]);
+
+ $sMiddle1 = substr($s1, $iDiffPos, $aLastDiff[0] - $iDiffPos);
+ $sMiddle2 = substr($s2, $iDiffPos, $aLastDiff[1] - $iDiffPos);
+
+ echo "$sStart$sMiddle1$sEnd
\n";
+ echo "$sStart$sMiddle2$sEnd
\n";
+ }
+
+ protected static function object_cmp_html($oObj1, $oObj2, $sHighlight)
+ {
+ $sObj1 = self::var_dump_string($oObj1);
+ $sObj2 = self::var_dump_string($oObj2);
+ return self::text_cmp_html($sObj1, $sObj2, $sHighlight);
+ }
+
+ public static function var_cmp_html($var1, $var2, $sHighlight = 'color:red; font-weight:bold;')
+ {
+ if (is_object($var1))
+ {
+ return self::object_cmp_html($var1, $var2, $sHighlight);
+ }
+ else if (count(explode("\n", $var1)) > 1)
+ {
+ // multiline string
+ return self::text_cmp_html($var1, $var2, $sHighlight);
+ }
+ else
+ {
+ return self::string_cmp_html($var1, $var2, $sHighlight);
+ }
+ }
+
public static function get_callstack_html($iLevelsToIgnore = 0, $aCallStack = null)
{
if ($aCallStack == null) $aCallStack = debug_backtrace();
@@ -176,6 +283,7 @@ class MyHelpers
{
if (!is_array($aData)) trigger_error("make_table_from_assoc_array: Error - the passed argument is not an array", E_USER_ERROR);
$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);
$sOutput = "";
$sOutput .= "\n";
diff --git a/core/dbobject.class.php b/core/dbobject.class.php
index f96b4cf2f..93b221bca 100644
--- a/core/dbobject.class.php
+++ b/core/dbobject.class.php
@@ -113,7 +113,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)."', pkey = ".$this->m_iKey, E_USER_ERROR);
+ trigger_error("Failed to reload object of class '".get_class($this)."', id = ".$this->m_iKey, E_USER_ERROR);
}
$this->FromRow($aRow);
@@ -133,7 +133,7 @@ abstract class DBObject
$sMyClass = $oRemoteExtKeyAtt->GetTargetClass();
$oMyselfSearch = new DBObjectSearch($sMyClass);
- $oMyselfSearch->AddCondition('pkey', $this->m_iKey, '=');
+ $oMyselfSearch->AddCondition('id', $this->m_iKey, '=');
$oLinkSearch = new DBObjectSearch($sLinkClass);
$oLinkSearch->AddCondition_PointingTo($oMyselfSearch, $sExtKeyToMe);
@@ -157,7 +157,7 @@ abstract class DBObject
// Get the key
//
- $sKeyField = "pkey";
+ $sKeyField = "id";
if (!array_key_exists($sKeyField, $aRow))
{
// #@# Bug ?
@@ -168,7 +168,7 @@ abstract class DBObject
$iPKey = $aRow[$sKeyField];
if (!self::IsValidPKey($iPKey))
{
- trigger_error("An object PKey must be an integer value ($iPKey)", E_USER_NOTICE);
+ trigger_error("An object id must be an integer value ($iPKey)", E_USER_NOTICE);
}
$this->m_iKey = $iPKey;
}
@@ -367,7 +367,7 @@ abstract class DBObject
{
if (!self::IsValidPKey($iNewKey))
{
- trigger_error("An object PKey must be an integer value ($iNewKey)", E_USER_ERROR);
+ trigger_error("An object id must be an integer value ($iNewKey)", E_USER_ERROR);
}
if ($this->m_bIsInDB && !empty($this->m_iKey) && ($this->m_iKey != $iNewKey))
@@ -660,7 +660,7 @@ abstract class DBObject
if (count($aChanges) != 0)
{
$oFilter = new DBObjectSearch(get_class($this));
- $oFilter->AddCondition('pkey', $this->m_iKey, '=');
+ $oFilter->AddCondition('id', $this->m_iKey, '=');
$sSQL = MetaModel::MakeUpdateQuery($oFilter, $aChanges);
CMDBSource::Query($sSQL);
@@ -691,7 +691,7 @@ abstract class DBObject
public function DBDelete()
{
$oFilter = new DBObjectSearch(get_class($this));
- $oFilter->AddCondition('pkey', $this->m_iKey, '=');
+ $oFilter->AddCondition('id', $this->m_iKey, '=');
$sSQL = MetaModel::MakeDeleteQuery($oFilter);
CMDBSource::Query($sSQL);
diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php
index 45afef985..e7fa9dd95 100644
--- a/core/dbobjectsearch.class.php
+++ b/core/dbobjectsearch.class.php
@@ -162,7 +162,7 @@ class DBObjectSearch
public function __DescribeHTML()
{
- $sConditionDesc = $this->DescribeConditions();
+ $sConditionDesc = $this->DescribeConditions();
if (!empty($sConditionDesc))
{
return "Objects of class '$this->m_sClass', $sConditionDesc";
@@ -179,8 +179,8 @@ class DBObjectSearch
public function ResetCondition()
{
$this->m_oSearchCondition = new TrueExpression();
- // ? is that enough, do I need to rebuild the list after the subqueries ?
- $this->m_aClasses = array($this->m_sClassAlias => $this->m_sClass);
+ // ? is that usefull/enough, do I need to rebuild the list after the subqueries ?
+ // $this->m_aClasses = array($this->m_sClassAlias => $this->m_sClass);
}
public function AddConditionExpression($oExpression)
@@ -190,6 +190,11 @@ class DBObjectSearch
public function AddCondition($sFilterCode, $value, $sOpCode = null)
{
+ // #@# backward compatibility for pkey/id
+ if (strtolower(trim($sFilterCode)) == 'pkey') $sFilterCode = 'id';
+// #@# todo - obsolete smoothly, first send exceptions
+// throw new CoreException('SibusQL has been obsoleted, please update your queries', array('sibusql'=>$sQuery, 'oql'=>$oFilter->ToOQL()));
+
MyHelpers::CheckKeyInArray('filter code', $sFilterCode, MetaModel::GetClassFilterDefs($this->m_sClass));
$oFilterDef = MetaModel::GetClassFilterDef($this->m_sClass, $sFilterCode);
@@ -215,11 +220,13 @@ class DBObjectSearch
break;
case "IN":
+ if (!is_array($value)) $value = array($value);
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
$sOQLCondition = $oField->Render()." IN $sListExpr";
break;
case "NOTIN":
+ if (!is_array($value)) $value = array($value);
$sListExpr = '('.implode(', ', CMDBSource::Quote($value)).')';
$sOQLCondition = $oField->Render()." NOT IN $sListExpr";
break;
@@ -271,7 +278,7 @@ class DBObjectSearch
$sOrigAlias = $this->m_sClassAlias;
if (array_key_exists($sOrigAlias, $aClassAliases))
{
- $this->m_sClassAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $oFilter->GetClass());
+ $this->m_sClassAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $this->m_sClass);
// Translate the condition expression with the new alias
$aAliasTranslation[$sOrigAlias]['*'] = $this->m_sClassAlias;
}
@@ -316,19 +323,13 @@ class DBObjectSearch
}
else
{
- $sOrigAlias = $oFilter->GetClassAlias();
- $sKeyClassAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $oFilter->GetClass());
- if ($sKeyClassAlias != $sOrigAlias)
- {
- // Translate the condition expression with the new alias
- $aAliasTranslation[$sOrigAlias]['*'] = $sKeyClassAlias;
- }
+ $oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
// #@# The condition expression found in that filter should not be used - could be another kind of structure like a join spec tree !!!!
- $oNewFilter = clone $oFilter;
- $oNewFilter->ResetCondition();
+ // $oNewFilter = clone $oFilter;
+ // $oNewFilter->ResetCondition();
- $this->m_aPointingTo[$sExtKeyAttCode] = $oNewFilter;
+ $this->m_aPointingTo[$sExtKeyAttCode] = $oFilter;
}
}
@@ -340,7 +341,7 @@ class DBObjectSearch
return $res;
}
- public function AddCondition_ReferencedBy_InNameSpace(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, &$aClassAliases, &$aAliasTranslation)
+ protected function AddCondition_ReferencedBy_InNameSpace(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, &$aClassAliases, &$aAliasTranslation)
{
$sForeignClass = $oFilter->GetClass();
$sForeignClassAlias = $oFilter->GetClassAlias();
@@ -359,19 +360,13 @@ class DBObjectSearch
}
else
{
- $sOrigAlias = $oFilter->GetClassAlias();
- $sKeyClassAlias = MetaModel::GenerateUniqueAlias($aClassAliases, $sOrigAlias, $oFilter->GetClass());
- if ($sKeyClassAlias != $sOrigAlias)
- {
- // Translate the condition expression with the new alias
- $aAliasTranslation[$sOrigAlias]['*'] = $sKeyClassAlias;
- }
+ $oFilter->AddToNamespace($aClassAliases, $aAliasTranslation);
// #@# The condition expression found in that filter should not be used - could be another kind of structure like a join spec tree !!!!
- $oNewFilter = clone $oFilter;
- $oNewFilter->ResetCondition();
+ //$oNewFilter = clone $oFilter;
+ //$oNewFilter->ResetCondition();
- $this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]= $oNewFilter;
+ $this->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode]= $oFilter;
}
}
@@ -593,47 +588,36 @@ class DBObjectSearch
return $retValue;
}
- public function ToSibusQL()
+ public function ToOQL()
{
- $aConds = array(); // string conditions, to be merged into a logical AND
- foreach($this->m_aFullText as $sFullText)
- {
- $aConds[] = "* HAS ".self::Value2Expression($sFullText);
- }
- // #@# todo - changer ToSibusQL en ToOQL et l'implementer !
- // $aConds[] = $this->m_oSearchCondition->ToSibusQL
- /*
- foreach($this->m_aCriteria as $aCritInfo)
- {
- $aConds[] = $aCritInfo["filtercode"]." ".$aCritInfo["opcode"]." ".self::Value2Expression($aCritInfo["value"]);
- }
- */
+ $sRes = "SELECT ".$this->GetClass().' AS '.$this->GetClassAlias();
+ $sRes .= $this->ToOQL_Joins();
+ $sRes .= " WHERE ".$this->m_oSearchCondition->Render();
+ return $sRes;
+ }
+
+ protected function ToOQL_Joins()
+ {
+ $sRes = '';
foreach($this->m_aPointingTo as $sExtKey=>$oFilter)
{
- $aConds[] = $sExtKey." IN (".$oFilter->ToSibusQL().")";
+ $sRes .= ' JOIN '.$oFilter->GetClass().' AS '.$oFilter->GetClassAlias().' ON '.$this->GetClassAlias().'.'.$sExtKey.' = '.$oFilter->GetClassAlias().'.id';
+ $sRes .= $oFilter->ToOQL_Joins();
}
foreach($this->m_aReferencedBy as $sForeignClass=>$aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode=>$oForeignFilter)
{
- $aConds[] = "PKEY IS ".$sForeignExtKeyAttCode." IN (".$oForeignFilter->ToSibusQL().")";
+ $sRes .= ' JOIN '.$oForeignFilter->GetClass().' AS '.$oForeignFilter->GetClassAlias().' ON '.$oForeignFilter->GetClassAlias().'.'.$sForeignExtKeyAttCode.' = '.$this->GetClassAlias().'.id';
+ $sRes .= $oForeignFilter->ToOQL_Joins();
}
}
- foreach($this->m_aRelatedTo as $aRelatedTo)
- {
- $oFilter = $aRelatedTo['flt'];
- $sRelCode = $aRelatedTo['relcode'];
- $iMaxDepth = $aRelatedTo['maxdepth'];
-
- $aConds[] = "RELATED ($sRelCode, $iMaxDepth) TO (".$oFilter->ToSibuSQL().")";
- }
+ return $sRes;
+ }
- $sValue = $this->GetClass();
- if (count($aConds) > 0)
- {
- $sValue .= ": ".implode(" AND ", $aConds);
- }
- return $sValue;
+ public function ToSibusQL()
+ {
+ return "NONONO";
}
static private function privProcessParams($sQuery, array $aParams, $oDbObject)
@@ -659,7 +643,7 @@ class DBObjectSearch
if (strpos($sParameterName, "this.") === 0)
{
$sAttCode = substr($sParameterName, strlen("this."));
- if ($sAttCode == 'pkey')
+ if ($sAttCode == 'id')
{
$sValue = $oDbObject->GetKey();
}
@@ -717,19 +701,37 @@ class DBObjectSearch
$sFltCode = $oExpression->GetName();
if (empty($sClassAlias))
{
- $iPos = $oExpression->GetPosition();
- throw new OqlNormalizeException('Missing class specification', $sQuery, 0, $iPos, '');
+ // Try to find an alias
+ // Build an array of field => array of aliases
+ $aFieldClasses = array();
+ foreach($aClassAliases as $sAlias => $sReal)
+ {
+ foreach(MetaModel::GetFiltersList($sReal) as $sAnFltCode)
+ {
+ $aFieldClasses[$sAnFltCode][] = $sAlias;
+ }
+ }
+ if (!array_key_exists($sFltCode, $aFieldClasses))
+ {
+ throw new OqlNormalizeException('Unknown filter code', $sQuery, $oExpression->GetNameDetails(), array_keys($aFieldClasses));
+ }
+ if (count($aFieldClasses[$sFltCode]) > 1)
+ {
+ throw new OqlNormalizeException('Ambiguous filter code', $sQuery, $oExpression->GetNameDetails());
+ }
+ $sClassAlias = $aFieldClasses[$sFltCode][0];
}
- if (!array_key_exists($sClassAlias, $aClassAliases))
+ else
{
- $iPos = $oExpression->GetPosition();
- throw new OqlNormalizeException('Unknown class', $sQuery, 0, $iPos, $sClassAlias, array_keys($aClassAliases));
- }
- $sClass = $aClassAliases[$sClassAlias];
- if (!MetaModel::IsValidFilterCode($sClass, $sFltCode))
- {
- $iPos = $oExpression->GetPosition();
- throw new OqlNormalizeException('Unknown filter code', $sQuery, 0, $iPos, "$sFltCode in class $sClassAlias", MetaModel::GetFiltersList($sClass));
+ if (!array_key_exists($sClassAlias, $aClassAliases))
+ {
+ throw new OqlNormalizeException('Unknown class [alias]', $sQuery, $oExpression->GetParentDetails(), array_keys($aClassAliases));
+ }
+ $sClass = $aClassAliases[$sClassAlias];
+ if (!MetaModel::IsValidFilterCode($sClass, $sFltCode))
+ {
+ throw new OqlNormalizeException('Unknown filter code', $sQuery, $oExpression->GetNameDetails(), MetaModel::GetFiltersList($sClass));
+ }
}
return new FieldExpression($sFltCode, $sClassAlias);
@@ -768,11 +770,11 @@ class DBObjectSearch
if (!MetaModel::IsValidClass($sClass))
{
- throw new OqlNormalizeException('Unknown class', $sQuery, 0, 0, $sClass, MetaModel::GetClasses());
+ throw new OqlNormalizeException('Unknown class', $sQuery, $oOqlQuery->GetClassDetails(), MetaModel::GetClasses());
}
$oResultFilter = new DBObjectSearch($sClass, $sClassAlias);
- $oResultFilter->m_aClasses = array($sClassAlias => $sClass);
+ $aAliases = array($sClassAlias => $sClass);
// Maintain an array of filters, because the flat list is in fact referring to a tree
// And this will be an easy way to dispatch the conditions
@@ -788,17 +790,17 @@ class DBObjectSearch
$sJoinClassAlias = $oJoinSpec->GetClassAlias();
if (!MetaModel::IsValidClass($sJoinClass))
{
- throw new OqlNormalizeException('Unknown class', $sQuery, 0, 0, $sJoinClass, MetaModel::GetClasses());
+ throw new OqlNormalizeException('Unknown class', $sQuery, $oJoinSpec->GetClassDetails(), MetaModel::GetClasses());
}
- if (array_key_exists($sJoinClassAlias, $oResultFilter->m_aClasses))
+ if (array_key_exists($sJoinClassAlias, $aAliases))
{
if ($sJoinClassAlias != $sJoinClass)
{
- throw new OqlNormalizeException('Duplicate class alias', $sQuery, 0, 0, $sJoinClassAlias);
+ throw new OqlNormalizeException('Duplicate class alias', $sQuery, $oJoinSpec->GetClassAliasDetails());
}
else
{
- throw new OqlNormalizeException('Duplicate class name', $sQuery, 0, 0, $sJoinClass);
+ throw new OqlNormalizeException('Duplicate class name', $sQuery, $oJoinSpec->GetClassDetails());
}
}
@@ -813,24 +815,24 @@ class DBObjectSearch
$sPKeyDescriptor = $oRightField->GetName();
if ($sPKeyDescriptor != 'id')
{
- throw new OqlNormalizeException('Wrong format for Join clause (right hand), expecting an id', $sQuery, 0, $oRightField->GetPosition(), $sPKeyDescriptor, array('id'));
+ throw new OqlNormalizeException('Wrong format for Join clause (right hand), expecting an id', $sQuery, $oRightField->GetNameDetails(), array('id'));
}
- $oResultFilter->m_aClasses[$sJoinClassAlias] = $sJoinClass;
+ $aAliases[$sJoinClassAlias] = $sJoinClass;
$aJoinItems[$sJoinClassAlias] = new DBObjectSearch($sJoinClass, $sJoinClassAlias);
if (!array_key_exists($sFromClass, $aJoinItems))
{
- throw new OqlNormalizeException('Unknown class in join condition (left expression)', $sQuery, 0, $oLeftField->GetPosition(), $sFromClass, array_keys($aJoinItems));
+ throw new OqlNormalizeException('Unknown class in join condition (left expression)', $sQuery, $oLeftField->GetParentDetails(), array_keys($aJoinItems));
}
if (!array_key_exists($sToClass, $aJoinItems))
{
- throw new OqlNormalizeException('Unknown class in join condition (right expression)', $sQuery, 0, $oRightField->GetPosition(), $sToClass, array_keys($aJoinItems));
+ throw new OqlNormalizeException('Unknown class in join condition (right expression)', $sQuery, $oRightField->GetParentDetails(), array_keys($aJoinItems));
}
- $aExtKeys = array_keys(MetaModel::GetExternalKeys($oResultFilter->m_aClasses[$sFromClass]));
+ $aExtKeys = array_keys(MetaModel::GetExternalKeys($aAliases[$sFromClass]));
if (!in_array($sExtKeyAttCode, $aExtKeys))
{
- throw new OqlNormalizeException('Unknown external key in join condition (left expression)', $sQuery, 0, $oLeftField->GetPosition(), $sExtKeyAttCode, $aExtKeys);
+ throw new OqlNormalizeException('Unknown external key in join condition (left expression)', $sQuery, $oLeftField->GetNameDetails(), $aExtKeys);
}
if ($sFromClass == $sJoinClassAlias)
@@ -847,7 +849,7 @@ class DBObjectSearch
$oConditionTree = $oOqlQuery->GetCondition();
if ($oConditionTree instanceof Expression)
{
- $oResultFilter->m_oSearchCondition = $oResultFilter->OQLExpressionToCondition($sQuery, $oConditionTree, $oResultFilter->m_aClasses);
+ $oResultFilter->m_oSearchCondition = $oResultFilter->OQLExpressionToCondition($sQuery, $oConditionTree, $aAliases);
}
return $oResultFilter;
@@ -934,6 +936,10 @@ class DBObjectSearch
}
}
}
+
+// #@# todo - obsolete smoothly, first give the OQL version !
+// throw new CoreException('SibusQL has been obsoleted, please update your queries', array('sibusql'=>$sQuery, 'oql'=>$oFilter->ToOQL()));
+
return $oFilter;
}
diff --git a/core/expression.class.inc.php b/core/expression.class.inc.php
index 427fcb4ad..76409cdc1 100644
--- a/core/expression.class.inc.php
+++ b/core/expression.class.inc.php
@@ -22,6 +22,8 @@ abstract class Expression
// recursively builds an array of class => fieldname
abstract public function ListRequiredFields();
+ abstract public function IsTrue();
+
public function RequiresField($sClass, $sFieldName)
{
// #@# todo - optimize : this is called quite often when building a single query !
@@ -50,6 +52,8 @@ abstract class Expression
public function LogAnd($oExpr)
{
+ if ($this->IsTrue()) return clone $oExpr;
+ if ($oExpr->IsTrue()) return clone $this;
return new BinaryExpression($this, 'AND', $oExpr);
}
@@ -57,7 +61,6 @@ abstract class Expression
{
return new BinaryExpression($this, 'OR', $oExpr);
}
-
}
@@ -90,6 +93,16 @@ class BinaryExpression extends Expression
$this->m_sOperator = $sOperator;
}
+ public function IsTrue()
+ {
+ // return true if we are certain that it will be true
+ if ($this->m_sOperator == 'AND')
+ {
+ if ($this->m_oLeftExpr->IsTrue() && $this->m_oLeftExpr->IsTrue()) return true;
+ }
+ return false;
+ }
+
public function GetLeftExpr()
{
return $this->m_oLeftExpr;
@@ -139,6 +152,12 @@ class UnaryExpression extends Expression
$this->m_value = $value;
}
+ public function IsTrue()
+ {
+ // return true if we are certain that it will be true
+ return ($this->m_value == 1);
+ }
+
public function GetValue()
{
return $this->m_value;
@@ -179,6 +198,11 @@ class TrueExpression extends ScalarExpression
{
parent::__construct(1);
}
+
+ public function IsTrue()
+ {
+ return true;
+ }
}
class FieldExpression extends UnaryExpression
@@ -194,6 +218,12 @@ class FieldExpression extends UnaryExpression
$this->m_sName = $sName;
}
+ public function IsTrue()
+ {
+ // return true if we are certain that it will be true
+ return false;
+ }
+
public function GetParent() {return $this->m_sParent;}
public function GetName() {return $this->m_sName;}
@@ -251,6 +281,12 @@ class ListExpression extends Expression
$this->m_aExpressions = $aExpressions;
}
+ public function IsTrue()
+ {
+ // return true if we are certain that it will be true
+ return false;
+ }
+
public function GetItems()
{
return $this->m_aExpressions;
@@ -300,6 +336,12 @@ class FunctionExpression extends Expression
$this->m_aArgs = $aArgExpressions;
}
+ public function IsTrue()
+ {
+ // return true if we are certain that it will be true
+ return false;
+ }
+
public function GetVerb()
{
return $this->m_sVerb;
@@ -353,6 +395,12 @@ class IntervalExpression extends Expression
$this->m_sUnit = $sUnit;
}
+ public function IsTrue()
+ {
+ // return true if we are certain that it will be true
+ return false;
+ }
+
public function GetValue()
{
return $this->m_oValue;
@@ -389,6 +437,12 @@ class CharConcatExpression extends Expression
$this->m_aExpressions = $aExpressions;
}
+ public function IsTrue()
+ {
+ // return true if we are certain that it will be true
+ return false;
+ }
+
public function GetItems()
{
return $this->m_aExpressions;
diff --git a/core/filterdef.class.inc.php b/core/filterdef.class.inc.php
index 46ec424ed..ec09f50a0 100644
--- a/core/filterdef.class.inc.php
+++ b/core/filterdef.class.inc.php
@@ -107,10 +107,10 @@ class FilterPrivateKey extends FilterDefinition
{
static protected function ListExpectedParams()
{
- return array_merge(parent::ListExpectedParams(), array("pkey_field"));
+ return array_merge(parent::ListExpectedParams(), array("id_field"));
}
- public function GetType() {return "PKey";}
+ public function GetType() {return "PrivateKey";}
public function GetTypeDesc() {return "Match against object identifier";}
public function GetLabel()
@@ -139,7 +139,7 @@ class FilterPrivateKey extends FilterDefinition
public function GetFilterSQLExpr($sOpCode, $value)
{
- $sFieldName = $this->Get("pkey_field");
+ $sFieldName = $this->Get("id_field");
// #@# not obliged to quote... these are numbers !!!
$sQValue = CMDBSource::Quote($value);
switch($sOpCode)
@@ -162,7 +162,7 @@ class FilterPrivateKey extends FilterDefinition
}
public function TemporaryGetSQLCol()
{
- return $this->Get("pkey_field");
+ return $this->Get("id_field");
}
}
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index 96bb44dac..ed6dfc87f 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -274,7 +274,7 @@ abstract class MetaModel
final static public function DBGetTable($sClass, $sAttCode = null)
{
self::_check_subclass($sClass);
- if (empty($sAttCode) || ($sAttCode == "pkey"))
+ if (empty($sAttCode) || ($sAttCode == "id"))
{
$sTableRaw = self::$m_aClassParams[$sClass]["db_table"];
if (empty($sTableRaw))
@@ -801,19 +801,19 @@ abstract class MetaModel
}
}
- // Add a 'pkey' filter
+ // Add a 'id' filter
//
- if (array_key_exists('pkey', self::$m_aAttribDefs[$sClass]))
+ if (array_key_exists('id', self::$m_aAttribDefs[$sClass]))
{
- trigger_error("Class $sClass, 'pkey' is a reserved keyword, it cannot be used as an attribute code", E_USER_ERROR);
+ trigger_error("Class $sClass, 'id' is a reserved keyword, it cannot be used as an attribute code", E_USER_ERROR);
}
- if (array_key_exists('pkey', self::$m_aFilterDefs[$sClass]))
+ if (array_key_exists('id', self::$m_aFilterDefs[$sClass]))
{
- trigger_error("Class $sClass, 'pkey' is a reserved keyword, it cannot be used as a filter code", E_USER_ERROR);
+ trigger_error("Class $sClass, 'id' is a reserved keyword, it cannot be used as a filter code", E_USER_ERROR);
}
- $oFilter = new FilterPrivateKey('pkey', array('pkey_field' => self::DBGetKey($sClass)));
- self::$m_aFilterDefs[$sClass]['pkey'] = $oFilter;
- self::$m_aFilterOrigins[$sClass]['pkey'] = $sClass;
+ $oFilter = new FilterPrivateKey('id', array('id_field' => self::DBGetKey($sClass)));
+ self::$m_aFilterDefs[$sClass]['id'] = $oFilter;
+ self::$m_aFilterOrigins[$sClass]['id'] = $sClass;
// Add a 'class' attribute/filter to the root classes and their children
//
@@ -1270,8 +1270,8 @@ abstract class MetaModel
if (empty($aExpectedAtts) && $bIsOnQueriedClass)
{
- // default to the whole list of attributes + the very std pkey/finalclass
- $aExpectedAtts['pkey'] = 'pkey';
+ // default to the whole list of attributes + the very std id/finalclass
+ $aExpectedAtts['id'] = 'id';
foreach (self::GetAttributesList($sClass) as $sAttCode)
{
$aExpectedAtts[$sAttCode] = $sAttCode; // alias == attcode
@@ -1337,7 +1337,6 @@ abstract class MetaModel
// Filter on objects referencing me
foreach ($oFilter->GetCriteria_ReferencedBy() as $sForeignClass => $aKeysAndFilters)
{
- $sForeignClassAlias = $oFilter->GetClassAlias();
foreach ($aKeysAndFilters as $sForeignKeyAttCode => $oForeignFilter)
{
$oForeignKeyAttDef = self::GetAttributeDef($sForeignClass, $sForeignKeyAttCode);
@@ -1352,8 +1351,10 @@ abstract class MetaModel
//self::DbgTrace($oSelectForeign->RenderSelect(array()));
$oSelectForeign = self::MakeQuery($sGlobalTargetAlias, $oConditionTree, $aClassAliases, $aTableAliases, $aTranslation, $oForeignFilter, $aExpAtts);
- $sForeignKeyField = $oForeignKeyAttDef->GetSQLExpr();
- $oSelectBase->AddInnerJoin($oSelectForeign, $sKeyField, $sForeignKeyField);
+ $sForeignClassAlias = $oForeignFilter->GetClassAlias();
+ $sForeignKeyTable = $aTranslation[$sForeignClassAlias][$sForeignKeyAttCode][0];
+ $sForeignKeyColumn = $aTranslation[$sForeignClassAlias][$sForeignKeyAttCode][1];
+ $oSelectBase->AddInnerJoin($oSelectForeign, $sKeyField, $sForeignKeyColumn, $sForeignKeyTable);
}
}
@@ -1415,7 +1416,7 @@ abstract class MetaModel
$sTargetClass = $oFilter->GetClass();
$sTargetAlias = $oFilter->GetClassAlias();
$sTable = self::DBGetTable($sTableClass);
- $sTableAlias = self::GenerateUniqueAlias($aTableAliases, $sTable, $sTable);
+ $sTableAlias = self::GenerateUniqueAlias($aTableAliases, $sTargetAlias.'_'.$sTable, $sTable);
$bIsOnQueriedClass = ($sTargetAlias == $sGlobalTargetAlias);
@@ -1432,12 +1433,12 @@ abstract class MetaModel
//
if ($bIsOnQueriedClass)
{
- $aSelect[$aExpectedAtts['pkey']] = new FieldExpression(self::DBGetKey($sTableClass), $sTableAlias);
+ $aSelect[$aExpectedAtts['id']] = new FieldExpression(self::DBGetKey($sTableClass), $sTableAlias);
}
// We need one pkey to be the key, let's take the one corresponding to the leaf
if ($sTableClass == $sTargetClass)
{
- $aTranslation[$sTargetAlias]['pkey'] = array($sTableAlias, self::DBGetKey($sTableClass));
+ $aTranslation[$sTargetAlias]['id'] = array($sTableAlias, self::DBGetKey($sTableClass));
}
// 1/b - Get the other attributes
@@ -1481,10 +1482,6 @@ abstract class MetaModel
//
foreach(self::$m_aFilterDefs[$sTargetClass] as $sFltCode => $oFltAtt)
{
- // Skip pkey
- // no, this is a bug now! ?!?!?
- // if ($sFltCode == 'pkey') continue;
-
// Skip this filter if not defined in this table
if (self::$m_aFilterOrigins[$sTargetClass][$sFltCode] != $sTableClass) continue;
@@ -1579,23 +1576,25 @@ abstract class MetaModel
return $oSelectBase;
}
- public static function GenerateUniqueAlias(&$aAliases, $sNewName, $sRealName, $iTentative = 0)
+ public static function GenerateUniqueAlias(&$aAliases, $sNewName, $sRealName)
{
- // Algo: Build an alias, then check it amongst the contents of $aAliases
-
- if ($iTentative == 0) $sProposedAlias = $sNewName;
- else $sProposedAlias = $sNewName.$iTentative;
-
- foreach($aAliases as $sAlias=>$sNameWeDontCare)
+ if (!array_key_exists($sNewName, $aAliases))
{
- // If the name is already used, then recursively try to get another one
- if ($sProposedAlias == $sAlias) return self::GenerateUniqueAlias($aAliases, $sNewName, $sRealName, $iTentative + 1);
+ $aAliases[$sNewName] = $sRealName;
+ return $sNewName;
}
-
- // The proposed alias has been proven to be unique
- // Record it and return its value
- $aAliases[$sProposedAlias] = $sRealName;
- return $sProposedAlias;
+
+ for ($i = 1 ; $i < 100 ; $i++)
+ {
+ $sAnAlias = $sNewName.$i;
+ if (!array_key_exists($sAnAlias, $aAliases))
+ {
+ // Create that new alias
+ $aAliases[$sAnAlias] = $sRealName;
+ return $sAnAlias;
+ }
+ }
+ throw new CoreException('Failed to create an alias', array('aliases' => $aAliases, 'new'=>$sNewName));
}
public static function CheckDefinitions()
@@ -1630,7 +1629,7 @@ abstract class MetaModel
if (empty($sNameAttCode))
{
// let's try this !!!
- // $aErrors[$sClass][] = "Missing value for name definition: the framework will (should...) replace it by the pkey";
+ // $aErrors[$sClass][] = "Missing value for name definition: the framework will (should...) replace it by the id";
// $aSugFix[$sClass][] = "Expecting a value in ".implode(", ", self::GetAttributesList($sClass));
}
else if(!self::IsValidAttCode($sClass, $sNameAttCode))
@@ -2013,7 +2012,7 @@ abstract class MetaModel
{
$sSelWrongRecs .= " AND maintable.`$sKeyField` NOT IN ('".implode("', '", $aPlannedDel[$sTable])."')";
}
- $aWrongRecords = CMDBSource::QueryToCol($sSelWrongRecs, "pkey");
+ $aWrongRecords = CMDBSource::QueryToCol($sSelWrongRecs, "id");
if (count($aWrongRecords) == 0) return;
if (!array_key_exists($sRootClass, $aErrorsAndFixes)) $aErrorsAndFixes[$sRootClass] = array();
@@ -2069,7 +2068,7 @@ abstract class MetaModel
// skip the current table
if ($sFriendTable == $sTable) continue;
- $sFindRelatedRec = "SELECT DISTINCT maintable.`$sFriendKey` AS pkey FROM `$sFriendTable` AS maintable WHERE maintable.`$sFriendKey` IN ($sDeleteKeys)";
+ $sFindRelatedRec = "SELECT DISTINCT maintable.`$sFriendKey` AS id FROM `$sFriendTable` AS maintable WHERE maintable.`$sFriendKey` IN ($sDeleteKeys)";
self::DBCheckIntegrity_Check2Delete($sFindRelatedRec, "Cascading deletion of record in friend table `$sTable`", $sFriendClass, $aErrorsAndFixes, $iNewDelCount, $aPlannedDel, true);
}
}
@@ -2085,7 +2084,7 @@ abstract class MetaModel
{
$sSelWrongRecs .= " AND maintable.`$sKeyField` NOT IN ('".implode("', '", $aPlannedDel[$sTable])."')";
}
- $aWrongRecords = CMDBSource::QueryToCol($sSelWrongRecs, "pkey");
+ $aWrongRecords = CMDBSource::QueryToCol($sSelWrongRecs, "id");
if (count($aWrongRecords) == 0) return;
if (!array_key_exists($sRootClass, $aErrorsAndFixes)) $aErrorsAndFixes[$sRootClass] = array();
@@ -2150,7 +2149,7 @@ abstract class MetaModel
$aAllowedValues = self::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL);
$sAllowedValues = implode(",", CMDBSource::Quote($aAllowedValues, true));
- $sSelWrongRecs = "SELECT DISTINCT maintable.`$sKeyField` AS pkey FROM `$sTable` AS maintable WHERE `$sFinalClassField` NOT IN ($sAllowedValues)";
+ $sSelWrongRecs = "SELECT DISTINCT maintable.`$sKeyField` AS id FROM `$sTable` AS maintable WHERE `$sFinalClassField` NOT IN ($sAllowedValues)";
self::DBCheckIntegrity_Check2Delete($sSelWrongRecs, "final class (field `$sFinalClassField`) is wrong (expected a value in {".$sAllowedValues."})", $sClass, $aErrorsAndFixes, $iNewDelCount, $aPlannedDel);
}
@@ -2168,13 +2167,13 @@ abstract class MetaModel
// Check that any record found here has its counterpart in the root table
// and which refers to a child class
//
- $sSelWrongRecs = "SELECT DISTINCT maintable.`$sKeyField` AS pkey FROM `$sTable` as maintable LEFT JOIN `$sRootTable` ON maintable.`$sKeyField` = `$sRootTable`.`$sRootKey` AND `$sRootTable`.`$sFinalClassField` IN ($sExpectedClasses) WHERE `$sRootTable`.`$sRootKey` IS NULL";
+ $sSelWrongRecs = "SELECT DISTINCT maintable.`$sKeyField` AS id FROM `$sTable` as maintable LEFT JOIN `$sRootTable` ON maintable.`$sKeyField` = `$sRootTable`.`$sRootKey` AND `$sRootTable`.`$sFinalClassField` IN ($sExpectedClasses) WHERE `$sRootTable`.`$sRootKey` IS NULL";
self::DBCheckIntegrity_Check2Delete($sSelWrongRecs, "Found a record in `$sTable`, but no counterpart in root table `$sRootTable` (inc. records pointing to a class in {".$sExpectedClasses."})", $sClass, $aErrorsAndFixes, $iNewDelCount, $aPlannedDel);
// Check that any record found in the root table and referring to a child class
// has its counterpart here (detect orphan nodes -root or in the middle of the hierarchy)
//
- $sSelWrongRecs = "SELECT DISTINCT maintable.`$sRootKey` AS pkey FROM `$sRootTable` AS maintable LEFT JOIN `$sTable` ON maintable.`$sRootKey` = `$sTable`.`$sKeyField` WHERE `$sTable`.`$sKeyField` IS NULL AND maintable.`$sFinalClassField` IN ($sExpectedClasses)";
+ $sSelWrongRecs = "SELECT DISTINCT maintable.`$sRootKey` AS id FROM `$sRootTable` AS maintable LEFT JOIN `$sTable` ON maintable.`$sRootKey` = `$sTable`.`$sKeyField` WHERE `$sTable`.`$sKeyField` IS NULL AND maintable.`$sFinalClassField` IN ($sExpectedClasses)";
self::DBCheckIntegrity_Check2Delete($sSelWrongRecs, "Found a record in root table `$sRootTable`, but no counterpart in table `$sTable` (root records pointing to a class in {".$sExpectedClasses."})", $sRootClass, $aErrorsAndFixes, $iNewDelCount, $aPlannedDel);
}
@@ -2194,7 +2193,7 @@ abstract class MetaModel
$sExtKeyField = $oAttDef->GetSQLExpr();
// Note: a class/table may have an external key on itself
- $sSelBase = "SELECT DISTINCT maintable.`$sKeyField` AS pkey, maintable.`$sExtKeyField` AS extkey FROM `$sTable` AS maintable LEFT JOIN `$sRemoteTable` ON maintable.`$sExtKeyField` = `$sRemoteTable`.`$sRemoteKey`";
+ $sSelBase = "SELECT DISTINCT maintable.`$sKeyField` AS id, maintable.`$sExtKeyField` AS extkey FROM `$sTable` AS maintable LEFT JOIN `$sRemoteTable` ON maintable.`$sExtKeyField` = `$sRemoteTable`.`$sRemoteKey`";
$sSelWrongRecs = $sSelBase." WHERE `$sRemoteTable`.`$sRemoteKey` IS NULL";
if ($oAttDef->IsNullAllowed())
@@ -2239,7 +2238,7 @@ abstract class MetaModel
$sMyAttributeField = $oAttDef->GetSQLExpr();
$sDefaultValue = $oAttDef->GetDefaultValue();
- $sSelWrongRecs = "SELECT DISTINCT maintable.`$sKeyField` AS pkey FROM `$sTable` AS maintable WHERE maintable.`$sMyAttributeField` NOT IN ($sExpectedValues)";
+ $sSelWrongRecs = "SELECT DISTINCT maintable.`$sKeyField` AS id FROM `$sTable` AS maintable WHERE maintable.`$sMyAttributeField` NOT IN ($sExpectedValues)";
self::DBCheckIntegrity_Check2Update($sSelWrongRecs, "Record having a column ('$sAttCode') with an unexpected value", $sMyAttributeField, CMDBSource::Quote($sDefaultValue), $sClass, $aErrorsAndFixes, $iNewDelCount, $aPlannedDel);
}
}
@@ -2464,7 +2463,7 @@ abstract class MetaModel
public static function MakeSingleRow($sClass, $iKey)
{
$oFilter = new DBObjectSearch($sClass);
- $oFilter->AddCondition('pkey', $iKey, '=');
+ $oFilter->AddCondition('id', $iKey, '=');
$sSQL = self::MakeSelectQuery($oFilter);
//echo "$sSQL\n";
@@ -2496,7 +2495,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["pkey"]} (root class '$sRootClass', field '{$sFinalClassField}' is empty)", E_USER_ERROR);
+ trigger_error("Empty class name for object $sClass::{$aRow["id"]} (root class '$sRootClass', field '{$sFinalClassField}' is empty)", E_USER_ERROR);
}
else
{
diff --git a/core/oql/oql-parser.php b/core/oql/oql-parser.php
index faf64faee..4fdffa704 100644
--- a/core/oql/oql-parser.php
+++ b/core/oql/oql-parser.php
@@ -131,14 +131,14 @@ class OQLParserRaw#line 102 "oql-parser.php"
const NOT_EQ = 18;
const LOG_AND = 19;
const LOG_OR = 20;
- const GT = 21;
- const LT = 22;
- const GE = 23;
- const LE = 24;
- const MATH_DIV = 25;
- const MATH_MULT = 26;
- const MATH_PLUS = 27;
- const MATH_MINUS = 28;
+ const MATH_DIV = 21;
+ const MATH_MULT = 22;
+ const MATH_PLUS = 23;
+ const MATH_MINUS = 24;
+ const GT = 25;
+ const LT = 26;
+ const GE = 27;
+ const LE = 28;
const LIKE = 29;
const NOT_LIKE = 30;
const IN = 31;
@@ -160,9 +160,9 @@ class OQLParserRaw#line 102 "oql-parser.php"
const F_DATE_SUB = 47;
const F_ROUND = 48;
const F_FLOOR = 49;
- const YY_NO_ACTION = 186;
- const YY_ACCEPT_ACTION = 185;
- const YY_ERROR_ACTION = 184;
+ const YY_NO_ACTION = 205;
+ const YY_ACCEPT_ACTION = 204;
+ const YY_ERROR_ACTION = 203;
/* Next are that tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
@@ -214,99 +214,111 @@ class OQLParserRaw#line 102 "oql-parser.php"
** shifting non-terminals after a reduce.
** self::$yy_default Default action for each state.
*/
- const YY_SZ_ACTTAB = 369;
+ const YY_SZ_ACTTAB = 419;
static public $yy_action = array(
- /* 0 */ 6, 67, 66, 5, 61, 62, 60, 65, 35, 67,
- /* 10 */ 66, 82, 30, 83, 13, 81, 75, 74, 68, 81,
- /* 20 */ 75, 74, 68, 8, 29, 20, 42, 44, 41, 43,
- /* 30 */ 36, 37, 38, 39, 63, 58, 57, 56, 59, 55,
- /* 40 */ 54, 48, 47, 23, 40, 40, 31, 49, 4, 6,
- /* 50 */ 27, 52, 14, 61, 62, 60, 94, 35, 67, 66,
- /* 60 */ 64, 2, 69, 70, 73, 22, 40, 50, 15, 18,
- /* 70 */ 26, 21, 18, 19, 33, 42, 44, 41, 43, 36,
- /* 80 */ 37, 38, 39, 63, 58, 57, 56, 59, 55, 54,
- /* 90 */ 48, 47, 6, 4, 40, 27, 61, 62, 60, 3,
- /* 100 */ 35, 67, 66, 46, 24, 1, 18, 69, 70, 73,
- /* 110 */ 80, 25, 16, 19, 35, 77, 17, 158, 42, 44,
- /* 120 */ 41, 43, 36, 37, 38, 39, 63, 58, 57, 56,
- /* 130 */ 59, 55, 54, 48, 47, 72, 40, 158, 158, 158,
- /* 140 */ 93, 92, 105, 158, 158, 158, 158, 71, 84, 85,
- /* 150 */ 99, 98, 97, 100, 101, 104, 103, 102, 96, 95,
- /* 160 */ 89, 88, 72, 158, 79, 158, 158, 158, 158, 158,
- /* 170 */ 158, 158, 158, 158, 71, 84, 85, 99, 98, 97,
- /* 180 */ 100, 101, 104, 103, 102, 96, 95, 89, 88, 72,
- /* 190 */ 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
- /* 200 */ 158, 71, 84, 85, 99, 98, 97, 100, 101, 104,
- /* 210 */ 103, 102, 96, 95, 89, 88, 185, 90, 78, 31,
- /* 220 */ 158, 158, 158, 158, 86, 12, 158, 87, 158, 31,
- /* 230 */ 32, 158, 158, 53, 34, 81, 75, 74, 68, 40,
- /* 240 */ 31, 158, 158, 158, 158, 86, 11, 158, 87, 40,
- /* 250 */ 158, 32, 28, 158, 45, 158, 81, 75, 74, 68,
- /* 260 */ 40, 31, 158, 158, 158, 158, 86, 11, 158, 87,
- /* 270 */ 158, 158, 32, 158, 158, 91, 158, 81, 75, 74,
- /* 280 */ 68, 40, 158, 158, 76, 31, 158, 158, 158, 158,
- /* 290 */ 86, 12, 158, 87, 158, 31, 32, 158, 158, 51,
- /* 300 */ 34, 81, 75, 74, 68, 40, 31, 158, 158, 158,
- /* 310 */ 158, 86, 9, 158, 87, 40, 158, 32, 158, 158,
- /* 320 */ 158, 158, 81, 75, 74, 68, 40, 31, 158, 158,
- /* 330 */ 158, 158, 86, 10, 158, 87, 158, 158, 32, 158,
- /* 340 */ 158, 158, 158, 81, 75, 74, 68, 40, 31, 158,
- /* 350 */ 158, 158, 158, 86, 7, 158, 87, 158, 158, 32,
- /* 360 */ 158, 158, 158, 158, 81, 75, 74, 68, 40,
+ /* 0 */ 5, 57, 8, 4, 95, 96, 97, 6, 93, 76,
+ /* 10 */ 77, 89, 2, 53, 86, 50, 54, 25, 52, 55,
+ /* 20 */ 51, 46, 47, 49, 56, 70, 94, 110, 109, 108,
+ /* 30 */ 107, 111, 112, 115, 114, 113, 106, 71, 98, 99,
+ /* 40 */ 100, 104, 103, 26, 66, 38, 42, 9, 81, 5,
+ /* 50 */ 62, 44, 82, 95, 96, 97, 3, 93, 76, 77,
+ /* 60 */ 39, 102, 92, 75, 74, 73, 72, 75, 74, 73,
+ /* 70 */ 72, 10, 66, 41, 91, 94, 110, 109, 108, 107,
+ /* 80 */ 111, 112, 115, 114, 113, 106, 71, 98, 99, 100,
+ /* 90 */ 104, 103, 5, 63, 90, 22, 95, 96, 97, 61,
+ /* 100 */ 93, 76, 77, 65, 64, 60, 83, 11, 80, 79,
+ /* 110 */ 91, 33, 91, 22, 21, 18, 16, 12, 94, 110,
+ /* 120 */ 109, 108, 107, 111, 112, 115, 114, 113, 106, 71,
+ /* 130 */ 98, 99, 100, 104, 103, 204, 105, 87, 42, 23,
+ /* 140 */ 43, 24, 66, 88, 30, 28, 84, 45, 36, 6,
+ /* 150 */ 22, 20, 58, 15, 32, 37, 1, 76, 77, 101,
+ /* 160 */ 116, 75, 74, 73, 72, 41, 13, 66, 7, 160,
+ /* 170 */ 67, 93, 24, 42, 35, 78, 173, 173, 88, 34,
+ /* 180 */ 28, 84, 45, 40, 42, 173, 20, 173, 15, 69,
+ /* 190 */ 37, 173, 173, 173, 59, 173, 75, 74, 73, 72,
+ /* 200 */ 41, 42, 173, 173, 173, 173, 88, 34, 28, 84,
+ /* 210 */ 45, 41, 173, 173, 20, 173, 15, 173, 37, 173,
+ /* 220 */ 173, 173, 68, 173, 75, 74, 73, 72, 41, 173,
+ /* 230 */ 173, 173, 85, 42, 173, 173, 173, 173, 88, 30,
+ /* 240 */ 28, 84, 45, 173, 173, 173, 20, 173, 15, 173,
+ /* 250 */ 37, 173, 173, 173, 173, 173, 75, 74, 73, 72,
+ /* 260 */ 41, 42, 173, 173, 173, 173, 88, 17, 28, 84,
+ /* 270 */ 45, 173, 173, 173, 20, 173, 15, 42, 37, 173,
+ /* 280 */ 173, 48, 44, 173, 75, 74, 73, 72, 41, 173,
+ /* 290 */ 173, 173, 173, 42, 173, 173, 173, 173, 88, 27,
+ /* 300 */ 28, 84, 45, 173, 41, 173, 20, 173, 15, 173,
+ /* 310 */ 37, 173, 173, 173, 173, 173, 75, 74, 73, 72,
+ /* 320 */ 41, 42, 173, 173, 173, 173, 88, 173, 28, 84,
+ /* 330 */ 45, 173, 173, 173, 20, 173, 15, 173, 31, 173,
+ /* 340 */ 173, 173, 173, 173, 75, 74, 73, 72, 41, 173,
+ /* 350 */ 173, 173, 173, 42, 173, 173, 173, 173, 88, 173,
+ /* 360 */ 28, 84, 45, 173, 173, 173, 20, 173, 14, 173,
+ /* 370 */ 173, 173, 173, 173, 173, 173, 75, 74, 73, 72,
+ /* 380 */ 41, 42, 173, 173, 173, 173, 88, 173, 28, 84,
+ /* 390 */ 45, 42, 173, 173, 19, 173, 88, 173, 29, 84,
+ /* 400 */ 45, 173, 173, 173, 75, 74, 73, 72, 41, 173,
+ /* 410 */ 173, 173, 173, 173, 75, 74, 73, 72, 41,
);
static public $yy_lookahead = array(
- /* 0 */ 7, 16, 17, 10, 11, 12, 13, 62, 15, 16,
- /* 10 */ 17, 62, 67, 8, 9, 70, 71, 72, 73, 70,
- /* 20 */ 71, 72, 73, 7, 54, 54, 33, 34, 35, 36,
+ /* 0 */ 7, 6, 70, 10, 11, 12, 13, 73, 15, 16,
+ /* 10 */ 17, 8, 9, 18, 56, 83, 84, 54, 23, 24,
+ /* 20 */ 25, 26, 27, 28, 29, 30, 33, 34, 35, 36,
/* 30 */ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
- /* 40 */ 47, 48, 49, 1, 74, 74, 54, 56, 61, 7,
- /* 50 */ 63, 59, 5, 11, 12, 13, 69, 15, 16, 17,
- /* 60 */ 8, 9, 75, 76, 77, 2, 74, 55, 5, 57,
- /* 70 */ 55, 2, 57, 4, 54, 33, 34, 35, 36, 37,
+ /* 40 */ 47, 48, 49, 1, 81, 54, 54, 68, 62, 7,
+ /* 50 */ 58, 59, 62, 11, 12, 13, 3, 15, 16, 17,
+ /* 60 */ 74, 82, 8, 77, 78, 79, 80, 77, 78, 79,
+ /* 70 */ 80, 7, 81, 81, 20, 33, 34, 35, 36, 37,
/* 80 */ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- /* 90 */ 48, 49, 7, 61, 74, 63, 11, 12, 13, 3,
- /* 100 */ 15, 16, 17, 74, 55, 7, 57, 75, 76, 77,
- /* 110 */ 64, 14, 6, 4, 15, 56, 54, 78, 33, 34,
+ /* 90 */ 48, 49, 7, 55, 66, 57, 11, 12, 13, 56,
+ /* 100 */ 15, 16, 17, 11, 12, 13, 8, 9, 31, 32,
+ /* 110 */ 20, 55, 20, 57, 2, 54, 6, 5, 33, 34,
/* 120 */ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- /* 130 */ 45, 46, 47, 48, 49, 6, 74, 78, 78, 78,
- /* 140 */ 11, 12, 13, 78, 78, 78, 78, 18, 19, 20,
- /* 150 */ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- /* 160 */ 31, 32, 6, 78, 8, 78, 78, 78, 78, 78,
- /* 170 */ 78, 78, 78, 78, 18, 19, 20, 21, 22, 23,
- /* 180 */ 24, 25, 26, 27, 28, 29, 30, 31, 32, 6,
- /* 190 */ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- /* 200 */ 78, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- /* 210 */ 27, 28, 29, 30, 31, 32, 51, 52, 53, 54,
- /* 220 */ 78, 78, 78, 78, 59, 60, 78, 62, 78, 54,
- /* 230 */ 65, 78, 78, 58, 59, 70, 71, 72, 73, 74,
- /* 240 */ 54, 78, 78, 78, 78, 59, 60, 78, 62, 74,
- /* 250 */ 78, 65, 66, 78, 68, 78, 70, 71, 72, 73,
- /* 260 */ 74, 54, 78, 78, 78, 78, 59, 60, 78, 62,
- /* 270 */ 78, 78, 65, 78, 78, 68, 78, 70, 71, 72,
- /* 280 */ 73, 74, 78, 78, 53, 54, 78, 78, 78, 78,
- /* 290 */ 59, 60, 78, 62, 78, 54, 65, 78, 78, 58,
- /* 300 */ 59, 70, 71, 72, 73, 74, 54, 78, 78, 78,
- /* 310 */ 78, 59, 60, 78, 62, 74, 78, 65, 78, 78,
- /* 320 */ 78, 78, 70, 71, 72, 73, 74, 54, 78, 78,
- /* 330 */ 78, 78, 59, 60, 78, 62, 78, 78, 65, 78,
- /* 340 */ 78, 78, 78, 70, 71, 72, 73, 74, 54, 78,
- /* 350 */ 78, 78, 78, 59, 60, 78, 62, 78, 78, 65,
- /* 360 */ 78, 78, 78, 78, 70, 71, 72, 73, 74,
+ /* 130 */ 45, 46, 47, 48, 49, 51, 52, 53, 54, 2,
+ /* 140 */ 54, 4, 81, 59, 60, 61, 62, 63, 55, 73,
+ /* 150 */ 57, 67, 76, 69, 14, 71, 7, 16, 17, 21,
+ /* 160 */ 22, 77, 78, 79, 80, 81, 5, 81, 72, 14,
+ /* 170 */ 19, 15, 4, 54, 65, 81, 85, 85, 59, 60,
+ /* 180 */ 61, 62, 63, 64, 54, 85, 67, 85, 69, 59,
+ /* 190 */ 71, 85, 85, 85, 75, 85, 77, 78, 79, 80,
+ /* 200 */ 81, 54, 85, 85, 85, 85, 59, 60, 61, 62,
+ /* 210 */ 63, 81, 85, 85, 67, 85, 69, 85, 71, 85,
+ /* 220 */ 85, 85, 75, 85, 77, 78, 79, 80, 81, 85,
+ /* 230 */ 85, 85, 53, 54, 85, 85, 85, 85, 59, 60,
+ /* 240 */ 61, 62, 63, 85, 85, 85, 67, 85, 69, 85,
+ /* 250 */ 71, 85, 85, 85, 85, 85, 77, 78, 79, 80,
+ /* 260 */ 81, 54, 85, 85, 85, 85, 59, 60, 61, 62,
+ /* 270 */ 63, 85, 85, 85, 67, 85, 69, 54, 71, 85,
+ /* 280 */ 85, 58, 59, 85, 77, 78, 79, 80, 81, 85,
+ /* 290 */ 85, 85, 85, 54, 85, 85, 85, 85, 59, 60,
+ /* 300 */ 61, 62, 63, 85, 81, 85, 67, 85, 69, 85,
+ /* 310 */ 71, 85, 85, 85, 85, 85, 77, 78, 79, 80,
+ /* 320 */ 81, 54, 85, 85, 85, 85, 59, 85, 61, 62,
+ /* 330 */ 63, 85, 85, 85, 67, 85, 69, 85, 71, 85,
+ /* 340 */ 85, 85, 85, 85, 77, 78, 79, 80, 81, 85,
+ /* 350 */ 85, 85, 85, 54, 85, 85, 85, 85, 59, 85,
+ /* 360 */ 61, 62, 63, 85, 85, 85, 67, 85, 69, 85,
+ /* 370 */ 85, 85, 85, 85, 85, 85, 77, 78, 79, 80,
+ /* 380 */ 81, 54, 85, 85, 85, 85, 59, 85, 61, 62,
+ /* 390 */ 63, 54, 85, 85, 67, 85, 59, 85, 61, 62,
+ /* 400 */ 63, 85, 85, 85, 77, 78, 79, 80, 81, 85,
+ /* 410 */ 85, 85, 85, 85, 77, 78, 79, 80, 81,
);
- const YY_SHIFT_USE_DFLT = -16;
- const YY_SHIFT_MAX = 34;
+ const YY_SHIFT_USE_DFLT = -8;
+ const YY_SHIFT_MAX = 45;
static public $yy_shift_ofst = array(
- /* 0 */ 42, -7, -7, 85, 85, 85, 85, 129, -15, 156,
- /* 10 */ 183, 183, 183, -15, 99, 99, 99, 69, 109, 99,
- /* 20 */ 109, 99, 99, 99, 96, 99, 96, 16, 52, 63,
- /* 30 */ 5, 97, 98, 47, 106,
+ /* 0 */ 42, -7, -7, 85, 85, 85, 85, 85, 85, 85,
+ /* 10 */ 141, 141, 156, 156, -5, -5, 156, 92, 137, 138,
+ /* 20 */ 138, 156, 168, 156, 156, 168, 156, 54, 77, 77,
+ /* 30 */ 90, 151, 156, 53, 90, 64, 53, 151, 112, 98,
+ /* 40 */ 3, 155, 140, 161, 110, 149,
);
- const YY_REDUCE_USE_DFLT = -56;
- const YY_REDUCE_MAX = 27;
+ const YY_REDUCE_USE_DFLT = -69;
+ const YY_REDUCE_MAX = 37;
static public $yy_reduce_ofst = array(
- /* 0 */ 165, 186, 207, 231, 273, 294, 252, -13, -55, 32,
- /* 10 */ 32, 32, 32, -51, 175, 241, -8, 49, 12, -30,
- /* 20 */ 15, -29, 20, 62, 59, 29, -9, 46,
+ /* 0 */ 84, 119, 147, 179, 207, 239, 267, 299, 327, 337,
+ /* 10 */ -14, -10, 223, -8, -68, -68, 130, 76, 93, -21,
+ /* 20 */ -21, 86, 38, -37, -9, 56, 61, -66, 109, 109,
+ /* 30 */ -66, 96, 94, 43, -66, 28, -42, 96,
);
static public $yyExpectedTokens = array(
/* 0 */ array(1, 7, 11, 12, 13, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ),
@@ -316,45 +328,45 @@ static public $yy_action = array(
/* 4 */ array(7, 11, 12, 13, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ),
/* 5 */ array(7, 11, 12, 13, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ),
/* 6 */ array(7, 11, 12, 13, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ),
- /* 7 */ array(6, 11, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ),
- /* 8 */ array(16, 17, ),
- /* 9 */ array(6, 8, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ),
- /* 10 */ array(6, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ),
- /* 11 */ array(6, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ),
- /* 12 */ array(6, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ),
- /* 13 */ array(16, 17, ),
- /* 14 */ array(15, ),
- /* 15 */ array(15, ),
+ /* 7 */ array(7, 11, 12, 13, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ),
+ /* 8 */ array(7, 11, 12, 13, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ),
+ /* 9 */ array(7, 11, 12, 13, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ),
+ /* 10 */ array(16, 17, ),
+ /* 11 */ array(16, 17, ),
+ /* 12 */ array(15, ),
+ /* 13 */ array(15, ),
+ /* 14 */ array(6, 18, 23, 24, 25, 26, 27, 28, 29, 30, ),
+ /* 15 */ array(6, 18, 23, 24, 25, 26, 27, 28, 29, 30, ),
/* 16 */ array(15, ),
- /* 17 */ array(2, 4, ),
- /* 18 */ array(4, ),
- /* 19 */ array(15, ),
- /* 20 */ array(4, ),
+ /* 17 */ array(11, 12, 13, 20, ),
+ /* 18 */ array(2, 4, ),
+ /* 19 */ array(21, 22, ),
+ /* 20 */ array(21, 22, ),
/* 21 */ array(15, ),
- /* 22 */ array(15, ),
+ /* 22 */ array(4, ),
/* 23 */ array(15, ),
- /* 24 */ array(3, ),
- /* 25 */ array(15, ),
- /* 26 */ array(3, ),
- /* 27 */ array(7, ),
- /* 28 */ array(8, 9, ),
- /* 29 */ array(2, 5, ),
- /* 30 */ array(8, 9, ),
- /* 31 */ array(14, ),
- /* 32 */ array(7, ),
- /* 33 */ array(5, ),
- /* 34 */ array(6, ),
- /* 35 */ array(),
- /* 36 */ array(),
- /* 37 */ array(),
- /* 38 */ array(),
- /* 39 */ array(),
- /* 40 */ array(),
- /* 41 */ array(),
- /* 42 */ array(),
- /* 43 */ array(),
- /* 44 */ array(),
- /* 45 */ array(),
+ /* 24 */ array(15, ),
+ /* 25 */ array(4, ),
+ /* 26 */ array(15, ),
+ /* 27 */ array(8, 20, ),
+ /* 28 */ array(31, 32, ),
+ /* 29 */ array(31, 32, ),
+ /* 30 */ array(20, ),
+ /* 31 */ array(19, ),
+ /* 32 */ array(15, ),
+ /* 33 */ array(3, ),
+ /* 34 */ array(20, ),
+ /* 35 */ array(7, ),
+ /* 36 */ array(3, ),
+ /* 37 */ array(19, ),
+ /* 38 */ array(2, 5, ),
+ /* 39 */ array(8, 9, ),
+ /* 40 */ array(8, 9, ),
+ /* 41 */ array(14, ),
+ /* 42 */ array(14, ),
+ /* 43 */ array(5, ),
+ /* 44 */ array(6, ),
+ /* 45 */ array(7, ),
/* 46 */ array(),
/* 47 */ array(),
/* 48 */ array(),
@@ -415,19 +427,31 @@ static public $yy_action = array(
/* 103 */ array(),
/* 104 */ array(),
/* 105 */ array(),
+ /* 106 */ array(),
+ /* 107 */ array(),
+ /* 108 */ array(),
+ /* 109 */ array(),
+ /* 110 */ array(),
+ /* 111 */ array(),
+ /* 112 */ array(),
+ /* 113 */ array(),
+ /* 114 */ array(),
+ /* 115 */ array(),
+ /* 116 */ array(),
);
static public $yy_default = array(
- /* 0 */ 184, 128, 184, 184, 184, 184, 184, 184, 184, 184,
- /* 10 */ 120, 131, 118, 184, 184, 184, 184, 114, 113, 184,
- /* 20 */ 114, 184, 184, 184, 111, 184, 111, 184, 184, 184,
- /* 30 */ 184, 184, 184, 184, 184, 142, 168, 169, 170, 171,
- /* 40 */ 141, 166, 164, 167, 165, 129, 140, 183, 182, 109,
- /* 50 */ 112, 116, 117, 115, 181, 180, 175, 174, 173, 176,
- /* 60 */ 177, 179, 178, 172, 124, 126, 144, 143, 139, 145,
- /* 70 */ 146, 149, 148, 147, 138, 137, 110, 108, 107, 119,
- /* 80 */ 123, 136, 127, 125, 150, 151, 122, 121, 163, 162,
- /* 90 */ 106, 130, 134, 133, 132, 161, 160, 154, 153, 152,
- /* 100 */ 155, 156, 159, 158, 157, 135,
+ /* 0 */ 203, 146, 203, 203, 203, 203, 203, 203, 203, 203,
+ /* 10 */ 203, 203, 203, 203, 140, 139, 203, 203, 125, 138,
+ /* 20 */ 137, 203, 124, 203, 203, 125, 203, 203, 135, 136,
+ /* 30 */ 129, 142, 203, 122, 149, 203, 122, 141, 203, 203,
+ /* 40 */ 203, 158, 203, 203, 203, 203, 176, 177, 127, 178,
+ /* 50 */ 165, 175, 173, 168, 166, 174, 179, 167, 150, 147,
+ /* 60 */ 153, 120, 126, 123, 152, 151, 160, 169, 148, 128,
+ /* 70 */ 180, 194, 157, 156, 155, 154, 162, 163, 159, 182,
+ /* 80 */ 181, 144, 145, 143, 130, 121, 119, 118, 131, 132,
+ /* 90 */ 134, 170, 133, 161, 183, 198, 197, 196, 195, 199,
+ /* 100 */ 200, 171, 164, 202, 201, 117, 193, 187, 186, 185,
+ /* 110 */ 184, 188, 189, 192, 191, 190, 172,
);
/* The next thing included is series of defines which control
** various aspects of the generated parser.
@@ -444,10 +468,10 @@ static public $yy_action = array(
** self::YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
*/
- const YYNOCODE = 79;
+ const YYNOCODE = 86;
const YYSTACKDEPTH = 100;
- const YYNSTATE = 106;
- const YYNRULE = 78;
+ const YYNSTATE = 117;
+ const YYNRULE = 86;
const YYERRORSYMBOL = 50;
const YYERRSYMDT = 'yy0';
const YYFALLBACK = 0;
@@ -535,9 +559,9 @@ static public $yy_action = array(
'PAR_CLOSE', 'COMA', 'INTERVAL', 'F_DAY',
'F_MONTH', 'F_YEAR', 'DOT', 'NAME',
'NUMVAL', 'STRVAL', 'NOT_EQ', 'LOG_AND',
- 'LOG_OR', 'GT', 'LT', 'GE',
- 'LE', 'MATH_DIV', 'MATH_MULT', 'MATH_PLUS',
- 'MATH_MINUS', 'LIKE', 'NOT_LIKE', 'IN',
+ 'LOG_OR', 'MATH_DIV', 'MATH_MULT', 'MATH_PLUS',
+ 'MATH_MINUS', 'GT', 'LT', 'GE',
+ 'LE', 'LIKE', 'NOT_LIKE', 'IN',
'NOT_IN', 'F_IF', 'F_ELT', 'F_COALESCE',
'F_CONCAT', 'F_SUBSTR', 'F_TRIM', 'F_DATE',
'F_DATE_FORMAT', 'F_CURRENT_DATE', 'F_NOW', 'F_TIME',
@@ -545,11 +569,13 @@ static public $yy_action = array(
'F_ROUND', 'F_FLOOR', 'error', 'result',
'query', 'condition', 'class_name', 'join_statement',
'where_statement', 'join_item', 'join_condition', 'field_id',
- 'expression', 'operator', 'scalar', 'list_operator',
- 'list', 'func_name', 'arg_list', 'scalar_list',
- 'argument', 'interval_unit', 'num_scalar', 'str_scalar',
- 'num_value', 'str_value', 'name', 'log_operator',
- 'num_operator', 'str_operator',
+ 'expression_prio4', 'expression_basic', 'scalar', 'func_name',
+ 'arg_list', 'list_operator', 'list', 'expression_prio1',
+ 'operator1', 'expression_prio2', 'operator2', 'expression_prio3',
+ 'operator3', 'operator4', 'scalar_list', 'argument',
+ 'interval_unit', 'num_scalar', 'str_scalar', 'num_value',
+ 'str_value', 'name', 'num_operator1', 'num_operator2',
+ 'str_operator',
);
/**
@@ -569,72 +595,80 @@ static public $yy_action = array(
/* 9 */ "join_item ::= JOIN class_name AS_ALIAS class_name ON join_condition",
/* 10 */ "join_item ::= JOIN class_name ON join_condition",
/* 11 */ "join_condition ::= field_id EQ field_id",
- /* 12 */ "condition ::= expression",
- /* 13 */ "expression ::= PAR_OPEN expression PAR_CLOSE",
- /* 14 */ "expression ::= expression operator expression",
- /* 15 */ "expression ::= scalar",
- /* 16 */ "expression ::= field_id",
- /* 17 */ "expression ::= expression list_operator list",
- /* 18 */ "expression ::= func_name PAR_OPEN arg_list PAR_CLOSE",
- /* 19 */ "list ::= PAR_OPEN scalar_list PAR_CLOSE",
- /* 20 */ "scalar_list ::= scalar",
- /* 21 */ "scalar_list ::= scalar_list COMA scalar",
- /* 22 */ "arg_list ::=",
- /* 23 */ "arg_list ::= argument",
- /* 24 */ "arg_list ::= arg_list COMA argument",
- /* 25 */ "argument ::= expression",
- /* 26 */ "argument ::= INTERVAL expression interval_unit",
- /* 27 */ "interval_unit ::= F_DAY",
- /* 28 */ "interval_unit ::= F_MONTH",
- /* 29 */ "interval_unit ::= F_YEAR",
- /* 30 */ "scalar ::= num_scalar",
- /* 31 */ "scalar ::= str_scalar",
- /* 32 */ "num_scalar ::= num_value",
- /* 33 */ "str_scalar ::= str_value",
- /* 34 */ "field_id ::= class_name DOT name",
- /* 35 */ "class_name ::= name",
- /* 36 */ "name ::= NAME",
- /* 37 */ "num_value ::= NUMVAL",
- /* 38 */ "str_value ::= STRVAL",
- /* 39 */ "operator ::= log_operator",
- /* 40 */ "operator ::= num_operator",
- /* 41 */ "operator ::= str_operator",
- /* 42 */ "operator ::= EQ",
- /* 43 */ "operator ::= NOT_EQ",
- /* 44 */ "log_operator ::= LOG_AND",
- /* 45 */ "log_operator ::= LOG_OR",
- /* 46 */ "num_operator ::= GT",
- /* 47 */ "num_operator ::= LT",
- /* 48 */ "num_operator ::= GE",
- /* 49 */ "num_operator ::= LE",
- /* 50 */ "num_operator ::= MATH_DIV",
- /* 51 */ "num_operator ::= MATH_MULT",
- /* 52 */ "num_operator ::= MATH_PLUS",
- /* 53 */ "num_operator ::= MATH_MINUS",
- /* 54 */ "str_operator ::= LIKE",
- /* 55 */ "str_operator ::= NOT_LIKE",
- /* 56 */ "list_operator ::= IN",
- /* 57 */ "list_operator ::= NOT_IN",
- /* 58 */ "func_name ::= F_IF",
- /* 59 */ "func_name ::= F_ELT",
- /* 60 */ "func_name ::= F_COALESCE",
- /* 61 */ "func_name ::= F_CONCAT",
- /* 62 */ "func_name ::= F_SUBSTR",
- /* 63 */ "func_name ::= F_TRIM",
- /* 64 */ "func_name ::= F_DATE",
- /* 65 */ "func_name ::= F_DATE_FORMAT",
- /* 66 */ "func_name ::= F_CURRENT_DATE",
- /* 67 */ "func_name ::= F_NOW",
- /* 68 */ "func_name ::= F_TIME",
- /* 69 */ "func_name ::= F_TO_DAYS",
- /* 70 */ "func_name ::= F_FROM_DAYS",
- /* 71 */ "func_name ::= F_YEAR",
- /* 72 */ "func_name ::= F_MONTH",
- /* 73 */ "func_name ::= F_DAY",
- /* 74 */ "func_name ::= F_DATE_ADD",
- /* 75 */ "func_name ::= F_DATE_SUB",
- /* 76 */ "func_name ::= F_ROUND",
- /* 77 */ "func_name ::= F_FLOOR",
+ /* 12 */ "condition ::= expression_prio4",
+ /* 13 */ "expression_basic ::= scalar",
+ /* 14 */ "expression_basic ::= field_id",
+ /* 15 */ "expression_basic ::= func_name PAR_OPEN arg_list PAR_CLOSE",
+ /* 16 */ "expression_basic ::= PAR_OPEN expression_prio4 PAR_CLOSE",
+ /* 17 */ "expression_basic ::= expression_basic list_operator list",
+ /* 18 */ "expression_prio1 ::= expression_basic",
+ /* 19 */ "expression_prio1 ::= expression_prio1 operator1 expression_basic",
+ /* 20 */ "expression_prio2 ::= expression_prio1",
+ /* 21 */ "expression_prio2 ::= expression_prio2 operator2 expression_prio1",
+ /* 22 */ "expression_prio3 ::= expression_prio2",
+ /* 23 */ "expression_prio3 ::= expression_prio3 operator3 expression_prio2",
+ /* 24 */ "expression_prio4 ::= expression_prio3",
+ /* 25 */ "expression_prio4 ::= expression_prio4 operator4 expression_prio3",
+ /* 26 */ "list ::= PAR_OPEN scalar_list PAR_CLOSE",
+ /* 27 */ "scalar_list ::= scalar",
+ /* 28 */ "scalar_list ::= scalar_list COMA scalar",
+ /* 29 */ "arg_list ::=",
+ /* 30 */ "arg_list ::= argument",
+ /* 31 */ "arg_list ::= arg_list COMA argument",
+ /* 32 */ "argument ::= expression_prio4",
+ /* 33 */ "argument ::= INTERVAL expression_prio4 interval_unit",
+ /* 34 */ "interval_unit ::= F_DAY",
+ /* 35 */ "interval_unit ::= F_MONTH",
+ /* 36 */ "interval_unit ::= F_YEAR",
+ /* 37 */ "scalar ::= num_scalar",
+ /* 38 */ "scalar ::= str_scalar",
+ /* 39 */ "num_scalar ::= num_value",
+ /* 40 */ "str_scalar ::= str_value",
+ /* 41 */ "field_id ::= name",
+ /* 42 */ "field_id ::= class_name DOT name",
+ /* 43 */ "class_name ::= name",
+ /* 44 */ "name ::= NAME",
+ /* 45 */ "num_value ::= NUMVAL",
+ /* 46 */ "str_value ::= STRVAL",
+ /* 47 */ "operator1 ::= num_operator1",
+ /* 48 */ "operator2 ::= num_operator2",
+ /* 49 */ "operator2 ::= str_operator",
+ /* 50 */ "operator2 ::= EQ",
+ /* 51 */ "operator2 ::= NOT_EQ",
+ /* 52 */ "operator3 ::= LOG_AND",
+ /* 53 */ "operator4 ::= LOG_OR",
+ /* 54 */ "num_operator1 ::= MATH_DIV",
+ /* 55 */ "num_operator1 ::= MATH_MULT",
+ /* 56 */ "num_operator2 ::= MATH_PLUS",
+ /* 57 */ "num_operator2 ::= MATH_MINUS",
+ /* 58 */ "num_operator2 ::= GT",
+ /* 59 */ "num_operator2 ::= LT",
+ /* 60 */ "num_operator2 ::= GE",
+ /* 61 */ "num_operator2 ::= LE",
+ /* 62 */ "str_operator ::= LIKE",
+ /* 63 */ "str_operator ::= NOT_LIKE",
+ /* 64 */ "list_operator ::= IN",
+ /* 65 */ "list_operator ::= NOT_IN",
+ /* 66 */ "func_name ::= F_IF",
+ /* 67 */ "func_name ::= F_ELT",
+ /* 68 */ "func_name ::= F_COALESCE",
+ /* 69 */ "func_name ::= F_CONCAT",
+ /* 70 */ "func_name ::= F_SUBSTR",
+ /* 71 */ "func_name ::= F_TRIM",
+ /* 72 */ "func_name ::= F_DATE",
+ /* 73 */ "func_name ::= F_DATE_FORMAT",
+ /* 74 */ "func_name ::= F_CURRENT_DATE",
+ /* 75 */ "func_name ::= F_NOW",
+ /* 76 */ "func_name ::= F_TIME",
+ /* 77 */ "func_name ::= F_TO_DAYS",
+ /* 78 */ "func_name ::= F_FROM_DAYS",
+ /* 79 */ "func_name ::= F_YEAR",
+ /* 80 */ "func_name ::= F_MONTH",
+ /* 81 */ "func_name ::= F_DAY",
+ /* 82 */ "func_name ::= F_DATE_ADD",
+ /* 83 */ "func_name ::= F_DATE_SUB",
+ /* 84 */ "func_name ::= F_ROUND",
+ /* 85 */ "func_name ::= F_FLOOR",
);
/**
@@ -1012,71 +1046,79 @@ static public $yy_action = array(
array( 'lhs' => 57, 'rhs' => 4 ),
array( 'lhs' => 58, 'rhs' => 3 ),
array( 'lhs' => 53, 'rhs' => 1 ),
- array( 'lhs' => 60, 'rhs' => 3 ),
- array( 'lhs' => 60, 'rhs' => 3 ),
- array( 'lhs' => 60, 'rhs' => 1 ),
- array( 'lhs' => 60, 'rhs' => 1 ),
- array( 'lhs' => 60, 'rhs' => 3 ),
- array( 'lhs' => 60, 'rhs' => 4 ),
- array( 'lhs' => 64, 'rhs' => 3 ),
+ array( 'lhs' => 61, 'rhs' => 1 ),
+ array( 'lhs' => 61, 'rhs' => 1 ),
+ array( 'lhs' => 61, 'rhs' => 4 ),
+ array( 'lhs' => 61, 'rhs' => 3 ),
+ array( 'lhs' => 61, 'rhs' => 3 ),
array( 'lhs' => 67, 'rhs' => 1 ),
array( 'lhs' => 67, 'rhs' => 3 ),
- array( 'lhs' => 66, 'rhs' => 0 ),
- array( 'lhs' => 66, 'rhs' => 1 ),
- array( 'lhs' => 66, 'rhs' => 3 ),
- array( 'lhs' => 68, 'rhs' => 1 ),
- array( 'lhs' => 68, 'rhs' => 3 ),
array( 'lhs' => 69, 'rhs' => 1 ),
- array( 'lhs' => 69, 'rhs' => 1 ),
- array( 'lhs' => 69, 'rhs' => 1 ),
- array( 'lhs' => 62, 'rhs' => 1 ),
- array( 'lhs' => 62, 'rhs' => 1 ),
- array( 'lhs' => 70, 'rhs' => 1 ),
+ array( 'lhs' => 69, 'rhs' => 3 ),
array( 'lhs' => 71, 'rhs' => 1 ),
+ array( 'lhs' => 71, 'rhs' => 3 ),
+ array( 'lhs' => 60, 'rhs' => 1 ),
+ array( 'lhs' => 60, 'rhs' => 3 ),
+ array( 'lhs' => 66, 'rhs' => 3 ),
+ array( 'lhs' => 74, 'rhs' => 1 ),
+ array( 'lhs' => 74, 'rhs' => 3 ),
+ array( 'lhs' => 64, 'rhs' => 0 ),
+ array( 'lhs' => 64, 'rhs' => 1 ),
+ array( 'lhs' => 64, 'rhs' => 3 ),
+ array( 'lhs' => 75, 'rhs' => 1 ),
+ array( 'lhs' => 75, 'rhs' => 3 ),
+ array( 'lhs' => 76, 'rhs' => 1 ),
+ array( 'lhs' => 76, 'rhs' => 1 ),
+ array( 'lhs' => 76, 'rhs' => 1 ),
+ array( 'lhs' => 62, 'rhs' => 1 ),
+ array( 'lhs' => 62, 'rhs' => 1 ),
+ array( 'lhs' => 77, 'rhs' => 1 ),
+ array( 'lhs' => 78, 'rhs' => 1 ),
+ array( 'lhs' => 59, 'rhs' => 1 ),
array( 'lhs' => 59, 'rhs' => 3 ),
array( 'lhs' => 54, 'rhs' => 1 ),
- array( 'lhs' => 74, 'rhs' => 1 ),
+ array( 'lhs' => 81, 'rhs' => 1 ),
+ array( 'lhs' => 79, 'rhs' => 1 ),
+ array( 'lhs' => 80, 'rhs' => 1 ),
+ array( 'lhs' => 68, 'rhs' => 1 ),
+ array( 'lhs' => 70, 'rhs' => 1 ),
+ array( 'lhs' => 70, 'rhs' => 1 ),
+ array( 'lhs' => 70, 'rhs' => 1 ),
+ array( 'lhs' => 70, 'rhs' => 1 ),
array( 'lhs' => 72, 'rhs' => 1 ),
array( 'lhs' => 73, 'rhs' => 1 ),
- array( 'lhs' => 61, 'rhs' => 1 ),
- array( 'lhs' => 61, 'rhs' => 1 ),
- array( 'lhs' => 61, 'rhs' => 1 ),
- array( 'lhs' => 61, 'rhs' => 1 ),
- array( 'lhs' => 61, 'rhs' => 1 ),
- array( 'lhs' => 75, 'rhs' => 1 ),
- array( 'lhs' => 75, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 76, 'rhs' => 1 ),
- array( 'lhs' => 77, 'rhs' => 1 ),
- array( 'lhs' => 77, 'rhs' => 1 ),
+ array( 'lhs' => 82, 'rhs' => 1 ),
+ array( 'lhs' => 82, 'rhs' => 1 ),
+ array( 'lhs' => 83, 'rhs' => 1 ),
+ array( 'lhs' => 83, 'rhs' => 1 ),
+ array( 'lhs' => 83, 'rhs' => 1 ),
+ array( 'lhs' => 83, 'rhs' => 1 ),
+ array( 'lhs' => 83, 'rhs' => 1 ),
+ array( 'lhs' => 83, 'rhs' => 1 ),
+ array( 'lhs' => 84, 'rhs' => 1 ),
+ array( 'lhs' => 84, 'rhs' => 1 ),
+ array( 'lhs' => 65, 'rhs' => 1 ),
+ array( 'lhs' => 65, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
+ array( 'lhs' => 63, 'rhs' => 1 ),
array( 'lhs' => 63, 'rhs' => 1 ),
array( 'lhs' => 63, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
- array( 'lhs' => 65, 'rhs' => 1 ),
);
/**
@@ -1099,71 +1141,79 @@ static public $yy_action = array(
10 => 10,
11 => 11,
12 => 12,
- 16 => 12,
- 25 => 12,
- 27 => 12,
- 28 => 12,
- 29 => 12,
- 30 => 12,
- 31 => 12,
- 13 => 13,
- 14 => 14,
- 17 => 14,
+ 13 => 12,
+ 14 => 12,
+ 18 => 12,
+ 20 => 12,
+ 22 => 12,
+ 24 => 12,
+ 32 => 12,
+ 34 => 12,
+ 35 => 12,
+ 36 => 12,
+ 37 => 12,
+ 38 => 12,
15 => 15,
- 58 => 15,
- 59 => 15,
- 60 => 15,
- 61 => 15,
- 62 => 15,
- 63 => 15,
- 64 => 15,
- 65 => 15,
- 66 => 15,
- 67 => 15,
- 68 => 15,
- 69 => 15,
- 70 => 15,
- 71 => 15,
- 72 => 15,
- 73 => 15,
- 74 => 15,
- 75 => 15,
- 76 => 15,
- 77 => 15,
- 18 => 18,
- 19 => 19,
- 20 => 20,
- 23 => 20,
- 21 => 21,
- 24 => 21,
- 22 => 22,
+ 16 => 16,
+ 17 => 17,
+ 19 => 17,
+ 21 => 17,
+ 23 => 17,
+ 25 => 17,
26 => 26,
- 32 => 32,
- 33 => 32,
- 34 => 34,
- 35 => 35,
- 37 => 35,
- 39 => 35,
- 40 => 35,
- 41 => 35,
- 42 => 35,
- 43 => 35,
- 44 => 35,
- 45 => 35,
- 46 => 35,
- 47 => 35,
- 48 => 35,
- 49 => 35,
- 50 => 35,
- 51 => 35,
- 52 => 35,
- 53 => 35,
- 54 => 35,
- 55 => 35,
- 56 => 35,
- 57 => 35,
- 36 => 36,
- 38 => 38,
+ 27 => 27,
+ 30 => 27,
+ 28 => 28,
+ 31 => 28,
+ 29 => 29,
+ 33 => 33,
+ 39 => 39,
+ 40 => 39,
+ 41 => 41,
+ 42 => 42,
+ 43 => 43,
+ 66 => 43,
+ 67 => 43,
+ 68 => 43,
+ 69 => 43,
+ 70 => 43,
+ 71 => 43,
+ 72 => 43,
+ 73 => 43,
+ 74 => 43,
+ 75 => 43,
+ 76 => 43,
+ 77 => 43,
+ 78 => 43,
+ 79 => 43,
+ 80 => 43,
+ 81 => 43,
+ 82 => 43,
+ 83 => 43,
+ 84 => 43,
+ 85 => 43,
+ 44 => 44,
+ 45 => 45,
+ 47 => 45,
+ 48 => 45,
+ 49 => 45,
+ 50 => 45,
+ 51 => 45,
+ 52 => 45,
+ 53 => 45,
+ 54 => 45,
+ 55 => 45,
+ 56 => 45,
+ 57 => 45,
+ 58 => 45,
+ 59 => 45,
+ 60 => 45,
+ 61 => 45,
+ 62 => 45,
+ 63 => 45,
+ 64 => 45,
+ 65 => 45,
+ 46 => 46,
);
/* Beginning here are the reduction cases. A typical example
** follows:
@@ -1173,23 +1223,23 @@ static public $yy_action = array(
*/
#line 7 "oql-parser.y"
function yy_r0(){ $this->my_result = $this->yystack[$this->yyidx + 0]->minor; }
-#line 1180 "oql-parser.php"
+#line 1230 "oql-parser.php"
#line 10 "oql-parser.y"
function yy_r2(){
$this->_retvalue = new OqlQuery($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor);
}
-#line 1185 "oql-parser.php"
+#line 1235 "oql-parser.php"
#line 13 "oql-parser.y"
function yy_r3(){
$this->_retvalue = new OqlQuery($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor);
}
-#line 1190 "oql-parser.php"
+#line 1240 "oql-parser.php"
#line 17 "oql-parser.y"
function yy_r4(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; }
-#line 1193 "oql-parser.php"
+#line 1243 "oql-parser.php"
#line 18 "oql-parser.y"
function yy_r5(){ $this->_retvalue = null; }
-#line 1196 "oql-parser.php"
+#line 1246 "oql-parser.php"
#line 20 "oql-parser.y"
function yy_r6(){
// insert the join statement on top of the existing list
@@ -1197,90 +1247,94 @@ static public $yy_action = array(
// and return the updated array
$this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
}
-#line 1204 "oql-parser.php"
+#line 1254 "oql-parser.php"
#line 26 "oql-parser.y"
function yy_r7(){
$this->_retvalue = Array($this->yystack[$this->yyidx + 0]->minor);
}
-#line 1209 "oql-parser.php"
+#line 1259 "oql-parser.php"
#line 32 "oql-parser.y"
function yy_r9(){
// create an array with one single item
$this->_retvalue = new OqlJoinSpec($this->yystack[$this->yyidx + -4]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor);
}
-#line 1215 "oql-parser.php"
+#line 1265 "oql-parser.php"
#line 37 "oql-parser.y"
function yy_r10(){
// create an array with one single item
$this->_retvalue = new OqlJoinSpec($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor);
}
-#line 1221 "oql-parser.php"
+#line 1271 "oql-parser.php"
#line 42 "oql-parser.y"
function yy_r11(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, '=', $this->yystack[$this->yyidx + 0]->minor); }
-#line 1224 "oql-parser.php"
+#line 1274 "oql-parser.php"
#line 44 "oql-parser.y"
function yy_r12(){ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor; }
-#line 1227 "oql-parser.php"
-#line 46 "oql-parser.y"
- function yy_r13(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; }
-#line 1230 "oql-parser.php"
-#line 47 "oql-parser.y"
- function yy_r14(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); }
-#line 1233 "oql-parser.php"
+#line 1277 "oql-parser.php"
#line 48 "oql-parser.y"
- function yy_r15(){ $this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; }
-#line 1236 "oql-parser.php"
-#line 51 "oql-parser.y"
- function yy_r18(){ $this->_retvalue = new FunctionOqlExpression($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor); }
-#line 1239 "oql-parser.php"
-#line 54 "oql-parser.y"
- function yy_r19(){
+ function yy_r15(){ $this->_retvalue = new FunctionOqlExpression($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor); }
+#line 1280 "oql-parser.php"
+#line 49 "oql-parser.y"
+ function yy_r16(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor; }
+#line 1283 "oql-parser.php"
+#line 50 "oql-parser.y"
+ function yy_r17(){ $this->_retvalue = new BinaryOqlExpression($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); }
+#line 1286 "oql-parser.php"
+#line 65 "oql-parser.y"
+ function yy_r26(){
$this->_retvalue = new ListOqlExpression($this->yystack[$this->yyidx + -1]->minor);
}
-#line 1244 "oql-parser.php"
-#line 57 "oql-parser.y"
- function yy_r20(){
+#line 1291 "oql-parser.php"
+#line 68 "oql-parser.y"
+ function yy_r27(){
$this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor);
}
-#line 1249 "oql-parser.php"
-#line 60 "oql-parser.y"
- function yy_r21(){
+#line 1296 "oql-parser.php"
+#line 71 "oql-parser.y"
+ function yy_r28(){
array_push($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor);
$this->_retvalue = $this->yystack[$this->yyidx + -2]->minor;
}
-#line 1255 "oql-parser.php"
-#line 65 "oql-parser.y"
- function yy_r22(){
+#line 1302 "oql-parser.php"
+#line 76 "oql-parser.y"
+ function yy_r29(){
$this->_retvalue = array();
}
-#line 1260 "oql-parser.php"
-#line 76 "oql-parser.y"
- function yy_r26(){ $this->_retvalue = new IntervalOqlExpression($this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); }
-#line 1263 "oql-parser.php"
-#line 85 "oql-parser.y"
- function yy_r32(){ $this->_retvalue = new ScalarOqlExpression($this->yystack[$this->yyidx + 0]->minor); }
-#line 1266 "oql-parser.php"
-#line 88 "oql-parser.y"
- function yy_r34(){ $this->_retvalue = new FieldOqlExpression($this->m_iCol, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -2]->minor); }
-#line 1269 "oql-parser.php"
-#line 89 "oql-parser.y"
- function yy_r35(){$this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; }
-#line 1272 "oql-parser.php"
-#line 91 "oql-parser.y"
- function yy_r36(){
+#line 1307 "oql-parser.php"
+#line 87 "oql-parser.y"
+ function yy_r33(){ $this->_retvalue = new IntervalOqlExpression($this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor); }
+#line 1310 "oql-parser.php"
+#line 96 "oql-parser.y"
+ function yy_r39(){ $this->_retvalue = new ScalarOqlExpression($this->yystack[$this->yyidx + 0]->minor); }
+#line 1313 "oql-parser.php"
+#line 99 "oql-parser.y"
+ function yy_r41(){ $this->_retvalue = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor); }
+#line 1316 "oql-parser.php"
+#line 100 "oql-parser.y"
+ function yy_r42(){ $this->_retvalue = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -2]->minor); }
+#line 1319 "oql-parser.php"
+#line 101 "oql-parser.y"
+ function yy_r43(){ $this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; }
+#line 1322 "oql-parser.php"
+#line 103 "oql-parser.y"
+ function yy_r44(){
if ($this->yystack[$this->yyidx + 0]->minor[0] == '`')
{
- $this->_retvalue = substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2);
+ $name = substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2);
}
else
{
- $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
+ $name = $this->yystack[$this->yyidx + 0]->minor;
}
+ $this->_retvalue = new OqlName($name, $this->m_iColPrev);
}
-#line 1284 "oql-parser.php"
-#line 103 "oql-parser.y"
- function yy_r38(){$this->_retvalue=stripslashes(substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2)); }
-#line 1287 "oql-parser.php"
+#line 1335 "oql-parser.php"
+#line 115 "oql-parser.y"
+ function yy_r45(){$this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; }
+#line 1338 "oql-parser.php"
+#line 116 "oql-parser.y"
+ function yy_r46(){$this->_retvalue=stripslashes(substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2)); }
+#line 1341 "oql-parser.php"
/**
* placeholder for the left hand side in a reduce operation.
@@ -1395,7 +1449,7 @@ static public $yy_action = array(
#line 3 "oql-parser.y"
throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN);
-#line 1403 "oql-parser.php"
+#line 1457 "oql-parser.php"
}
/**
@@ -1547,7 +1601,7 @@ throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCo
}
} while ($yymajor != self::YYNOCODE && $this->yyidx >= 0);
}
-}#line 151 "oql-parser.y"
+}#line 164 "oql-parser.y"
@@ -1575,18 +1629,21 @@ class OQLParser extends OQLParserRaw
// Data used when an exception is raised
protected $m_iLine; // still not used
protected $m_iCol;
+ protected $m_iColPrev; // this is the interesting one, because the parser will reduce on the next token
protected $m_sSourceQuery;
public function __construct($sQuery)
{
$this->m_iLine = 0;
$this->m_iCol = 0;
+ $this->m_iColPrev = 0;
$this->m_sSourceQuery = $sQuery;
// no constructor - parent::__construct();
}
public function doParse($token, $value, $iCurrPosition = 0)
{
+ $this->m_iColPrev = $this->m_iCol;
$this->m_iCol = $iCurrPosition;
return parent::DoParse($token, $value);
@@ -1610,4 +1667,4 @@ class OQLParser extends OQLParserRaw
}
}
-#line 1620 "oql-parser.php"
+#line 1677 "oql-parser.php"
diff --git a/core/oql/oql-parser.y b/core/oql/oql-parser.y
index 02df9f519..b86423b77 100644
--- a/core/oql/oql-parser.y
+++ b/core/oql/oql-parser.y
@@ -41,14 +41,25 @@ join_item(A) ::= JOIN class_name(X) ON join_condition(C).
join_condition(A) ::= field_id(X) EQ field_id(Y). { A = new BinaryOqlExpression(X, '=', Y); }
-condition(A) ::= expression(X). { A = X; }
+condition(A) ::= expression_prio4(X). { A = X; }
-expression(A) ::= PAR_OPEN expression(X) PAR_CLOSE. { A = X; }
-expression(A) ::= expression(X) operator(Y) expression(Z). { A = new BinaryOqlExpression(X, Y, Z); }
-expression(A) ::= scalar(X). { A=X; }
-expression(A) ::= field_id(X). { A = X; }
-expression(A) ::= expression(X) list_operator(Y) list(Z). { A = new BinaryOqlExpression(X, Y, Z); }
-expression(A) ::= func_name(X) PAR_OPEN arg_list(Y) PAR_CLOSE. { A = new FunctionOqlExpression(X, Y); }
+expression_basic(A) ::= scalar(X). { A = X; }
+expression_basic(A) ::= field_id(X). { A = X; }
+expression_basic(A) ::= func_name(X) PAR_OPEN arg_list(Y) PAR_CLOSE. { A = new FunctionOqlExpression(X, Y); }
+expression_basic(A) ::= PAR_OPEN expression_prio4(X) PAR_CLOSE. { A = X; }
+expression_basic(A) ::= expression_basic(X) list_operator(Y) list(Z). { A = new BinaryOqlExpression(X, Y, Z); }
+
+expression_prio1(A) ::= expression_basic(X). { A = X; }
+expression_prio1(A) ::= expression_prio1(X) operator1(Y) expression_basic(Z). { A = new BinaryOqlExpression(X, Y, Z); }
+
+expression_prio2(A) ::= expression_prio1(X). { A = X; }
+expression_prio2(A) ::= expression_prio2(X) operator2(Y) expression_prio1(Z). { A = new BinaryOqlExpression(X, Y, Z); }
+
+expression_prio3(A) ::= expression_prio2(X). { A = X; }
+expression_prio3(A) ::= expression_prio3(X) operator3(Y) expression_prio2(Z). { A = new BinaryOqlExpression(X, Y, Z); }
+
+expression_prio4(A) ::= expression_prio3(X). { A = X; }
+expression_prio4(A) ::= expression_prio4(X) operator4(Y) expression_prio3(Z). { A = new BinaryOqlExpression(X, Y, Z); }
list(A) ::= PAR_OPEN scalar_list(X) PAR_CLOSE. {
@@ -72,8 +83,8 @@ arg_list(A) ::= arg_list(L) COMA argument(X). {
array_push(L, X);
A = L;
}
-argument(A) ::= expression(X). { A = X; }
-argument(A) ::= INTERVAL expression(X) interval_unit(Y). { A = new IntervalOqlExpression(X, Y); }
+argument(A) ::= expression_prio4(X). { A = X; }
+argument(A) ::= INTERVAL expression_prio4(X) interval_unit(Y). { A = new IntervalOqlExpression(X, Y); }
interval_unit(A) ::= F_DAY(X). { A = X; }
interval_unit(A) ::= F_MONTH(X). { A = X; }
@@ -85,40 +96,42 @@ scalar(A) ::= str_scalar(X). { A = X; }
num_scalar(A) ::= num_value(X). { A = new ScalarOqlExpression(X); }
str_scalar(A) ::= str_value(X). { A = new ScalarOqlExpression(X); }
-field_id(A) ::= class_name(X) DOT name(Y). { A = new FieldOqlExpression($this->m_iCol, Y, X); }
-class_name(A) ::= name(X). {A=X;}
+field_id(A) ::= name(X). { A = new FieldOqlExpression(X); }
+field_id(A) ::= class_name(X) DOT name(Y). { A = new FieldOqlExpression(Y, X); }
+class_name(A) ::= name(X). { A=X; }
name(A) ::= NAME(X). {
if (X[0] == '`')
{
- A = substr(X, 1, strlen(X) - 2);
+ $name = substr(X, 1, strlen(X) - 2);
}
else
{
- A = X;
+ $name = X;
}
+ A = new OqlName($name, $this->m_iColPrev);
}
num_value(A) ::= NUMVAL(X). {A=X;}
str_value(A) ::= STRVAL(X). {A=stripslashes(substr(X, 1, strlen(X) - 2));}
-operator(A) ::= log_operator(X). {A=X;}
-operator(A) ::= num_operator(X). {A=X;}
-operator(A) ::= str_operator(X). {A=X;}
-operator(A) ::= EQ(X). {A=X;}
-operator(A) ::= NOT_EQ(X). {A=X;}
-log_operator(A) ::= LOG_AND(X). {A=X;}
-log_operator(A) ::= LOG_OR(X). {A=X;}
+operator1(A) ::= num_operator1(X). {A=X;}
+operator2(A) ::= num_operator2(X). {A=X;}
+operator2(A) ::= str_operator(X). {A=X;}
+operator2(A) ::= EQ(X). {A=X;}
+operator2(A) ::= NOT_EQ(X). {A=X;}
+operator3(A) ::= LOG_AND(X). {A=X;}
+operator4(A) ::= LOG_OR(X). {A=X;}
-num_operator(A) ::= GT(X). {A=X;}
-num_operator(A) ::= LT(X). {A=X;}
-num_operator(A) ::= GE(X). {A=X;}
-num_operator(A) ::= LE(X). {A=X;}
-num_operator(A) ::= MATH_DIV(X). {A=X;}
-num_operator(A) ::= MATH_MULT(X). {A=X;}
-num_operator(A) ::= MATH_PLUS(X). {A=X;}
-num_operator(A) ::= MATH_MINUS(X). {A=X;}
+num_operator1(A) ::= MATH_DIV(X). {A=X;}
+num_operator1(A) ::= MATH_MULT(X). {A=X;}
+num_operator2(A) ::= MATH_PLUS(X). {A=X;}
+num_operator2(A) ::= MATH_MINUS(X). {A=X;}
+num_operator2(A) ::= GT(X). {A=X;}
+num_operator2(A) ::= LT(X). {A=X;}
+num_operator2(A) ::= GE(X). {A=X;}
+num_operator2(A) ::= LE(X). {A=X;}
str_operator(A) ::= LIKE(X). {A=X;}
str_operator(A) ::= NOT_LIKE(X). {A=X;}
@@ -175,18 +188,21 @@ class OQLParser extends OQLParserRaw
// Data used when an exception is raised
protected $m_iLine; // still not used
protected $m_iCol;
+ protected $m_iColPrev; // this is the interesting one, because the parser will reduce on the next token
protected $m_sSourceQuery;
public function __construct($sQuery)
{
$this->m_iLine = 0;
$this->m_iCol = 0;
+ $this->m_iColPrev = 0;
$this->m_sSourceQuery = $sQuery;
// no constructor - parent::__construct();
}
public function doParse($token, $value, $iCurrPosition = 0)
{
+ $this->m_iColPrev = $this->m_iCol;
$this->m_iCol = $iCurrPosition;
return parent::DoParse($token, $value);
diff --git a/core/oql/oqlexception.class.inc.php b/core/oql/oqlexception.class.inc.php
index 3395df05f..512a3077f 100644
--- a/core/oql/oqlexception.class.inc.php
+++ b/core/oql/oqlexception.class.inc.php
@@ -11,26 +11,66 @@ class OQLException extends CoreException
$this->m_sUnexpected = $sUnexpected;
$this->m_aExpecting = $aExpecting;
- if (is_null($this->m_aExpecting))
+ if (is_null($this->m_aExpecting) || (count($this->m_aExpecting) == 0))
{
- $sMessage = "$sIssue - found '$sUnexpected' at $iCol in '$sInput'";
+ $sMessage = "$sIssue - found '{$this->m_sUnexpected}' at $iCol in '$sInput'";
}
else
{
- $sExpectations = '{'.implode(', ', $aExpecting).'}';
- $sMessage = "$sIssue - found '$sUnexpected' at $iCol in '$sInput', expecting $sExpectations";
+ $sExpectations = '{'.implode(', ', $this->m_aExpecting).'}';
+ $sSuggest = self::FindClosestString($this->m_sUnexpected, $this->m_aExpecting);
+ $sMessage = "$sIssue - found '{$this->m_sUnexpected}' at $iCol in '$sInput', expecting $sExpectations, I would suggest to use '$sSuggest'";
}
// make sure everything is assigned properly
parent::__construct($sMessage, 0);
}
-
+
public function getHtmlDesc($sHighlightHtmlBegin = '', $sHighlightHtmlEnd = '')
{
$sRet = htmlentities($this->m_MyIssue.", found '".$this->m_sUnexpected."' in: ");
$sRet .= htmlentities(substr($this->m_sInput, 0, $this->m_iCol));
$sRet .= $sHighlightHtmlBegin.htmlentities(substr($this->m_sInput, $this->m_iCol, strlen($this->m_sUnexpected))).$sHighlightHtmlEnd;
$sRet .= htmlentities(substr($this->m_sInput, $this->m_iCol + strlen($this->m_sUnexpected)));
+
+ if (!is_null($this->m_aExpecting) && (count($this->m_aExpecting) > 0))
+ {
+ $sExpectations = '{'.implode(', ', $this->m_aExpecting).'}';
+ $sRet .= ", expecting ".htmlentities($sExpectations);
+ $sSuggest = self::FindClosestString($this->m_sUnexpected, $this->m_aExpecting);
+ if (strlen($sSuggest) > 0)
+ {
+ $sRet .= ", I would suggest to use '$sHighlightHtmlBegin".htmlentities($sSuggest)."$sHighlightHtmlEnd'";
+ }
+ }
+
+ return $sRet;
+ }
+
+ static protected function FindClosestString($sInput, $aDictionary)
+ {
+ // no shortest distance found, yet
+ $fShortest = -1;
+ $sRet = '';
+
+ // loop through words to find the closest
+ foreach ($aDictionary as $sSuggestion)
+ {
+ // calculate the distance between the input string and the suggested one
+ $fDist = levenshtein($sInput, $sSuggestion);
+ if ($fDist == 0)
+ {
+ // Exact match
+ return $sSuggestion;
+ }
+
+ if ($fShortest < 0 || ($fDist < 4 && $fDist <= $fShortest))
+ {
+ // set the closest match, and shortest distance
+ $sRet = $sSuggestion;
+ $fShortest = $fDist;
+ }
+ }
return $sRet;
}
}
diff --git a/core/oql/oqlinterpreter.class.inc.php b/core/oql/oqlinterpreter.class.inc.php
index b9a2ba5cc..a464413da 100644
--- a/core/oql/oqlinterpreter.class.inc.php
+++ b/core/oql/oqlinterpreter.class.inc.php
@@ -2,6 +2,10 @@
class OqlNormalizeException extends OQLException
{
+ public function __construct($sIssue, $sInput, OqlName $oName, $aExpecting = null)
+ {
+ parent::__construct($sIssue, $sInput, 0, $oName->GetPos(), $oName->GetValue(), $aExpecting);
+ }
}
class OqlInterpreterException extends OQLException
diff --git a/core/oql/oqlquery.class.inc.php b/core/oql/oqlquery.class.inc.php
index 5173704d7..ad71950b3 100644
--- a/core/oql/oqlquery.class.inc.php
+++ b/core/oql/oqlquery.class.inc.php
@@ -1,30 +1,70 @@
+// Position a string within an OQL query
+// This is a must if we want to be able to pinpoint an error at any stage of the query interpretation
+// In particular, the normalization phase requires this
+class OqlName
+{
+ protected $m_sValue;
+ protected $m_iPos;
+
+ public function __construct($sValue, $iPos)
+ {
+ $this->m_iPos = $iPos;
+ $this->m_sValue = $sValue;
+ }
+
+ public function GetValue()
+ {
+ return $this->m_sValue;
+ }
+
+ public function GetPos()
+ {
+ return $this->m_iPos;
+ }
+
+ public function __toString()
+ {
+ return $this->m_sValue;
+ }
+}
+
class OqlJoinSpec
{
- protected $m_sClass;
- protected $m_sClassAlias;
+ protected $m_oClass;
+ protected $m_oClassAlias;
protected $m_oLeftField;
protected $m_oRightField;
protected $m_oNextJoinspec;
- public function __construct($sClass, $sClassAlias, BinaryExpression $oExpression)
+ public function __construct($oClass, $oClassAlias, BinaryExpression $oExpression)
{
- $this->m_sClass = $sClass;
- $this->m_sClassAlias = $sClassAlias;
+ $this->m_oClass = $oClass;
+ $this->m_oClassAlias = $oClassAlias;
$this->m_oLeftField = $oExpression->GetLeftExpr();
$this->m_oRightField = $oExpression->GetRightExpr();
}
public function GetClass()
{
- return $this->m_sClass;
+ return $this->m_oClass->GetValue();
}
public function GetClassAlias()
{
- return $this->m_sClassAlias;
+ return $this->m_oClassAlias->GetValue();
}
+
+ public function GetClassDetails()
+ {
+ return $this->m_oClass;
+ }
+ public function GetClassAliasDetails()
+ {
+ return $this->m_oClassAlias;
+ }
+
public function GetLeftField()
{
return $this->m_oLeftField;
@@ -45,18 +85,30 @@ class ScalarOqlExpression extends ScalarExpression
class FieldOqlExpression extends FieldExpression
{
- protected $m_iPosition; // position in the source string
-
- public function __construct($iPosition, $sName, $sParent = '')
+ protected $m_oParent;
+ protected $m_oName;
+
+ public function __construct($oName, $oParent = null)
{
- $this->m_iPosition = $iPosition;
- parent::__construct($sName, $sParent);
+ if (is_null($oParent))
+ {
+ $oParent = new OqlName('', 0);
+ }
+ $this->m_oParent = $oParent;
+ $this->m_oName = $oName;
+
+ parent::__construct($oName->GetValue(), $oParent->GetValue());
}
- public function GetPosition()
+ public function GetParentDetails()
{
- return $this->m_iPosition;
- }
+ return $this->m_oParent;
+ }
+
+ public function GetNameDetails()
+ {
+ return $this->m_oName;
+ }
}
class ListOqlExpression extends ListExpression
@@ -72,27 +124,37 @@ class IntervalOqlExpression extends IntervalExpression
}
class OqlQuery
{
- protected $m_sClass;
- protected $m_sClassAlias;
+ protected $m_oClass;
+ protected $m_oClassAlias;
protected $m_aJoins; // array of OqlJoinSpec
protected $m_oCondition; // condition tree (expressions)
- public function __construct($sClass, $sClassAlias = '', $oCondition = null, $aJoins = null)
+ public function __construct($oClass, $oClassAlias = '', $oCondition = null, $aJoins = null)
{
- $this->m_sClass = $sClass;
- $this->m_sClassAlias = $sClassAlias;
+ $this->m_oClass = $oClass;
+ $this->m_oClassAlias = $oClassAlias;
$this->m_aJoins = $aJoins;
$this->m_oCondition = $oCondition;
}
public function GetClass()
{
- return $this->m_sClass;
+ return $this->m_oClass->GetValue();
}
public function GetClassAlias()
{
- return $this->m_sClassAlias;
+ return $this->m_oClassAlias->GetValue();
}
+
+ public function GetClassDetails()
+ {
+ return $this->m_oClass;
+ }
+ public function GetClassAliasDetails()
+ {
+ return $this->m_oClassAlias;
+ }
+
public function GetJoins()
{
return $this->m_aJoins;
diff --git a/core/sqlquery.class.inc.php b/core/sqlquery.class.inc.php
index 4e747de53..06a8bd35f 100644
--- a/core/sqlquery.class.inc.php
+++ b/core/sqlquery.class.inc.php
@@ -104,8 +104,9 @@ class SQLQuery
$oSQLQuery = $aJoinInfo["select"];
$sLeftField = $aJoinInfo["leftfield"];
$sRightField = $aJoinInfo["rightfield"];
+ $sRightTableAlias = $aJoinInfo["righttablealias"];
- echo "Join '$sJoinType', $sLeftField, $sRightField".$oSQLQuery->DisplayHtml()."\n";
+ echo "Join '$sJoinType', $sLeftField, $sRightTableAlias.$sRightField".$oSQLQuery->DisplayHtml()."\n";
}
echo "";
}
@@ -131,28 +132,35 @@ class SQLQuery
$this->m_oConditionExpr->LogAnd($oConditionExpr);
}
- private function AddJoin($sJoinType, $oSQLQuery, $sLeftField, $sRightField)
+ private function AddJoin($sJoinType, $oSQLQuery, $sLeftField, $sRightField, $sRightTableAlias = '')
{
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);
}
- if (!CMDBSource::IsField($oSQLQuery->m_sTable, $sRightField))
+ if (empty($sRightTableAlias))
{
- trigger_error("Unknown field '$sRightField' in table '".$oSQLQuery->m_sTable."'", E_USER_ERROR);
+ $sRightTableAlias = $oSQLQuery->m_sTableAlias;
}
+// #@# Could not be verified here because the namespace is unknown - do we need to check it there?
+//
+// if (!CMDBSource::IsField($sRightTable, $sRightField))
+// {
+// trigger_error("Unknown field '$sRightField' in table '".$sRightTable."'", E_USER_ERROR);
+// }
$this->m_aJoinSelects[] = array(
"jointype" => $sJoinType,
"select" => $oSQLQuery,
"leftfield" => $sLeftField,
- "rightfield" => $sRightField
+ "rightfield" => $sRightField,
+ "righttablealias" => $sRightTableAlias
);
}
- public function AddInnerJoin($oSQLQuery, $sLeftField, $sRightField)
+ public function AddInnerJoin($oSQLQuery, $sLeftField, $sRightField, $sRigthtTable = '')
{
- $this->AddJoin("inner", $oSQLQuery, $sLeftField, $sRightField);
+ $this->AddJoin("inner", $oSQLQuery, $sLeftField, $sRightField, $sRigthtTable);
}
public function AddLeftJoin($oSQLQuery, $sLeftField, $sRightField)
{
@@ -259,9 +267,9 @@ class SQLQuery
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
break;
case "inner":
- $sFrom .= " INNER JOIN `".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
- $sFrom .= " ON ".$aJoinInfo["joincondition"];
+ $sFrom .= " INNER JOIN (`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
$sFrom .= " ".self::ClauseFrom($aJoinInfo["subfrom"]);
+ $sFrom .= ") ON ".$aJoinInfo["joincondition"];
break;
case "left":
$sFrom .= " LEFT JOIN (`".$aJoinInfo["tablename"]."` AS `$sTableAlias`";
@@ -339,7 +347,7 @@ class SQLQuery
return $sTableAlias;
}
- private function privRenderSingleTable(&$aFrom, &$aFields, &$aDelTables, &$aSetValues, $sJoinType = "first", $sCallerAlias = "", $sLeftField = "", $sRightField = "")
+ private function privRenderSingleTable(&$aFrom, &$aFields, &$aDelTables, &$aSetValues, $sJoinType = 'first', $sCallerAlias = '', $sLeftField = '', $sRightField = '', $sRightTableAlias = '')
{
$aActualTableFields = CMDBSource::GetTableFieldsList($this->m_sTable);
@@ -347,7 +355,11 @@ class SQLQuery
// Handle the various kinds of join (or first table in the list)
//
- $sJoinCond = "`$sCallerAlias`.`$sLeftField` = `{$this->m_sTableAlias}`.`$sRightField`";
+ if (empty($sRightTableAlias))
+ {
+ $sRightTableAlias = $this->m_sTableAlias;
+ }
+ $sJoinCond = "`$sCallerAlias`.`$sLeftField` = `$sRightTableAlias`.`$sRightField`";
switch ($sJoinType)
{
case "first":
@@ -355,6 +367,7 @@ class SQLQuery
break;
case "inner":
case "left":
+ // table or tablealias ???
$aFrom[$this->m_sTableAlias] = array("jointype"=>$sJoinType, "tablename"=>$this->m_sTable, "joincondition"=>"$sJoinCond");
break;
}
@@ -386,8 +399,9 @@ class SQLQuery
$oRightSelect = $aJoinData["select"];
$sLeftField = $aJoinData["leftfield"];
$sRightField = $aJoinData["rightfield"];
+ $sRightTableAlias = $aJoinData["righttablealias"];
- $sJoinTableAlias = $oRightSelect->privRenderSingleTable($aTempFrom, $aFields, $aDelTables, $aSetValues, $sJoinType, $this->m_sTableAlias, $sLeftField, $sRightField);
+ $sJoinTableAlias = $oRightSelect->privRenderSingleTable($aTempFrom, $aFields, $aDelTables, $aSetValues, $sJoinType, $this->m_sTableAlias, $sLeftField, $sRightField, $sRightTableAlias);
}
$aFrom[$this->m_sTableAlias]['subfrom'] = $aTempFrom;
diff --git a/core/test.class.inc.php b/core/test.class.inc.php
index e5cffe37f..bcf94eb91 100644
--- a/core/test.class.inc.php
+++ b/core/test.class.inc.php
@@ -337,15 +337,18 @@ abstract class TestBizModel extends TestHandler
static protected function show_list($oObjectSet)
{
$oObjectSet->Rewind();
+ $aData = array();
while ($oItem = $oObjectSet->Fetch())
{
$aValues = array();
foreach(MetaModel::GetAttributesList(get_class($oItem)) as $sAttCode)
{
- $aValues[] = $oItem->GetAsHTML($sAttCode);
+ $aValues[$sAttCode] = $oItem->GetAsHTML($sAttCode);
}
- echo $oItem->GetKey()." => ".implode(", ", $aValues)."\n";
+ //echo $oItem->GetKey()." => ".implode(", ", $aValues)."\n";
+ $aData[] = $aValues;
}
+ echo MyHelpers::make_table_from_assoc_array($aData);
}
static protected function search_and_show_list(DBObjectSearch $oMyFilter)
diff --git a/pages/ITopConsultant.php b/pages/ITopConsultant.php
index 7dd161166..f17ed1933 100644
--- a/pages/ITopConsultant.php
+++ b/pages/ITopConsultant.php
@@ -42,7 +42,7 @@ function ShowClass($sClass, $sBaseArgs)
$aProps["Subclasses (children + pure PHP)"] = sexyclasslist(MetaModel::GetSubclasses($sClass), $sBaseArgs);
$aProps["Description"] = MetaModel::GetClassDescription($sClass);
- $aProps["Autoincrement pkey?"] = MetaModel::IsAutoIncrementKey($sClass);
+ $aProps["Autoincrement id?"] = MetaModel::IsAutoIncrementKey($sClass);
$aProps["Key label"] = MetaModel::GetKeyLabel($sClass);
$aProps["Name attribute"] = MetaModel::GetNameAttributeCode($sClass);
$aProps["Reconciliation keys"] = implode(", ", MetaModel::GetReconcKeys($sClass));
@@ -188,7 +188,8 @@ function DebugQuery($sConfigFile)
echo "Follow up the query build
\n";
MetaModel::StartDebugQuery();
- $oFlt = DBObjectSearch::FromSibuSQL($sQuery);
+ $oFlt = DBObjectSearch::FromOQL($sQuery);
+ echo "To OQL: ".$oFlt->ToOQL()."
";
$sSQL = MetaModel::MakeSelectQuery($oFlt);
MetaModel::StopDebugQuery();
diff --git a/pages/testlist.inc.php b/pages/testlist.inc.php
index 571c5a566..af834e991 100644
--- a/pages/testlist.inc.php
+++ b/pages/testlist.inc.php
@@ -706,6 +706,7 @@ class TestQueriesOnFarm extends TestBizModel
throw new UnitTestException("The query '$sQuery' was parsed with success, while it shouldn't (?)");
return false;
}
+ echo "To OQL: ".$oMyFilter->ToOQL()."
";
$this->search_and_show_list($oMyFilter);
@@ -721,25 +722,21 @@ class TestQueriesOnFarm extends TestBizModel
$oFilter2 = DBObjectSearch::unserialize($sSerialize);
try
{
- $sQuery2 = MetaModel::MakeSelectQuery($oFilter2);
+ $sQuery2 = MetaModel::MakeSelectQuery($oFilter2);
}
catch (Exception $e)
{
echo "Could not compute the query after unserialize
\n";
echo "Query 1: $sQuery1
\n";
- MyHelpers::var_dump_html($oMyFilter, true);
- echo "Query 2: FAILED
\n";
- MyHelpers::var_dump_html($oFilter2, true);
+ MyHelpers::var_cmp_html($oMyFilter, $oFilter2);
throw $e;
}
//if ($oFilter2 != $oMyFilter) no, they may differ while the resulting query is the same!
if ($sQuery1 != $sQuery2)
{
echo "serialize/unserialize mismatch :-(
\n";
- echo "Query 1: $sQuery1
\n";
- MyHelpers::var_dump_html($oMyFilter, true);
- echo "Query 2: $sQuery2
\n";
- MyHelpers::var_dump_html($oFilter2, true);
+ MyHelpers::var_cmp_html($sQuery1, $sQuery2);
+ MyHelpers::var_cmp_html($oMyFilter, $oFilter2);
return false;
}
return true;
@@ -782,10 +779,14 @@ class TestQueriesOnFarm extends TestBizModel
$aQueries = array(
'SELECT Animal' => true,
+ 'SELECT Animal WHERE Animal.pkey = 1' => false,
+ 'SELECT Animal WHERE Animal.id = 1' => true,
'SELECT Aniiimal' => false,
'SELECTe Animal' => false,
'SELECT * FROM Animal' => false,
'SELECT Animal AS zoo WHERE zoo.species = \'human\'' => true,
+ 'SELECT Animal AS zoo WHERE species = \'human\'' => true,
+ 'SELECT Animal AS zoo WHERE espece = \'human\'' => false,
'SELECT Animal AS zoo WHERE zoo.species IN (\'human\', "pig")' => true,
'SELECT Animal AS zoo WHERE CONCATENATION(zoo.species, zoo.sex) LIKE "hum%male"' => false,
'SELECT Animal AS zoo WHERE CONCAT(zoo.species, zoo.sex) LIKE "hum%male"' => true,
@@ -793,6 +794,7 @@ class TestQueriesOnFarm extends TestBizModel
'SELECT Animal AS zoo WHERE zoo.kind = \'human\'' => false,
'SELECT Animal WHERE Animal.species = \'human\' AND Animal.sex = \'female\'' => true,
'SELECT Mammal AS x WHERE (x.species = \'human\' AND x.name LIKE \'ro%\') OR (x.species = \'donkey\' AND x.name LIKE \'po%\')' => true,
+ 'SELECT Mammal AS x WHERE x.species = \'human\' AND x.name LIKE \'ro%\' OR x.species = \'donkey\' AND x.name LIKE \'po%\'' => true,
'SELECT Mammal AS m WHERE MONTH(m.birth) = 7' => true,
'SELECT Mammal AS m WHERE DAY(m.birth) = 19' => true,
'SELECT Mammal AS m WHERE YEAR(m.birth) = 1971' => true,
@@ -802,6 +804,7 @@ class TestQueriesOnFarm extends TestBizModel
'SELECT Mammal AS m WHERE m.name = IF(FLOOR(ROUND(m.height)) > 2, "pomme", "romain")' => true,
'SELECT Mammal AS m WHERE (1 + 2' => false,
'SELECT Mammal AS m WHERE (1 + 2 * 4 / 23) > 0' => true,
+ 'SELECT Mammal AS m WHERE (4 / 23 * 2 + 1) > 0' => true,
'SELECT Mammal AS m WHERE 1/0' => true,
'SELECT Mammal AS m WHERE MONTH(m.birth) = 7' => true,
'SELECT Animal JOIN Group ON Group.leader = Animal.id' => true,
@@ -813,20 +816,30 @@ class TestQueriesOnFarm extends TestBizModel
'SELECT Animal AS A JOIN Group AS G ON A.id = G.leader' => false,
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.sex=\'male\' OR G.qwerty = 123' => false,
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.sex=\'male\' OR G.name LIKE "a%"' => true,
+ 'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.id = 1' => true,
+ 'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE id = 1' => false,
'SELECT Animal AS A JOIN Group AS G ON A.member = G.id' => false,
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id' => true,
'SELECT Mammal AS M JOIN Group AS G ON A.member = G.id' => false,
+ 'SELECT Mammal AS myAlias JOIN Group AS myAlias ON myAlias.member = myAlias.id' => false,
+ 'SELECT Mammal AS Mammal JOIN Group AS Mammal ON Mammal.member = Mammal.id' => false,
'SELECT Group AS G WHERE G.leader_name LIKE "%"' => true,
'SELECT Group AS G WHERE G.leader_speed < 100000' => true,
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_name LIKE "%"' => true,
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_speed < 100000' => true,
+ 'SELECT Mammal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
+ 'SELECT Mammal AS Child JOIN Animal AS Dad ON Child.father = Dad.id' => true,
+ 'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id' => true,
'SELECT Animal AS Dad JOIN Animal AS Child ON Child.father = Dad.id' => true,
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id' => true,
- 'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.pkey = 1' => true,
+ 'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.id = 1' => true,
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\'' => false,
'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
- 'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\'' => true,
+ 'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\' OR Mum.speed = 0' => true,
+ 'SELECT Animal AS Dad JOIN Animal AS Child ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id' => true,
+ 'SELECT Mammal AS Dad JOIN Mammal AS Child ON Child.father = Dad.id' => true,
+ 'SELECT Mammal AS Dad JOIN Mammal AS Child ON Child.father = Dad.id JOIN Mammal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\' OR Mum.name=\'chloe\' OR Child.name=\'bizounours\'' => true,
);
//$aQueries = array(
// 'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_name LIKE "%"' => true,