Browse Source

Fixed issues from code review

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 13 years ago
parent
commit
f12e0f665c

+ 5 - 5
ecl/hql/hqlutil.cpp

@@ -1174,12 +1174,12 @@ IHqlExpression * createIf(IHqlExpression * cond, IHqlExpression * left, IHqlExpr
     if (left->isDataset() || right->isDataset())
         return createDataset(no_if, cond, createComma(left, right));
 
-    if (left->isDatarow() || right->isDatarow())
-        return createRow(no_if, cond, createComma(left, right));
-
     if (left->isDictionary() || right->isDictionary())
         return createDictionary(no_if, cond, createComma(left, right));
 
+    if (left->isDatarow() || right->isDatarow())
+        return createRow(no_if, cond, createComma(left, right));
+
     ITypeInfo * type = ::getPromotedECLType(left->queryType(), right->queryType());
     return createValue(no_if, type, cond, left, right);
 }
@@ -1882,10 +1882,10 @@ unsigned isEmptyRecord(IHqlExpression * record)
 
 bool isTrivialSelectN(IHqlExpression * expr)
 {
-    if (expr->getOperator() == no_index || expr->getOperator() == no_index)
+    if (expr->getOperator() == no_index || expr->getOperator() == no_selectnth)
     {
         IHqlExpression * index = expr->queryChild(1);
-        if (index->queryValue() && (index->queryValue()->getIntValue() == 1))
+        if (matchesConstantValue(index, 1))
             return hasSingleRow(expr->queryChild(0));
     }
     return false;

+ 2 - 1
ecl/hqlcpp/hqlcpp.ipp

@@ -173,7 +173,8 @@ interface IHqlCppDatasetCursor : public IInterface
     virtual void buildExists(BuildCtx & ctx, CHqlBoundExpr & tgt) = 0;
     virtual BoundRow * buildIterateLoop(BuildCtx & ctx, bool needToBreak) = 0;
     virtual void buildIterateClass(BuildCtx & ctx, SharedHqlExpr & iter, SharedHqlExpr & row) = 0;
-    virtual BoundRow * buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr) = 0;
+    virtual BoundRow * buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr) = 0;
+    virtual BoundRow * buildSelectMap(BuildCtx & ctx, IHqlExpression * indexExpr) = 0;
     virtual void buildIterateMembers(BuildCtx & declarectx, BuildCtx & initctx) = 0;
 };
 

+ 2 - 2
ecl/hqlcpp/hqlcppds.cpp

