Implemented the OQL operator ABOVE (and its variants ABOVE STRICT, NOT ABOVE and NOT ABOVE STRICT) that returns the (indirect) parents of a given node in a hierarchy. It's the opposite to 'BELOW' that returns the (indirect) children.

SVN:trunk[1454]
This commit is contained in:
Denis Flaven
2011-08-16 08:14:11 +00:00
parent 74baca3a7b
commit 2ad9d69396
7 changed files with 726 additions and 581 deletions

View File

@@ -28,6 +28,10 @@ define('TREE_OPERATOR_BELOW', 1);
define('TREE_OPERATOR_BELOW_STRICT', 2);
define('TREE_OPERATOR_NOT_BELOW', 3);
define('TREE_OPERATOR_NOT_BELOW_STRICT', 4);
define('TREE_OPERATOR_ABOVE', 5);
define('TREE_OPERATOR_ABOVE_STRICT', 6);
define('TREE_OPERATOR_NOT_ABOVE', 7);
define('TREE_OPERATOR_NOT_ABOVE_STRICT', 8);
class DBObjectSearch
{
@@ -155,6 +159,22 @@ class DBObjectSearch
case TREE_OPERATOR_NOT_BELOW_STRICT:
$sOperator = 'strictly not below';
break;
case TREE_OPERATOR_ABOVE:
$sOperator = 'above';
break;
case TREE_OPERATOR_ABOVE_STRICT:
$sOperator = 'strictly above';
break;
case TREE_OPERATOR_NOT_ABOVE:
$sOperator = 'not above';
break;
case TREE_OPERATOR_NOT_ABOVE_STRICT:
$sOperator = 'strictly not above';
break;
}
$aDescription[] = $oAtt->GetLabel()."$sOperator ({$oFilter->DescribeConditions()})";
}
@@ -842,6 +862,22 @@ class DBObjectSearch
$sOperator = ' NOT BELOW STRICT ';
break;
case TREE_OPERATOR_ABOVE:
$sOperator = ' ABOVE ';
break;
case TREE_OPERATOR_ABOVE_STRICT:
$sOperator = ' ABOVE STRICT ';
break;
case TREE_OPERATOR_NOT_ABOVE:
$sOperator = ' NOT ABOVE ';
break;
case TREE_OPERATOR_NOT_ABOVE_STRICT:
$sOperator = ' NOT ABOVE STRICT ';
break;
}
$sRes .= ' JOIN '.$oFilter->GetClass().' AS '.$oFilter->GetClassAlias().' ON '.$this->GetClassAlias().'.'.$sExtKey.$sOperator.$oFilter->GetClassAlias().'.id';
$sRes .= $oFilter->ToOQL_Joins();
@@ -1077,6 +1113,18 @@ class DBObjectSearch
case 'NOT_BELOW_STRICT':
$iOperatorCode = TREE_OPERATOR_NOT_BELOW_STRICT;
break;
case 'ABOVE':
$iOperatorCode = TREE_OPERATOR_ABOVE;
break;
case 'ABOVE_STRICT':
$iOperatorCode = TREE_OPERATOR_ABOVE_STRICT;
break;
case 'NOT_ABOVE':
$iOperatorCode = TREE_OPERATOR_NOT_ABOVE;
break;
case 'NOT_ABOVE_STRICT':
$iOperatorCode = TREE_OPERATOR_NOT_ABOVE_STRICT;
break;
}
$aJoinItems[$sFromClass]->AddCondition_PointingTo($aJoinItems[$sToClass], $sExtKeyAttCode, $iOperatorCode);
}

View File

@@ -2519,9 +2519,10 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
$sRightIndex = $sExternalKeyField.'_right'; // TODO use GetSQLRight()
$LocalKeyLeft = $oKeyAttDef->GetSQLLeft();
$LocalKeyRight = $oKeyAttDef->GetSQLRight();
//echo "MAKEQUERY-LocalKeyLeft pour $sKeyAttCode => $LocalKeyLeft<br/>\n";
$oSelectBase->AddInnerJoinTree($oSelectExtKey, $LocalKeyLeft, $sLeftIndex, $sRightIndex, $sExternalKeyTable, $iOperatorCode);
$oSelectBase->AddInnerJoinTree($oSelectExtKey, $LocalKeyLeft, $LocalKeyRight, $sLeftIndex, $sRightIndex, $sExternalKeyTable, $iOperatorCode);
}
}
}

