ソースを参照

Fix locality of activities within nested thor loops

Activities within nested thor loops were incorrectly being marked as
colocal (i.e. able to access data from their parent activity).  This
fix also removes spurious code generated for grouped disk aggregate
callbacks.

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 13 年 前
コミット
770ef32606

+ 1 - 0
ecl/hqlcpp/CMakeLists.txt

@@ -67,6 +67,7 @@ set (    SRCS
          hqlcpputil.hpp
          hqlecl.hpp
          hqlfunc.hpp
+         hqlinline.hpp
          hqlpopt.hpp
          hqlregex.hpp
          hqlres.hpp

+ 1 - 1
ecl/hqlcpp/hqlcerrors.hpp

@@ -550,7 +550,7 @@
 #define HQLERR_LibraryNoWorkunitRead_Text       "INTERNAL: Library '%s' shouldn't access work unit temporary '%s'"
 #define HQLERR_LibraryNoWorkunitWrite_Text      "INTERNAL: Library '%s' shouldn't create work unit temporary '%s'"
 #define HQLERR_GraphInputAccessedChild_Text     "INTERNAL: Attempting to access graph output directly from a child query"
-#define HQLERR_InconsisentLocalisation_Text     "INTERNAL: Inconsistent activity localisation (%d:%d)"
+#define HQLERR_InconsisentLocalisation_Text     "INTERNAL: Inconsistent activity localisation (child %d:graph %d)"
 #define HQLERR_NoParentExtract_Text             "INTERNAL: No active parent extract - activity has incorrect localisation?"
 #define HQLERR_InconsistentNaryInput_Text       "INTERNAL: Inputs to nary operation have inconsistent record structures"
 #define HQLERR_LinkedDatasetNoContext_Text      "INTERNAL: Linked child rows required without legal context available"

+ 1 - 0
ecl/hqlcpp/hqlcpp.cpp

@@ -52,6 +52,7 @@
 #include "hqlpopt.hpp"
 #include "hqlcse.ipp"
 #include "thorplugin.hpp"
+#include "hqlinline.hpp"
 
 #ifdef _DEBUG
 //#define ADD_ASSIGNMENT_COMMENTS

+ 23 - 245
ecl/hqlcpp/hqlcpp.ipp

@@ -39,7 +39,14 @@
 #define MAX_RECORD_SIZE     4096                // default value
 
 enum { HintSpeed = 1, HintSize = 2 };
-enum GraphLocalisation { GraphCoLocal, GraphNonLocal, GraphCoNonLocal, GraphRemote, GraphNoAccess };
+enum GraphLocalisation {
+    GraphNoAccess = 0,
+    GraphCoLocal = 1,
+    GraphNonLocal = 2,
+    GraphCoNonLocal = 3,
+    GraphRemote = 4
+};
+
 enum { 
     EclTextPrio = 1000,         // has no dependencies on anything else
     TypeInfoPrio = 1200,
@@ -454,247 +461,6 @@ class ActivityInstance;
 class SerializationRow;
 class EvalContext;
 class InternalResultTracker;
-// A parent extract represents the set of fields etc. which are used from the parent activity,
-// which are local to the point that the executeChildActivity() is called.
-class ParentExtract : public HqlExprAssociation
-{
-public:
-    ParentExtract(HqlCppTranslator & _translator, GraphLocalisation _localisation, EvalContext * _container=NULL);
-    ~ParentExtract();
-
-//HqlExprAssociation
-    virtual AssocKind getKind() { return AssocExtract; }
-
-    void beginCreateExtract(BuildCtx & buildctx, bool doDeclare);
-    void beginNestedExtract(BuildCtx & clonectx);
-    void beginReuseExtract();
-    void endCreateExtract(CHqlBoundExpr & boundExtract);
-    void endUseExtract(BuildCtx & ctx);
-    IHqlExpression * queryExtractName()             { return boundExtract.expr; }
-
-    bool canEvaluate(IHqlExpression * expr);
-    bool canSerializeFields()                       { return buildctx != NULL; }
-    void associateCursors(BuildCtx & declarectx, BuildCtx & evalctx, GraphLocalisation childLocalisation);
-    void beginChildActivity(BuildCtx & declareCtx, BuildCtx & startCtx, GraphLocalisation childLocalisation, IHqlExpression * colocal, bool nested, bool ignoreSelf, ActivityInstance * activityRequiringCast);
-    void endChildActivity();
-
-    void addSerializedExpression(IHqlExpression * value, ITypeInfo * type);
-    void buildAssign(IHqlExpression * serializedTarget, IHqlExpression * originalValue);
-    AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, IHqlExpression * colocal, bool evaluateLocally);
-
-    void setAllowDestructor() { canDestroyExtract = true; }
-    inline GraphLocalisation queryLocalisation() { return localisation; }
-
-protected:
-    void ensureAccessible(BuildCtx & ctx, IHqlExpression * expr, const CHqlBoundExpr & bound, CHqlBoundExpr & tgt, IHqlExpression * colocal);
-    void gatherActiveRows(BuildCtx & ctx);
-
-protected:
-    HqlCppTranslator & translator;
-    EvalContext * container;
-    SerializationRow * serialization;           // fields that are serialized to the children
-    SerializationRow * childSerialization;      // same serialization, but as it is bound in the child.
-
-    CursorArray colocalBoundCursors;            // what rows/cursors are available at the point of executeChildGraph()
-    CursorArray nonlocalBoundCursors;           // what rows/cursors are available at the point of executeChildGraph()
-    GraphLocalisation localisation;             // what kind of localisation do ALL the children have?
-
-    CursorArray inheritedCursors;
-    CursorArray localCursors;       // does not include colocal
-    CursorArray cursorToBind;
-    CHqlBoundExpr boundBuilder;     // may have wrapper, or be a char[n]
-    CHqlBoundExpr boundExtract;     // always a reference to a row. for "extract"
-    Owned<BuildCtx> buildctx;       // may be null if nested extract
-    bool canDestroyExtract;
-};
-
-
-class CtxCollection : public CInterface
-{
-public:
-    CtxCollection(BuildCtx & _declareCtx)   : clonectx(_declareCtx), childctx(_declareCtx), declarectx(_declareCtx) {}
-
-    void createFunctionStructure(HqlCppTranslator & translator, BuildCtx & ctx, bool canEvaluate, const char * serializeFunc);
-
-public:
-    BuildCtx clonectx;
-    BuildCtx childctx;      // child.onCreate() is called from here..
-    BuildCtx declarectx;
-
-    //following are always null for nested classes, always created for others.
-    Owned<BuildCtx> evalctx;
-    Owned<BuildCtx> serializectx;
-    Owned<BuildCtx> deserializectx;
-};
-
-
-//A potential location for an extract to be created...
-class EvalContext : public HqlExprAssociation
-{
-public:
-    EvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent);
-
-    virtual AssocKind getKind() { return AssocExtractContext; }
-
-    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
-    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally) = 0;
-    virtual bool isColocal()                                { return true; }
-    virtual ActivityInstance * queryActivity();
-    virtual bool isLibraryContext()                         { return false; }
-
-    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt) = 0;
-    virtual bool getInvariantMemberContext(BuildCtx * ctx, BuildCtx * * declarectx, BuildCtx * * initctx, bool isIndependentMaybeShared, bool invariantEachStart) { return false; }
-
-    void ensureContextAvailable()                           { ensureHelpersExist(); }
-    virtual bool evaluateInParent(BuildCtx & ctx, IHqlExpression * expr, bool hasOnStart);
-    bool hasParent()                                        { return parent != NULL; }
-    bool needToEvaluateLocally(BuildCtx & ctx, IHqlExpression * expr);
-
-public://only used by friends
-    virtual void callNestedHelpers(const char * memberName) = 0;
-    virtual void ensureHelpersExist() = 0;
-    virtual bool insideQueryDepth(unsigned depth) = 0;
-    virtual bool isRowInvariant(IHqlExpression * expr)      { return false; }
-
-    bool insideChildQuery();
-
-protected:
-    Owned<ParentExtract> parentExtract;         // extract of the parent EvalContext
-    HqlCppTranslator & translator;
-    EvalContext * parent;
-    OwnedHqlExpr colocalMember;
-};
-
-class ClassEvalContext : public EvalContext
-{
-    friend class ActivityInstance;
-    friend class GlobalClassBuilder;
-public:
-    ClassEvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent, BuildCtx & createctx, BuildCtx & startctx);
-
-    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally);
-    virtual bool isRowInvariant(IHqlExpression * expr);
-
-    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt);
-    virtual bool getInvariantMemberContext(BuildCtx * ctx, BuildCtx * * declarectx, BuildCtx * * initctx, bool isIndependentMaybeShared, bool invariantEachStart);
-
-protected:
-    void cloneAliasInClass(CtxCollection & ctxs, const CHqlBoundExpr & bound, CHqlBoundExpr & tgt);
-    IHqlExpression * cloneExprInClass(CtxCollection & ctxs, IHqlExpression * expr);
-    void createMemberAlias(CtxCollection & ctxs, BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt);
-    void doCallNestedHelpers(const char * member, const char * acticity);
-    void ensureSerialized(CtxCollection & ctxs, const CHqlBoundTarget & tgt);
-
-protected:
-    CtxCollection onCreate;
-    CtxCollection onStart;
-};
-
-
-class GlobalClassEvalContext : public ClassEvalContext
-{
-public:
-    GlobalClassEvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent, BuildCtx & createctx, BuildCtx & startctx);
-
-    virtual void callNestedHelpers(const char * memberName);
-    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild) { throwUnexpected(); }
-    virtual void ensureHelpersExist();
-    virtual bool insideQueryDepth(unsigned depth)           { return false; }
-    virtual bool isColocal()                                { return false; }
-};
-
-
-
-class ActivityEvalContext : public ClassEvalContext
-{
-    friend class ActivityInstance;
-public:
-    ActivityEvalContext(HqlCppTranslator & _translator, ActivityInstance * _activity, ParentExtract * _parentExtract, EvalContext * _parent, IHqlExpression * _colocal, BuildCtx & createctx, BuildCtx & startctx);
-
-    virtual void callNestedHelpers(const char * memberName);
-    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
-    virtual void ensureHelpersExist();
-    virtual bool insideQueryDepth(unsigned depth);
-    virtual bool isColocal()                                { return (colocalMember != NULL); }
-    virtual ActivityInstance * queryActivity();
-
-    void createMemberAlias(CtxCollection & ctxs, BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt);
-
-protected:
-    ActivityInstance * activity;
-};
-
-
-class NestedEvalContext : public ClassEvalContext
-{
-public:
-    NestedEvalContext(HqlCppTranslator & _translator, const char * _memberName, ParentExtract * _parentExtract, EvalContext * _parent, IHqlExpression * _colocal, BuildCtx & createctx, BuildCtx & startctx);
-
-    virtual void callNestedHelpers(const char * memberName);
-    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
-    virtual void ensureHelpersExist();
-    virtual bool insideQueryDepth(unsigned depth);
-
-    void initContext();
-    virtual bool evaluateInParent(BuildCtx & ctx, IHqlExpression * expr, bool hasOnStart);
-
-protected:
-    bool helpersExist;
-
-protected:
-    StringAttr memberName;
-};
-
-
-
-class MemberEvalContext : public EvalContext
-{
-public:
-    MemberEvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent, BuildCtx & _ctx);
-
-    virtual void callNestedHelpers(const char * memberName);
-    virtual void ensureHelpersExist();
-    virtual bool insideQueryDepth(unsigned depth);
-    virtual bool isRowInvariant(IHqlExpression * expr);
-
-    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
-    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally);
-
-    virtual bool getInvariantMemberContext(BuildCtx * ctx, BuildCtx * * declarectx, BuildCtx * * initctx, bool isIndependentMaybeShared, bool invariantEachStart);
-    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt);
-
-    void initContext();
-
-protected:
-    BuildCtx ctx;
-};
-
-
-
-class LibraryEvalContext : public EvalContext
-{
-public:
-    LibraryEvalContext(HqlCppTranslator & _translator);
-
-    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally);
-    virtual bool isColocal()                                { return false; }
-    virtual bool isLibraryContext()                         { return true; }
-
-    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt);
-
-    void associateExpression(BuildCtx & ctx, IHqlExpression * value);
-    void ensureContextAvailable()                           { }
-
-public:
-    virtual void callNestedHelpers(const char * memberName)     {}
-    virtual void ensureHelpersExist()                           {}
-    virtual bool insideQueryDepth(unsigned depth)               { return false; }
-
-protected:
-    HqlExprArray values;
-    HqlExprArray bound;
-};
-
 //---------------------------------------------------------------------------
 
 typedef CIArrayOf<BuildCtx> BuildCtxArray;