@@ -4222,7 +4222,7 @@ IReferenceSelector * HqlCppTranslator::buildDatasetIndex(BuildCtx & ctx, IHqlExp
     if (!row)
     {
         Owned<IHqlCppDatasetCursor> cursor = createDatasetSelector(ctx, dataset);
-        row = cursor->buildSelect(ctx, expr);
+        row = cursor->buildSelectNth(ctx, expr);
 
         if (!row)
         {
@@ -4258,7 +4258,7 @@ IReferenceSelector * HqlCppTranslator::buildDatasetSelectMap(BuildCtx & ctx, IHq
     if (!row)
     {
         Owned<IHqlCppDatasetCursor> cursor = createDatasetSelector(ctx, dataset);
-        row = cursor->buildSelect(ctx, expr);
+        row = cursor->buildSelectMap(ctx, expr);
 
         if (!row)
         {

+ 50 - 175
ecl/hqlcpp/hqlcset.cpp

@@ -128,7 +128,13 @@ void BaseDatasetCursor::buildIterateMembers(BuildCtx & declarectx, BuildCtx & in
     translator.bindTableCursor(declarectx, ds, row);
 }
 
-BoundRow * BaseDatasetCursor::buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr)
+BoundRow * BaseDatasetCursor::buildSelectMap(BuildCtx & ctx, IHqlExpression * indexExpr)
+{
+    // Should only be seen for dictionaries
+    throwUnexpected();
+}
+
+BoundRow * BaseDatasetCursor::buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr)
 {
     //MORE: Check if the cursor already exists....
 
@@ -409,7 +415,7 @@ BoundRow * InlineBlockDatasetCursor::buildSelectFirst(BuildCtx & ctx, IHqlExpres
 }
 
 
-BoundRow * InlineBlockDatasetCursor::buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr)
+BoundRow * InlineBlockDatasetCursor::buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr)
 {
     assertex(!isArrayRowset(boundDs.expr->queryType()));        // I don't think this can ever be called at the moment
 
@@ -418,7 +424,7 @@ BoundRow * InlineBlockDatasetCursor::buildSelect(BuildCtx & ctx, IHqlExpression
     {
         if (matchesConstantValue(index, 1))
             return buildSelectFirst(ctx, indexExpr, CREATE_DEAULT_ROW_IF_NULL_VALUE);
-        return BlockDatasetCursor::buildSelect(ctx, indexExpr);
+        return BlockDatasetCursor::buildSelectNth(ctx, indexExpr);
     }
     if (matchesConstantValue(index, 1))
         return buildSelectFirst(ctx, indexExpr, CREATE_DEAULT_ROW_IF_NULL_VALUE);
@@ -607,7 +613,7 @@ BoundRow * InlineLinkedDatasetCursor::buildIterateLoop(BuildCtx & ctx, bool need
     return cursor;
 }
 
-BoundRow * InlineLinkedDatasetCursor::buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr)
+BoundRow * InlineLinkedDatasetCursor::buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr)
 {
     OwnedHqlExpr index = foldHqlExpression(indexExpr->queryChild(1));
 
@@ -697,7 +703,7 @@ InlineLinkedDictionaryCursor::InlineLinkedDictionaryCursor(HqlCppTranslator & _t
 {
 }
 
-BoundRow * InlineLinkedDictionaryCursor::buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr)
+BoundRow * InlineLinkedDictionaryCursor::buildSelectMap(BuildCtx & ctx, IHqlExpression * indexExpr)
 {
     OwnedHqlExpr index = foldHqlExpression(indexExpr->queryChild(1));
 
@@ -748,7 +754,7 @@ BoundRow * MultiLevelDatasetCursor::buildIterateLoop(BuildCtx & ctx, bool needTo
     return doBuildIterateLoop(ctx, ds, breakVar, true);
 }
 
-BoundRow * MultiLevelDatasetCursor::buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr)
+BoundRow * MultiLevelDatasetCursor::buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr)
 {
     //Declare row for final level, iterate the appropriate number of times, and then assign and break.
     BuildCtx initctx(ctx);
@@ -1118,7 +1124,7 @@ void GeneralSetCursor::buildExprSelect(BuildCtx & ctx, IHqlExpression * indexExp
             checkNotAll(ctx);
 
         OwnedHqlExpr dsIndexExpr = createDatasetSelect(indexExpr);
-        BoundRow * cursor = dsCursor->buildSelect(ctx, dsIndexExpr);
+        BoundRow * cursor = dsCursor->buildSelectNth(ctx, dsIndexExpr);
         OwnedHqlExpr select = createSelectExpr(LINK(dsIndexExpr), LINK(element));
         translator.buildExpr(ctx, select, tgt);
     }
@@ -1136,7 +1142,7 @@ void GeneralSetCursor::buildAssignSelect(BuildCtx & ctx, const CHqlBoundTarget &
         checkNotAll(ctx);
 
     OwnedHqlExpr dsIndexExpr = createDatasetSelect(indexExpr);
-    BoundRow * cursor = dsCursor->buildSelect(ctx, dsIndexExpr);
+    BoundRow * cursor = dsCursor->buildSelectNth(ctx, dsIndexExpr);
 
     if (cursor)
     {
@@ -1389,6 +1395,12 @@ BoundRow * DatasetBuilderBase::buildDeserializeRow(BuildCtx & ctx, IHqlExpressio
 void DatasetBuilderBase::finishRow(BuildCtx & ctx, BoundRow * selfCursor)
 {
     OwnedHqlExpr size = createSizeof(selfCursor->querySelector());
+    doFinishRow(ctx, selfCursor, size);
+}
+
+
+void DatasetBuilderBase::doFinishRow(BuildCtx & ctx, BoundRow * selfCursor, IHqlExpression *size)
+{
     CHqlBoundExpr boundSize;
     translator.buildExpr(ctx, size, boundSize);
 
@@ -1399,7 +1411,6 @@ void DatasetBuilderBase::finishRow(BuildCtx & ctx, BoundRow * selfCursor)
     ctx.removeAssociation(selfCursor);
 }
 
-
 //---------------------------------------------------------------------------
 
 
@@ -1580,45 +1591,17 @@ void InlineDatasetBuilder::finishRow(BuildCtx & ctx, BoundRow * selfCursor)
 
 //---------------------------------------------------------------------------
 
-
-LinkedDatasetBuilder::LinkedDatasetBuilder(HqlCppTranslator & _translator, IHqlExpression * _record, IHqlExpression * _choosenLimit) : DatasetBuilderBase(_translator, _record, true)
+LinkedDatasetBuilderBase::LinkedDatasetBuilderBase(HqlCppTranslator & _translator, IHqlExpression * _record) : DatasetBuilderBase(_translator, _record, true)
 {
-    choosenLimit.set(_choosenLimit);
-}
-
-void LinkedDatasetBuilder::buildDeclare(BuildCtx & ctx)
-{
-    StringBuffer decl, allocatorName;
-
-    OwnedHqlExpr curActivityId = translator.getCurrentActivityId(ctx);
-    translator.ensureRowAllocator(allocatorName, ctx, record, curActivityId);
-
-    decl.append("RtlLinkedDatasetBuilder ").append(instanceName).append("(");
-    decl.append(allocatorName);
-    if (choosenLimit)
-    {
-        CHqlBoundExpr boundLimit;
-        translator.buildExpr(ctx, choosenLimit, boundLimit);
-        translator.generateExprCpp(decl.append(", "), boundLimit.expr);
-    }
-    decl.append(");");
-
-    ctx.addQuoted(decl);
 }
 
-void LinkedDatasetBuilder::finishRow(BuildCtx & ctx, BoundRow * selfCursor)
+void LinkedDatasetBuilderBase::finishRow(BuildCtx & ctx, BoundRow * selfCursor)
 {
     OwnedHqlExpr size = translator.getRecordSize(selfCursor->querySelector());
-    CHqlBoundExpr boundSize;
-    translator.buildExpr(ctx, size, boundSize);
-
-    StringBuffer s;
-    s.append(instanceName).append(".finalizeRow(");
-    translator.generateExprCpp(s, boundSize.expr).append(");");
-    ctx.addQuoted(s);
+    doFinishRow(ctx, selfCursor, size);
 }
 
-void LinkedDatasetBuilder::buildFinish(BuildCtx & ctx, const CHqlBoundTarget & target)
+void LinkedDatasetBuilderBase::buildFinish(BuildCtx & ctx, const CHqlBoundTarget & target)
 {
     //more: should I do this by really calling a function?
     StringBuffer s;
@@ -1643,7 +1626,7 @@ void LinkedDatasetBuilder::buildFinish(BuildCtx & ctx, const CHqlBoundTarget & t
 }
 
 
-void LinkedDatasetBuilder::buildFinish(BuildCtx & ctx, CHqlBoundExpr & bound)
+void LinkedDatasetBuilderBase::buildFinish(BuildCtx & ctx, CHqlBoundExpr & bound)
 {
     StringBuffer s;
     s.clear().append(instanceName).append(".getcount()");
@@ -1652,7 +1635,7 @@ void LinkedDatasetBuilder::buildFinish(BuildCtx & ctx, CHqlBoundExpr & bound)
     bound.expr.setown(createQuoted(s.str(), makeReferenceModifier(dataset->getType())));
 }
 
-bool LinkedDatasetBuilder::buildLinkRow(BuildCtx & ctx, BoundRow * sourceRow)
+bool LinkedDatasetBuilderBase::buildLinkRow(BuildCtx & ctx, BoundRow * sourceRow)
 {
     IHqlExpression * sourceRecord = sourceRow->queryRecord();
     if (recordTypesMatch(sourceRecord, record) && sourceRow->isBinary())
@@ -1689,7 +1672,7 @@ bool LinkedDatasetBuilder::buildLinkRow(BuildCtx & ctx, BoundRow * sourceRow)
     return false;
 }
 
-bool LinkedDatasetBuilder::buildAppendRows(BuildCtx & ctx, IHqlExpression * expr) 
+bool LinkedDatasetBuilderBase::buildAppendRows(BuildCtx & ctx, IHqlExpression * expr)
 {
     IHqlExpression * sourceRecord = expr->queryRecord();
     if (recordTypesMatch(sourceRecord, record))
@@ -1736,160 +1719,52 @@ bool LinkedDatasetBuilder::buildAppendRows(BuildCtx & ctx, IHqlExpression * expr
     return false;
 }
 
-
-//---------------------------------------------------------------------------
-
-
-LinkedDictionaryBuilder::LinkedDictionaryBuilder(HqlCppTranslator & _translator, IHqlExpression * _record) : DatasetBuilderBase(_translator, _record, true)
+LinkedDatasetBuilder::LinkedDatasetBuilder(HqlCppTranslator & _translator, IHqlExpression * _record, IHqlExpression * _choosenLimit) : LinkedDatasetBuilderBase(_translator, _record)
 {
+    choosenLimit.set(_choosenLimit);
 }
 
-void LinkedDictionaryBuilder::buildDeclare(BuildCtx & ctx)
+void LinkedDatasetBuilder::buildDeclare(BuildCtx & ctx)
 {
     StringBuffer decl, allocatorName;
 
     OwnedHqlExpr curActivityId = translator.getCurrentActivityId(ctx);
     translator.ensureRowAllocator(allocatorName, ctx, record, curActivityId);
 
-    StringBuffer lookupHelperName;
-    OwnedHqlExpr dict = createDictionary(no_null, record.getLink()); // MORE - is the actual dict not available?
-    translator.buildDictionaryHashClass(ctx, record, dict, lookupHelperName);
-
-    decl.append("RtlLinkedDictionaryBuilder ").append(instanceName).append("(");
-    decl.append(allocatorName).append(", &").append(lookupHelperName);
+    decl.append("RtlLinkedDatasetBuilder ").append(instanceName).append("(");
+    decl.append(allocatorName);
+    if (choosenLimit)
+    {
+        CHqlBoundExpr boundLimit;
+        translator.buildExpr(ctx, choosenLimit, boundLimit);
+        translator.generateExprCpp(decl.append(", "), boundLimit.expr);
+    }
     decl.append(");");
 
     ctx.addQuoted(decl);
 }
 
-void LinkedDictionaryBuilder::finishRow(BuildCtx & ctx, BoundRow * selfCursor)
-{
-    OwnedHqlExpr size = translator.getRecordSize(selfCursor->querySelector());
-    CHqlBoundExpr boundSize;
-    translator.buildExpr(ctx, size, boundSize);
 
-    StringBuffer s;
-    s.append(instanceName).append(".finalizeRow(");
-    translator.generateExprCpp(s, boundSize.expr).append(");");
-    ctx.addQuoted(s);
-}
-
-void LinkedDictionaryBuilder::buildFinish(BuildCtx & ctx, const CHqlBoundTarget & target)
+LinkedDictionaryBuilder::LinkedDictionaryBuilder(HqlCppTranslator & _translator, IHqlExpression * _record) : LinkedDatasetBuilderBase(_translator, _record)
 {
-    //more: should I do this by really calling a function?
-    StringBuffer s;
-
-    s.append(instanceName).append(".getcount()");
-
-    if (hasWrapperModifier(target.queryType()))
-    {
-        translator.generateExprCpp(s.clear(), target.expr);
-        s.append(".setown(").append(instanceName).append(".getcount()");
-        s.append(",").append(instanceName).append(".linkrows());");
-        ctx.addQuoted(s);
-    }
-    else
-    {
-        OwnedHqlExpr countExpr = createQuoted(s.str(), LINK(unsignedType));
-        ctx.addAssign(target.count, countExpr);
-        s.clear().append(instanceName).append(".linkrows()");
-        OwnedHqlExpr rowsExpr = createQuoted(s.str(), dataset->getType());
-        ctx.addAssign(target.expr, rowsExpr);
-    }
 }
 
-
-void LinkedDictionaryBuilder::buildFinish(BuildCtx & ctx, CHqlBoundExpr & bound)
-{
-    StringBuffer s;
-    s.clear().append(instanceName).append(".getcount()");
-    bound.count.setown(createQuoted(s.str(), LINK(unsignedType)));
-    s.clear().append(instanceName).append(".queryrows()");
-    bound.expr.setown(createQuoted(s.str(), makeReferenceModifier(dataset->getType())));
-}
-
-bool LinkedDictionaryBuilder::buildLinkRow(BuildCtx & ctx, BoundRow * sourceRow)
+void LinkedDictionaryBuilder::buildDeclare(BuildCtx & ctx)
 {
-    IHqlExpression * sourceRecord = sourceRow->queryRecord();
-    if (recordTypesMatch(sourceRecord, record) && sourceRow->isBinary())
-    {
-        OwnedHqlExpr source = getPointer(sourceRow->queryBound());
-        BuildCtx subctx(ctx);
-        if (sourceRow->isConditional())
-            subctx.addFilter(source);
-
-        if (sourceRow->isLinkCounted())
-        {
-            StringBuffer s;
-            s.append(instanceName).append(".append(");
-            translator.generateExprCpp(s, source);
-            s.append(");");
-            subctx.addQuoted(s);
-            return true;
-        }
-
-        IHqlExpression * sourceExpr = sourceRow->querySelector();
-        OwnedHqlExpr rowExpr = sourceExpr->isDataset() ? ensureActiveRow(sourceExpr) : LINK(sourceExpr);
-        OwnedHqlExpr size = createSizeof(rowExpr);
-        CHqlBoundExpr boundSize;
-        translator.buildExpr(ctx, size, boundSize);
+    StringBuffer decl, allocatorName;
 
-        StringBuffer s;
-        s.append(instanceName).append(".cloneRow(");
-        translator.generateExprCpp(s, boundSize.expr).append(",");
-        translator.generateExprCpp(s, source);
-        s.append(");");
-        subctx.addQuoted(s);
-        return true;
-    }
-    return false;
-}
+    OwnedHqlExpr curActivityId = translator.getCurrentActivityId(ctx);
+    translator.ensureRowAllocator(allocatorName, ctx, record, curActivityId);
 
-bool LinkedDictionaryBuilder::buildAppendRows(BuildCtx & ctx, IHqlExpression * expr)
-{
-    IHqlExpression * sourceRecord = expr->queryRecord();
-    if (recordTypesMatch(sourceRecord, record))
-    {
-        CHqlBoundExpr bound;
-        if (!ctx.getMatchExpr(expr, bound))
-        {
-            bool tryToOptimize = false;
-            switch (expr->getOperator())
-            {
-            case no_select:
-                if (isMultiLevelDatasetSelector(expr, false))
-                    break;
-                if (!hasLinkedRow(expr->queryType()))
-                    break;
-                tryToOptimize = true;
-                break;
-            default:
-                //Don't speculatively evaluate if the expression isn't pure
-                tryToOptimize = alwaysEvaluatesToBound(expr) && expr->isPure();
-                break;
-            }
+    StringBuffer lookupHelperName;
+    OwnedHqlExpr dict = createDictionary(no_null, record.getLink()); // MORE - is the actual dict not available?
+    translator.buildDictionaryHashClass(ctx, record, dict, lookupHelperName);
 
-            if (tryToOptimize)
-                translator.buildDataset(ctx, expr, bound, FormatNatural);
-        }
+    decl.append("RtlLinkedDictionaryBuilder ").append(instanceName).append("(");
+    decl.append(allocatorName).append(", &").append(lookupHelperName);
+    decl.append(");");
 
-        if (bound.expr)
-        {
-            if (hasLinkedRow(bound.queryType()))
-            {
-                OwnedHqlExpr source = getPointer(bound.expr);
-                StringBuffer s;
-                s.append(instanceName).append(".appendRows(");
-                translator.generateExprCpp(s, bound.count);
-                s.append(",");
-                translator.generateExprCpp(s, source);
-                s.append(");");
-                ctx.addQuoted(s);
-                return true;
-            }
-        }
-    }
-    return false;
+    ctx.addQuoted(decl);
 }
 
 

+ 20 - 15
ecl/hqlcpp/hqlcset.ipp

@@ -26,7 +26,8 @@ public:
 
     virtual BoundRow * buildIterateLoop(BuildCtx & ctx, bool needToBreak);
     virtual void buildIterateClass(BuildCtx & ctx, SharedHqlExpr & iter, SharedHqlExpr & row);
-    virtual BoundRow * buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr);
+    virtual BoundRow * buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr);
+    virtual BoundRow * buildSelectMap(BuildCtx & ctx, IHqlExpression * indexExpr);
     virtual void buildIterateMembers(BuildCtx & declarectx, BuildCtx & initctx);
 
 protected:
@@ -58,7 +59,7 @@ public:
     InlineBlockDatasetCursor(HqlCppTranslator & _translator, IHqlExpression * _ds, CHqlBoundExpr & _boundDs);
 
     virtual BoundRow * buildIterateLoop(BuildCtx & ctx, bool needToBreak);
-    virtual BoundRow * buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr);
+    virtual BoundRow * buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr);
 
 protected:
     BoundRow * buildSelectFirst(BuildCtx & ctx, IHqlExpression * indexExpr, bool createDefaultRowIfNull);
@@ -72,7 +73,7 @@ public:
     virtual void buildCount(BuildCtx & ctx, CHqlBoundExpr & tgt);
     virtual void buildExists(BuildCtx & ctx, CHqlBoundExpr & tgt);
     virtual BoundRow * buildIterateLoop(BuildCtx & ctx, bool needToBreak);
-    virtual BoundRow * buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr);
+    virtual BoundRow * buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr);
     virtual void buildIterateClass(BuildCtx & ctx, StringBuffer & cursorName, BuildCtx * initctx);
 };
 
@@ -82,7 +83,7 @@ public:
     InlineLinkedDictionaryCursor(HqlCppTranslator & _translator, IHqlExpression * _ds, CHqlBoundExpr & _boundDs);
 
     virtual BoundRow * buildIterateLoop(BuildCtx & ctx, bool needToBreak) { throwUnexpected(); }
-    virtual BoundRow * buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr);
+    virtual BoundRow * buildSelectMap(BuildCtx & ctx, IHqlExpression * indexExpr);
     virtual void buildIterateClass(BuildCtx & ctx, StringBuffer & cursorName, BuildCtx * initctx) { throwUnexpected(); }
 };
 
