浏览代码

Merge pull request #11984 from ghalliday/issue20933b

HPCC-20933 Fix the interpretation of an active table for no_selectnth

Reviewed-By: Shamser Ahmed <shamser.ahmed@lexisnexis.co.uk>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 6 年之前
父节点
当前提交
d8593a8d06
共有 3 个文件被更改,包括 37 次插入3 次删除
  1. 2 1
      ecl/hql/hqlexpr.cpp
  2. 34 2
      ecl/hql/hqlexpr.ipp
  3. 1 0
      ecl/hqlcpp/hqlttcpp.cpp

+ 2 - 1
ecl/hql/hqlexpr.cpp

@@ -5417,6 +5417,7 @@ void CUsedTables::gatherTablesUsed(HqlExprCopyArray & inScope) const
 void CUsedTables::set(HqlExprCopyArray & activeTables)
 {
     numActiveTables = activeTables.ordinality();
+
     if (numActiveTables == 1)
     {
         tables.single = &activeTables.item(0);
@@ -5474,7 +5475,7 @@ void CUsedTablesBuilder::removeParent(IHqlExpression * expr)
         if (!root->hasAttribute(newAtom))
             break;
         expr = root->queryChild(0);
-        removeActive(expr->queryNormalizedSelector());
+        removeActiveSelector(expr->queryNormalizedSelector());
     }
 }
 

+ 34 - 2
ecl/hql/hqlexpr.ipp

@@ -132,7 +132,28 @@ class HQL_API CUsedTablesBuilder
 public:
     void addActiveTable(IHqlExpression * expr);
     void cleanupProduction();
-    inline void removeActive(IHqlExpression * expr) { inScopeTables.remove(expr); }
+    inline void removeActive(IHqlExpression * expr)
+    {
+        HqlExprCopyArray toRemove;
+        for (IHqlExpression & cur : inScopeTables)
+        {
+            IHqlExpression * selector = &cur;
+            for(;;)
+            {
+                if (selector == expr)
+                {
+                    toRemove.append(cur);
+                    break;
+                }
+                if (selector->getOperator() != no_select)
+                    break;
+                selector = selector->queryChild(0);
+            }
+        }
+        ForEachItemIn(i, toRemove)
+            removeActiveSelector(&toRemove.item(i));
+    }
+    void removeActiveSelector(IHqlExpression * expr) { inScopeTables.remove(expr); }
     void removeParent(IHqlExpression * expr);
     void removeActiveRecords();
     void removeRows(IHqlExpression * expr, IHqlExpression * left, IHqlExpression * right);
@@ -181,14 +202,25 @@ protected:
 
 protected:
     //For a no_select, is this the root no_select (rather than a.b.c), and is it also an active selector.
+    //That requires the left hand side to be a dataset, and not marked as new.
     //Used for determining how a no_select should be interpreted e.g., in table gathering. 
     inline bool isSelectRootAndActive() const
     {
+        dbgassertex(op == no_select);
         if (hasAttribute(newAtom))
             return false;
+        //If lhs is a row then this is not the root selection from a dataset
         IHqlExpression * ds = queryChild(0);
-        if ((ds->getOperator() == no_select) && ds->isDatarow())
+        if (ds->isDatarow())
+        {
+            switch (ds->getOperator())
+            {
+            //This is a complete hack - but prevents scrub2 from generating invalid code.  HPCC-21084 created for a correct fix.
+            case no_typetransfer:
+                return true;
+            }
             return false;
+        }
         return true;
     }
 

+ 1 - 0
ecl/hqlcpp/hqlttcpp.cpp

@@ -9933,6 +9933,7 @@ IHqlExpression * HqlLinkedChildRowTransformer::createTransformedBody(IHqlExpress
 
 HqlScopeTaggerInfo::HqlScopeTaggerInfo(IHqlExpression * _expr) : MergingTransformInfo(_expr)
 {
+    //IsIndependentOFScope is potentially quite expensive to evaluate, but significantly reduces the cost of this transformation
     if (!onlyTransformOnce() && (!containsImplicitNormalize(_expr) || _expr->isIndependentOfScope()))
     {
         //If the node doesn't have any active selectors then it isn't going to be context dependent