From 19005464409e8de68d669ea02c8c43dd7ab31e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20Espi=C3=A9?= Date: Thu, 26 Apr 2018 14:59:30 +0000 Subject: [PATCH] Parser for Short Hand Syntax (->) Check method SVN:b1312[5747] --- core/oql/expression.class.inc.php | 5 ++- core/oql/oql-parser.php | 47 ++++++++++--------- core/oql/oql-parser.y | 6 ++- core/oql/oqlquery.class.inc.php | 75 +++++++++++++++++++++++++------ core/oql/version.txt | 2 +- 5 files changed, 97 insertions(+), 38 deletions(-) diff --git a/core/oql/expression.class.inc.php b/core/oql/expression.class.inc.php index 622a192607..928c59d9cc 100644 --- a/core/oql/expression.class.inc.php +++ b/core/oql/expression.class.inc.php @@ -843,7 +843,10 @@ class FalseExpression extends ScalarExpression class ExternalFieldExpression extends UnaryExpression { - + public function __construct($value) + { + parent::__construct($value); + } } class FieldExpression extends UnaryExpression diff --git a/core/oql/oql-parser.php b/core/oql/oql-parser.php index 7bddeca4ae..4671b038b6 100644 --- a/core/oql/oql-parser.php +++ b/core/oql/oql-parser.php @@ -1596,16 +1596,19 @@ static public $yy_action = array( #line 158 "..\oql-parser.y" function yy_r61(){ $this->_retvalue = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -2]->minor); } #line 1602 "..\oql-parser.php" -#line 161 "..\oql-parser.y" - function yy_r63(){ $this->_retvalue = new ExternalFieldOqlExpression($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor); } -#line 1605 "..\oql-parser.php" -#line 163 "..\oql-parser.y" - function yy_r64(){ $this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; } +#line 162 "..\oql-parser.y" + function yy_r63(){ + $expr = new FieldOqlExpression($this->yystack[$this->yyidx + 0]->minor); + $this->_retvalue = new ExternalFieldOqlExpression($this->yystack[$this->yyidx + -2]->minor, $expr); + } #line 1608 "..\oql-parser.php" -#line 166 "..\oql-parser.y" - function yy_r65(){ $this->_retvalue = new VariableOqlExpression(substr($this->yystack[$this->yyidx + 0]->minor, 1)); } +#line 167 "..\oql-parser.y" + function yy_r64(){ $this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; } #line 1611 "..\oql-parser.php" -#line 168 "..\oql-parser.y" +#line 170 "..\oql-parser.y" + function yy_r65(){ $this->_retvalue = new VariableOqlExpression(substr($this->yystack[$this->yyidx + 0]->minor, 1)); } +#line 1614 "..\oql-parser.php" +#line 172 "..\oql-parser.y" function yy_r66(){ if ($this->yystack[$this->yyidx + 0]->minor[0] == '`') { @@ -1617,22 +1620,22 @@ static public $yy_action = array( } $this->_retvalue = new OqlName($name, $this->m_iColPrev); } -#line 1624 "..\oql-parser.php" -#line 179 "..\oql-parser.y" - function yy_r67(){$this->_retvalue=(int)$this->yystack[$this->yyidx + 0]->minor; } #line 1627 "..\oql-parser.php" -#line 180 "..\oql-parser.y" - function yy_r68(){$this->_retvalue=(int)-$this->yystack[$this->yyidx + 0]->minor; } +#line 183 "..\oql-parser.y" + function yy_r67(){$this->_retvalue=(int)$this->yystack[$this->yyidx + 0]->minor; } #line 1630 "..\oql-parser.php" -#line 181 "..\oql-parser.y" - function yy_r69(){$this->_retvalue=new OqlHexValue($this->yystack[$this->yyidx + 0]->minor); } +#line 184 "..\oql-parser.y" + function yy_r68(){$this->_retvalue=(int)-$this->yystack[$this->yyidx + 0]->minor; } #line 1633 "..\oql-parser.php" -#line 182 "..\oql-parser.y" - function yy_r70(){$this->_retvalue=stripslashes(substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2)); } -#line 1636 "..\oql-parser.php" #line 185 "..\oql-parser.y" - function yy_r71(){$this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; } + function yy_r69(){$this->_retvalue=new OqlHexValue($this->yystack[$this->yyidx + 0]->minor); } +#line 1636 "..\oql-parser.php" +#line 186 "..\oql-parser.y" + function yy_r70(){$this->_retvalue=stripslashes(substr($this->yystack[$this->yyidx + 0]->minor, 1, strlen($this->yystack[$this->yyidx + 0]->minor) - 2)); } #line 1639 "..\oql-parser.php" +#line 189 "..\oql-parser.y" + function yy_r71(){$this->_retvalue=$this->yystack[$this->yyidx + 0]->minor; } +#line 1642 "..\oql-parser.php" /** * placeholder for the left hand side in a reduce operation. @@ -1747,7 +1750,7 @@ static public $yy_action = array( #line 25 "..\oql-parser.y" throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCol, $this->tokenName($yymajor), $TOKEN); -#line 1755 "..\oql-parser.php" +#line 1758 "..\oql-parser.php" } /** @@ -1914,7 +1917,7 @@ throw new OQLParserException($this->m_sSourceQuery, $this->m_iLine, $this->m_iCo } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); } } -#line 243 "..\oql-parser.y" +#line 247 "..\oql-parser.y" class OQLParserException extends OQLException @@ -1979,4 +1982,4 @@ class OQLParser extends OQLParserRaw } } -#line 1988 "..\oql-parser.php" +#line 1991 "..\oql-parser.php" diff --git a/core/oql/oql-parser.y b/core/oql/oql-parser.y index 5809332345..aa5f48c631 100644 --- a/core/oql/oql-parser.y +++ b/core/oql/oql-parser.y @@ -158,7 +158,11 @@ basic_field_id(A) ::= name(X). { A = new FieldOqlExpression(X); } basic_field_id(A) ::= class_name(X) DOT name(Y). { A = new FieldOqlExpression(Y, X); } field_id(A) ::= basic_field_id(X). { A = X; } -field_id(A) ::= field_id(X) ARROW name(Y). { A = new ExternalFieldOqlExpression(X, Y); } +field_id(A) ::= field_id(X) ARROW name(Y). +{ + $expr = new FieldOqlExpression(Y); + A = new ExternalFieldOqlExpression(X, $expr); +} class_name(A) ::= name(X). { A=X; } diff --git a/core/oql/oqlquery.class.inc.php b/core/oql/oqlquery.class.inc.php index a5288eb046..eeeb2618e9 100644 --- a/core/oql/oqlquery.class.inc.php +++ b/core/oql/oqlquery.class.inc.php @@ -208,7 +208,34 @@ class ExternalFieldOqlExpression extends ExternalFieldExpression implements Chec */ public function Check(ModelReflection $oModelReflection, $aAliases, $sSourceQuery) { - // TODO: Implement Check() method. + $sParentAlias = null; + foreach($this->aExpression as $i => $oFieldOqlExpression) + { + if (is_null($sParentAlias)) + { + $oFieldOqlExpression->RefreshAlias($oModelReflection, $aAliases, $sSourceQuery); + } + else + { + $oFieldOqlExpression->SetParent($sParentAlias); + } + $oFieldOqlExpression->Check($oModelReflection, $aAliases, $sSourceQuery); + + $sClass = $aAliases[$oFieldOqlExpression->GetParent()]; + $sTargetClass = $oModelReflection->GetAttributeProperty($sClass, $oFieldOqlExpression->GetName(), 'targetclass'); + if (is_null($sTargetClass)) + { + if ($i != (count($this->aExpression) - 1)) + { + throw new OqlNormalizeException('Forbiden operation for attribute', $sSourceQuery, $oFieldOqlExpression->GetNameDetails(), $oModelReflection->GetFiltersList($sClass)); + } + } + else + { + $aAliases[$sTargetClass] = $sTargetClass; + $sParentAlias = $sTargetClass; + } + } } } @@ -240,6 +267,39 @@ class FieldOqlExpression extends FieldExpression implements CheckableExpression } public function Check(ModelReflection $oModelReflection, $aAliases, $sSourceQuery) + { + $sClassAlias = $this->GetParent(); + $sFltCode = $this->GetName(); + if (empty($sClassAlias)) + { + // Try to find an alias + // Build an array of field => array of aliases + $this->RefreshAlias($oModelReflection, $aAliases, $sSourceQuery); + } + else + { + if (!array_key_exists($sClassAlias, $aAliases)) + { + throw new OqlNormalizeException('Unknown class [alias]', $sSourceQuery, $this->GetParentDetails(), array_keys($aAliases)); + } + $sClass = $aAliases[$sClassAlias]; + if (!$oModelReflection->IsValidFilterCode($sClass, $sFltCode)) + { + throw new OqlNormalizeException('Unknown filter code', $sSourceQuery, $this->GetNameDetails(), $oModelReflection->GetFiltersList($sClass)); + } + } + } + + /** + * Used by Check => throws exception if error + * + * @param \ModelReflection $oModelReflection + * @param $aAliases + * @param $sSourceQuery + * + * @throws \OqlNormalizeException + */ + public function RefreshAlias(ModelReflection $oModelReflection, $aAliases, $sSourceQuery) { $sClassAlias = $this->GetParent(); $sFltCode = $this->GetName(); @@ -264,18 +324,7 @@ class FieldOqlExpression extends FieldExpression implements CheckableExpression throw new OqlNormalizeException('Ambiguous filter code', $sSourceQuery, $this->GetNameDetails()); } $sClassAlias = $aFieldClasses[$sFltCode][0]; - } - else - { - if (!array_key_exists($sClassAlias, $aAliases)) - { - throw new OqlNormalizeException('Unknown class [alias]', $sSourceQuery, $this->GetParentDetails(), array_keys($aAliases)); - } - $sClass = $aAliases[$sClassAlias]; - if (!$oModelReflection->IsValidFilterCode($sClass, $sFltCode)) - { - throw new OqlNormalizeException('Unknown filter code', $sSourceQuery, $this->GetNameDetails(), $oModelReflection->GetFiltersList($sClass)); - } + $this->SetParent($sClassAlias); } } } diff --git a/core/oql/version.txt b/core/oql/version.txt index 25ada144d7..eafdf558bf 100644 --- a/core/oql/version.txt +++ b/core/oql/version.txt @@ -1 +1 @@ -2015-08-31 +2018-04-26 \ No newline at end of file