浏览代码

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.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1454 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 14 年之前
父节点
当前提交
280e159e3f
共有 7 个文件被更改,包括 648 次插入515 次删除
  1. 48 0
      core/dbobjectsearch.class.php
  2. 2 1
      core/metamodel.class.php
  3. 34 10
      core/oql/oql-lexer.php
  4. 16 0
      core/oql/oql-lexer.plex
  5. 524 501
      core/oql/oql-parser.php
  6. 4 0
      core/oql/oql-parser.y
  7. 20 3
      core/sqlquery.class.inc.php

+ 48 - 0
core/dbobjectsearch.class.php

@@ -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);
 				}

+ 2 - 1
core/metamodel.class.php

@@ -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);
 					}
 				}
 			}

+ 34 - 10
core/oql/oql-lexer.php

@@ -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,33 +558,53 @@ 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;
     }
 
 
 }
 
-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)
 		{

+ 16 - 0
core/oql/oql-lexer.plex

@@ -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;
 }

文件差异内容过多而无法显示
+ 524 - 501
core/oql/oql-parser.php


+ 4 - 0
core/oql/oql-parser.y

@@ -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; }
 

+ 20 - 3
core/sqlquery.class.inc.php

@@ -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");

部分文件因为文件数量过多而无法显示