@@ -94,7 +95,7 @@ public:
     virtual void buildCount(BuildCtx & ctx, CHqlBoundExpr & tgt);
     virtual void buildExists(BuildCtx & ctx, CHqlBoundExpr & tgt);
     virtual BoundRow * buildIterateLoop(BuildCtx & ctx, bool needToBreak);
-    virtual BoundRow * buildSelect(BuildCtx & ctx, IHqlExpression * indexExpr);
+    virtual BoundRow * buildSelectNth(BuildCtx & ctx, IHqlExpression * indexExpr);
     virtual void buildIterateClass(BuildCtx & ctx, StringBuffer & cursorName, BuildCtx * initctx) { UNIMPLEMENTED; }
 
 protected:
@@ -226,6 +227,8 @@ public:
     virtual void finishRow(BuildCtx & ctx, BoundRow * selfCursor);
 
 protected:
+    void doFinishRow(BuildCtx & ctx, BoundRow * selfCursor, IHqlExpression *size);
+
     StringBuffer instanceName;
     StringBuffer builderName;
     OwnedHqlExpr dataset;
@@ -268,34 +271,36 @@ protected:
     Owned<BoundRow> cursor;
 };
 
-class LinkedDatasetBuilder : public DatasetBuilderBase
+class LinkedDatasetBuilderBase : public DatasetBuilderBase
 {
 public:
-    LinkedDatasetBuilder(HqlCppTranslator & _translator, IHqlExpression * _record, IHqlExpression * _choosenLimit);
+    LinkedDatasetBuilderBase(HqlCppTranslator & _translator, IHqlExpression * _record);
 
-    virtual void buildDeclare(BuildCtx & ctx);
     virtual void buildFinish(BuildCtx & ctx, const CHqlBoundTarget & target);
     virtual void buildFinish(BuildCtx & ctx, CHqlBoundExpr & bound);
     virtual bool buildLinkRow(BuildCtx & ctx, BoundRow * sourceRow);
     virtual bool buildAppendRows(BuildCtx & ctx, IHqlExpression * expr);
     virtual void finishRow(BuildCtx & ctx, BoundRow * selfCursor);
-    virtual bool isRestricted()                             { return choosenLimit != NULL; }
+};
+
+class LinkedDatasetBuilder : public LinkedDatasetBuilderBase
+{
+public:
+    LinkedDatasetBuilder(HqlCppTranslator & _translator, IHqlExpression * _record, IHqlExpression * _choosenLimit);
+
+    virtual void buildDeclare(BuildCtx & ctx);
+    virtual bool isRestricted() { return choosenLimit != NULL; }
 
 protected:
     LinkedHqlExpr choosenLimit;
 };
 
