/*##############################################################################
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 .
############################################################################## */
#ifndef __HQLTTCPP_IPP_
#define __HQLTTCPP_IPP_
#include "hqlcpp.hpp"
#include "hqlcpp.ipp"
#include "hqlhtcpp.ipp"
#include "hqltrans.ipp"
//---------------------------------------------------------------------------
class NewThorStoredReplacer : public QuickHqlTransformer
{
public:
NewThorStoredReplacer(HqlCppTranslator & _translator, IWorkUnit * _wu, ICodegenContextCallback * _logger);
virtual void doAnalyseBody(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
bool needToTransform();
protected:
HqlCppTranslator & translator;
IWorkUnit * wu;
ICodegenContextCallback * ctxCallback;
HqlExprArray commands;
HqlExprArray storedNames;
HqlExprArray storedValues;
HqlExprCopyArray activeReplacements;
BoolArray storedIsConstant;
bool foldStored;
bool seenMeta;
};
//---------------------------------------------------------------------------
enum YesNoOption { OptionUnknown, OptionNo, OptionMaybe, OptionSome, OptionYes }; //NB: last 3 IN ascending order of definiteness.
class HqlThorBoundaryInfo : public NewTransformInfo
{
public:
HqlThorBoundaryInfo(IHqlExpression * _original) : NewTransformInfo(_original) { normalize = OptionUnknown; }
public:
YesNoOption normalize;
};
class HqlThorBoundaryTransformer : public NewHqlTransformer
{
public:
HqlThorBoundaryTransformer(IConstWorkUnit * wu, bool _isRoxie, unsigned _maxRootMaybes, bool _resourceConditionalActions, bool _resourceSequential);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(HqlThorBoundaryInfo, expr); }
inline HqlThorBoundaryInfo * queryBodyExtra(IHqlExpression * expr) { return static_cast(queryTransformExtra(expr->queryBody())); }
void transformRoot(const HqlExprArray & in, HqlExprArray & out);
protected:
void transformCompound(HqlExprArray & result, node_operator compoundOp, const HqlExprArray & args, unsigned MaxMaybes);
protected:
YesNoOption calcNormalizeThor(IHqlExpression * expr);
YesNoOption normalizeThor(IHqlExpression * expr);
protected:
IConstWorkUnit * wu;
unsigned maxRootMaybes;
bool isRoxie;
bool resourceConditionalActions;
bool resourceSequential;
};
//---------------------------------------------------------------------------
class ThorScalarInfo : public HoistingTransformInfo
{
public:
ThorScalarInfo(IHqlExpression * _original) : HoistingTransformInfo(_original) { }
public:
HqlExprAttr transformed[2];
HqlExprAttr transformedSelector[2];
};
class ThorScalarTransformer : public HoistingHqlTransformer
{
public:
ThorScalarTransformer(const HqlCppOptions & _options);
virtual void doAnalyseExpr(IHqlExpression * expr);
IHqlExpression * createTransformed(IHqlExpression * expr);
inline bool needToTransform() { return seenCandidate || containsUnknownIndependentContents; }
protected:
void createHoisted(IHqlExpression * expr, SharedHqlExpr & setResultStmt, SharedHqlExpr & getResult, bool addWrapper);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(ThorScalarInfo, expr); }
virtual IHqlExpression * queryAlreadyTransformed(IHqlExpression * expr);
virtual IHqlExpression * queryAlreadyTransformedSelector(IHqlExpression * expr);
virtual void setTransformed(IHqlExpression * expr, IHqlExpression * transformed);
virtual void setTransformedSelector(IHqlExpression * expr, IHqlExpression * transformed);
virtual IHqlExpression * doTransformIndependent(IHqlExpression * expr)
{
ThorScalarTransformer nested(options);
nested.setParent(this);
nested.analyse(expr, 0);
if (nested.needToTransform())
return nested.transformRoot(expr);
return LINK(expr);
}
//This is unusual that it is queryExtra() instead of queryBodyExtra() - since it is used to store the transformed
//values, not any extra information.
inline ThorScalarInfo * queryExtra(IHqlExpression * expr) { return static_cast(queryTransformExtra(expr)); }
inline bool isConditional() { return isConditionalDepth != 0; }
protected:
const HqlCppOptions & options;
unsigned isConditionalDepth;
bool seenCandidate;
};
//---------------------------------------------------------------------------
class SequenceNumberInfo : public NewTransformInfo
{
public:
SequenceNumberInfo(IHqlExpression * expr) : NewTransformInfo(expr), getsSequence(false) {}
void setGetsSequence() { getsSequence = true; }
virtual IHqlExpression * queryTransformed() { if(getsSequence) return NULL; else return NewTransformInfo::queryTransformed(); } //must transform again if expression takes sequence number, as require different sequence number each time
private:
bool getsSequence;
};
class SequenceNumberAllocator : public NewHqlTransformer
{
public:
SequenceNumberAllocator();
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(SequenceNumberInfo, expr); }
//queryExtra() instead of queryBodyExtra() because it is used to modify how queryTransform() acts.
//NOTE: I'm not sure this really works e.g., if the transformed expression is a sequence list.
SequenceNumberInfo * queryExtra(IHqlExpression * expr) { return dynamic_cast(queryTransformExtra(expr)); }
unsigned getMaxSequence() { return sequence; }
protected:
void nextSequence(HqlExprArray & args, IHqlExpression * name, _ATOM overwriteAction, IHqlExpression * value, bool needAttr, bool * duplicate);
virtual IHqlExpression * doTransformRootExpr(IHqlExpression * expr);
IHqlExpression * attachSequenceNumber(IHqlExpression * expr);
protected:
unsigned sequence;
MapOwnedHqlToOwnedHql namedMap;
};
//---------------------------------------------------------------------------
class ThorHqlTransformer : public NewHqlTransformer
{
public:
ThorHqlTransformer(HqlCppTranslator & _translator, ClusterType _targetClusterType, IConstWorkUnit * _wu);
protected:
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
protected:
IHqlExpression * getMergeTransform(IHqlExpression * dataset, IHqlExpression * transform);
IHqlExpression * normalizeChooseN(IHqlExpression * expr);
IHqlExpression * normalizeCoGroup(IHqlExpression * expr);
IHqlExpression * normalizeDedup(IHqlExpression * expr);
// IHqlExpression * normalizeIndexBuild(IHqlExpression * expr);
IHqlExpression * normalizeGroup(IHqlExpression * expr);
IHqlExpression * normalizeJoinOrDenormalize(IHqlExpression * expr);
IHqlExpression * normalizeTableToAggregate(IHqlExpression * expr, bool canOptimizeCasts);
IHqlExpression * normalizeTableGrouping(IHqlExpression * expr);
IHqlExpression * normalizeMergeAggregate(IHqlExpression * expr);
IHqlExpression * normalizePrefetchAggregate(IHqlExpression * expr);
IHqlExpression * normalizeRollup(IHqlExpression * expr);
IHqlExpression * normalizeScalarAggregate(IHqlExpression * expr);
IHqlExpression * normalizeSelect(IHqlExpression * expr);
IHqlExpression * normalizeShuffle(IHqlExpression * expr);
IHqlExpression * normalizeSort(IHqlExpression * expr);
IHqlExpression * normalizeSortSteppedIndex(IHqlExpression * expr, _ATOM attrName);
IHqlExpression * normalizeTempTable(IHqlExpression * expr);
IHqlExpression * skipGroupsWithinGroup(IHqlExpression * expr, bool isLocal);
IHqlExpression * skipOverGroups(IHqlExpression * dataset, bool isLocal);
protected:
typedef NewHqlTransformer PARENT;
HqlCppTranslator & translator;
const HqlCppOptions & options;
ClusterType targetClusterType;
unsigned topNlimit;
bool groupAllDistribute;
};
//---------------------------------------------------------------------------
class CompoundSourceInfo : public NewTransformInfo
{
public:
CompoundSourceInfo(IHqlExpression * _original);
bool canMergeLimit(IHqlExpression * expr, ClusterType targetClusterType) const;
void ensureCompound();
bool isAggregate() const;
inline bool isShared() { return splitCount > 1; }
bool inherit(const CompoundSourceInfo & other, node_operator newSourceOp = no_none);
inline bool isNoteUsageFirst()
{
noteUsage();
return (splitCount == 1);
}
inline void noteUsage() { if (splitCount < 10) splitCount++; }
inline bool isBinary() const { return mode != no_csv && mode != no_xml; }
inline bool hasAnyLimit() const { return isLimited || hasChoosen; }
void reset();
public:
HqlExprAttr uid;
node_operator sourceOp;
node_operator mode;
byte splitCount;
bool forceCompound:1;
bool isBoundary:1;
bool isCloned:1;
bool isLimited:1;
bool hasChoosen:1;
bool hasSkipLimit:1;
bool isPreloaded:1;
bool isFiltered:1;
bool isPostFiltered:1;
bool isCreateRowLimited:1;
};
enum
{
CSFpreload = 0x0001,
CSFindex = 0x0002,
CSFignoreShared = 0x0010,
CSFnewdisk = 0x0020,
CSFnewindex = 0x0040,
CSFnewchild = 0x0080,
CSFnewinline = 0x0100,
CSFcompoundSpill= 0x0200,
};
//MORE: Could remove dependency on insideCompound if it was ok to have compound operators scattered through the
// contents of a compound item. Probably would cause few problems, and would make life simpler
class CompoundSourceTransformer : public NewHqlTransformer
{
public:
CompoundSourceTransformer(HqlCppTranslator & _translator, unsigned _flags);
IHqlExpression * process(IHqlExpression * expr);
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr);
protected:
bool childrenAreShared(IHqlExpression * expr);
bool createCompoundSource(IHqlExpression * expr);
CompoundSourceInfo * queryBodyExtra(IHqlExpression * expr) { return (CompoundSourceInfo *)queryTransformExtra(expr->queryBody()); }
void analyseGatherInfo(IHqlExpression * expr);
void analyseMarkBoundaries(IHqlExpression * expr);
bool needToCloneLimit(IHqlExpression * expr, node_operator sourceOp);
protected:
HqlCppTranslator & translator;
ClusterType targetClusterType;
unsigned flags;
bool insideCompound;
bool candidate;
};
//---------------------------------------------------------------------------
class CompoundActivityTransformer : public NewHqlTransformer
{
public:
CompoundActivityTransformer(ClusterType _targetClusterType);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
protected:
ClusterType targetClusterType;
};
//---------------------------------------------------------------------------
class OptimizeActivityInfo : public NewTransformInfo
{
public:
OptimizeActivityInfo(IHqlExpression * _original) : NewTransformInfo(_original) { setNumUses(0); }
inline bool isShared() { return getNumUses() > 1; }
inline void noteUsed() { setNumUses(getNumUses()+1); }
inline void inherit(const OptimizeActivityInfo * other)
{
setNumUses(getNumUses() + other->getNumUses());
}
private:
inline byte getNumUses() const { return spareByte1; }
inline void setNumUses(unsigned value) { spareByte1 = value < 100 ? value : 100; }
using NewTransformInfo::spareByte1; // used to hold a numUses()
};
//Various activity optimizations which can be done if nodes aren't shared
//sort(ds,x)[n] -> topn(ds,x,n)[n]
//count(x) > n -> count(choosen(x,n+1)) > n
class OptimizeActivityTransformer : public NewHqlTransformer
{
public:
OptimizeActivityTransformer(bool _optimizeCountCompare, bool _optimizeNonEmpty);
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
protected:
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(OptimizeActivityInfo, expr); }
IHqlExpression * doCreateTransformed(IHqlExpression * expr);
IHqlExpression * insertChoosen(IHqlExpression * lhs, IHqlExpression * limit, __int64 limitDelta);
IHqlExpression * optimizeCompare(IHqlExpression * lhs, IHqlExpression * rhs, node_operator op);
OptimizeActivityInfo * queryBodyExtra(IHqlExpression * expr) { return (OptimizeActivityInfo *)queryTransformExtra(expr->queryBody()); }
inline bool isShared(IHqlExpression * expr) { return queryBodyExtra(expr)->isShared(); }
protected:
bool optimizeCountCompare;
bool optimizeNonEmpty;
};
//---------------------------------------------------------------------------
class WorkflowTransformInfo : public NewTransformInfo
{
public:
WorkflowTransformInfo(IHqlExpression * expr) : NewTransformInfo(expr) { wfid = 0; lastWfid = 0; manyWorkflow = false; firstUseIsConditional = false; }
UnsignedArray const & queryDependencies() const { return dependencies; }
void addDependency(unsigned dep)
{
if (dependencies.find(dep) == NotFound)
dependencies.append(dep);
}
inline bool isCommonUpCandidate() { return manyWorkflow && !firstUseIsConditional; }
inline bool noteWorkflow(unsigned wfid, bool isConditional)
{
if (lastWfid)
{
if (wfid != lastWfid)
{
manyWorkflow = true;
lastWfid = wfid;
}
return true;
}
lastWfid = wfid;
firstUseIsConditional = isConditional;
return false;
}
private:
UnsignedArray dependencies;
unsigned short wfid;
unsigned short lastWfid; // used during analysis
bool firstUseIsConditional;
bool manyWorkflow;
};
class ContingencyData
{
public:
ContingencyData() : success(0), failure(0), recovery(0), retries(0), contingencyFor(0) {}
unsigned success;
unsigned failure;
unsigned recovery;
unsigned retries;
unsigned contingencyFor;
};
class ScheduleData
{
public:
ScheduleData() : independent(false), now(true), priority(50), counting(false), count(0) {}
bool independent;
bool now;
StringBuffer eventName;
StringBuffer eventText;
int priority;
bool counting;
unsigned count;
};
class WorkflowTransformer : public NewHqlTransformer
{
public:
WorkflowTransformer(IWorkUnit * _wu, HqlCppTranslator & _translator);
void analyseAll(const HqlExprArray & in);
void transformRoot(const HqlExprArray & in, WorkflowArray & out);
protected:
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(WorkflowTransformInfo, expr); }
IWorkflowItem * addWorkflowToWorkunit(unsigned wfid, WFType type, WFMode mode, IHqlExpression * cluster)
{
UnsignedArray dependencies;
ContingencyData conts;
return addWorkflowToWorkunit(wfid, type, mode, dependencies, conts, cluster);
}
IWorkflowItem * addWorkflowToWorkunit(unsigned wfid, WFType type, WFMode mode, UnsignedArray const & dependencies, IHqlExpression * cluster)
{
ContingencyData conts;
return addWorkflowToWorkunit(wfid, type, mode, dependencies, conts, cluster);
}
IWorkflowItem * addWorkflowToWorkunit(unsigned wfid, WFType type, WFMode mode, UnsignedArray const & dependencies, ContingencyData const & conts, IHqlExpression * cluster);
IWorkflowItem * addWorkflowContingencyToWorkunit(unsigned wfid, WFType type, WFMode mode, UnsignedArray const & dependencies, IHqlExpression * cluster, unsigned wfidFor) { ContingencyData conts; conts.contingencyFor = wfidFor; return addWorkflowToWorkunit(wfid, type, mode, dependencies, conts, cluster); }
void setWorkflowPersist(IWorkflowItem * wf, char const * persistName, unsigned persistWfid);
void setWorkflowSchedule(IWorkflowItem * wf, ScheduleData const & sched);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
void inheritDependencies(IHqlExpression * expr);
void copyDependencies(WorkflowTransformInfo * source, WorkflowTransformInfo * dest);
void copySetValueDependencies(WorkflowTransformInfo * source, IHqlExpression * expr);
unsigned splitValue(IHqlExpression * value);
IHqlExpression * extractWorkflow(IHqlExpression * untransformed, IHqlExpression * transformed);
IHqlExpression * extractClusterWorkflow(IHqlExpression * expr);
IHqlExpression * extractCommonWorkflow(IHqlExpression * expr, IHqlExpression * transformed);
IHqlExpression * transformInternalCall(IHqlExpression * transformed);
IHqlExpression * transformInternalFunction(IHqlExpression * transformed);
IHqlExpression * createCompoundWorkflow(IHqlExpression * expr);
IHqlExpression * createIfWorkflow(IHqlExpression * expr);
IHqlExpression * createParallelWorkflow(IHqlExpression * expr);
IHqlExpression * createSequentialWorkflow(IHqlExpression * expr);
IHqlExpression * createWaitWorkflow(IHqlExpression * expr);
IHqlExpression * transformRootAction(IHqlExpression * expr);
IHqlExpression * transformSequentialEtc(IHqlExpression * expr);
IWorkflowItem * lookupWorkflowItem(unsigned wfid);
IHqlExpression * createWorkflowAction(unsigned wfid);
unsigned ensureWorkflowAction(IHqlExpression * expr);
void ensureWorkflowAction(UnsignedArray & dependencies, IHqlExpression * expr);
WorkflowItem * createWorkflowItem(IHqlExpression * expr, unsigned wfid, unsigned persistWfid = 0);
void percolateScheduledIds(WorkflowArray & workflow);
void cacheWorkflowDependencies(unsigned wfid, UnsignedArray & extra);
inline bool hasDependencies(IHqlExpression * expr) { return queryDirectDependencies(expr).ordinality() != 0; }
bool hasStoredDependencies(IHqlExpression * expr);
UnsignedArray const & queryDependencies(unsigned wfid);
UnsignedArray const & queryDirectDependencies(IHqlExpression * expr); // don't include children.
void gatherIndirectDependencies(UnsignedArray & match, IHqlExpression * expr);
inline WorkflowTransformInfo * queryBodyExtra(IHqlExpression * expr) { return static_cast(queryTransformExtra(expr->queryBody())); }
inline unsigned markDependencies() { return cumulativeDependencies.ordinality(); }
inline bool restoreDependencies(unsigned mark)
{
bool anyAdded = (mark == cumulativeDependencies.ordinality());
cumulativeDependencies.trunc(mark);
return anyAdded;
}
bool haveSameDependencies(IHqlExpression * expr1, IHqlExpression * expr2);
bool includesNewDependencies(IHqlExpression * prev, IHqlExpression * next);
bool hasNonTrivialDependencies(IHqlExpression * expr);
void transformSequential(HqlExprArray & transformed);
void analyseExpr(IHqlExpression * expr);
protected:
IWorkUnit * wu;
HqlCppTranslator & translator;
WorkflowArray * workflowOut;
unsigned wfidCount;
HqlExprArray alreadyProcessed;
HqlExprArray alreadyProcessedExpr;
HqlExprArray alreadyProcessedUntransformed;
HqlExprCopyArray activeLocations;
unsigned trivialStoredWfid;
unsigned onceWfid;
unsigned nextInternalFunctionId;
HqlExprArray trivialStoredExprs;
HqlExprArray onceExprs;
bool combineAllStored;
bool combineTrivialStored;
bool isRootAction;
bool isRoxie;
UnsignedArray cumulativeDependencies;
UnsignedArray emptyDependencies;
UnsignedArray storedWfids;
OwnedHqlExpr rootCluster; // currently unset, but if need to
//used while analysing..
unsigned activeWfid;
bool isConditional;
bool insideStored;
};
//------------------------------------------------------------------------
class ExplicitGlobalTransformer : public HoistingHqlTransformer
{
public:
ExplicitGlobalTransformer(IWorkUnit * _wu, HqlCppTranslator & _translator);
inline bool needToTransform() const { return seenGlobalScope || containsUnknownIndependentContents; }
protected:
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual void doAnalyseExpr(IHqlExpression * expr);
virtual IHqlExpression * doTransformIndependent(IHqlExpression * expr)
{
if (containsUnknownIndependentContents || seenLocalGlobalScope)
{
ExplicitGlobalTransformer nested(wu, translator);
nested.setParent(this);
nested.analyse(expr, 0);
if (nested.needToTransform())
return nested.transformRoot(expr);
}
return LINK(expr);
}
private:
IWorkUnit * wu;
HqlCppTranslator & translator;
bool seenGlobalScope;
bool seenLocalGlobalScope;
bool isRoxie;
};
class ScalarGlobalExtra : public HoistingTransformInfo
{
public:
ScalarGlobalExtra(IHqlExpression * _original) : HoistingTransformInfo(_original) { numUses = 0; alreadyGlobal = false; createGlobal = false; couldHoist = false; candidate = false; neverHoist = false; }
public:
unsigned numUses;
bool alreadyGlobal;
bool createGlobal;
bool couldHoist;
bool candidate;
bool neverHoist;
};
//Only does anything to scalar expressions => don't need a mergingTransformer
class ScalarGlobalTransformer : public HoistingHqlTransformer
{
public:
ScalarGlobalTransformer(HqlCppTranslator & _translator);
protected:
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(ScalarGlobalExtra, expr); }
virtual void doAnalyseExpr(IHqlExpression * expr);
bool isComplex(IHqlExpression * expr, bool checkGlobal);
virtual IHqlExpression * doTransformIndependent(IHqlExpression * expr)
{
ScalarGlobalTransformer nested(translator);
nested.setParent(this);
nested.analyse(expr, 0);
return nested.transformRoot(expr);
}
inline ScalarGlobalExtra * queryBodyExtra(IHqlExpression * expr) { return static_cast(queryTransformExtra(expr->queryBody())); }
protected:
HqlCppTranslator & translator;
bool okToHoist;
bool neverHoist;
};
class ScopeMigrateInfo : public HoistingTransformInfo
{
public:
ScopeMigrateInfo(IHqlExpression * _original) : HoistingTransformInfo(_original) { maxActivityDepth = 0; }//useCount = 0; condUseCount = 0; }
public:
unsigned maxActivityDepth;
// unsigned useCount;
// unsigned condUseCount;
};
class NewScopeMigrateTransformer : public HoistingHqlTransformer
{
public:
NewScopeMigrateTransformer(IWorkUnit * _wu, HqlCppTranslator & _translator);
protected:
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(ScopeMigrateInfo, expr); }
virtual IHqlExpression * doTransformIndependent(IHqlExpression * expr)
{
NewScopeMigrateTransformer nested(wu, translator);
nested.setParent(this);
nested.analyse(expr, 0);
return nested.transformRoot(expr);
}
IHqlExpression * hoist(IHqlExpression * expr, IHqlExpression * hoisted);
IHqlExpression * transformCond(IHqlExpression * expr);
inline unsigned extraIndex() { return activityDepth != 0 ? 0 : 1; }
inline ScopeMigrateInfo * queryBodyExtra(IHqlExpression * expr) { return static_cast(queryTransformExtra(expr->queryBody())); }
private:
IWorkUnit * wu;
HqlCppTranslator & translator;
bool isRoxie;
bool minimizeWorkunitTemporaries;
unsigned activityDepth;
};
class AutoScopeMigrateInfo : public NewTransformInfo
{
public:
AutoScopeMigrateInfo(IHqlExpression * _original) : NewTransformInfo(_original) { useCount = 0; condUseCount = 0; manyGraphs = false; firstUseIsConditional = false; firstUseIsSequential = false; globalInsideChild = false; lastGraph = 0; }
bool addGraph(unsigned graph);
bool doAutoHoist(IHqlExpression * transformed, bool minimizeWorkunitTemporaries);
public:
unsigned useCount;
unsigned condUseCount;
unsigned lastGraph;
bool manyGraphs;
bool firstUseIsConditional;
bool firstUseIsSequential;
bool globalInsideChild;
};
class AutoScopeMigrateTransformer : public NewHqlTransformer
{
public:
AutoScopeMigrateTransformer(IWorkUnit * _wu, HqlCppTranslator & _translator);
void transformRoot(const HqlExprArray & in, HqlExprArray & out);
bool worthTransforming() const { return hasCandidate; }
protected:
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(AutoScopeMigrateInfo, expr); }
IHqlExpression * hoist(IHqlExpression * expr, IHqlExpression * hoisted);
IHqlExpression * transformCond(IHqlExpression * expr);
void doAnalyseExpr(IHqlExpression * expr);
inline AutoScopeMigrateInfo * queryBodyExtra(IHqlExpression * expr) { return static_cast(queryTransformExtra(expr->queryBody())); }
private:
IWorkUnit * wu;
HqlCppTranslator & translator;
bool isRoxie;
bool isConditional;
bool hasCandidate;
bool isSequential;
unsigned curGraph;
unsigned nextGraph;
HqlExprArray graphActions;
unsigned activityDepth;
HqlExprArray * globalTarget;
};
//---------------------------------------------------------------------------
class TrivialGraphRemover : public NewHqlTransformer
{
public:
TrivialGraphRemover();
bool worthTransforming() const { return hasCandidate; }
protected:
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
bool isTrivialGraph(IHqlExpression * expr);
private:
bool hasCandidate;
};
//---------------------------------------------------------------------------
class ThorCountTransformer : public NewHqlTransformer
{
public:
ThorCountTransformer(HqlCppTranslator & _translator, bool _countDiskFuncOk);
IHqlExpression * createTransformed(IHqlExpression * expr);
protected:
HqlCppTranslator & translator;
bool countDiskFuncOk;
};
//---------------------------------------------------------------------------
class FilteredIndexOptimizer : public NewHqlTransformer
{
public:
FilteredIndexOptimizer(bool _processJoins, bool _processReads);
protected:
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
protected:
bool processJoins;
bool processReads;
};
//---------------------------------------------------------------------------
class LocalUploadTransformer : public NewHqlTransformer
{
public:
LocalUploadTransformer(IWorkUnit * _wu);
protected:
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
protected:
IWorkUnit * wu;
};
//---------------------------------------------------------------------------
class NestedSelectorInfo : public NewTransformInfo
{
public:
NestedSelectorInfo(IHqlExpression * _original) : NewTransformInfo(_original) { isDenormalized = false; insertDenormalize = false; }
public:
bool isDenormalized;
bool insertDenormalize;
};
class NestedSelectorNormalizer : public NewHqlTransformer
{
public:
NestedSelectorNormalizer();
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
inline bool requiresTransforming() { return spottedCandidate; }
protected:
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr) { return CREATE_NEWTRANSFORMINFO(NestedSelectorInfo, expr); }
IHqlExpression * createNormalized(IHqlExpression * expr);
NestedSelectorInfo * queryBodyExtra(IHqlExpression * expr) { return (NestedSelectorInfo *)queryTransformExtra(expr->queryBody()); }
protected:
bool spottedCandidate;
};
//---------------------------------------------------------------------------
class LeftRightSelectorNormalizer : public NewHqlTransformer
{
public:
LeftRightSelectorNormalizer(bool _allowAmbiguity);
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual IHqlExpression * createTransformedSelector(IHqlExpression * expr);
inline bool containsAmbiguity() { return isAmbiguous; }
protected:
void checkAmbiguity(const HqlExprCopyArray & inScope, IHqlExpression * selector);
protected:
bool allowAmbiguity;
bool isAmbiguous;
};
//---------------------------------------------------------------------------
class SharedTableInfo : public CInterface
{
public:
SharedTableInfo(IHqlExpression * _dataset, unsigned _depth) : dataset(_dataset), depth(_depth) {}
IHqlExpression * dataset;
unsigned depth;
OwnedHqlExpr uid; // if (depth > 0)
};
class ImplicitAliasTransformInfo : public NewTransformInfo
{
public:
ImplicitAliasTransformInfo(IHqlExpression * _expr) : NewTransformInfo(_expr) { containsAmbiguity = false; }
void add(SharedTableInfo * table);
void addAmbiguity(SharedTableInfo * table);
void inherit(const ImplicitAliasTransformInfo * other);
void merge(SharedTableInfo * table);
SharedTableInfo * uses(IHqlExpression * tableBody) const;
public:
CIArrayOf sharedTables;
Owned shared;
bool containsAmbiguity;
};
class ImplicitAliasTransformer : public NewHqlTransformer
{
public:
ImplicitAliasTransformer();
void process(HqlExprArray & exprs);
inline bool hasAmbiguity() const { return seenAmbiguity; }
protected:
virtual void analyseExpr(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
inline ImplicitAliasTransformInfo * queryExtra(IHqlExpression * expr) { return (ImplicitAliasTransformInfo *)queryTransformExtra(expr); }
SharedTableInfo * createAmbiguityInfo(IHqlExpression * dataset, unsigned depth);
protected:
CIArrayOf ambiguousTables;
bool seenAmbiguity;
bool seenShared;
};
//---------------------------------------------------------------------------
class ForceLocalTransformInfo : public NewTransformInfo
{
friend class ForceLocalTransformer;
public:
ForceLocalTransformInfo(IHqlExpression * _expr) : NewTransformInfo(_expr) { }
public:
//Theoretically this should be [insideForceLocal][allNodesDepth], but using insideAllNodes instead will just some obscure selfnodes in wrong place.
HqlExprAttr localTransformed[2][2];
HqlExprAttr localTransformedSelector[2][2];
};
//MORE: I think this might need to be a scoped transformer to cope with the general case
class ForceLocalTransformer : public NewHqlTransformer
{
public:
ForceLocalTransformer(ClusterType _targetClusterType);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual IHqlExpression * queryAlreadyTransformed(IHqlExpression * expr);
virtual void setTransformed(IHqlExpression * expr, IHqlExpression * transformed);
virtual IHqlExpression * queryAlreadyTransformedSelector(IHqlExpression * expr);
virtual void setTransformedSelector(IHqlExpression * expr, IHqlExpression * transformed);
protected:
bool queryAddLocal(IHqlExpression * expr);
inline bool insideAllNodes() { return allNodesDepth > 0; }
//Another exception
inline ForceLocalTransformInfo * queryExtra(IHqlExpression * expr) { return (ForceLocalTransformInfo *)queryTransformExtra(expr); }
protected:
ClusterType targetClusterType;
bool insideForceLocal;
unsigned allNodesDepth;
};
class HqlLinkedChildRowTransformer : public QuickHqlTransformer
{
public:
HqlLinkedChildRowTransformer(bool _implicitLinkedChildRows);
virtual IHqlExpression * createTransformedBody(IHqlExpression * expr);
protected:
IHqlExpression * ensureInputSerialized(IHqlExpression * expr);
IHqlExpression * transformBuildIndex(IHqlExpression * expr);
IHqlExpression * transformPipeThrough(IHqlExpression * expr);
protected:
bool implicitLinkedChildRows;
};
//---------------------------------------------------------------------------
class HqlScopeTaggerInfo : public MergingTransformInfo
{
public:
HqlScopeTaggerInfo(IHqlExpression * _expr);
};
class HqlScopeTagger : public ScopedDependentTransformer
{
typedef ScopedDependentTransformer Parent;
public:
HqlScopeTagger(IErrorReceiver * _errors);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr);
void reportWarnings();
protected:
void beginTableScope();
void endTableScope(HqlExprArray & attrs, IHqlExpression * ds, IHqlExpression * newExpr);
void checkActiveRow(IHqlExpression * expr);
IHqlExpression * transformSelect(IHqlExpression * expr);
IHqlExpression * transformAmbiguous(IHqlExpression * expr, bool isActiveOk);
IHqlExpression * transformAmbiguousChildren(IHqlExpression * expr);
IHqlExpression * transformNewDataset(IHqlExpression * expr, bool isActiveOk);
IHqlExpression * transformRelated(IHqlExpression * expr);
IHqlExpression * transformSelectorsAttr(IHqlExpression * expr);
IHqlExpression * transformSizeof(IHqlExpression * expr);
IHqlExpression * transformWithin(IHqlExpression * dataset, IHqlExpression * scope);
bool isValidNormalizeSelector(IHqlExpression * expr);
void reportError(const char * msg, bool warning = false);
void reportSelectorError(IHqlExpression * selector, IHqlExpression * expr);
protected:
IErrorReceiver * errors;
WarningProcessor collector;
};
//---------------------------------------------------------------------------
class ContainsCompoundTransformer : public QuickHqlTransformer
{
public:
ContainsCompoundTransformer();
protected:
virtual void doAnalyseBody(IHqlExpression * expr);
public:
bool containsCompound;
};
bool containsCompound(const HqlExprArray & exprs);
bool containsCompound(IHqlExpression * expr);
//---------------------------------------------------------------------------
class AnnotationTransformInfo : public NewTransformInfo
{
public:
AnnotationTransformInfo(IHqlExpression * _expr) : NewTransformInfo(_expr) { }
IHqlExpression * cloneAnnotations(IHqlExpression * body);
void noteAnnotation(IHqlExpression * _annotation);
public:
HqlExprCopyArray annotations;
};
class AnnotationNormalizerTransformer : public NewHqlTransformer
{
public:
AnnotationNormalizerTransformer();
virtual void analyseExpr(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
// virtual void analyseSelector(IHqlExpression * expr);
// virtual IHqlExpression * transformSelector(IHqlExpression * expr);
protected:
AnnotationTransformInfo * queryCommonExtra(IHqlExpression * expr);
};
void normalizeAnnotations(HqlCppTranslator & translator, HqlExprArray & exprs);
void normalizeAnnotations(HqlCppTranslator & translator, WorkflowArray & workflow);
//---------------------------------------------------------------------------
class NestedCompoundTransformer : public HoistingHqlTransformer
{
public:
NestedCompoundTransformer(HqlCppTranslator & _translator);
protected:
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual IHqlExpression * doTransformIndependent(IHqlExpression * expr)
{
if (!containsCompound(expr))
return LINK(expr);
NestedCompoundTransformer nested(translator);
nested.setParent(this);
nested.analyse(expr, 0); // analyse called so set up whether expressions are unconditional etc.
return nested.transformRoot(expr);
}
public:
HqlCppTranslator & translator;
const HqlCppOptions & translatorOptions;
};
class HqlTreeNormalizerInfo : public NewTransformInfo
{
public:
HqlTreeNormalizerInfo(IHqlExpression * _expr) : NewTransformInfo(_expr) { symbol = NULL; }
void noteSymbol(IHqlExpression * _symbol);
public:
IHqlExpression * symbol;
};
class HqlTreeNormalizer : public NewHqlTransformer
{
typedef NewHqlTransformer Parent;
public:
HqlTreeNormalizer(HqlCppTranslator & _translator);
virtual void analyseExpr(IHqlExpression * expr);
virtual IHqlExpression * createTransformed(IHqlExpression * expr);
virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr);
bool querySeenForceLocal() const { return seenForceLocal; }
bool querySeenLocalUpload() const { return seenLocalUpload; }
protected:
virtual IHqlExpression * createTransformedSelector(IHqlExpression * expr);
virtual ITypeInfo * transformType(ITypeInfo * type);
inline IHqlExpression * createTransformedBody(IHqlExpression * expr);
IHqlExpression * convertSelectToProject(IHqlExpression * newRecord, IHqlExpression * expr);
void convertRecordToAssigns(HqlExprArray & assigns, IHqlExpression * oldRecord, IHqlExpression * targetSelector, bool canOmit, bool onlyConstant);
IHqlExpression * convertRecordToAssigns(IHqlExpression * oldRecord, bool canOmit, bool onlyConstant);
IHqlExpression * removeDefaultsFromExpr(IHqlExpression * expr, unsigned recordChildIndex, node_operator newOp);
IHqlExpression * optimizeAssignSkip(HqlExprArray & children, IHqlExpression * expr, IHqlExpression * cond, unsigned depth);
IHqlExpression * queryTransformPatternDefine(IHqlExpression * expr);
IHqlExpression * transformActionList(IHqlExpression * expr);
IHqlExpression * transformCase(IHqlExpression * expr);
IHqlExpression * transformExecuteWhen(IHqlExpression * expr);
IHqlExpression * transformEvaluate(IHqlExpression * expr);
IHqlExpression * transformIfAssert(node_operator newOp, IHqlExpression * expr);
IHqlExpression * transformKeyIndex(IHqlExpression * expr);
IHqlExpression * transformMerge(IHqlExpression * expr);
IHqlExpression * transformNewKeyIndex(IHqlExpression * expr);
IHqlExpression * transformPatNamedUse(IHqlExpression * expr);
IHqlExpression * transformPatCheckIn(IHqlExpression * expr);
IHqlExpression * transformMap(IHqlExpression * expr);
IHqlExpression * transformTempRow(IHqlExpression * expr);
IHqlExpression * transformTempTable(IHqlExpression * expr);
IHqlExpression * transformTable(IHqlExpression * untransformed);
IHqlExpression * transformWithinFilter(IHqlExpression * expr);
bool transformTransform(HqlExprArray & children, IHqlExpression * expr);
IHqlExpression * transformTransform(IHqlExpression * expr);
IHqlExpression * validateKeyedJoin(IHqlExpression * expr);
protected:
IHqlExpression * makeRecursiveName(_ATOM searchModule, _ATOM searchName);
HqlTreeNormalizerInfo * queryCommonExtra(IHqlExpression * expr);
IHqlExpression * transformSimpleConst(IHqlExpression * expr)
{
if (expr->isConstant())
return transform(expr);
return LINK(expr);
}
protected:
HqlCppTranslator & translator;
IErrorReceiver * errors;
HqlExprArray forwardReferences;
HqlExprArray defines;
struct
{
bool removeAsserts;
bool commonUniqueNameAttributes;
bool simplifySelectorSequence;
bool sortIndexPayload;
bool allowSections;
bool normalizeExplicitCasts;
bool ensureRecordsHaveSymbols;
bool outputRowsAsDatasets;
bool constantFoldNormalize;
bool allowActivityForKeyedJoin;
bool implicitShuffle;
} options;
unsigned nextSequenceValue;
bool seenForceLocal;
bool seenLocalUpload;
};
void normalizeHqlTree(HqlCppTranslator & translator, HqlExprArray & exprs);
IHqlExpression * normalizeHqlTree(HqlCppTranslator & translator, IHqlExpression * expr);
// more: This really shouldn't need a translator argument - but it is a bit of a god class, and error reporting needs splitting from it.
IHqlExpression * normalizeRecord(HqlCppTranslator & translator, IHqlExpression * expr);
IHqlExpression * removeNamedSymbols(IHqlExpression * expr);
void hoistNestedCompound(HqlCppTranslator & _translator, HqlExprArray & exprs);
void hoistNestedCompound(HqlCppTranslator & _translator, WorkflowArray & workflow);
//---------------------------------------------------------------------------
void expandGlobalDatasets(WorkflowArray & array, IWorkUnit * wu, HqlCppTranslator & translator);
void mergeThorGraphs(WorkflowArray & array, bool resourceConditionalActions, bool resourceSequential);
void migrateExprToNaturalLevel(WorkflowArray & array, IWorkUnit * wu, HqlCppTranslator & translator);
void removeTrivialGraphs(WorkflowArray & workflow);
void extractWorkflow(HqlCppTranslator & translator, HqlExprArray & exprs, WorkflowArray & out);
void optimizeActivities(HqlExprArray & exprs, bool optimizeCountCompare, bool optimizeNonEmpty);
void optimizeActivities(WorkflowArray & array, bool optimizeCountCompare, bool optimizeNonEmpty);
IHqlExpression * optimizeActivities(IHqlExpression * expr, bool optimizeCountCompare, bool optimizeNonEmpty);
IHqlExpression * insertImplicitProjects(HqlCppTranslator & translator, IHqlExpression * expr, bool optimizeSpills);
void insertImplicitProjects(HqlCppTranslator & translator, HqlExprArray & exprs);
//------------------------------------------------------------------------
#endif