瀏覽代碼

HPCC-16697 Fix problem commoning conditional and unconditional expressions

If the first use of an expression is conditional, but subsequent uses
are unconditional, then the common expression must be evaluated
unconditionally.  This includes if the graph is inside a scalar
conditional context.

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 8 年之前
父節點
當前提交
2b99de3312
共有 2 個文件被更改,包括 26 次插入7 次删除
  1. 24 7
      ecl/hqlcpp/hqlttcpp.cpp
  2. 2 0
      ecl/hqlcpp/hqlttcpp.ipp

+ 24 - 7
ecl/hqlcpp/hqlttcpp.cpp

@@ -8305,6 +8305,18 @@ void AutoScopeMigrateTransformer::analyseExpr(IHqlExpression * expr)
     activityDepth = savedDepth;
 }
 
+void AutoScopeMigrateTransformer::doAnalyseConditionalExpr(IHqlExpression * expr, unsigned firstConditional)
+{
+    bool wasConditional = isConditional;
+    ForEachChild(i, expr)
+    {
+        if (i == firstConditional)
+            isConditional = true;
+       analyseExpr(expr->queryChild(i));
+    }
+    isConditional = wasConditional;
+}
+
 void AutoScopeMigrateTransformer::doAnalyseExpr(IHqlExpression * expr)
 {
     AutoScopeMigrateInfo * extra = queryBodyExtra(expr);
@@ -8336,15 +8348,11 @@ void AutoScopeMigrateTransformer::doAnalyseExpr(IHqlExpression * expr)
         return;
     case no_if:
     case no_choose:
+    case no_case:
         {
-            if (expr->isAction())
+            if (expr->isAction() || (graphDepth == 0))
             {
-                bool wasConditional = isConditional;
-                analyseExpr(expr->queryChild(0));
-                isConditional = true;
-                ForEachChildFrom(i, expr, 1)
-                    analyseExpr(expr->queryChild(i));
-                isConditional = wasConditional;
+                doAnalyseConditionalExpr(expr, 1);
                 return;
             }
             break;
@@ -8359,13 +8367,22 @@ void AutoScopeMigrateTransformer::doAnalyseExpr(IHqlExpression * expr)
             return;
         }
         break;
+    case no_map:
+        if (expr->isAction() || (graphDepth == 0))
+        {
+            doAnalyseConditionalExpr(expr, 0);
+            return;
+        }
+        break;
     case no_thor:
         //ignore thor attribute on a dataset..
         if (expr->queryType())
         {
             curGraph++;
+            graphDepth++;
             NewHqlTransformer::analyseExpr(expr);
             curGraph++;     // don't restore - new pseudo graph to aid cse between global branches separated by graphs
+            graphDepth--;
             return;
         }
         break;

+ 2 - 0
ecl/hqlcpp/hqlttcpp.ipp

@@ -744,6 +744,7 @@ protected:
     IHqlExpression * hoist(IHqlExpression * expr, IHqlExpression * hoisted);
     IHqlExpression * transformCond(IHqlExpression * expr);
     void doAnalyseExpr(IHqlExpression * expr);
+    void doAnalyseConditionalExpr(IHqlExpression * expr, unsigned firstConditional);
 
     inline AutoScopeMigrateInfo * queryBodyExtra(IHqlExpression * expr)     { return static_cast<AutoScopeMigrateInfo *>(queryTransformExtra(expr->queryBody())); }
 
@@ -755,6 +756,7 @@ private:
     bool hasCandidate;
     bool isSequential;
     unsigned curGraph;
+    unsigned graphDepth = 0;
     HqlExprArray graphActions;
     unsigned activityDepth;
     HqlExprArray * globalTarget;