hqlhoist.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*##############################################################################
  2. Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef __HQLHOIST_HPP_
  14. #define __HQLHOIST_HPP_
  15. #include "hqltrans.ipp"
  16. bool canSurroundWithAlias(IHqlExpression * expr);
  17. //This class represents the guard/protection condition for a single candiate expression
  18. class CHqlExprGuard : public CInterface
  19. {
  20. public:
  21. CHqlExprGuard(IHqlExpression * _guard, IHqlExpression * _original, bool _guardContainsCandidate)
  22. : guard(_guard), original(_original), guardContainsCandidate(_guardContainsCandidate)
  23. {
  24. }
  25. bool guardContainsCandidate;
  26. LinkedHqlExpr guard;
  27. LinkedHqlExpr original;
  28. };
  29. //This class represents a list of the guards for each of the guarded expressions used within the owning expression.
  30. class CHqlExprMultiGuard : public CInterface
  31. {
  32. public:
  33. CHqlExprMultiGuard() {}
  34. CHqlExprMultiGuard(const CHqlExprMultiGuard * other)
  35. {
  36. if (other)
  37. {
  38. CloneArray(guarded, other->guarded);
  39. }
  40. }
  41. void addGuarded(IHqlExpression * original);
  42. void addGuarded(IHqlExpression * cond, IHqlExpression * original, bool guardContainsCandidate);
  43. void combine(CHqlExprMultiGuard & other);
  44. void combine(CHqlExprGuard & other);
  45. void gatherCandidates(HqlExprCopyArray & candidiates) const;
  46. bool guardContainsCandidate(IHqlExpression * original) const;
  47. IHqlExpression * queryGuardCondition(IHqlExpression * original) const;
  48. public:
  49. CIArrayOf<CHqlExprGuard> guarded;
  50. };
  51. //---------------------------------------------------------------------------------------------------------------------
  52. class ConditionalContextInfo : public ConditionalTransformInfo
  53. {
  54. public:
  55. ConditionalContextInfo(IHqlExpression * expr) : ConditionalTransformInfo(expr)
  56. {
  57. firstParent = NULL;
  58. commonLocation = NULL;
  59. moveTo = NULL;
  60. firstAnnotatedExpr = NULL;
  61. seq = 0;
  62. hasSharedParent = false;
  63. calcedCommonLocation = false;
  64. isCandidateExpr = false;
  65. createAlias = false;
  66. }
  67. void addExtraParent(ConditionalContextInfo * nextParent, bool noteManyUnconditionalParents)
  68. {
  69. hasSharedParent = true;
  70. //We only care about parents of conditional expressions
  71. if (!isUnconditional() || noteManyUnconditionalParents || canSurroundWithAlias(original))
  72. {
  73. extraParents.append(nextParent);
  74. }
  75. }
  76. void calcInheritedGuards();
  77. bool isCandidateThatMoves() const;
  78. bool usedOnMultiplePaths() const;
  79. inline bool hasDefinitions() const { return definitions.ordinality() != 0; }
  80. inline bool changesLocation() const { return moveTo != this; }
  81. inline void setFirstParent(ConditionalContextInfo * parent) { firstParent = parent; }
  82. public:
  83. // use a pointer for the first match to avoid reallocation for unshared items
  84. ConditionalContextInfo * firstParent; // NULL for the root item
  85. // if this expression is conditional, then which expression contains all uses of it?
  86. ConditionalContextInfo * commonLocation;
  87. // where will the definition be moved to. NULL if it will not be moved.
  88. ConditionalContextInfo * moveTo;
  89. // First annotated expression seen (if any)
  90. IHqlExpression * firstAnnotatedExpr;
  91. //Which guarded expressions need to be created at this point?
  92. HqlExprArray definitions;
  93. //If conditional, a list of all the other places it is used.
  94. PointerArrayOf<ConditionalContextInfo> extraParents;
  95. // guards for all expressions that this expression contains
  96. Owned<CHqlExprMultiGuard> guards;
  97. //All guards that need to be passed on the container/parent expressions [excludes definitions]
  98. Owned<CHqlExprMultiGuard> inheritedGuards;
  99. //A sequence number use to ensure it is efficient to find a common parent
  100. unsigned seq;
  101. bool hasSharedParent;
  102. bool calcedCommonLocation;
  103. //Is this a candidate for evaluating in a single location with guards?
  104. bool isCandidateExpr;
  105. bool createAlias;
  106. };
  107. //---------------------------------------------------------------------------------------------------------------------
  108. class ConditionalContextTransformer : public ConditionalHqlTransformer
  109. {
  110. public:
  111. enum { PassFindConditions,
  112. PassFindCandidates,
  113. PassFindParents,
  114. PassGatherGuards,
  115. };
  116. public:
  117. virtual void analyseExpr(IHqlExpression * expr);
  118. bool findSingleCommonLocation();
  119. bool findCommonLocations();
  120. bool associateCandidatesWithRoot();
  121. bool analyseNeedsTransform(const HqlExprArray & exprs);
  122. bool hasSingleConditionalCandidate() const;
  123. void transformAll(HqlExprArray & exprs, bool forceRootFirst);
  124. protected:
  125. virtual void transformCandidate(ConditionalContextInfo * candidate) = 0;
  126. ConditionalContextTransformer(HqlTransformerInfo & info, bool _alwaysEvaluateGuardedTogether);
  127. virtual ANewTransformInfo * createTransformInfo(IHqlExpression * expr);
  128. bool hasUnconditionalCandidate() const;
  129. void analyseConditionalParents(IHqlExpression * expr);
  130. void analyseGatherGuards(IHqlExpression * expr);
  131. ConditionalContextInfo * calcCommonLocation(ConditionalContextInfo * extra);
  132. ConditionalContextInfo * findCandidateLocation(ConditionalContextInfo * extra);
  133. ConditionalContextInfo * findCommonPath(ConditionalContextInfo * left, ConditionalContextInfo * right);
  134. ConditionalContextInfo * selectParent(ConditionalContextInfo * info);
  135. CHqlExprMultiGuard * calcGuard(ConditionalContextInfo * cur, unsigned firstGuard);
  136. CHqlExprMultiGuard * createAndOrGuard(ConditionalContextInfo * cur);
  137. CHqlExprMultiGuard * createCaseMapGuard(ConditionalContextInfo * cur, node_operator op);
  138. CHqlExprMultiGuard * createIfGuard(ConditionalContextInfo * cur);
  139. CHqlExprMultiGuard * createIfGuard(IHqlExpression * ifCond, CHqlExprMultiGuard * condGuard, CHqlExprMultiGuard * trueGuard, CHqlExprMultiGuard * falseGuard);
  140. CHqlExprMultiGuard * queryGuards(IHqlExpression * expr);
  141. void addDefinition(ConditionalContextInfo * location, ConditionalContextInfo * candidate);
  142. void removeDefinition(ConditionalContextInfo * location, ConditionalContextInfo * candidate);
  143. virtual IHqlExpression * createDefinitions(ConditionalContextInfo * extra) = 0;
  144. inline ConditionalContextInfo * queryBodyExtra(IHqlExpression * expr) { return (ConditionalContextInfo*)NewHqlTransformer::queryTransformExtra(expr->queryBody()); }
  145. void noteCandidate(ConditionalContextInfo * extra);
  146. inline void noteCandidate(IHqlExpression * expr) { noteCandidate(queryBodyExtra(expr)); }
  147. IHqlExpression * getGuardCondition(ConditionalContextInfo * extra, IHqlExpression * expr);
  148. IHqlExpression * createGuardedDefinition(ConditionalContextInfo * extra, IHqlExpression * expr);
  149. IHqlExpression * createGuardedDefinition(ConditionalContextInfo * extra, IHqlExpression * expr, IHqlExpression * condition);
  150. virtual IHqlExpression * createTransformed(IHqlExpression * expr);
  151. void transformAllCandidates();
  152. protected:
  153. IArrayOf<ConditionalContextInfo> candidates;
  154. ConditionalContextInfo * activeParent;
  155. OwnedHqlExpr rootExpr;
  156. CICopyArrayOf<CHqlExprMultiGuard> childGuards;
  157. ICopyArrayOf<ConditionalContextInfo> insertLocations;
  158. unsigned seq;
  159. bool alwaysEvaluateGuardedTogether;
  160. bool noteManyUnconditionalParents;
  161. bool hasConditionalCandidate;
  162. bool createRootGraph;
  163. };
  164. IHqlExpression * mapExternalToInternalResults(IHqlExpression * expr, IHqlExpression * graph);
  165. #endif