-class LinkedDictionaryBuilder : public DatasetBuilderBase
+class LinkedDictionaryBuilder : public LinkedDatasetBuilderBase
 {
 public:
     LinkedDictionaryBuilder(HqlCppTranslator & _translator, IHqlExpression * _record);
 
     virtual void buildDeclare(BuildCtx & ctx);
-    virtual void buildFinish(BuildCtx & ctx, const CHqlBoundTarget & target);
-    virtual void buildFinish(BuildCtx & ctx, CHqlBoundExpr & bound);
-    virtual bool buildLinkRow(BuildCtx & ctx, BoundRow * sourceRow);
-    virtual bool buildAppendRows(BuildCtx & ctx, IHqlExpression * expr);
-    virtual void finishRow(BuildCtx & ctx, BoundRow * selfCursor);
 };
 
 //---------------------------------------------------------------------------

+ 3 - 2
ecl/hqlcpp/hqliproj.cpp

@@ -1971,8 +1971,9 @@ ProjectExprKind ImplicitProjectTransformer::getProjectExprKind(IHqlExpression *
         return CreateRecordActivity;
     case no_inlinetable:
     case no_dataset_from_transform:
-    case no_inlinedictionary:
         return CreateRecordSourceActivity;
+    case no_inlinedictionary:
+        return SourceActivity;
     case no_extractresult:
     case no_apply:
         return SinkActivity;
@@ -2771,7 +2772,7 @@ IHqlExpression * ImplicitProjectTransformer::createTransformed(IHqlExpression *
         }
     case CreateRecordSourceActivity:
         {
-            assertex(expr->getOperator() == no_inlinetable || expr->getOperator() == no_dataset_from_transform || expr->getOperator() == no_inlinedictionary);
+            assertex(expr->getOperator() == no_inlinetable || expr->getOperator() == no_dataset_from_transform);
             //Always reduce things that create a new record so they only project the fields they need to
             if (complexExtra->outputChanged())
             {

+ 2 - 2
rtl/eclrtl/rtlds.cpp

@@ -631,8 +631,8 @@ void RtlLinkedDictionaryBuilder::checkSpace()
         // Rehash
         byte * * oldTable = table;
         unsigned oldSize = tableSize;
-        tableSize = tableSize*2;
-        table = rowAllocator->createRowset(tableSize);
+        table = rowAllocator->createRowset(tableSize*2);
+        tableSize = tableSize*2; // Don't update until we have successfully allocated, so that we remain consistent if createRowset throws an exception.
         memset(table, 0, tableSize * sizeof(byte *));
         usedLimit = (tableSize * 3) / 4;
         usedCount = 0;