View File

@@ -164,6 +164,10 @@ class OQLLexerRaw
'/\GBELOW STRICT/ ',
'/\GNOT BELOW/ ',
'/\GNOT BELOW STRICT/ ',
'/\GABOVE/ ',
'/\GABOVE STRICT/ ',
'/\GNOT ABOVE/ ',
'/\GNOT ABOVE STRICT/ ',
'/\G[0-9]+|0x[0-9a-fA-F]+/ ',
'/\G\"([^\\\\\"]|\\\\\"|\\\\\\\\)*\"|'.chr(94).chr(39).'([^\\\\'.chr(39).']|\\\\'.chr(39).'|\\\\\\\\)*'.chr(39).'/ ',
'/\G([_a-zA-Z][_a-zA-Z0-9]*|`[^`]+`)/ ',
@@ -554,24 +558,44 @@ class OQLLexerRaw
function yy_r1_58($yy_subpatterns)
{
$this->token = OQLParser::NUMVAL;
$this->token = OQLParser::ABOVE;
}
function yy_r1_59($yy_subpatterns)
{
$this->token = OQLParser::STRVAL;
$this->token = OQLParser::ABOVE_STRICT;
}
function yy_r1_60($yy_subpatterns)
{
$this->token = OQLParser::NAME;
$this->token = OQLParser::NOT_ABOVE;
}
function yy_r1_61($yy_subpatterns)
{
$this->token = OQLParser::VARNAME;
$this->token = OQLParser::NOT_ABOVE_STRICT;
}
function yy_r1_62($yy_subpatterns)
{
$this->token = OQLParser::NUMVAL;
}
function yy_r1_63($yy_subpatterns)
{
$this->token = OQLParser::STRVAL;
}
function yy_r1_64($yy_subpatterns)
{
$this->token = OQLParser::NAME;
}
function yy_r1_65($yy_subpatterns)
{
$this->token = OQLParser::VARNAME;
}
function yy_r1_66($yy_subpatterns)
{
$this->token = OQLParser::DOT;
@@ -580,7 +604,7 @@ class OQLLexerRaw
}
define('UNEXPECTED_INPUT_AT_LINE', 'Unexpected input at line ');
define('UNEXPECTED_INPUT_AT_LINE', 'Unexpected input at line');
class OQLLexerException extends OQLException
{
@@ -597,11 +621,11 @@ class OQLLexer extends OQLLexerRaw
return max(0, $this->count - strlen($this->value));
}
function yylex()
{
try
{
return parent::yylex();
function yylex()
{
try
{
return parent::yylex();
}
catch (Exception $e)
{

View File

@@ -136,6 +136,10 @@ below = "BELOW"
below_strict = "BELOW STRICT"
not_below = "NOT BELOW"
not_below_strict = "NOT BELOW STRICT"
above = "ABOVE"
above_strict = "ABOVE STRICT"
not_above = "NOT ABOVE"
not_above_strict = "NOT ABOVE STRICT"
numval = /[0-9]+|0x[0-9a-fA-F]+/
strval = /"([^\\"]|\\"|\\\\)*"|'.chr(94).chr(39).'([^\\'.chr(39).']|\\'.chr(39).'|\\\\)*'.chr(39).'/
name = /([_a-zA-Z][_a-zA-Z0-9]*|`[^`]+`)/
@@ -318,6 +322,18 @@ not_below {
not_below_strict {
$this->token = OQLParser::NOT_BELOW_STRICT;
}
above {
$this->token = OQLParser::ABOVE;
}
above_strict {
$this->token = OQLParser::ABOVE_STRICT;
}
not_above {
$this->token = OQLParser::NOT_ABOVE;
}
not_above_strict {
$this->token = OQLParser::NOT_ABOVE_STRICT;
}
numval {
$this->token = OQLParser::NUMVAL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -82,6 +82,10 @@ join_condition(A) ::= field_id(X) BELOW field_id(Y). { A = new BinaryOqlExpressi
join_condition(A) ::= field_id(X) BELOW_STRICT field_id(Y). { A = new BinaryOqlExpression(X, 'BELOW_STRICT', Y); }
join_condition(A) ::= field_id(X) NOT_BELOW field_id(Y). { A = new BinaryOqlExpression(X, 'NOT_BELOW', Y); }
join_condition(A) ::= field_id(X) NOT_BELOW_STRICT field_id(Y). { A = new BinaryOqlExpression(X, 'NOT_BELOW_STRICT', Y); }
join_condition(A) ::= field_id(X) ABOVE field_id(Y). { A = new BinaryOqlExpression(X, 'ABOVE', Y); }
join_condition(A) ::= field_id(X) ABOVE_STRICT field_id(Y). { A = new BinaryOqlExpression(X, 'ABOVE_STRICT', Y); }
join_condition(A) ::= field_id(X) NOT_ABOVE field_id(Y). { A = new BinaryOqlExpression(X, 'NOT_ABOVE', Y); }
join_condition(A) ::= field_id(X) NOT_ABOVE_STRICT field_id(Y). { A = new BinaryOqlExpression(X, 'NOT_ABOVE_STRICT', Y); }
condition(A) ::= expression_prio4(X). { A = X; }

View File

@@ -163,7 +163,6 @@ class SQLQuery
// {
// throw new CoreException("Unknown field '$sRightField' in table '".$sRightTable."'");
// }
$this->m_aJoinSelects[] = array(
"jointype" => $sJoinType,
"select" => $oSQLQuery,
@@ -176,7 +175,7 @@ class SQLQuery
{
$this->AddJoin("inner", $oSQLQuery, $sLeftField, $sRightField, $sRightTable);
}
public function AddInnerJoinTree($oSQLQuery, $sLeftField, $sRightFieldLeft, $sRightFieldRight, $sRightTableAlias = '', $iOperatorCode = TREE_OPERATOR_BELOW)
public function AddInnerJoinTree($oSQLQuery, $sLeftFieldLeft, $sLeftFieldRight, $sRightFieldLeft, $sRightFieldRight, $sRightTableAlias = '', $iOperatorCode = TREE_OPERATOR_BELOW)
{
assert((get_class($oSQLQuery) == __CLASS__) || is_subclass_of($oSQLQuery, __CLASS__));
if (empty($sRightTableAlias))
@@ -186,7 +185,8 @@ class SQLQuery
$this->m_aJoinSelects[] = array(
"jointype" => 'inner_tree',
"select" => $oSQLQuery,
"leftfield" => $sLeftField,
"leftfield" => $sLeftFieldLeft,
"rightfield" => $sLeftFieldRight,
"rightfield_left" => $sRightFieldLeft,
"rightfield_right" => $sRightFieldRight,
"righttablealias" => $sRightTableAlias,
@@ -418,6 +418,7 @@ class SQLQuery
break;
case "inner_tree":
$sNodeLeft = "`$sCallerAlias`.`{$aJoinData['leftfield']}`";
$sNodeRight = "`$sCallerAlias`.`{$aJoinData['rightfield']}`";
$sRootLeft = "`$sRightTableAlias`.`{$aJoinData['rightfield_left']}`";
$sRootRight = "`$sRightTableAlias`.`{$aJoinData['rightfield_right']}`";
switch($aJoinData['tree_operator'])
@@ -437,6 +438,22 @@ class SQLQuery
case TREE_OPERATOR_NOT_BELOW_STRICT: // Complementary of BELOW_STRICT
$sJoinCond = "$sNodeLeft <= $sRootLeft OR $sNodeLeft >= $sRootRight";
break;
case TREE_OPERATOR_ABOVE:
$sJoinCond = "$sNodeLeft <= $sRootLeft AND $sNodeRight >= $sRootRight";
break;
case TREE_OPERATOR_ABOVE_STRICT:
$sJoinCond = "$sNodeLeft < $sRootLeft AND $sNodeRight > $sRootRight";
break;
case TREE_OPERATOR_NOT_ABOVE: // Complementary of 'ABOVE'
$sJoinCond = "$sNodeLeft > $sRootLeft OR $sNodeRight < $sRootRight";
break;
case TREE_OPERATOR_NOT_ABOVE_STRICT: // Complementary of ABOVE_STRICT
$sJoinCond = "$sNodeLeft >= $sRootLeft OR $sNodeRight <= $sRootRight";
break;
}
$aFrom[$this->m_sTableAlias] = array("jointype"=>$aJoinData['jointype'], "tablename"=>$this->m_sTable, "joincondition"=>"$sJoinCond");