فهرست منبع

HPCC-10189 Add a flag to indicate a row in a self-join never matches itself

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 11 سال پیش
والد
کامیت
3ddd78dfe6
4فایلهای تغییر یافته به همراه50 افزوده شده و 0 حذف شده
  1. 45 0
      ecl/hql/hqlutil.cpp
  2. 2 0
      ecl/hql/hqlutil.hpp
  3. 2 0
      ecl/hqlcpp/hqlhtcpp.cpp
  4. 1 0
      rtl/include/eclhelper.hpp

+ 45 - 0
ecl/hql/hqlutil.cpp

@@ -1162,6 +1162,51 @@ void JoinSortInfo::initSorts()
     }
 }
 
+static bool isSameFieldSelected(IHqlExpression * leftExpr, IHqlExpression * rightExpr, IHqlExpression * left, IHqlExpression * right)
+{
+    if ((leftExpr->getOperator() != no_select) || (rightExpr->getOperator() != no_select))
+        return false;
+    if (leftExpr->queryChild(1) != rightExpr->queryChild(1))
+        return false;
+ 
+    IHqlExpression * leftSelector = leftExpr->queryChild(0);
+    IHqlExpression * rightSelector = rightExpr->queryChild(0);
+    if (leftSelector == left || rightSelector == right)
+        return (leftSelector == left) && (rightSelector == right);
+    if (leftSelector == right || rightSelector == left)
+        return (leftSelector == right) && (rightSelector == left);
+    return isSameFieldSelected(leftSelector, rightSelector, left, right);
+}
+
+
+static bool hasNeverMatchCompare(IHqlExpression * expr, IHqlExpression * left, IHqlExpression * right)
+{
+    switch (expr->getOperator())
+    {
+    case no_and:
+        return hasNeverMatchCompare(expr->queryChild(0), left, right) ||
+               hasNeverMatchCompare(expr->queryChild(1), left, right);
+    case no_ne:
+    case no_gt:
+    case no_lt:
+        return isSameFieldSelected(expr->queryChild(0), expr->queryChild(1), left, right);
+    default:
+        return false;
+    }
+}
+
+bool JoinSortInfo::neverMatchSelf(IHqlExpression * leftDs, IHqlExpression * rightDs, IHqlExpression * selSeq)
+{
+    if (!extraMatch)
+        return false;
+    if (!recordTypesMatch(leftDs, rightDs))
+        return false;
+
+    OwnedHqlExpr left = createSelector(no_left, leftDs, selSeq);
+    OwnedHqlExpr right = createSelector(no_right, rightDs, selSeq);
+    return hasNeverMatchCompare(extraMatch, left, right);
+}
+
 
 extern HQL_API bool joinHasRightOnlyHardMatch(IHqlExpression * expr, bool allowSlidingMatch)
 {

+ 2 - 0
ecl/hql/hqlutil.hpp

@@ -709,6 +709,8 @@ public:
     inline const HqlExprArray & queryLeftSort() { initSorts(); return leftSorts; }
     inline const HqlExprArray & queryRightSort() { initSorts(); return rightSorts; }
 
+    bool neverMatchSelf(IHqlExpression * left, IHqlExpression * right, IHqlExpression * selSeq);
+
 protected:
     void initSorts();
 

+ 2 - 0
ecl/hqlcpp/hqlhtcpp.cpp

@@ -11818,6 +11818,8 @@ ABoundActivity * HqlCppTranslator::doBuildActivityJoinOrDenormalize(BuildCtx & c
     if (isSmartJoin) flags.append("|JFsmart|JFmanylookup");
     if (isSmartJoin || expr->hasAttribute(unstableAtom))
         flags.append("|JFunstable");
+    if (joinInfo.neverMatchSelf(dataset1, dataset2, selSeq))
+        flags.append("|JFnevermatchself");
 
     if (flags.length())
         doBuildUnsignedFunction(instance->classctx, "getJoinFlags", flags.str()+1);

+ 1 - 0
rtl/include/eclhelper.hpp

@@ -1578,6 +1578,7 @@ enum {
     JFrightSortedLocally         = 0x08000000,
     JFsmart                      = 0x10000000,
     JFunstable                   = 0x20000000, // can sorts be unstable?
+    JFnevermatchself             = 0x40000000, // for a self join can a record match itself
 };
 
 // FetchFlags