Selaa lähdekoodia

HPCC-8411 Improve conditonal assignments of datasets

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 12 vuotta sitten
vanhempi
commit
0131f1cbc2
2 muutettua tiedostoa jossa 65 lisäystä ja 0 poistoa
  1. 2 0
      ecl/hqlcpp/hqlcpp.ipp
  2. 63 0
      ecl/hqlcpp/hqlcppds.cpp

+ 2 - 0
ecl/hqlcpp/hqlcpp.ipp

@@ -1182,6 +1182,8 @@ public:
     void buildDatasetAssignTempTable(BuildCtx & ctx, IHqlCppDatasetBuilder * target, IHqlExpression * expr);
     void buildDatasetAssignXmlProject(BuildCtx & ctx, IHqlCppDatasetBuilder * target, IHqlExpression * expr);
 
+    void buildDatasetAssignChoose(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr);
+    void buildDatasetAssignIf(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr);
     BoundRow * buildDatasetIterateSelectN(BuildCtx & ctx, IHqlExpression * expr, bool needToBreak);
     BoundRow * buildDatasetIterateChoosen(BuildCtx & ctx, IHqlExpression * expr, bool needToBreak);
     BoundRow * buildDatasetIterateLimit(BuildCtx & ctx, IHqlExpression * expr, bool needToBreak);

+ 63 - 0
ecl/hqlcpp/hqlcppds.cpp

@@ -2188,6 +2188,15 @@ void HqlCppTranslator::doBuildDataset(BuildCtx & ctx, IHqlExpression * expr, CHq
 //---------------------------------------------------------------------------
 // Dataset assignment - to temp
 
+static bool isWorthAssigningDirectly(BuildCtx & ctx, const CHqlBoundTarget & /*target*/, IHqlExpression * expr)
+{
+    //target parameter is currently unused - it should be used to check that linkcounted attributes match etc.
+    if (expr->getOperator() == no_null)
+        return false;
+    //A poor approximation.  Could also include function calls if the is-link-counted matches.
+    return ::canEvaluateInline(&ctx, expr);
+}
+
 void HqlCppTranslator::buildDatasetAssign(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
 {
     node_operator op = expr->getOperator();
@@ -2275,6 +2284,23 @@ void HqlCppTranslator::buildDatasetAssign(BuildCtx & ctx, const CHqlBoundTarget
     case no_sectioninput:
         buildDatasetAssign(ctx, target, expr->queryChild(0));
         return;
+    case no_if:
+        //Only generate conditional assignments to a target if both source and target require no temporary.
+        if (expr->isDictionary() || (::canEvaluateInline(&ctx, expr->queryChild(1)) && ::canEvaluateInline(&ctx, expr->queryChild(2))))
+        //The following line would be better, but it needs improvements to the cse generation first, otherwise some examples get worse.
+        //if (expr->isDictionary() || (isWorthAssigningDirectly(ctx, target, expr->queryChild(1)) || isWorthAssigningDirectly(ctx, target, expr->queryChild(2))))
+        {
+            buildDatasetAssignIf(ctx, target, expr);
+            return;
+        }
+        break;
+    case no_chooseds:
+        if (expr->isDictionary())
+        {
+            buildDatasetAssignChoose(ctx, target, expr);
+            return;
+        }
+        break;
     case no_serialize:
         if (isDummySerializeDeserialize(expr))
             buildDatasetAssign(ctx, target, expr->queryChild(0)->queryChild(0));
@@ -2862,6 +2888,43 @@ void HqlCppTranslator::buildDatasetAssignChoose(BuildCtx & ctx, IHqlCppDatasetBu
 }
 
 
+void HqlCppTranslator::buildDatasetAssignChoose(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
+{
+    CHqlBoundExpr cond;
+    buildExpr(ctx, expr->queryChild(0), cond);
+
+    IHqlExpression * last = queryLastNonAttribute(expr);
+    BuildCtx subctx(ctx);
+    IHqlStmt * switchstmt = subctx.addSwitch(cond.expr);
+    ForEachChildFrom(i, expr, 1)
+    {
+        IHqlExpression * cur = expr->queryChild(i);
+        if (cur != last)
+        {
+            OwnedHqlExpr label = getSizetConstant(i);
+            subctx.addCase(switchstmt, label);
+        }
+        else
+            subctx.addDefault(switchstmt);
+
+        buildDatasetAssign(subctx, target, cur);
+    }
+}
+
+
+void HqlCppTranslator::buildDatasetAssignIf(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
+{
+    BuildCtx subctx(ctx);
+    IHqlStmt * filter = buildFilterViaExpr(subctx, expr->queryChild(0));
+    buildDatasetAssign(subctx, target, expr->queryChild(1));
+
+    IHqlExpression * elseExpr = expr->queryChild(2);
+    assertex(elseExpr);
+    subctx.selectElse(filter);
+    buildDatasetAssign(subctx, target, elseExpr);
+}
+
+
 void HqlCppTranslator::buildDatasetAssign(BuildCtx & ctx, IHqlCppDatasetBuilder * target, IHqlExpression * _expr)
 {
     OwnedHqlExpr expr = forceInlineAssignDataset(ctx, _expr);