@@ -967,6 +733,17 @@ public:
 
 class AliasExpansionInfo;
 class HashCodeCreator;
+class ParentExtract;
+enum PEtype {
+    PETnone,
+    PETchild,       // child query
+    PETremote,      // allnodes
+    PETloop,        // loop
+    PETnested,      // nested class
+    PETcallback,    // callback within a function
+    PETlibrary,     // a library
+    PETmax };
+
 class HQLCPP_API HqlCppTranslator : public CInterface, implements IHqlCppTranslator
 {
 //MORE: This is in serious need of refactoring....
@@ -1208,8 +985,8 @@ public:
     IHqlExpression * createRowSerializer(BuildCtx & ctx, IHqlExpression * record, _ATOM kind);
 
     AliasKind buildExprInCorrectContext(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt, bool evaluateLocally);
-    ParentExtract * createExtractBuilder(BuildCtx & ctx, IHqlExpression * expr, bool doDeclare);
-    ParentExtract * createExtractBuilder(BuildCtx & ctx, GraphLocalisation localisation, bool doDeclare);
+    ParentExtract * createExtractBuilder(BuildCtx & ctx, PEtype type, IHqlExpression * expr, bool doDeclare);
+    ParentExtract * createExtractBuilder(BuildCtx & ctx, PEtype type, GraphLocalisation localisation, bool doDeclare);
         
     void buildDefaultRow(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & bound);
     void buildNullRow(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & bound);
@@ -1840,6 +1617,7 @@ public:
     EvalContext * queryEvalContext(BuildCtx & ctx)          { return (EvalContext *)ctx.queryFirstAssociation(AssocExtractContext); }
     inline unsigned nextActivityId()                        { return ++curActivityId; }
     bool insideChildGraph(BuildCtx & ctx);
+    bool insideChildQuery(BuildCtx & ctx);
     bool insideRemoteGraph(BuildCtx & ctx);
     bool isCurrentActiveGraph(BuildCtx & ctx, IHqlExpression * graphTag);
 
@@ -2004,7 +1782,7 @@ protected:
     IHqlExpression * optimizeCompoundSource(IHqlExpression * expr, unsigned flags);
     IHqlExpression * optimizeGraphPostResource(IHqlExpression * expr, unsigned csfFlags);
     bool isInlineOk();
-    GraphLocalisation getGraphLocalisation(IHqlExpression * expr);
+    GraphLocalisation getGraphLocalisation(IHqlExpression * expr, bool isInsideChildQuery);
     bool isAlwaysCoLocal();
     bool isNeverDistributed(IHqlExpression * expr);
 

+ 12 - 11
ecl/hqlcpp/hqlcppds.cpp

@@ -47,6 +47,7 @@
 #include "hqlgraph.ipp"
 #include "hqlccommon.hpp"
 #include "hqliter.ipp"
+#include "hqlinline.hpp"
 
 #define MAX_FIXED_SIZE_RAW 1024
 #define INLINE_TABLE_EXPAND_LIMIT 4
@@ -1171,7 +1172,7 @@ void ChildGraphBuilder::generateGraph(BuildCtx & ctx)
     OwnedHqlExpr query = createActionList(results);
     OwnedHqlExpr resourced = translator.getResourcedChildGraph(graphctx, query, represents, numResults, no_none);
 
-    Owned<ParentExtract> extractBuilder = translator.createExtractBuilder(graphctx, resourced, true);
+    Owned<ParentExtract> extractBuilder = translator.createExtractBuilder(graphctx, PETchild, resourced, true);
     if (!translator.queryOptions().serializeRowsetInExtract)
         extractBuilder->setAllowDestructor();
     translator.beginExtract(graphctx, extractBuilder);
@@ -1220,7 +1221,7 @@ void ChildGraphBuilder::generatePrefetchGraph(BuildCtx & _ctx, OwnedHqlExpr * re
     OwnedHqlExpr query = createActionList(results);
     OwnedHqlExpr resourced = translator.getResourcedChildGraph(ctx, query, represents, numResults, no_none);
 
-    Owned<ParentExtract> extractBuilder = translator.createExtractBuilder(ctx, resourced, false);
+    Owned<ParentExtract> extractBuilder = translator.createExtractBuilder(ctx, PETchild, resourced, false);
     createBuilderAlias(aliasctx, extractBuilder);
     translator.beginExtract(ctx, extractBuilder);
 
@@ -1341,9 +1342,9 @@ unique_id_t ChildGraphBuilder::buildLoopBody(BuildCtx & ctx, IHqlExpression * da
     if (multiInstance)
         resourced.setown(appendOwnedOperand(resourced, createAttribute(multiInstanceAtom)));
 
-    bool isGlobalThorLoop = translator.targetThor() && !translator.insideChildGraph(ctx);
-    Owned<ParentExtract> extractBuilder = isGlobalThorLoop ? translator.createExtractBuilder(ctx, GraphRemote, false)
-                                                           : translator.createExtractBuilder(ctx, resourced, false);
+    bool isGlobalThorLoop = translator.targetThor() && !translator.insideChildQuery(ctx);
+    Owned<ParentExtract> extractBuilder = isGlobalThorLoop ? translator.createExtractBuilder(ctx, PETloop, GraphRemote, false)
+                                                           : translator.createExtractBuilder(ctx, PETloop, resourced, false);
 
     createBuilderAlias(subctx, extractBuilder);
 
@@ -1465,9 +1466,9 @@ unique_id_t ChildGraphBuilder::buildGraphLoopBody(BuildCtx & ctx, IHqlExpression
         resourced.setown(resourced->clone(args));
     }
 
-    bool isGlobalThorLoop = translator.targetThor() && !translator.insideChildGraph(ctx);
-    Owned<ParentExtract> extractBuilder = isGlobalThorLoop ? translator.createExtractBuilder(ctx, GraphRemote, false)
-                                                           : translator.createExtractBuilder(ctx, resourced, false);
+    bool isGlobalThorLoop = translator.targetThor() && !translator.insideChildQuery(ctx);
+    Owned<ParentExtract> extractBuilder = isGlobalThorLoop ? translator.createExtractBuilder(ctx, PETloop, GraphRemote, false)
+                                                           : translator.createExtractBuilder(ctx, PETloop, resourced, false);
 
     createBuilderAlias(subctx, extractBuilder);
 
@@ -1493,7 +1494,7 @@ unique_id_t ChildGraphBuilder::buildRemoteGraph(BuildCtx & ctx, IHqlExpression *
         query.set(ds);
     OwnedHqlExpr resourced = translator.getResourcedChildGraph(ctx, query, represents, numResults, no_allnodes);
 
-    Owned<ParentExtract> extractBuilder = translator.createExtractBuilder(ctx, GraphRemote, false);
+    Owned<ParentExtract> extractBuilder = translator.createExtractBuilder(ctx, PETremote, GraphRemote, false);
 
     createBuilderAlias(subctx, extractBuilder);
 
@@ -1584,7 +1585,7 @@ IHqlExpression * HqlCppTranslator::getResourcedChildGraph(BuildCtx & ctx, IHqlEx
     gatherActiveCursors(ctx, activeRows);
     if (graphKind == no_loop)
     {
-        bool insideChild = insideChildGraph(ctx);
+        bool insideChild = insideChildQuery(ctx);
         resourced.setown(resourceLoopGraph(*this, activeRows, resourced, targetClusterType, graphIdExpr, &numResults, insideChild));
     }
     else
@@ -4457,7 +4458,7 @@ static IHqlExpression * queryResultExpr(IHqlExpression * expr)
 ABoundActivity * HqlCppTranslator::doBuildActivityForceLocal(BuildCtx & ctx, IHqlExpression * expr)
 {
     IHqlExpression * child = expr->queryChild(0);
-    if (targetHThor() || (targetThor() && !insideChildGraph(ctx)))
+    if (targetHThor() || (targetThor() && !insideChildQuery(ctx)))
     {
         WARNING(HQLWRN_LocalHasNoEffect);
         return buildCachedActivity(ctx, child);

+ 40 - 19
ecl/hqlcpp/hqlhtcpp.cpp

@@ -53,6 +53,7 @@
 #include "hqlscope.hpp"
 #include "hqlccommon.hpp"
 #include "deffield.hpp"
+#include "hqlinline.hpp"
 
 //The following are include to ensure they call compile...
 #include "eclhelper.hpp"
@@ -1844,7 +1845,7 @@ ActivityInstance::ActivityInstance(HqlCppTranslator & _translator, BuildCtx & ct
     hasChildActivity = false;
 
     includedInHeader = false;
-    isCoLocal = true;
+    isCoLocal = false;
     executedRemotely = translator.targetThor();// && !translator.isNeverDistributed(dataset);
     containerActivity = NULL;
     subgraph = queryActiveSubGraph(ctx);
@@ -1853,32 +1854,36 @@ ActivityInstance::ActivityInstance(HqlCppTranslator & _translator, BuildCtx & ct
 
     //count index and count disk need to be swapped to the new (much simpler) mechanism
     //until then, they need to be special cased.
-    activityLocalisation = GraphCoLocal;
+    activityLocalisation = GraphNoAccess;
     if (kind != TAKcountindex && kind != TAKcountdisk)
     {
         containerActivity = translator.queryCurrentActivity(ctx);
         parentEvalContext.set(translator.queryEvalContext(ctx));
         parentExtract.set(static_cast<ParentExtract*>(ctx.queryFirstAssociation(AssocExtract)));
+
         if (parentExtract)
         {
-            if (!translator.isAlwaysCoLocal())
-            {
-                GraphLocalisation localisation = parentExtract->queryLocalisation();
-                activityLocalisation = queryActivityLocalisation(dataset);
+            GraphLocalisation localisation = parentExtract->queryLocalisation();
+            activityLocalisation = translator.isAlwaysCoLocal() ? GraphCoLocal : queryActivityLocalisation(dataset);
+
+            if (translator.targetThor() && !translator.insideChildQuery(ctx))
+                executedRemotely = true;
+            else
                 executedRemotely = ((activityLocalisation == GraphNonLocal) || (localisation == GraphRemote));
-                isCoLocal = !executedRemotely && (localisation != GraphNonLocal) && (activityLocalisation != GraphNoAccess);    // if we supported GraphNonCoLocal the last test would not be needed
-                //if top level activity within a query library then need to force access to the parent extract
-                if (!containerActivity && translator.insideLibrary())
-                {
-                    //there should be no colocal activity (container = null)
-                    if (activityLocalisation != GraphNoAccess)
-                        activityLocalisation = GraphNonLocal;
-                }
-                if (activityLocalisation == GraphNoAccess)
-                    parentExtract.clear();
+
+            isCoLocal = containerActivity && !executedRemotely && (localisation != GraphNonLocal) && (activityLocalisation != GraphNoAccess);    // if we supported GraphNonCoLocal the last test would not be needed
+
+            //if top level activity within a query library then need to force access to the parent extract
+            if (!containerActivity && translator.insideLibrary())
+            {
+                //there should be no colocal activity (container = null)
+                if (activityLocalisation != GraphNoAccess)
+                    activityLocalisation = GraphNonLocal;
             }
+            if (activityLocalisation == GraphNoAccess)
+                parentExtract.clear();
 
-            if (isCoLocal && containerActivity)
+            if (isCoLocal)
                 colocalMember.setown(createVariable("colocal", makeVoidType()));
         }
         else
@@ -1917,6 +1922,10 @@ ABoundActivity * ActivityInstance::getBoundActivity()
     return LINK(table);
 }
 
+BuildCtx & ActivityInstance::onlyEvalOnceContext()
+{
+    return evalContext->onCreate.childctx;
+}
 
 bool ActivityInstance::isExternal()
 {
@@ -2475,7 +2484,7 @@ ParentExtract * ActivityInstance::createNestedExtract()
 {
     if (!nestedExtract)
     {
-        nestedExtract.setown(new ParentExtract(translator, GraphCoLocal, evalContext));
+        nestedExtract.setown(new ParentExtract(translator, PETnested, GraphCoLocal, evalContext));
         nestedExtract->beginNestedExtract(startctx);
     }
     return LINK(nestedExtract);
@@ -8385,7 +8394,7 @@ ABoundActivity * HqlCppTranslator::doBuildActivityGraphLoop(BuildCtx & ctx, IHql
 ABoundActivity * HqlCppTranslator::doBuildActivityRemote(BuildCtx & ctx, IHqlExpression * expr, bool isRoot)
 {
     IHqlExpression * child = expr->queryChild(0);
-    if (targetHThor() || (targetThor() && !insideChildGraph(ctx)))
+    if (targetHThor() || (targetThor() && !insideChildQuery(ctx)))
     {
         if (!options.alwaysAllowAllNodes)
             throwError(HQLERR_RemoteNoMeaning);
@@ -8792,6 +8801,18 @@ bool HqlCppTranslator::insideChildGraph(BuildCtx & ctx)
     return false;
 }
 
+bool HqlCppTranslator::insideChildQuery(BuildCtx & ctx)
+{
+    ParentExtract * extract = static_cast<ParentExtract*>(ctx.queryFirstAssociation(AssocExtract));
+    if (extract)
+        return extract->insideChildQuery();
+    EvalContext * instance = queryEvalContext(ctx);
+    if (instance)
+        return instance->insideChildQuery();
+    return false;
+}
+
+
 unsigned HqlCppTranslator::curSubGraphId(BuildCtx & ctx)
 {
     SubGraphInfo * activeSubgraph = queryActiveSubGraph(ctx);

+ 3 - 2
ecl/hqlcpp/hqlhtcpp.ipp

@@ -84,6 +84,7 @@ public:
 //===========================================================================
 
 //MORE: I should derive the following and ActivityInstance from a common base class
+class GlobalClassEvalContext;
 class GlobalClassBuilder
 {
 public:
@@ -119,7 +120,7 @@ class JoinKeyInfo;
 class ActivityInstance;
 class NlpParseContext;
 extern StringBuffer &expandLiteral(StringBuffer &s, const char *f);
-
+class ActivityEvalContext;
 class ActivityInstance : public HqlExprAssociation
 {
 public:
@@ -161,7 +162,7 @@ public:
     void processHints(IHqlExpression * hintAttr);
     void processSection(IHqlExpression * hintAttr);
 
-    BuildCtx &   onlyEvalOnceContext()              { return evalContext->onCreate.childctx; }
+    BuildCtx &   onlyEvalOnceContext();
     inline IPropertyTree * querySubgraphNode() { return subgraph ? subgraph->tree.get() : NULL; }
     inline void setImplementationClass(_ATOM name) { implementationClassName = name; }
     void setInternalSink(bool value);

+ 63 - 44
ecl/hqlcpp/hqlinline.cpp

@@ -35,6 +35,7 @@
 #include "hqlccommon.hpp"
 #include "hqlcerrors.hpp"
 #include "hqlpmap.hpp"
+#include "hqlinline.hpp"
 
 //I don't think the following is needed yet, but when it is, just enable following...
 //#define ONSTART_IN_NESTED_TOPLEVEL
@@ -695,9 +696,11 @@ bool HqlCppTranslator::isAlwaysCoLocal()
     return targetHThor();
 }
 
-GraphLocalisation HqlCppTranslator::getGraphLocalisation(IHqlExpression * expr)
+GraphLocalisation HqlCppTranslator::getGraphLocalisation(IHqlExpression * expr, bool isInsideChildQuery)
 {
     if (isAlwaysCoLocal()) return GraphCoLocal;
+    if (targetThor() && !isInsideChildQuery)
+        return GraphNonLocal;
 
     TransformMutexBlock lock;
     return doGetGraphLocalisation(expr);
@@ -722,7 +725,8 @@ bool HqlCppTranslator::isNeverDistributed(IHqlExpression * expr)
 //============================================================================
 
 
-ParentExtract::ParentExtract(HqlCppTranslator & _translator, GraphLocalisation _localisation, EvalContext * _container) : HqlExprAssociation(parentExtractMarkerExpr), translator(_translator)
+ParentExtract::ParentExtract(HqlCppTranslator & _translator, PEtype _type, GraphLocalisation _localisation, EvalContext * _container)
+: HqlExprAssociation(parentExtractMarkerExpr), translator(_translator), type(_type)
 {
     localisation = _localisation;
     container = _container;
@@ -908,6 +912,33 @@ void ParentExtract::endChildActivity()
 {
 }
 
+bool ParentExtract::requiresOnStart() const
+{
+    switch (type)
+    {
+    case PETchild:
+    case PETremote:
+    case PETloop:
+    case PETlibrary:
+        return true;
+    case PETnested:
+    case PETcallback:
+        return container->requiresOnStart();
+    default:
+        throwUnexpected();
+    }
+}
+
+
+bool ParentExtract::insideChildQuery() const
+{
+    switch (type)
+    {
+    case PETchild:
+        return true;
+    }
+    return container->insideChildQuery();
+}
 
 void ParentExtract::endCreateExtract(CHqlBoundExpr & boundExtract)
 {
@@ -1138,14 +1169,14 @@ void ParentExtract::gatherActiveRows(BuildCtx & ctx)
 
 //----------------------------------------------------------------------------
 
-ParentExtract * HqlCppTranslator::createExtractBuilder(BuildCtx & ctx, GraphLocalisation localisation, bool doDeclare)
+ParentExtract * HqlCppTranslator::createExtractBuilder(BuildCtx & ctx, PEtype type, GraphLocalisation localisation, bool doDeclare)
 {
     ParentExtract * extractor = NULL;
 //  if (localisation == GraphCoLocal)
 //      extract = checkForPreexistingExtract - find a bound association before a row association is found;
     if (!extractor)
     {
-        extractor = new ParentExtract(*this, localisation, queryEvalContext(ctx));
+        extractor = new ParentExtract(*this, type, localisation, queryEvalContext(ctx));
         extractor->beginCreateExtract(ctx, doDeclare);
     }
     else
@@ -1154,11 +1185,12 @@ ParentExtract * HqlCppTranslator::createExtractBuilder(BuildCtx & ctx, GraphLoca
 }
 
 
-ParentExtract * HqlCppTranslator::createExtractBuilder(BuildCtx & ctx, IHqlExpression * expr, bool doDeclare)
+ParentExtract * HqlCppTranslator::createExtractBuilder(BuildCtx & ctx, PEtype type, IHqlExpression * expr, bool doDeclare)
 {
     if (isAlwaysCoLocal())
-        return createExtractBuilder(ctx, GraphCoLocal, true);
-    return createExtractBuilder(ctx, getGraphLocalisation(expr), true);
+        return createExtractBuilder(ctx, type, GraphCoLocal, true);
+    bool isInsideChildQuery = (type == PETchild) || insideChildQuery(ctx);
+    return createExtractBuilder(ctx, type, getGraphLocalisation(expr, isInsideChildQuery), true);
 }
 
 
@@ -1290,9 +1322,23 @@ bool EvalContext::evaluateInParent(BuildCtx & ctx, IHqlExpression * expr, bool h
     return false;
 }
 
-bool EvalContext::insideChildQuery()
+bool EvalContext::insideChildQuery() const
 {
-    return insideQueryDepth(1);
+    if (parentExtract)
+        return parentExtract->insideChildQuery();
+    if (parent)
+        return parent->insideChildQuery();
+    return false;
+}
+
+
+bool EvalContext::requiresOnStart() const
+{
+    if (parentExtract)
+        return parentExtract->requiresOnStart();
+    if (parent)
+        return parent->requiresOnStart();
+    return false;
 }
 
 
@@ -1411,12 +1457,8 @@ void ClassEvalContext::doCallNestedHelpers(const char * member, const char * act
 
     onCreate.childctx.addQuoted(s.clear().append(member).append(".onCreate(ctx, ").append(activity).append(");"));
 
-    if (insideChildQuery())
+    if (requiresOnStart())
         onStart.childctx.addQuoted(s.clear().append(member).append(".onStart();"));
-#ifdef ONSTART_IN_NESTED_TOPLEVEL
-    else
-        onStart.childctx.addQuoted(s.clear().append(member).append(".onStart();"));
-#endif
 }
 
 
@@ -1593,17 +1635,6 @@ void ActivityEvalContext::callNestedHelpers(const char * member)
     doCallNestedHelpers(member, "this");
 }
 
-bool ActivityEvalContext::insideQueryDepth(unsigned depth)
-{
-    if (!activity->parentExtract)
-        return false;
-    if (depth == 1)
-        return true;
-    if (!parent)
-        return false;
-    return parent->insideQueryDepth(depth-1);
-}
-
 ActivityInstance * ActivityEvalContext::queryActivity()
 {
     return activity;
@@ -1649,12 +1680,7 @@ void NestedEvalContext::ensureHelpersExist()
 
         //void onStart(const byte * parentExtract)
         BuildCtx onstartctx(onStart.declarectx);
-#ifndef ONSTART_IN_NESTED_TOPLEVEL
-        bool hasOnStart = (insideChildQuery() || parentExtract->canSerializeFields());
-#else
-        bool hasOnStart = true;
-#endif
-        if (hasOnStart)
+        if (requiresOnStart())
         {
             onstartctx.addQuotedCompound("inline void onStart()");
             if (parentExtract)
@@ -1672,8 +1698,13 @@ void NestedEvalContext::ensureHelpersExist()
 
 void NestedEvalContext::initContext()
 {
-    if (insideChildQuery() || parentExtract->canSerializeFields())
+    if (requiresOnStart())
         ensureHelpersExist();
+    else if (parentExtract && parentExtract->canSerializeFields())
+    {
+        ensureHelpersExist();
+        parentExtract->associateCursors(onStart.declarectx, onStart.declarectx, GraphCoLocal);
+    }
 }
 
 bool NestedEvalContext::evaluateInParent(BuildCtx & ctx, IHqlExpression * expr, bool hasOnStart) 
@@ -1687,13 +1718,6 @@ void NestedEvalContext::callNestedHelpers(const char * member)
     doCallNestedHelpers(member, "activity");
 }
 
-bool NestedEvalContext::insideQueryDepth(unsigned depth)
-{
-    if (parent)
-        return parent->insideQueryDepth(depth);
-    return false;
-}
-
 //---------------------------------------------------------------------------
 
 
@@ -1738,11 +1762,6 @@ void MemberEvalContext::initContext()
 }
 
 
-bool MemberEvalContext::insideQueryDepth(unsigned depth)
-{
-    return parent->insideQueryDepth(depth);
-}
-
 bool MemberEvalContext::getInvariantMemberContext(BuildCtx * ctx, BuildCtx * * declarectx, BuildCtx * * initctx, bool isIndependentMaybeShared, bool invariantEachStart)
 {
     return parent->getInvariantMemberContext(ctx, declarectx, initctx, isIndependentMaybeShared, invariantEachStart);

+ 265 - 0
ecl/hqlcpp/hqlinline.hpp

@@ -0,0 +1,265 @@
+/*##############################################################################
+
+    Copyright (C) 2011 HPCC Systems.
+
+    All rights reserved. This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as
+    published by the Free Software Foundation, either version 3 of the
+    License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+############################################################################## */
+
+#ifndef __HQLINLINE_HPP_
+#define __HQLINLINE_HPP_
+
+class ActivityInstance;
+class SerializationRow;
+class EvalContext;
+
+// A parent extract represents the set of fields etc. which are used from the parent activity,
+// which are local to the point that the executeChildActivity() is called.  The type indicates
+// the reason it is being created.
+class ParentExtract : public HqlExprAssociation
+{
+public:
+    ParentExtract(HqlCppTranslator & _translator, PEtype _type, GraphLocalisation _localisation, EvalContext * _container=NULL);
+    ~ParentExtract();
+
+//HqlExprAssociation
+    virtual AssocKind getKind() { return AssocExtract; }
+
+    void beginCreateExtract(BuildCtx & buildctx, bool doDeclare);
+    void beginNestedExtract(BuildCtx & clonectx);
+    void beginReuseExtract();
+    void endCreateExtract(CHqlBoundExpr & boundExtract);
+    void endUseExtract(BuildCtx & ctx);
+    IHqlExpression * queryExtractName()             { return boundExtract.expr; }
+
+    bool canEvaluate(IHqlExpression * expr);
+    bool canSerializeFields() const { return buildctx != NULL; }
+    void associateCursors(BuildCtx & declarectx, BuildCtx & evalctx, GraphLocalisation childLocalisation);
+    void beginChildActivity(BuildCtx & declareCtx, BuildCtx & startCtx, GraphLocalisation childLocalisation, IHqlExpression * colocal, bool nested, bool ignoreSelf, ActivityInstance * activityRequiringCast);
+    void endChildActivity();
+
+    void addSerializedExpression(IHqlExpression * value, ITypeInfo * type);
+    void buildAssign(IHqlExpression * serializedTarget, IHqlExpression * originalValue);
+    AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, IHqlExpression * colocal, bool evaluateLocally);
+
+    void setAllowDestructor() { canDestroyExtract = true; }
+    inline GraphLocalisation queryLocalisation() { return localisation; }
+
+    bool requiresOnStart() const;
+    bool insideChildQuery() const;
+
+protected:
+    void ensureAccessible(BuildCtx & ctx, IHqlExpression * expr, const CHqlBoundExpr & bound, CHqlBoundExpr & tgt, IHqlExpression * colocal);
+    void gatherActiveRows(BuildCtx & ctx);
+
+protected:
+    HqlCppTranslator & translator;
+    EvalContext * container;
+    SerializationRow * serialization;           // fields that are serialized to the children
+    SerializationRow * childSerialization;      // same serialization, but as it is bound in the child.
+
+    CursorArray colocalBoundCursors;            // what rows/cursors are available at the point of executeChildGraph()
+    CursorArray nonlocalBoundCursors;           // what rows/cursors are available at the point of executeChildGraph()
+    GraphLocalisation localisation;             // what kind of localisation do ALL the children have?
+
+    CursorArray inheritedCursors;
+    CursorArray localCursors;       // does not include colocal
+    CursorArray cursorToBind;
+    CHqlBoundExpr boundBuilder;     // may have wrapper, or be a char[n]
+    CHqlBoundExpr boundExtract;     // always a reference to a row. for "extract"
+    Owned<BuildCtx> buildctx;       // may be null if nested extract
+    PEtype type;
+    bool canDestroyExtract;
+};
+
+
+class CtxCollection : public CInterface
+{
+public:
+    CtxCollection(BuildCtx & _declareCtx)   : clonectx(_declareCtx), childctx(_declareCtx), declarectx(_declareCtx) {}
+
+    void createFunctionStructure(HqlCppTranslator & translator, BuildCtx & ctx, bool canEvaluate, const char * serializeFunc);
+
+public:
+    BuildCtx clonectx;
+    BuildCtx childctx;      // child.onCreate() is called from here..
+    BuildCtx declarectx;
+
+    //following are always null for nested classes, always created for others.
+    Owned<BuildCtx> evalctx;
+    Owned<BuildCtx> serializectx;
+    Owned<BuildCtx> deserializectx;
+};
+
+
+//A potential location for an extract to be created...
+class EvalContext : public HqlExprAssociation
+{
+public:
+    EvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent);
+
+    virtual AssocKind getKind() { return AssocExtractContext; }
+
+    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
+    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally) = 0;
+    virtual bool isColocal()                                { return true; }
+    virtual ActivityInstance * queryActivity();
+    virtual bool isLibraryContext()                         { return false; }
+
+    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt) = 0;
+    virtual bool getInvariantMemberContext(BuildCtx * ctx, BuildCtx * * declarectx, BuildCtx * * initctx, bool isIndependentMaybeShared, bool invariantEachStart) { return false; }
+
+    void ensureContextAvailable()                           { ensureHelpersExist(); }
+    virtual bool evaluateInParent(BuildCtx & ctx, IHqlExpression * expr, bool hasOnStart);
+    bool hasParent()                                        { return parent != NULL; }
+    bool needToEvaluateLocally(BuildCtx & ctx, IHqlExpression * expr);
+
+public://only used by friends
+    virtual void callNestedHelpers(const char * memberName) = 0;
+    virtual void ensureHelpersExist() = 0;
+    virtual bool isRowInvariant(IHqlExpression * expr)      { return false; }
+
+    bool requiresOnStart() const;
+    bool insideChildQuery() const;
+
+protected:
+    Owned<ParentExtract> parentExtract;         // extract of the parent EvalContext
+    HqlCppTranslator & translator;
+    EvalContext * parent;
+    OwnedHqlExpr colocalMember;
+};
+
+class ClassEvalContext : public EvalContext
+{
+    friend class ActivityInstance;
+    friend class GlobalClassBuilder;
+public:
+    ClassEvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent, BuildCtx & createctx, BuildCtx & startctx);
+
+    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally);
+    virtual bool isRowInvariant(IHqlExpression * expr);
+
+    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt);
+    virtual bool getInvariantMemberContext(BuildCtx * ctx, BuildCtx * * declarectx, BuildCtx * * initctx, bool isIndependentMaybeShared, bool invariantEachStart);
+
+protected:
+    void cloneAliasInClass(CtxCollection & ctxs, const CHqlBoundExpr & bound, CHqlBoundExpr & tgt);
+    IHqlExpression * cloneExprInClass(CtxCollection & ctxs, IHqlExpression * expr);
+    void createMemberAlias(CtxCollection & ctxs, BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt);
+    void doCallNestedHelpers(const char * member, const char * acticity);
+    void ensureSerialized(CtxCollection & ctxs, const CHqlBoundTarget & tgt);
+
+protected:
+    CtxCollection onCreate;
+    CtxCollection onStart;
+};
+
+
+class GlobalClassEvalContext : public ClassEvalContext
+{
+public:
+    GlobalClassEvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent, BuildCtx & createctx, BuildCtx & startctx);
+
+    virtual void callNestedHelpers(const char * memberName);
+    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild) { throwUnexpected(); }
+    virtual void ensureHelpersExist();
+    virtual bool isColocal()                                { return false; }
+};
+
+
+
+class ActivityEvalContext : public ClassEvalContext
+{
+    friend class ActivityInstance;
+public:
+    ActivityEvalContext(HqlCppTranslator & _translator, ActivityInstance * _activity, ParentExtract * _parentExtract, EvalContext * _parent, IHqlExpression * _colocal, BuildCtx & createctx, BuildCtx & startctx);
+
+    virtual void callNestedHelpers(const char * memberName);
+    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
+    virtual void ensureHelpersExist();
+    virtual bool isColocal()                                { return (colocalMember != NULL); }
+    virtual ActivityInstance * queryActivity();
+
+    void createMemberAlias(CtxCollection & ctxs, BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt);
+
+protected:
+    ActivityInstance * activity;
+};
+
+
+class NestedEvalContext : public ClassEvalContext
+{
+public:
+    NestedEvalContext(HqlCppTranslator & _translator, const char * _memberName, ParentExtract * _parentExtract, EvalContext * _parent, IHqlExpression * _colocal, BuildCtx & createctx, BuildCtx & startctx);
+
+    virtual void callNestedHelpers(const char * memberName);
+    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
+    virtual void ensureHelpersExist();
+
+    void initContext();
+    virtual bool evaluateInParent(BuildCtx & ctx, IHqlExpression * expr, bool hasOnStart);
+
+protected:
+    bool helpersExist;
+
+protected:
+    StringAttr memberName;
+};
+
+
+
+class MemberEvalContext : public EvalContext
+{
+public:
+    MemberEvalContext(HqlCppTranslator & _translator, ParentExtract * _parentExtract, EvalContext * _parent, BuildCtx & _ctx);
+
+    virtual void callNestedHelpers(const char * memberName);
+    virtual void ensureHelpersExist();
+    virtual bool isRowInvariant(IHqlExpression * expr);
+
+    virtual IHqlExpression * createGraphLookup(unique_id_t id, bool isChild);
+    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally);
+
+    virtual bool getInvariantMemberContext(BuildCtx * ctx, BuildCtx * * declarectx, BuildCtx * * initctx, bool isIndependentMaybeShared, bool invariantEachStart);
+    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt);
+
+    void initContext();
+
+protected:
+    BuildCtx ctx;
+};
+
+class LibraryEvalContext : public EvalContext
+{
+public:
+    LibraryEvalContext(HqlCppTranslator & _translator);
+
+    virtual AliasKind evaluateExpression(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt, bool evaluateLocally);
+    virtual bool isColocal()                                { return false; }
+    virtual bool isLibraryContext()                         { return true; }
+
+    virtual void tempCompatiablityEnsureSerialized(const CHqlBoundTarget & tgt);
+
+    void associateExpression(BuildCtx & ctx, IHqlExpression * value);
+    void ensureContextAvailable()                           { }
+
+public:
+    virtual void callNestedHelpers(const char * memberName)     {}
+    virtual void ensureHelpersExist()                           {}
+
+protected:
+    HqlExprArray values;
+    HqlExprArray bound;
+};
+
+#endif

+ 1 - 0
ecl/hqlcpp/hqliter.cpp

@@ -40,6 +40,7 @@
 #include "hqlutil.hpp"
 #include "hqlcse.ipp"
 #include "hqliter.ipp"
+#include "hqlinline.hpp"
 
 //===========================================================================
 

+ 3 - 2
ecl/hqlcpp/hqllib.cpp

@@ -38,6 +38,7 @@
 #include "hqllib.ipp"
 #include "hqlwcpp.hpp"
 #include "hqlttcpp.ipp"
+#include "hqlinline.hpp"
 
 static IHqlExpression * queryLibraryInputSequence(IHqlExpression * expr)
 {
@@ -478,7 +479,7 @@ void HqlCppTranslator::buildLibraryInstanceExtract(BuildCtx & ctx, HqlCppLibrary
 
     BuildCtx beforeBuilderCtx(subctx);
     beforeBuilderCtx.addGroup();
-    Owned<ParentExtract> extractBuilder = createExtractBuilder(subctx, GraphNonLocal, false);
+    Owned<ParentExtract> extractBuilder = createExtractBuilder(subctx, PETlibrary, GraphNonLocal, false);
 
     StringBuffer s;
     s.append("rtlRowBuilder & ");
@@ -629,7 +630,7 @@ void HqlCppTranslator::buildLibraryGraph(BuildCtx & ctx, IHqlExpression * expr,
         libraryContext->associateExpression(initctx, &parameter);
     }
 
-    Owned<ParentExtract> extractBuilder = createExtractBuilder(initctx, GraphRemote, false);
+    Owned<ParentExtract> extractBuilder = createExtractBuilder(initctx, PETlibrary, GraphRemote, false);
     beginExtract(initctx, extractBuilder);
 
     BuildCtx evalctx(ctx);

+ 2 - 2
ecl/hqlcpp/hqlresource.cpp

@@ -4518,9 +4518,9 @@ IHqlExpression * resourceNewChildGraph(HqlCppTranslator & translator, HqlExprCop
     return doResourceGraph(translator, &activeRows, expr, targetClusterType, 0, graphIdExpr, numResults, true, true);
 }
 
-IHqlExpression * resourceLoopGraph(HqlCppTranslator & translator, HqlExprCopyArray & activeRows, IHqlExpression * expr, ClusterType targetClusterType, IHqlExpression * graphIdExpr, unsigned * numResults, bool insideChildGraph)
+IHqlExpression * resourceLoopGraph(HqlCppTranslator & translator, HqlExprCopyArray & activeRows, IHqlExpression * expr, ClusterType targetClusterType, IHqlExpression * graphIdExpr, unsigned * numResults, bool insideChildQuery)
 {
-    return doResourceGraph(translator, &activeRows, expr, targetClusterType, 0, graphIdExpr, numResults, insideChildGraph, true);
+    return doResourceGraph(translator, &activeRows, expr, targetClusterType, 0, graphIdExpr, numResults, insideChildQuery, true);
 }
 
 IHqlExpression * resourceRemoteGraph(HqlCppTranslator & translator, IHqlExpression * expr, ClusterType targetClusterType, unsigned clusterSize)

+ 1 - 1
ecl/hqlcpp/hqlresource.hpp

@@ -24,7 +24,7 @@
 
 IHqlExpression * resourceThorGraph(HqlCppTranslator & translator, IHqlExpression * expr, ClusterType targetClusterType, unsigned clusterSize, IHqlExpression * graphIdExpr);
 IHqlExpression * resourceLibraryGraph(HqlCppTranslator & translator, IHqlExpression * expr, ClusterType targetClusterType, unsigned clusterSize, IHqlExpression * graphIdExpr, unsigned * numResults);
-IHqlExpression * resourceLoopGraph(HqlCppTranslator & translator, HqlExprCopyArray & activeRows, IHqlExpression * expr, ClusterType targetClusterType, IHqlExpression * graphIdExpr, unsigned * numResults, bool insideChildGraph);
+IHqlExpression * resourceLoopGraph(HqlCppTranslator & translator, HqlExprCopyArray & activeRows, IHqlExpression * expr, ClusterType targetClusterType, IHqlExpression * graphIdExpr, unsigned * numResults, bool insideChildQuery);
 IHqlExpression * resourceNewChildGraph(HqlCppTranslator & translator, HqlExprCopyArray & activeRows, IHqlExpression * expr, ClusterType targetClusterType, IHqlExpression * graphIdExpr, unsigned * numResults);
 IHqlExpression * resourceRemoteGraph(HqlCppTranslator & translator, IHqlExpression * expr, ClusterType targetClusterType, unsigned clusterSize);
 

+ 2 - 1
ecl/hqlcpp/hqlsource.cpp

@@ -47,6 +47,7 @@
 #include "hqlcse.ipp"
 #include "hqliter.ipp"
 #include "thorcommon.hpp"
+#include "hqlinline.hpp"
 
 //#define FLATTEN_DATASETS
 //#define HACK_TO_IGNORE_TABLE
@@ -2362,7 +2363,7 @@ void SourceBuilder::buildGroupAggregateTransformBody(BuildCtx & transformCtx, IH
     Owned<ParentExtract> extractBuilder;
     if (useExtract || (aggregate != mappedAggregate))
     {
-        extractBuilder.setown(translator.createExtractBuilder(transformCtx, GraphCoLocal, true));
+        extractBuilder.setown(translator.createExtractBuilder(transformCtx, PETcallback, GraphCoLocal, true));
         if (!translator.queryOptions().serializeRowsetInExtract)
             extractBuilder->setAllowDestructor();
         translator.beginExtract(transformCtx, extractBuilder);

+ 1 - 0
ecl/hqlcpp/hqltcppc.cpp

@@ -41,6 +41,7 @@
 #include "hqlccommon.hpp"
 #include "hqlpmap.hpp"
 #include "hqlutil.hpp"
+#include "hqlinline.hpp"
 
 #define LIMIT_FOR_GET       (NULL)