瀏覽代碼

HPCC-9905 Fix problems with embeded functions returning datasets

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 12 年之前
父節點
當前提交
9127e15037
共有 5 個文件被更改,包括 47 次插入1 次删除
  1. 2 1
      ecl/hql/hqlattr.cpp
  2. 22 0
      ecl/hql/hqlexpr.cpp
  3. 2 0
      ecl/hql/hqlexpr.hpp
  4. 4 0
      ecl/hqlcpp/hqlcpp.cpp
  5. 17 0
      ecl/hqlcpp/hqlttcpp.cpp

+ 2 - 1
ecl/hql/hqlattr.cpp

@@ -3271,8 +3271,9 @@ bool recordRequiresDestructor(IHqlExpression * expr)
     if (!expr)
         return false;
 
+    IHqlExpression * body = expr->queryBody();
     //true if the internal serialized form is different
-    if (querySerializedForm(expr, internalAtom) != expr)
+    if (querySerializedForm(body, internalAtom) != body)
         return true;
 
     return false;

+ 22 - 0
ecl/hql/hqlexpr.cpp

@@ -3635,6 +3635,12 @@ switch (op)
     }
 #endif
 
+    if ((op == no_call) || (op == no_funcdef) || (op == no_outofline) || (op == no_embedbody))
+    {
+        if (recordRequiresLinkCount(::queryRecord(queryType())) && !hasLinkCountedModifier(queryType()))
+            throwUnexpected();
+    }
+
 #if 0
     //Useful code for detecting when types get messed up for comparisons
     if (op == no_eq || op == no_ne)
@@ -10503,6 +10509,22 @@ bool isExternalFunction(IHqlExpression * funcdef)
 }
 
 
+bool isEmbedFunction(IHqlExpression * funcdef)
+{
+    IHqlExpression * body = funcdef->queryChild(0);
+    if (body->getOperator() != no_outofline)
+        return false;
+    return body->queryChild(0)->getOperator() == no_embedbody;
+}
+
+
+bool isEmbedCall(IHqlExpression * expr)
+{
+    assertex(expr->getOperator() == no_call);
+    return isEmbedFunction(expr->queryBody()->queryFunctionDefinition());
+}
+
+
 inline bool isExternalMethodDefinition(IHqlExpression * funcdef)
 {
     if (funcdef->getOperator() == no_funcdef)

+ 2 - 0
ecl/hql/hqlexpr.hpp

@@ -1713,6 +1713,8 @@ extern HQL_API bool isUpdatedConditionally(IHqlExpression * expr);
 extern HQL_API bool activityMustBeCompound(IHqlExpression * expr);
 extern HQL_API unsigned queryCurrentTransformDepth();                   // debugging - only valid inside a transform
 extern HQL_API bool isExternalFunction(IHqlExpression * funcdef);
+extern HQL_API bool isEmbedFunction(IHqlExpression * expr);
+extern HQL_API bool isEmbedCall(IHqlExpression * expr);
 
 typedef enum { 
     //Flags to indicate which datasets are available in scope

+ 4 - 0
ecl/hqlcpp/hqlcpp.cpp

@@ -4336,6 +4336,10 @@ void HqlCppTranslator::buildTempExpr(BuildCtx & ctx, IHqlExpression * expr, CHql
     case no_id2blob:
         buildExpr(ctx, expr, tgt);
         return;
+    case no_call:
+        if (!isEmbedCall(expr))
+            break;
+        //fall through
     case no_externalcall:
         if (format == FormatNatural && expr->isDataset())
             format = hasLinkCountedModifier(expr->queryType()) ? FormatLinkedDataset : FormatBlockedDataset;

+ 17 - 0
ecl/hqlcpp/hqlttcpp.cpp

@@ -8616,6 +8616,23 @@ IHqlExpression * HqlLinkedChildRowTransformer::createTransformedBody(IHqlExpress
             }
         }
         break;
+    case no_embedbody:
+        //Don't change the type of an embed body - otherwise result it will become link counted when not expected.
+        return LINK(expr);
+    case no_select:
+        {
+            OwnedHqlExpr newDs = transform(expr->queryChild(0));
+            IHqlExpression * record = newDs->queryRecord();
+            IHqlExpression * field = expr->queryChild(1);
+            LinkedHqlExpr newField;
+            if (record)
+                newField.setown(record->querySimpleScope()->lookupSymbol(field->queryName()));
+            HqlExprArray children;
+            children.append(*LINK(newDs));
+            if (newField)
+                children.append(*newField.getClear());
+            return completeTransform(expr, children);
+        }
     }
     return QuickHqlTransformer::createTransformedBody(expr);
 }