hqlthql.cpp 114 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683
  1. /*##############################################################################
  2. HPCC SYSTEMS software 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. #include "hqlthql.hpp"
  14. #include <limits.h>
  15. #include "jmisc.hpp"
  16. #include "jlog.hpp"
  17. #include "hqltrans.ipp"
  18. #include "hqlutil.hpp"
  19. #include "hqlmeta.hpp"
  20. #include "workunit.hpp"
  21. #include "hqlerrors.hpp"
  22. //The following constants can be uncommented to increase the level of detail which is added to the processed graphs
  23. //E.g. generated when -fl used in hqltest
  24. //#define SHOWADDRSYM
  25. //#define SHOWBRACKETS
  26. //#define SHOWADDR
  27. //#define SHOWTYPES
  28. //#define SHOWFLAGS
  29. //#define SHOWCONTEXTDETAIL
  30. //#define SHOWFLAGSVALUE
  31. //#define SHOW_TABLES
  32. //#define SHOW_TABLES_EXISTANCE
  33. //#define SHOWCRC
  34. //#define SHOW_ANNOTATIONS
  35. //#define SHOW_NORMALIZED
  36. //#define SHOW_EXPAND_LEFTRIGHT
  37. //#define SHOW_DSRECORD
  38. //#define SHOW_DISTRIBUTION
  39. //#define SHOW_ORDER
  40. //#define SHOW_GROUPING
  41. //#define SHOW_GROUPING_DETAIL
  42. //#define SHOW_MODULE_STATUS
  43. //#define SHOW_FUNC_DEFINTION
  44. //#define SHOW_SYMBOL_LOCATION
  45. #define MAX_GRAPHTEXT_LEN 80 // Truncate anything more than 80 characters
  46. bool endsWithDotDotDot(const StringBuffer & s)
  47. {
  48. if (s.length() < 3)
  49. return false;
  50. return (memcmp(s.str() + s.length() -3, "...", 3) == 0);
  51. }
  52. typedef CopyReferenceArrayOf<HqlExprArray> HqlExprArrayArray;
  53. class HqltHql
  54. {
  55. public:
  56. HqltHql(bool recurse, bool _xgmmlGraphText);
  57. ~HqltHql();
  58. void toECL(IHqlExpression *expr, StringBuffer &s, bool paren, bool inType, unsigned recordIndex=0, bool isNamedSymbol=false);
  59. StringBuffer & gatherDefinitions(StringBuffer & out);
  60. StringBuffer & gatherServices(StringBuffer & out) { return out.append(m_services); }
  61. void setExpandProcessed(bool value) { expandProcessed = value; }
  62. void setExpandNamed(bool value) { expandNamed = value; }
  63. void setIgnoreModuleNames(bool value) { ignoreModuleNames = value; }
  64. void setIgnoreVirtualAttrs(bool value) { ignoreVirtualAttrs = value; }
  65. void setLowerCaseIds(bool value) { lowerCaseIds = value; }
  66. void setMinimalSelectors(bool value) { minimalSelectors = value; }
  67. void setMaxRecurseDepth(int depth) { maxDatasetDepth = depth; }
  68. void setTryToRegenerate(bool value) { tryToRegenerate = value; }
  69. StringBuffer &doAlias(IHqlExpression * expr, StringBuffer &name, bool inType);
  70. private:
  71. void childrenToECL(IHqlExpression *expr, StringBuffer &s, bool inType, bool needComma, unsigned first);
  72. void defaultToECL(IHqlExpression *expr, StringBuffer &s, bool inType);
  73. void defaultChildrenToECL(IHqlExpression *expr, StringBuffer &s, bool inType);
  74. void appendSortOrder(StringBuffer & s, const char * prefix, IHqlExpression * order);
  75. void createPseudoSymbol(StringBuffer & s, const char * prefix, IHqlExpression * expr);
  76. void expandTransformValues(StringBuffer & s, IHqlExpression * expr, bool & first);
  77. StringBuffer &getTypeString(ITypeInfo * i, StringBuffer &s);
  78. StringBuffer &getFieldTypeString(IHqlExpression * e, StringBuffer &s);
  79. const char *getEclOpString(node_operator op);
  80. void defineCallTarget(IHqlExpression * expr, StringBuffer & name);
  81. bool isFunctionDefined(IHqlExpression * expr);
  82. IHqlExpression * querySymbolDefined(IHqlExpression * expr);
  83. bool isSymbolDefined(IHqlExpression * expr) { return querySymbolDefined(expr) != NULL; }
  84. bool isAlienTypeDefined(ITypeInfo * type);
  85. IHqlExpression * queryAlienDefinition(ITypeInfo * type);
  86. void addExport(StringBuffer &s);
  87. void clearVisited();
  88. StringBuffer &callEclFunction(StringBuffer &s, IHqlExpression * expr, bool inType);
  89. bool isSelect(IHqlExpression * expr);
  90. StringBuffer &lookupSymbolName(IHqlExpression * expr, StringBuffer &s);
  91. StringBuffer &makeUniqueName(IHqlExpression * expr, StringBuffer &s);
  92. void addVisited(IHqlExpression * expr);
  93. HqlExprArray * findVisitedArray();
  94. void clearAllVisitedArrays();
  95. bool isServiceDefined(IHqlExpression * expr);
  96. bool isExportDefined(IHqlExpression * expr);
  97. void doFunctionDefinition(StringBuffer & newdef, IHqlExpression * funcdef, const char * name, bool inType);
  98. void sortlistToEcl(IHqlExpression *expr, StringBuffer &s, bool addCurleys, bool inType);
  99. bool matchesActiveDataset(IHqlExpression * expr);
  100. void pushScope(IHqlExpression * expr);
  101. void popScope();
  102. void mapDatasetRecord(IHqlExpression * expr);
  103. void popMapping();
  104. bool queryAddDotDotDot(StringBuffer & s, unsigned startLength);
  105. IHqlExpression * queryMapped(IHqlExpression * expr);
  106. IHqlExpression * queryChild(IHqlExpression * e, unsigned i);
  107. StringBuffer & appendId(StringBuffer & s, IIdAtom * name);
  108. StringBuffer & queryNewline(StringBuffer &s);
  109. bool isExported(IHqlExpression * expr)
  110. {
  111. return ::isExported(expr) && !tryToRegenerate;
  112. }
  113. bool isShared(IHqlExpression * expr)
  114. {
  115. return ::isShared(expr) && !tryToRegenerate;
  116. }
  117. bool isPublicSymbol(IHqlExpression * expr)
  118. {
  119. return ::isPublicSymbol(expr) && !tryToRegenerate;
  120. }
  121. bool isInternalAttribute(IHqlExpression * e)
  122. {
  123. if (e->isAttribute())
  124. {
  125. IAtom * name= e->queryName();
  126. if ((name == sequenceAtom) || isInternalAttributeName(name))
  127. return true;
  128. if ((name == updateAtom) && e->hasAttribute(alwaysAtom))
  129. return true;
  130. if (tryToRegenerate)
  131. {
  132. if (name == jobTempAtom || name == loopFirstAtom)
  133. return true;
  134. }
  135. }
  136. return false;
  137. }
  138. private:
  139. bool m_recurse;
  140. bool ignoreModuleNames;
  141. bool insideNewTransform;
  142. int maxDatasetDepth;
  143. int curDatasetDepth;
  144. StringBuffer m_definitions;
  145. StringBuffer m_services;
  146. IArray m_visitedAlienTypes;
  147. bool m_isTop;
  148. int m_export_level;
  149. unsigned indent;
  150. bool xgmmlGraphText;
  151. bool expandNamed;
  152. bool expandProcessed;
  153. bool ignoreVirtualAttrs;
  154. bool lowerCaseIds;
  155. bool minimalSelectors;
  156. bool tryToRegenerate;
  157. StringBufferArray m_exports;
  158. StringBufferArray m_service_names;
  159. StringBufferArray m_export_names;
  160. HqlExprArrayArray m_visited_array;
  161. PointerArray scope;
  162. HqlExprArray mapped;
  163. IPointerArray mapSaved;
  164. unsigned clashCounter;
  165. };
  166. HqltHql::HqltHql(bool recurse, bool _xgmmlGraphText) :
  167. m_recurse(recurse),
  168. maxDatasetDepth(_xgmmlGraphText ? 1 : INT_MAX),
  169. m_isTop(true),
  170. m_export_level(0)
  171. {
  172. lockTransformMutex();
  173. indent = 1;
  174. xgmmlGraphText = _xgmmlGraphText;
  175. curDatasetDepth = 0;
  176. ignoreModuleNames = false;
  177. expandNamed = true;
  178. expandProcessed = false;
  179. insideNewTransform = false;
  180. ignoreVirtualAttrs = false;
  181. minimalSelectors = false;
  182. lowerCaseIds = false;
  183. tryToRegenerate = false;
  184. clashCounter = 0;
  185. }
  186. HqltHql::~HqltHql()
  187. {
  188. clearAllVisitedArrays();
  189. unlockTransformMutex();
  190. }
  191. StringBuffer & HqltHql::appendId(StringBuffer & s, IIdAtom * id)
  192. {
  193. if (lowerCaseIds)
  194. return s.append(str(lower(id)));
  195. else
  196. return s.append(str(id));
  197. }
  198. StringBuffer &HqltHql::makeUniqueName(IHqlExpression * expr, StringBuffer &s)
  199. {
  200. IIdAtom * moduleName = expr->queryFullContainerId();
  201. if (moduleName && !ignoreModuleNames)
  202. {
  203. if (isPublicSymbol(expr))
  204. {
  205. if (xgmmlGraphText)
  206. appendId(s, moduleName).append(".");
  207. else
  208. {
  209. const char * moduleNameText = str(lower(moduleName));
  210. for (;;)
  211. {
  212. const char * dot = strchr(moduleNameText, '.');
  213. if (!dot)
  214. {
  215. s.append(moduleNameText);
  216. break;
  217. }
  218. s.append(dot-moduleNameText, moduleNameText).append("__");
  219. moduleNameText = dot+1;
  220. }
  221. s.append("__");
  222. }
  223. }
  224. }
  225. appendId(s, expr->queryId());
  226. #ifdef SHOWADDRSYM
  227. if (expandProcessed)
  228. s.appendf("[%p:%p]",expr, expr->queryBody());
  229. #endif
  230. return s;
  231. }
  232. bool HqltHql::isSelect(IHqlExpression * expr)
  233. {
  234. return expr->getOperator() == no_select;
  235. }
  236. void HqltHql::mapDatasetRecord(IHqlExpression * expr)
  237. {
  238. IHqlExpression * record = expr->queryRecord()->queryBody();
  239. mapped.append(*LINK(expr));
  240. IInterface * mapping = LINK(record->queryTransformExtra());
  241. mapSaved.append(mapping);
  242. if (!mapping && expr->queryName())
  243. record->setTransformExtra(expr);
  244. }
  245. void HqltHql::popMapping()
  246. {
  247. OwnedHqlExpr expr = &mapped.popGet();
  248. IHqlExpression * record = expr->queryRecord()->queryBody();
  249. if (record->queryTransformExtra() == expr)
  250. record->setTransformExtra(mapSaved.tos());
  251. mapSaved.pop();
  252. }
  253. IHqlExpression * HqltHql::queryMapped(IHqlExpression * expr)
  254. {
  255. for (;;)
  256. {
  257. IHqlExpression * extra = (IHqlExpression *)expr->queryTransformExtra();
  258. if (!extra || extra->isAttribute() || extra == expr)
  259. return expr;
  260. if (expr->queryName() == lower(unnamedId))
  261. return expr;
  262. expr = extra;
  263. }
  264. }
  265. void HqltHql::addExport(StringBuffer &s)
  266. {
  267. // Need a map of StringBuffers indexed by m_export_level
  268. for(int idx = m_exports.ordinality(); idx <= m_export_level; idx++)
  269. {
  270. m_exports.append(*new StringBufferItem);
  271. }
  272. m_exports.item(m_export_level).append(s);
  273. }
  274. StringBuffer & HqltHql::gatherDefinitions(StringBuffer & out)
  275. {
  276. out.append(m_definitions);
  277. for(int idx = (m_exports.length() - 1); idx >=0; idx--)
  278. out.append(m_exports.item(idx));
  279. return out;
  280. }
  281. void HqltHql::addVisited(IHqlExpression * expr)
  282. {
  283. findVisitedArray()->append(*LINK(expr));
  284. }
  285. HqlExprArray * HqltHql::findVisitedArray()
  286. {
  287. for(int idx = m_visited_array.ordinality(); idx <= m_export_level; idx++)
  288. m_visited_array.append(*(new HqlExprArray));
  289. return &(m_visited_array.item(m_export_level));
  290. }
  291. void HqltHql::clearVisited()
  292. {
  293. HqlExprArray * visited = findVisitedArray();
  294. ForEachItemInRev(idx, *visited)
  295. {
  296. IHqlExpression * expr = &(visited->item(idx));
  297. if (!isPublicSymbol(expr))
  298. {
  299. visited->remove(idx);
  300. }
  301. }
  302. }
  303. void HqltHql::clearAllVisitedArrays()
  304. {
  305. // Empty the array of visited IHqlExpression Arrays
  306. for(unsigned jdx = 0; jdx < m_visited_array.length(); jdx++)
  307. {
  308. delete &(m_visited_array.item(jdx));
  309. }
  310. m_visited_array.kill();
  311. }
  312. bool HqltHql::isServiceDefined(IHqlExpression * expr)
  313. {
  314. StringBuffer name;
  315. makeUniqueName(expr, name);
  316. for(unsigned jdx = 0; jdx < m_service_names.length(); jdx++)
  317. {
  318. if(!stricmp(m_service_names.item(jdx).str(), name.str()))
  319. return true;
  320. }
  321. return false;
  322. }
  323. bool HqltHql::isExportDefined(IHqlExpression * expr)
  324. {
  325. StringBuffer name;
  326. makeUniqueName(expr, name);
  327. for(unsigned jdx = 0; jdx < m_export_names.length(); jdx++)
  328. {
  329. if(!stricmp(m_export_names.item(jdx).str(), name.str()))
  330. return true;
  331. }
  332. return false;
  333. }
  334. bool HqltHql::isFunctionDefined(IHqlExpression * expr)
  335. {
  336. // THIS FUNCTION IS EXPORTED !!! CHECK THE OTHER EXPORTS TOO
  337. if(isExportDefined(expr))
  338. return true;
  339. return findVisitedArray()->contains(*expr);
  340. }
  341. StringBuffer &HqltHql::lookupSymbolName(IHqlExpression * expr, StringBuffer &s)
  342. {
  343. IHqlExpression * extra = (IHqlExpression *)expr->queryTransformExtra();
  344. if (extra)
  345. {
  346. if ((extra != expr) && !extra->isAttribute())
  347. return lookupSymbolName(extra, s);
  348. return appendId(s, extra->queryId());
  349. }
  350. makeUniqueName(expr, s);
  351. return s;
  352. }
  353. IHqlExpression * HqltHql::querySymbolDefined(IHqlExpression * expr)
  354. {
  355. StringBuffer xxx;
  356. lookupSymbolName(expr, xxx);
  357. HqlExprArray * visited = findVisitedArray();
  358. for (unsigned i = 0; i < visited->ordinality(); i++)
  359. {
  360. IHqlExpression * item = &(visited->item(i));
  361. IHqlExpression * extra = static_cast<IHqlExpression *>(item->queryTransformExtra());
  362. if(extra->queryName() && xxx.length())
  363. {
  364. if(!stricmp(str(extra->queryName()), xxx.str()))
  365. return item;
  366. }
  367. }
  368. return NULL;
  369. }
  370. IHqlExpression * HqltHql::queryAlienDefinition(ITypeInfo * type)
  371. {
  372. IHqlExpression * expr = queryExpression(queryUnqualifiedType(type));
  373. return expr->queryFunctionDefinition(); // Not really queryFunctionDefinition - original definition of the alien type
  374. }
  375. bool HqltHql::isAlienTypeDefined(ITypeInfo * type)
  376. {
  377. IHqlExpression * expr = queryAlienDefinition(type);
  378. if (m_visitedAlienTypes.find(*expr) != NotFound)
  379. return true;
  380. m_visitedAlienTypes.append(*LINK(expr));
  381. return false;
  382. }
  383. IHqlExpression * HqltHql::queryChild(IHqlExpression * expr, unsigned i)
  384. {
  385. IHqlExpression * child = expr->queryChild(i);
  386. if (!expandProcessed && isInternalAttribute(child))
  387. return NULL;
  388. return child;
  389. }
  390. StringBuffer &HqltHql::callEclFunction(StringBuffer &s, IHqlExpression * expr, bool inType)
  391. {
  392. assertex(expr->isNamedSymbol());
  393. IHqlExpression * funcdef = expr->queryFunctionDefinition();
  394. switch (funcdef->getOperator())
  395. {
  396. case no_funcdef:
  397. case no_internalselect:
  398. case no_delayedselect:
  399. break;
  400. default:
  401. throw makeStringExceptionV(ERR_INTERNALEXCEPTION, "Internal: Unexpected function definition %s", getOpString(funcdef->getOperator()));
  402. }
  403. IHqlExpression * formals = queryFunctionParameters(funcdef);
  404. s.append('(');
  405. unsigned numParameters = formals->numChildren();
  406. bool first = true;
  407. for (unsigned idx = 0; idx < numParameters; idx++)
  408. {
  409. if (expandProcessed || !formals->queryChild(idx)->hasAttribute(_hidden_Atom))
  410. {
  411. if (first)
  412. first = false;
  413. else
  414. s.append(", ");
  415. if(funcdef->isNamedSymbol())
  416. {
  417. IHqlExpression * param = expr->queryAnnotationParameter(idx);
  418. if(param)
  419. toECL(param, s, false, inType);
  420. }
  421. }
  422. }
  423. s.append(')');
  424. return s;
  425. }
  426. void HqltHql::popScope()
  427. {
  428. scope.pop();
  429. }
  430. void HqltHql::pushScope(IHqlExpression * expr)
  431. {
  432. if (expr)
  433. {
  434. expr = expr->queryNormalizedSelector();
  435. if (expr->getOperator() == no_selectnth)
  436. expr = expr->queryChild(0)->queryNormalizedSelector();
  437. }
  438. scope.append(expr);
  439. }
  440. bool HqltHql::matchesActiveDataset(IHqlExpression * expr)
  441. {
  442. if (!expr || (scope.ordinality() == 0))
  443. return false;
  444. return expr->queryNormalizedSelector() == scope.tos();
  445. }
  446. bool isEclAlias(IHqlExpression * expr)
  447. {
  448. IHqlExpression * symbol = queryNamedSymbol(expr);
  449. if (!symbol)
  450. return false;
  451. //don't add an alias around the definition of an external call. Maybe the tree shouldn't include the named symbol in the first place
  452. if (expr->getOperator() != no_externalcall)
  453. return true;
  454. IHqlExpression * funcdef = expr->queryFunctionDefinition();
  455. if (!funcdef) // attr := call();
  456. return true;
  457. return (funcdef->queryChild(0)->getOperator() != no_external);
  458. }
  459. static bool needParen(int precedence, IHqlExpression * child)
  460. {
  461. if (!child)
  462. return false;
  463. if (isEclAlias(child))
  464. return false;
  465. return (child->getPrecedence() < precedence) && (child->numChildren() > 1);
  466. }
  467. static bool needParen(IHqlExpression * expr, IHqlExpression * child)
  468. {
  469. return needParen(expr->getPrecedence(), child);
  470. }
  471. StringBuffer & HqltHql::queryNewline(StringBuffer &s)
  472. {
  473. const unsigned maxLineLength = 1000;
  474. unsigned len = s.length();
  475. if (len < maxLineLength)
  476. return s;
  477. const char * text = s.str();
  478. for (unsigned i = 0; i < maxLineLength; i++)
  479. if (text[--len] == '\n')
  480. return s;
  481. return s.newline();
  482. }
  483. void HqltHql::childrenToECL(IHqlExpression *expr, StringBuffer &s, bool inType, bool needComma, unsigned first)
  484. {
  485. unsigned kids = expr->numChildren();
  486. for (unsigned idx = first; idx < kids; idx++)
  487. {
  488. IHqlExpression * child = queryChild(expr, idx);
  489. if (child && (expandProcessed || !isInternalAttribute(expr)))
  490. {
  491. if (needComma) queryNewline(s.append(", "));
  492. needComma = true;
  493. toECL(child, s, false, inType);
  494. if (expandProcessed && child->isAction())
  495. s.newline();
  496. }
  497. }
  498. }
  499. void splitPayload(SharedHqlExpr & keyed, SharedHqlExpr & payload, IHqlExpression * expr, unsigned payloadFields)
  500. {
  501. unsigned numFields = 0;
  502. ForEachChild(i, expr)
  503. if (!expr->queryChild(i)->isAttribute())
  504. numFields++;
  505. HqlExprArray keyedArgs, payloadArgs;
  506. unsigned cnt = 0;
  507. ForEachChild(j, expr)
  508. {
  509. IHqlExpression * field = expr->queryChild(j);
  510. if (!field->isAttribute())
  511. {
  512. if (cnt++ < numFields - payloadFields)
  513. keyedArgs.append(*LINK(field));
  514. else
  515. payloadArgs.append(*LINK(field));
  516. }
  517. }
  518. keyed.setown(expr->clone(keyedArgs));
  519. payload.setown(expr->clone(payloadArgs));
  520. }
  521. bool HqltHql::queryAddDotDotDot(StringBuffer & s, unsigned startLength)
  522. {
  523. if (xgmmlGraphText && (s.length() - startLength) > MAX_GRAPHTEXT_LEN)
  524. {
  525. s.append("...");
  526. return true;
  527. }
  528. return false;
  529. }
  530. void HqltHql::expandTransformValues(StringBuffer & s, IHqlExpression * expr, bool & first)
  531. {
  532. switch (expr->getOperator())
  533. {
  534. case no_assign:
  535. if (first)
  536. first = false;
  537. else
  538. s.append(",");
  539. toECL(expr->queryChild(1), s, false, false, 0, false);
  540. break;
  541. case no_transform:
  542. case no_assignall:
  543. ForEachChild(i, expr)
  544. expandTransformValues(s, expr->queryChild(i), first);
  545. break;
  546. }
  547. }
  548. void HqltHql::appendSortOrder(StringBuffer & s, const char * prefix, IHqlExpression * order)
  549. {
  550. if (order)
  551. {
  552. s.append(prefix).append("[");
  553. toECL(order, s, false, false, 0, false);
  554. s.append("]");
  555. }
  556. }
  557. void HqltHql::createPseudoSymbol(StringBuffer & s, const char * prefix, IHqlExpression * expr)
  558. {
  559. StringBuffer name;
  560. bool alreadyDefined = findVisitedArray()->contains(*expr);
  561. if (!alreadyDefined)
  562. addVisited(expr);
  563. name.append(prefix).append(findVisitedArray()->find(*expr));
  564. if (!alreadyDefined)
  565. {
  566. expr->setTransformExtra(expr);
  567. bool wasInsideNewTransform = insideNewTransform;
  568. insideNewTransform = false;
  569. StringBuffer temp;
  570. scope.append(NULL);
  571. temp.append(name);
  572. #ifdef SHOW_NORMALIZED
  573. if (expandProcessed && expr->isDataset())
  574. temp.appendf(" [N%p]", expr->queryNormalizedSelector());
  575. #endif
  576. temp.append(" := ");
  577. toECL(expr, temp, false, false, 0, true);
  578. temp.append(";").newline();
  579. addExport(temp);
  580. scope.pop();
  581. insideNewTransform = wasInsideNewTransform;
  582. }
  583. s.append(name);
  584. }
  585. void HqltHql::toECL(IHqlExpression *expr, StringBuffer &s, bool paren, bool inType, unsigned recordIndex, bool isNamedSymbol)
  586. {
  587. if (expandProcessed)
  588. {
  589. #ifdef SHOWBRACKETS
  590. paren = true;
  591. #endif
  592. #ifdef SHOWCRC
  593. s.appendf("[%p]", getExpressionCRC(expr));
  594. #endif
  595. #ifdef SHOWADDR
  596. s.appendf("[%p]", expr);
  597. #endif
  598. #ifdef SHOWTYPES
  599. if (expr->queryType())
  600. expr->queryType()->getECLType(s.append("[T")).append("]");
  601. #endif
  602. #ifdef SHOWFLAGS
  603. s.append("[");
  604. #ifdef SHOWFLAGSVALUE
  605. s.appendf("%p/", expr->getInfoFlags());
  606. #endif
  607. if (!expr->isFullyBound())
  608. s.append("*U");
  609. if (expr->isPure())
  610. s.append('P');
  611. if (expr->isConstant())
  612. s.append('C');
  613. if (containsActiveDataset(expr))
  614. s.append('D');
  615. if (containsAnyDataset(expr))
  616. s.append('A');
  617. if (containsInternalSelect(expr))
  618. s.append('V');
  619. if (expr->getInfoFlags() & HEFaction)
  620. s.append('N');
  621. if (containsWorkflow(expr))
  622. s.append('W');
  623. if (containsSelf(expr))
  624. s.append('S');
  625. if (isContextDependent(expr))
  626. {
  627. s.append('X');
  628. #ifdef SHOWCONTEXTDETAIL
  629. s.append('[');
  630. unsigned flags = expr->getInfoFlags();
  631. if (flags & HEFnoduplicate) s.append('V');
  632. if (flags & HEFgraphDependent) s.append('G');
  633. if (flags & HEFcontainsSkip) s.append('S');
  634. if (flags & HEFcontainsCounter) s.append('C');
  635. if (flags & HEFtransformDependent) s.append('D');
  636. if (flags & HEFtranslated) s.append('R');
  637. if (flags & HEFonFailDependent) s.append('F');
  638. if (flags & HEFcontextDependentException) s.append('E');
  639. if (flags & HEFthrowscalar) s.append('T');
  640. if (flags & HEFthrowds) s.append('M');
  641. s.append(']');
  642. #endif
  643. }
  644. if (containsImplicitNormalize(expr))
  645. s.append('.');
  646. if (containsAssertKeyed(expr))
  647. s.append('K');
  648. if (containsAliasLocally(expr))
  649. s.append('L');
  650. if (containsCall(expr, false))
  651. s.append('c');
  652. if (isNamedSymbol)
  653. {
  654. if (expr->isDataset())
  655. {
  656. IHqlExpression * group = queryGrouping(expr);
  657. if (group)
  658. getExprECL(group, s.append("G(")).append(")");
  659. IHqlExpression * distrib = queryDistribution(expr);
  660. if (distrib) getExprECL(distrib, s.append("D(")).append(")");
  661. appendSortOrder(s, "GO", queryGlobalSortOrder(expr));
  662. appendSortOrder(s, "LO", queryLocalUngroupedSortOrder(expr));
  663. appendSortOrder(s, "RO", queryGroupSortOrder(expr));
  664. }
  665. }
  666. s.append("]");
  667. #endif
  668. #if defined(SHOW_TABLES) || defined(SHOW_TABLES_EXISTANCE)
  669. if (expr->isAction() || expr->isDataset() || expr->getOperator() == no_assign)
  670. {
  671. if (expr->getOperator() != no_rows)
  672. {
  673. HqlExprCopyArray inScope;
  674. expr->gatherTablesUsed(inScope);
  675. #ifdef SHOW_TABLES_EXISTANCE
  676. if (inScope.ordinality())
  677. s.append("[[!]]");
  678. #endif
  679. #ifdef SHOW_TABLES
  680. if (inScope.ordinality())
  681. {
  682. s.append("[[");
  683. ForEachItemIn(i, inScope)
  684. {
  685. if (i) s.append(",");
  686. toECL(&inScope.item(i), s, false, false, 0, false);
  687. }
  688. s.append("]]");
  689. }
  690. #endif
  691. }
  692. }
  693. else if (!expr->isIndependentOfScope())
  694. {
  695. s.append("[[!]]");
  696. }
  697. #endif
  698. #ifdef SHOW_DSRECORD
  699. if (expr->isDataset() || expr->isTransform())
  700. {
  701. s.append("R[");
  702. toECL(expr->queryRecord(), s, false, false, 0, false);
  703. s.append("]R");
  704. }
  705. #endif
  706. #ifdef SHOW_DISTRIBUTION
  707. if (expr->isDataset())
  708. {
  709. IHqlExpression * distribution = queryDistribution(expr);
  710. if (distribution)
  711. {
  712. s.append("dist[");
  713. toECL(distribution, s, false, false, 0, false);
  714. s.append("]");
  715. }
  716. }
  717. #endif
  718. #ifdef SHOW_ORDER
  719. if (expr->isDataset())
  720. {
  721. ITypeInfo * type = expr->queryType();
  722. appendSortOrder(s, "gorder", queryGlobalSortOrder(type));
  723. appendSortOrder(s, "lorder", queryLocalUngroupedSortOrder(type));
  724. appendSortOrder(s, "grorder", queryGroupSortOrder(type));
  725. }
  726. #endif
  727. #ifdef SHOW_GROUPING
  728. if (expr->isDataset())
  729. {
  730. IHqlExpression * grouping = queryGrouping(expr);
  731. if (grouping)
  732. {
  733. s.append("gr[");
  734. #ifdef SHOW_GROUPING_DETAIL
  735. toECL(grouping, s, false, false, 0, false);
  736. #endif
  737. s.append("]");
  738. }
  739. }
  740. #endif
  741. }
  742. // bool isTop = m_isTop;
  743. if(m_isTop)
  744. m_isTop = false;
  745. node_operator no = expr->getOperator();
  746. int precedence;
  747. bool lparen, rparen;
  748. IHqlExpression * child0 = expr->queryChild(0);
  749. IHqlExpression * child1 = expr->queryChild(1);
  750. unsigned savedDatasetDepth = curDatasetDepth;
  751. if(paren)
  752. s.append('(');
  753. for (;;)
  754. {
  755. annotate_kind kind = expr->getAnnotationKind();
  756. if ((kind == annotate_none) || (kind == annotate_symbol))
  757. break;
  758. #ifdef SHOW_ANNOTATIONS
  759. if (expandProcessed)
  760. {
  761. switch (kind)
  762. {
  763. case annotate_meta:
  764. s.append("#M[");
  765. for (unsigned i= 0; expr->queryAnnotationParameter(i); i++)
  766. {
  767. if (i) s.append(",");
  768. toECL(expr->queryAnnotationParameter(i), s, false, false);
  769. }
  770. s.append("]#");
  771. break;
  772. case annotate_warning:
  773. s.append("#W#");
  774. break;
  775. case annotate_javadoc:
  776. s.append("#J#");
  777. break;
  778. case annotate_location:
  779. s.append("#L#");
  780. break;
  781. }
  782. }
  783. #endif
  784. expr = expr->queryBody(true);
  785. }
  786. if (isEclAlias(expr))
  787. {
  788. StringBuffer name;
  789. if(/*isTop || */ m_recurse)
  790. {
  791. doAlias(expr, name, inType);
  792. s.append(name.str());
  793. }
  794. else
  795. lookupSymbolName(expr, s);
  796. if(!inType && expr->queryFunctionDefinition() && !expandProcessed)
  797. {
  798. callEclFunction(s, expr, inType);
  799. }
  800. }
  801. else if (!expandNamed && !expr->isAttribute() && expr->queryId() && lower(expr->queryId()) != lower(unnamedId) )
  802. {
  803. appendId(s, expr->queryId());
  804. }
  805. else
  806. {
  807. if (expr->isDataset() || expr->isDictionary())
  808. {
  809. if (!isNamedSymbol && (expandProcessed || tryToRegenerate) && no != no_field && no != no_rows && !isTargetSelector(expr))
  810. {
  811. if (!expr->queryTransformExtra())
  812. {
  813. bool wasInsideNewTransform = insideNewTransform;
  814. insideNewTransform = false;
  815. StringBuffer temp;
  816. scope.append(NULL);
  817. if (expr->isDataset())
  818. temp.appendf("dataset%012" I64F "x ", (__uint64)(memsize_t)expr);
  819. else
  820. temp.appendf("dictionary%012" I64F "x ", (__uint64)(memsize_t)expr);
  821. #ifdef SHOW_NORMALIZED
  822. if (expandProcessed)
  823. temp.appendf("[N%p] ", expr->queryNormalizedSelector());
  824. #endif
  825. temp.append(":= ");
  826. toECL(expr, temp, false, false, 0, true);
  827. temp.append(";").newline();
  828. addExport(temp);
  829. scope.pop();
  830. insideNewTransform = wasInsideNewTransform;
  831. expr->setTransformExtra(expr);
  832. }
  833. if (expr->isDataset())
  834. s.appendf("dataset%012" I64F "x", (__uint64)(memsize_t)expr);
  835. else
  836. s.appendf("dictionary%012" I64F "x", (__uint64)(memsize_t)expr);
  837. if (paren)
  838. s.append(')');
  839. return;
  840. }
  841. switch (no)
  842. {
  843. case no_addfiles: // looks silly otherwise...
  844. case no_select:
  845. case no_field:
  846. case no_compound_selectnew:
  847. break;
  848. case no_compound_diskread:
  849. case no_compound_indexread:
  850. case no_compound_disknormalize:
  851. case no_compound_diskaggregate:
  852. case no_compound_diskcount:
  853. case no_compound_diskgroupaggregate:
  854. case no_compound_indexnormalize:
  855. case no_compound_indexaggregate:
  856. case no_compound_indexcount:
  857. case no_compound_indexgroupaggregate:
  858. case no_compound_childread:
  859. case no_compound_childnormalize:
  860. case no_compound_childaggregate:
  861. case no_compound_childcount:
  862. case no_compound_childgroupaggregate:
  863. case no_compound_inline:
  864. curDatasetDepth = -1000;
  865. break;
  866. default:
  867. if (curDatasetDepth >= maxDatasetDepth)
  868. {
  869. s.append("...");
  870. if (paren)
  871. s.append(')');
  872. return;
  873. }
  874. curDatasetDepth++;
  875. break;
  876. }
  877. }
  878. else if (expandProcessed && no == no_alias)
  879. {
  880. if (!isNamedSymbol)
  881. {
  882. if (!expr->queryTransformExtra())
  883. {
  884. bool wasInsideNewTransform = insideNewTransform;
  885. insideNewTransform = false;
  886. StringBuffer temp;
  887. scope.append(NULL);
  888. temp.appendf("alias%012" I64F "x ", (__uint64)(memsize_t)expr);
  889. temp.append(":= ");
  890. toECL(expr, temp, false, false, 0, true);
  891. temp.append(";").newline();
  892. addExport(temp);
  893. scope.pop();
  894. insideNewTransform = wasInsideNewTransform;
  895. expr->setTransformExtra(expr);
  896. }
  897. s.appendf("alias%012" I64F "x", (__uint64)(memsize_t)expr);
  898. if (paren)
  899. s.append(')');
  900. return;
  901. }
  902. }
  903. if (expandProcessed && !isNamedSymbol && no == no_record)
  904. {
  905. if (!expr->queryTransformExtra())
  906. {
  907. StringBuffer temp;
  908. scope.append(NULL);
  909. temp.appendf("record%012" I64F "x := ", (__uint64)(memsize_t)expr);
  910. toECL(expr, temp, false, false, 0, true);
  911. temp.append(";").newline();
  912. addExport(temp);
  913. scope.pop();
  914. expr->setTransformExtra(expr);
  915. }
  916. s.appendf("record%012" I64F "x", (__uint64)(memsize_t)expr);
  917. return;
  918. }
  919. unsigned startLength = s.length();
  920. switch(no)
  921. {
  922. case no_none:
  923. s.append("<NONE>");
  924. break;
  925. case no_pat_instance:
  926. if (!isNamedSymbol && expandProcessed)
  927. {
  928. //Stops generated code exploding - not strictly correct...
  929. if (!expr->queryTransformExtra())
  930. {
  931. bool wasInsideNewTransform = insideNewTransform;
  932. insideNewTransform = false;
  933. StringBuffer temp;
  934. scope.append(NULL);
  935. temp.appendf("pattern%012" I64F "x := ", (__uint64)(memsize_t)expr);
  936. toECL(expr, temp, false, false, 0, true);
  937. temp.append(";").newline();
  938. addExport(temp);
  939. scope.pop();
  940. insideNewTransform = wasInsideNewTransform;
  941. expr->setTransformExtra(expr);
  942. }
  943. s.appendf("pattern%012" I64F "x", (__uint64)(memsize_t)expr);
  944. return;
  945. }
  946. else if (expandProcessed)
  947. {
  948. defaultToECL(expr, s, inType);
  949. }
  950. else
  951. toECL(expr->queryChild(0), s, false, inType);
  952. break;
  953. case no_cast:
  954. {
  955. s.append('(');
  956. getTypeString(expr->queryType(), s);
  957. s.append(") ");
  958. toECL(child0, s, needParen(expr->getPrecedence(), child0), inType);
  959. break;
  960. }
  961. case no_implicitcast:
  962. if (expandProcessed)
  963. {
  964. s.append("((");
  965. getTypeString(expr->queryType(), s);
  966. s.append(")) ");
  967. }
  968. toECL(child0, s, child0->getPrecedence() < 0, inType);
  969. break;
  970. case no_param:
  971. {
  972. if (expandProcessed)
  973. s.append("no_param(");
  974. if(inType) // Hack !
  975. {
  976. getTypeString(expr->queryType(), s);
  977. s.append(' ');
  978. }
  979. lookupSymbolName(expr, s);
  980. if (expandProcessed)
  981. s.append(")");
  982. break;
  983. }
  984. case no_substring:
  985. toECL(child0, s, child0->getPrecedence() < 0, inType);
  986. if(child1)
  987. {
  988. s.append("[");
  989. toECL(child1, s, false, inType);
  990. s.append("]");
  991. }
  992. break;
  993. case no_rangefrom:
  994. toECL(child0, s, false, inType);
  995. s.append("..");
  996. break;
  997. case no_rangecommon:
  998. toECL(child0, s, false, inType);
  999. s.append("..*");
  1000. break;
  1001. case no_range:
  1002. toECL(child0, s, false, inType);
  1003. s.append("..");
  1004. toECL(child1, s, false, inType);
  1005. break;
  1006. case no_rangeto:
  1007. s.append("..");
  1008. toECL(child0, s, false, inType);
  1009. break;
  1010. case NO_AGGREGATEGROUP:
  1011. {
  1012. s.append(getEclOpString(no));
  1013. s.append("(group");
  1014. childrenToECL(expr, s, inType, true, 0);
  1015. s.append(')');
  1016. break;
  1017. }
  1018. case no_sortlist:
  1019. {
  1020. sortlistToEcl(expr, s, false, inType);
  1021. break;
  1022. }
  1023. case no_rowvalue:
  1024. {
  1025. s.append("{");
  1026. childrenToECL(expr, s, inType, false, 0);
  1027. s.append("}");
  1028. break;
  1029. }
  1030. case no_record:
  1031. {
  1032. bool fieldsInline = (recordIndex == 0) && (expr->numChildren() <= 3) && !isNamedSymbol;
  1033. if (fieldsInline)
  1034. s.append('{');
  1035. else
  1036. {
  1037. s.append("RECORD");
  1038. indent++;
  1039. }
  1040. bool hadAttr = false;
  1041. //Slightly weird. no_record inside a record imply inheritance, and have a slightly different syntax.
  1042. //Should probably be expanded when the graph is normalized...
  1043. ForEachChild(i2, expr)
  1044. {
  1045. IHqlExpression *child = queryChild(expr, i2);
  1046. if (child && child->getOperator() == no_record)
  1047. {
  1048. s.append("(");
  1049. if (isEclAlias(child) || !m_recurse)
  1050. toECL(child, s, false, inType, i2+1);
  1051. else
  1052. createPseudoSymbol(s, "record__", child);
  1053. s.append(")");
  1054. hadAttr = true;
  1055. }
  1056. }
  1057. ForEachChild(i1, expr)
  1058. {
  1059. IHqlExpression *child = queryChild(expr, i1);
  1060. if (child && child->isAttribute())
  1061. {
  1062. s.append(",");
  1063. toECL(child, s, false, inType, 0);
  1064. hadAttr = true;
  1065. }
  1066. }
  1067. if (!fieldsInline)
  1068. s.newline();
  1069. //First output the attributes...
  1070. //MORE: Add attributes to the record definition
  1071. bool first = true;
  1072. bool firstPayload = true;
  1073. ForEachChild(idx, expr)
  1074. {
  1075. IHqlExpression *child = queryChild(expr, idx);
  1076. if (child && !child->isAttribute() && child->getOperator() != no_record)
  1077. {
  1078. if (queryAddDotDotDot(s, startLength))
  1079. break;
  1080. if (fieldsInline)
  1081. {
  1082. if (!first)
  1083. {
  1084. if (firstPayload && child->hasAttribute(_payload_Atom))
  1085. {
  1086. s.append(" =>");
  1087. firstPayload = false;
  1088. }
  1089. else
  1090. s.append(",");
  1091. }
  1092. s.append(" ");
  1093. }
  1094. else
  1095. {
  1096. if (!first)
  1097. {
  1098. if (firstPayload && child->hasAttribute(_payload_Atom))
  1099. {
  1100. s.remove(s.length()-2,2).append("\n").pad(indent).append("=>\n");
  1101. firstPayload = false;
  1102. }
  1103. }
  1104. s.pad(indent);
  1105. }
  1106. toECL(child, s, false, inType, idx+1);
  1107. if (!fieldsInline)
  1108. s.append(";\n");
  1109. first = false;
  1110. }
  1111. }
  1112. if (fieldsInline)
  1113. s.append(" }");
  1114. else
  1115. s.pad(--indent).append("END");
  1116. break;
  1117. }
  1118. case no_ifblock:
  1119. {
  1120. s.append("IFBLOCK");
  1121. indent++;
  1122. toECL(expr->queryChild(0), s, true, inType);
  1123. s.append("\n");
  1124. IHqlExpression * record = expr->queryChild(1);
  1125. ForEachChild(idx2, record)
  1126. {
  1127. s.pad(indent);
  1128. toECL(record->queryChild(idx2), s, false, inType, indent*100*recordIndex+idx2+1);
  1129. s.append(";\n");
  1130. }
  1131. s.pad(--indent).append("END");
  1132. break;
  1133. }
  1134. case no_assignall:
  1135. {
  1136. IHqlExpression * original = expr->queryAttribute(_original_Atom);
  1137. if (original)
  1138. {
  1139. toECL(original->queryChild(0), s, false, inType);
  1140. s.append(" := ");
  1141. IHqlExpression * rhs = original->queryChild(1);
  1142. if (rhs->getOperator() == no_null)
  1143. s.append("[]");
  1144. else
  1145. toECL(rhs, s, false, inType);
  1146. }
  1147. else if (child0)
  1148. {
  1149. s.append("SELF := ");
  1150. IHqlExpression * rhs = child0->queryChild(1);
  1151. if (rhs->getOperator() == no_select)
  1152. {
  1153. IHqlExpression * lhs = child0->queryChild(0);
  1154. while (lhs->getOperator() == no_select)
  1155. {
  1156. lhs = lhs->queryChild(0);
  1157. rhs = rhs->queryChild(0);
  1158. }
  1159. toECL(rhs, s, false, inType);
  1160. }
  1161. else
  1162. s.append("[]");
  1163. }
  1164. if (expandProcessed)
  1165. {
  1166. s.append("/* ");
  1167. unsigned max = expr->numChildren();
  1168. for (unsigned idx = 0; idx < max; idx++)
  1169. {
  1170. if (idx) s.append("; ");
  1171. toECL(expr->queryChild(idx), s, false, inType);
  1172. }
  1173. s.append(" */");
  1174. }
  1175. break;
  1176. }
  1177. case no_index:
  1178. case no_selectnth:
  1179. case no_selectmap:
  1180. case no_pat_index:
  1181. {
  1182. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1183. s.append('[');
  1184. toECL(child1, s, child1->getPrecedence() < 0, inType);
  1185. s.append(']');
  1186. break;
  1187. }
  1188. case no_bor:
  1189. case no_band:
  1190. case no_bxor:
  1191. case no_div:
  1192. case no_mul:
  1193. case no_modulus:
  1194. case no_concat:
  1195. case no_add:
  1196. case no_addsets:
  1197. case no_assign:
  1198. case no_addfiles:
  1199. case no_sub:
  1200. case no_eq:
  1201. case no_ne:
  1202. case no_lt:
  1203. case no_le:
  1204. case no_gt:
  1205. case no_ge:
  1206. case no_and:
  1207. case no_or:
  1208. case no_pat_or:
  1209. case no_xor:
  1210. case no_mapto:
  1211. case no_order:
  1212. case no_notin:
  1213. case no_in:
  1214. case no_indict:
  1215. case no_colon:
  1216. case no_pat_select:
  1217. case no_lshift:
  1218. case no_rshift:
  1219. {
  1220. // Standard binary infix operators
  1221. precedence = expr->getPrecedence();
  1222. lparen = needParen(precedence, child0);
  1223. if (child0)
  1224. toECL(child0, s, lparen, inType);
  1225. else
  1226. s.append("?NULL?");
  1227. const char * opText = getEclOpString(no);
  1228. if ((no == no_div) && expr->queryType()->isInteger())
  1229. opText = "DIV";
  1230. if (no == no_addfiles)
  1231. {
  1232. if (isOrdered(expr))
  1233. opText = "&";
  1234. if (expr->hasAttribute(pullAtom))
  1235. opText = "&&";
  1236. }
  1237. unsigned num = expr->numChildren();
  1238. for (unsigned i=1; i < num; i++)
  1239. {
  1240. IHqlExpression * child = queryChild(expr, i);
  1241. if (child)
  1242. {
  1243. if ((no == no_addfiles) && child->isAttribute())
  1244. {
  1245. if (child->queryName() == orderedAtom)
  1246. continue;
  1247. }
  1248. if (xgmmlGraphText && endsWithDotDotDot(s))
  1249. break;
  1250. s.append(' ').append(opText).append(' ');
  1251. if (queryAddDotDotDot(s, startLength))
  1252. break;
  1253. toECL(child, s, needParen(precedence, child), inType);
  1254. }
  1255. }
  1256. break;
  1257. }
  1258. case no_subsort:
  1259. {
  1260. s.append(getEclOpString(expr->getOperator()));
  1261. s.append('(');
  1262. if (!xgmmlGraphText)
  1263. {
  1264. toECL(child0, s, false, inType);
  1265. queryNewline(s.append(", "));
  1266. }
  1267. pushScope(child0);
  1268. //MORE: Sortlists should always be generated using the {} syntax - then this could be simplified
  1269. //NOTE: child(1) and child(2) are output in a different order from their representation
  1270. s.append("{");
  1271. toECL(expr->queryChild(2), s, false, inType);
  1272. s.append("}");
  1273. queryNewline(s.append(", "));
  1274. s.append("{");
  1275. toECL(expr->queryChild(1), s, false, inType);
  1276. s.append("}");
  1277. childrenToECL(expr, s, inType, true, 3);
  1278. popScope();
  1279. s.append(')');
  1280. break;
  1281. }
  1282. case no_select:
  1283. {
  1284. if (!expandProcessed &&
  1285. (matchesActiveDataset(child0) ||
  1286. (child0->getOperator() == no_self && insideNewTransform) ||
  1287. (minimalSelectors && !isAlwaysActiveRow(child0)) ||
  1288. (minimalSelectors && child0->getOperator() == no_activetable))
  1289. )
  1290. toECL(child1, s, false, inType);
  1291. else
  1292. {
  1293. if (!expandProcessed)
  1294. {
  1295. OwnedHqlExpr aggregate = convertToSimpleAggregate(expr);
  1296. if (aggregate)
  1297. {
  1298. toECL(aggregate, s, false, inType);
  1299. break;
  1300. }
  1301. }
  1302. {
  1303. lparen = needParen(expr, child0);
  1304. if (expandProcessed && !expr->hasAttribute(newAtom) && child0->queryName())
  1305. s.append("<").append(child0->queryName()).append(">");
  1306. if (xgmmlGraphText && expr->hasAttribute(newAtom))
  1307. s.append("<...>");
  1308. else
  1309. toECL(child0, s, lparen, inType);
  1310. }
  1311. s.append(getEclOpString(no)); // <- note: no padding
  1312. rparen = needParen(expr, child1);
  1313. toECL(child1, s, rparen, inType);
  1314. }
  1315. if (expandProcessed)
  1316. {
  1317. unsigned max = expr->numChildren();
  1318. if (max != 2)
  1319. {
  1320. s.append("(<");
  1321. for (unsigned i=2; i < max; i++)
  1322. {
  1323. if (i != 2) s.append(",");
  1324. toECL(expr->queryChild(i), s, false, inType);
  1325. }
  1326. s.append(">)");
  1327. }
  1328. }
  1329. break;
  1330. }
  1331. case no_notnot:
  1332. case no_not:
  1333. case no_negate:
  1334. case no_within:
  1335. // Standard unary operators
  1336. precedence = expr->getPrecedence();
  1337. rparen = child0->getPrecedence() < precedence;
  1338. s.append(getEclOpString(no));
  1339. toECL(child0, s, rparen, inType);
  1340. break;
  1341. case no_between:
  1342. case no_notbetween:
  1343. // Standard ternary operators
  1344. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1345. s.append(getEclOpString(no));
  1346. toECL(child1, s, child0->getPrecedence() < 0, inType);
  1347. s.append(',');
  1348. toECL(expr->queryChild(2), s, expr->queryChild(2)->getPrecedence() < 0, inType);
  1349. break;
  1350. #ifndef SHOW_EXPAND_LEFTRIGHT
  1351. case no_left:
  1352. case no_right:
  1353. case no_top:
  1354. #endif
  1355. case no_self:
  1356. case no_rows:
  1357. if (expandProcessed)
  1358. defaultToECL(expr, s, inType);
  1359. else
  1360. s.append(getEclOpString(no));
  1361. #ifdef SHOWADDR
  1362. if (expandProcessed)
  1363. s.appendf("{@%p:%p}", expr->queryChild(0), expr->queryChild(1));
  1364. #endif
  1365. break;
  1366. case no_getgraphloopresultset:
  1367. if (xgmmlGraphText)
  1368. s.append("ROWSET");
  1369. else
  1370. defaultToECL(expr, s, inType);
  1371. break;
  1372. case no_sql:
  1373. case no_flat:
  1374. case no_all:
  1375. case no_activetable:
  1376. case no_counter:
  1377. s.append(getEclOpString(no));
  1378. break;
  1379. case no_selfref:
  1380. if (expandProcessed)
  1381. s.append("SELFref");
  1382. else
  1383. s.append(getEclOpString(no));
  1384. break;
  1385. case no_thor:
  1386. {
  1387. unsigned kids = expr->numChildren();
  1388. if(kids)
  1389. {
  1390. if (expandProcessed)
  1391. s.append(getEclOpString(no)).append("(");
  1392. bool first=true;
  1393. for (unsigned idx = 0; idx < kids; idx++)
  1394. {
  1395. IHqlExpression *child = expr->queryChild(idx);
  1396. if (expandProcessed || !child->isAttribute())
  1397. {
  1398. if (!first)
  1399. s.append(", ");
  1400. first=false;
  1401. toECL(child, s, false, inType);
  1402. }
  1403. }
  1404. if (expandProcessed)
  1405. s.append(")");
  1406. }
  1407. else
  1408. {
  1409. s.append(getEclOpString(no));
  1410. }
  1411. break;
  1412. }
  1413. case no_attr:
  1414. case no_attr_expr:
  1415. case no_attr_link:
  1416. {
  1417. if (isInternalAttribute(expr) && !expandProcessed)
  1418. break;
  1419. IAtom * name = expr->queryName();
  1420. s.append(expr->queryName());
  1421. if (name == _workflowPersist_Atom || name == _original_Atom)
  1422. {
  1423. s.append("(...)");
  1424. break;
  1425. }
  1426. if (child0)
  1427. {
  1428. s.append('(');
  1429. childrenToECL(expr, s, false, false, 0);
  1430. s.append(')');
  1431. }
  1432. else if (expr->querySequenceExtra())
  1433. {
  1434. //Not sure any of these should be included
  1435. s.append("(").append(expr->querySequenceExtra()).append(")");
  1436. }
  1437. break;
  1438. }
  1439. case no_constant:
  1440. {
  1441. expr->queryValue()->generateECL(s);
  1442. if (xgmmlGraphText && (s.length() - startLength) > MAX_GRAPHTEXT_LEN)
  1443. {
  1444. bool addQuote = s.charAt(s.length()-1) == '\'';
  1445. s.setLength(startLength+MAX_GRAPHTEXT_LEN);
  1446. s.append("...");
  1447. if (addQuote)
  1448. s.append("'");
  1449. }
  1450. break;
  1451. }
  1452. case no_list:
  1453. case no_datasetlist:
  1454. case no_recordlist:
  1455. case no_transformlist:
  1456. {
  1457. s.append('[');
  1458. for (unsigned idx = 0; idx < expr->numChildren(); idx++)
  1459. {
  1460. IHqlExpression *child = expr->queryChild(idx);
  1461. if (idx)
  1462. s.append(", ");
  1463. queryNewline(s);
  1464. toECL(child, s, child->getPrecedence() < 0, inType);
  1465. }
  1466. s.append(']');
  1467. break;
  1468. }
  1469. case no_call:
  1470. if (expandProcessed)
  1471. {
  1472. s.append("CALL(");
  1473. toECL(expr->queryBody()->queryFunctionDefinition(), s, false, inType);
  1474. defaultChildrenToECL(expr, s, inType);
  1475. s.append(")");
  1476. break;
  1477. }
  1478. //fall through
  1479. case no_externalcall:
  1480. {
  1481. // OK we got us an external call. Let's try and define it.
  1482. StringBuffer name;
  1483. if (m_recurse)
  1484. defineCallTarget(expr, name);
  1485. else if (xgmmlGraphText)
  1486. lookupSymbolName(expr, name);
  1487. else
  1488. {
  1489. lookupSymbolName(expr, name);
  1490. name.append('.');
  1491. lookupSymbolName(expr, name);
  1492. }
  1493. IHqlExpression *funcdef = (no==no_externalcall) ? expr->queryBody()->queryExternalDefinition() : expr->queryBody()->queryFunctionDefinition();
  1494. IHqlExpression *formals = funcdef ? funcdef->queryChild(1) : nullptr;
  1495. s.append(name);
  1496. s.append('(');
  1497. unsigned idx = 0;
  1498. bool first = true;
  1499. while(IHqlExpression *kid = expr->queryChild(idx))
  1500. {
  1501. bool isHidden = !expandProcessed && kid->isAttribute();
  1502. if (formals && !expandProcessed)
  1503. {
  1504. IHqlExpression *formal = formals->queryChild(idx);
  1505. isHidden = formal && formal->hasAttribute(_hidden_Atom);
  1506. }
  1507. if (!isHidden)
  1508. {
  1509. if (first)
  1510. first = false;
  1511. else
  1512. s.append(", ");
  1513. toECL(kid, s, kid->getPrecedence() < 0, inType);
  1514. }
  1515. idx++;
  1516. }
  1517. s.append(')');
  1518. break;
  1519. }
  1520. case no_external:
  1521. {
  1522. unsigned kids = expr->numChildren();
  1523. bool first = true;
  1524. for (unsigned idx = 0; idx < kids; idx++)
  1525. {
  1526. IHqlExpression *kid = expr->queryChild(idx);
  1527. if (kid->queryName() != pluginAtom)
  1528. {
  1529. if(first)
  1530. first = false;
  1531. else
  1532. s.append(", ");
  1533. s.append(kid->queryName());
  1534. if (kid->isAttribute())
  1535. {
  1536. IHqlExpression * value = kid->queryChild(0);
  1537. if (value)
  1538. {
  1539. IValue * val = value->queryValue();
  1540. if (val)
  1541. {
  1542. s.append("='");
  1543. val->getStringValue(s);
  1544. s.append('\'');
  1545. }
  1546. else
  1547. {
  1548. s.append("=");
  1549. toECL(value, s, false, inType);
  1550. }
  1551. }
  1552. }
  1553. }
  1554. }
  1555. break;
  1556. }
  1557. case no_pat_const:
  1558. case no_pat_imptoken:
  1559. toECL(expr->queryChild(0), s, false, inType);
  1560. break;
  1561. case no_pat_pattern:
  1562. s.append("PATTERN(");
  1563. toECL(expr->queryChild(0), s, false, inType);
  1564. s.append(")");
  1565. break;
  1566. case no_pat_checkin:
  1567. toECL(expr->queryChild(0), s, false, inType);
  1568. s.append(" IN ");
  1569. toECL(expr->queryChild(1), s, false, inType);
  1570. break;
  1571. case no_pat_repeat:
  1572. {
  1573. unsigned low = getRepeatMin(expr);
  1574. unsigned high = getRepeatMax(expr);
  1575. if (isStandardRepeat(expr))
  1576. {
  1577. toECL(expr->queryChild(0), s, false, inType);
  1578. if ((low == 0) && (high == 1))
  1579. s.append("?");
  1580. else if ((low == 0) && (high == (unsigned)-1))
  1581. s.append("*");
  1582. else if ((low == 1) && (high == (unsigned)-1))
  1583. s.append("+");
  1584. }
  1585. else
  1586. {
  1587. s.append("REPEAT(");
  1588. toECL(expr->queryChild(0), s, false, inType);
  1589. s.append(",").append(low);
  1590. if (low != high)
  1591. {
  1592. s.append(",");
  1593. if (high == (unsigned)-1)
  1594. s.append("ANY");
  1595. else
  1596. s.append(high);
  1597. }
  1598. if (expr->hasAttribute(minimalAtom))
  1599. s.append(",MINIMAL");
  1600. s.append(")");
  1601. }
  1602. break;
  1603. }
  1604. case no_pat_follow:
  1605. {
  1606. precedence = expr->getPrecedence();
  1607. ForEachChild(idx, expr)
  1608. {
  1609. if (idx) s.append(" ");
  1610. IHqlExpression * child = expr->queryChild(idx);
  1611. toECL(child, s, needParen(precedence, child), inType);
  1612. }
  1613. break;
  1614. }
  1615. case no_field:
  1616. {
  1617. IHqlExpression * kid = expr->queryChild(0);
  1618. if (kid && kid->isAttribute())
  1619. kid = NULL;
  1620. if (recordIndex || inType)
  1621. {
  1622. if (expr->queryName())
  1623. {
  1624. bool addTypeAndName = true;
  1625. if (kid)
  1626. {
  1627. IHqlExpression * field = NULL;
  1628. if (kid->getOperator() == no_field)
  1629. field = kid;
  1630. else if (kid->getOperator() == no_select)
  1631. field = kid->queryChild(1);
  1632. if (field)
  1633. if ((expr->queryType() == field->queryType()) && (expr->queryName() == field->queryName()))
  1634. addTypeAndName = false;
  1635. }
  1636. if (addTypeAndName)
  1637. {
  1638. getFieldTypeString(expr, s);
  1639. s.append(' ');
  1640. lookupSymbolName(expr, s);
  1641. //Add the attributes....
  1642. bool seenAttr = false;
  1643. ForEachChild(kids, expr)
  1644. {
  1645. IHqlExpression *attr = expr->queryChild(kids);
  1646. if (attr->isAttribute())
  1647. {
  1648. IAtom * name = attr->queryName();
  1649. if (name != countAtom && name != sizeofAtom &&
  1650. !(isInternalAttribute(attr) && !expandProcessed))
  1651. {
  1652. if ((name != virtualAtom) || !ignoreVirtualAttrs)
  1653. {
  1654. if (!seenAttr)
  1655. {
  1656. s.append('{');
  1657. seenAttr = true;
  1658. }
  1659. else
  1660. s.append(", ");
  1661. toECL(attr, s, false, inType);
  1662. }
  1663. }
  1664. }
  1665. }
  1666. if (seenAttr)
  1667. s.append('}');
  1668. if (kid)
  1669. {
  1670. s.append(" := ");
  1671. toECL(kid, s, false, inType);
  1672. }
  1673. }
  1674. else
  1675. toECL(kid, s, false, inType);
  1676. }
  1677. else if (kid)
  1678. {
  1679. assertex(expr->queryType() == kid->queryType());
  1680. toECL(kid, s, false, inType);
  1681. }
  1682. else
  1683. {
  1684. getTypeString(expr->queryType(), s);
  1685. s.append(" _unnamed_").append(recordIndex-1);
  1686. }
  1687. }
  1688. else
  1689. {
  1690. if (expr->queryName())
  1691. lookupSymbolName(expr, s);
  1692. else if (kid)
  1693. toECL(kid, s, false, inType);
  1694. else
  1695. s.append("????");
  1696. break;
  1697. }
  1698. break;
  1699. }
  1700. case no_filter:
  1701. {
  1702. StringBuffer tmp;
  1703. unsigned kids = expr->numChildren();
  1704. if (xgmmlGraphText)
  1705. s.append("FILTER");
  1706. else
  1707. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1708. pushScope(child0);
  1709. for (unsigned idx = 1; idx < kids; idx++)
  1710. {
  1711. if (idx > 1)
  1712. queryNewline(tmp.append(", "));
  1713. IHqlExpression *child = expr->queryChild(idx);
  1714. toECL(child, tmp, false, inType);
  1715. }
  1716. popScope();
  1717. if(tmp.length())
  1718. queryNewline(s.append('(').append(tmp).append(')'));
  1719. break;
  1720. }
  1721. case no_httpcall:
  1722. case no_soapcall:
  1723. case no_soapcall_ds:
  1724. case no_newsoapcall_ds:
  1725. {
  1726. IHqlExpression * resultFormat = queryNewColumnProvider(expr);
  1727. s.append(getEclOpString(no));
  1728. s.append('(');
  1729. bool needComma = false;
  1730. StringBuffer tmp;
  1731. unsigned kids = expr->numChildren();
  1732. if (!xgmmlGraphText)
  1733. {
  1734. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1735. needComma = true;
  1736. }
  1737. pushScope(child0);
  1738. for (unsigned idx = 1; idx < kids; idx++)
  1739. {
  1740. if (needComma)
  1741. s.append(", ");
  1742. IHqlExpression *child = expr->queryChild(idx);
  1743. if (expr->isDataset() && (child == resultFormat))
  1744. {
  1745. s.append("DATASET(");
  1746. toECL(child, s, false, inType);
  1747. s.append(")");
  1748. }
  1749. else
  1750. toECL(child, s, false, inType);
  1751. needComma = true;
  1752. }
  1753. popScope();
  1754. s.append(")");
  1755. break;
  1756. }
  1757. case no_inlinetable:
  1758. {
  1759. s.append("DATASET([");
  1760. ForEachChild(i, child0)
  1761. {
  1762. IHqlExpression * cur = child0->queryChild(i);
  1763. if (i)
  1764. s.append(",");
  1765. s.append("{");
  1766. bool first = true;
  1767. expandTransformValues(s, cur, first);
  1768. s.append("}");
  1769. queryNewline(s);
  1770. if (xgmmlGraphText)
  1771. {
  1772. if (child0->numChildren() != 1)
  1773. s.append(",...");
  1774. break;
  1775. }
  1776. }
  1777. s.append("]");
  1778. childrenToECL(expr, s, inType, true, 1);
  1779. s.append(')');
  1780. break;
  1781. }
  1782. case no_temptable:
  1783. {
  1784. s.append("DATASET(");
  1785. ITypeInfo * child0Type = child0->queryType();
  1786. if (child0Type && child0Type->getTypeCode() == type_set)
  1787. {
  1788. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1789. }
  1790. else
  1791. {
  1792. HqlExprArray records;
  1793. child0->unwindList(records, no_recordlist);
  1794. s.append('[');
  1795. for (unsigned idx = 0; idx < records.length(); idx++)
  1796. {
  1797. IHqlExpression * kid = &records.item(idx);
  1798. if(kid && !kid->isAttribute())
  1799. {
  1800. if (kid->getOperator() == no_record)
  1801. {
  1802. s.append('{');
  1803. bool first = true;
  1804. for (unsigned i = 0; i < kid->numChildren(); i++)
  1805. {
  1806. if (kid->queryChild(i)->isAttribute())
  1807. continue;
  1808. if (!first)
  1809. s.append(", ");
  1810. toECL(kid->queryChild(i)->queryChild(0), s, false, inType);
  1811. first = false;
  1812. }
  1813. s.append('}');
  1814. }
  1815. else
  1816. toECL(kid, s, false, inType);
  1817. }
  1818. if (xgmmlGraphText)
  1819. {
  1820. if (records.length() != 1)
  1821. s.append(",...");
  1822. break;
  1823. }
  1824. if (idx < records.length()-1)
  1825. s.append(',');
  1826. }
  1827. s.append(']');
  1828. }
  1829. if (child1)
  1830. {
  1831. toECL(child1, s.append(", "), child1->getPrecedence() < 0, inType);
  1832. }
  1833. if (expandProcessed)
  1834. childrenToECL(expr, s, inType, true, 2);
  1835. s.append(')');
  1836. break;
  1837. }
  1838. case no_temprow:
  1839. {
  1840. if (expandProcessed)
  1841. defaultToECL(expr, s, inType);
  1842. else
  1843. {
  1844. s.append("ROW(");
  1845. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1846. toECL(child1, s.append(", "), child1->getPrecedence() < 0, inType);
  1847. s.append(")");
  1848. }
  1849. break;
  1850. }
  1851. case no_workunit_dataset:
  1852. {
  1853. s.append("DATASET(WORKUNIT(");
  1854. toECL(child1, s, false, inType);
  1855. if (!isInternalAttribute(expr->queryChild(2)) || expandProcessed)
  1856. {
  1857. s.append(", ");
  1858. toECL(expr->queryChild(2), s, false, inType);
  1859. }
  1860. if (expandProcessed)
  1861. childrenToECL(expr, s, false, true, 3);
  1862. s.append("), ");
  1863. toECL(child0, s, false, inType);
  1864. s.append(")");
  1865. break;
  1866. }
  1867. case no_funcdef:
  1868. {
  1869. if (expandProcessed)
  1870. {
  1871. s.append("funcdef");
  1872. defaultChildrenToECL(expr->queryChild(1), s, inType);
  1873. s.append(" := {");
  1874. defaultToECL(expr->queryChild(0), s, inType);
  1875. s.append("}");
  1876. }
  1877. else
  1878. {
  1879. unsigned kids = expr->numChildren();
  1880. for (unsigned idx = 0; idx < kids; idx++)
  1881. {
  1882. if (idx)
  1883. {
  1884. s.append(", ");
  1885. }
  1886. IHqlExpression *child = expr->queryChild(idx);
  1887. toECL(child, s, child->getPrecedence() < 0, inType);
  1888. }
  1889. }
  1890. break;
  1891. }
  1892. case no_buildindex:
  1893. case no_output:
  1894. {
  1895. s.append(getEclOpString(expr->getOperator())).append('(');
  1896. if (child1 && child1->queryName() == sequenceAtom && !expandProcessed)
  1897. child1 = NULL;
  1898. if (xgmmlGraphText)
  1899. {
  1900. if (child1)
  1901. s.append("..., ");
  1902. else
  1903. s.append("...");
  1904. }
  1905. else
  1906. {
  1907. toECL(child0, s, false, inType);
  1908. if (child0->getOperator() == no_selectfields)
  1909. {
  1910. pushScope(child0->queryChild(0));
  1911. IHqlExpression * c1 = child0->queryChild(1);
  1912. if(c1->numChildren())
  1913. {
  1914. s.append(", ");
  1915. if (hasNamedSymbol(c1))
  1916. toECL(c1, s, c1->getPrecedence() < 0, inType);
  1917. else
  1918. {
  1919. s.append('{');
  1920. for (unsigned idx = 0; idx < c1->numChildren(); idx++)
  1921. {
  1922. if (idx)
  1923. s.append(", ");
  1924. IHqlExpression *child = c1->queryChild(idx);
  1925. toECL(child, s, child->getPrecedence() < 0, inType, idx+1);
  1926. }
  1927. s.append('}');
  1928. }
  1929. }
  1930. else if(child1 && !isInternalAttribute(child1))
  1931. {
  1932. s.append(", ");
  1933. }
  1934. popScope();
  1935. }
  1936. else if(child1 && !isInternalAttribute(child1))
  1937. {
  1938. s.append(", ");
  1939. }
  1940. }
  1941. StringBuffer next;
  1942. unsigned kids = expr->numChildren();
  1943. for (unsigned idx=1; idx < kids; idx++)
  1944. {
  1945. IHqlExpression * cur = queryChild(expr, idx);
  1946. if (cur)
  1947. {
  1948. toECL(cur, next.clear(), cur->getPrecedence() < 0, inType);
  1949. if (next.length())
  1950. s.append(", ").append(next);
  1951. }
  1952. }
  1953. s.append(')');
  1954. break;
  1955. }
  1956. case no_null:
  1957. if (expr->isDataset())
  1958. {
  1959. s.append("_EMPTY_(");
  1960. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1961. s.append(')');
  1962. }
  1963. else
  1964. {
  1965. //MORE!
  1966. }
  1967. break;
  1968. case no_typetransfer:
  1969. {
  1970. if (expr->isDatarow())
  1971. {
  1972. s.append(getEclOpString(no));
  1973. s.append('(');
  1974. toECL(child1, s, child0->getPrecedence() < 0, inType);
  1975. s.append(", ");
  1976. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1977. s.append(')');
  1978. }
  1979. else
  1980. {
  1981. s.append(getEclOpString(no));
  1982. s.append('(');
  1983. toECL(child0, s, child0->getPrecedence() < 0, inType);
  1984. s.append(", ");
  1985. getTypeString(expr->queryType(), s);
  1986. s.append(')');
  1987. }
  1988. break;
  1989. }
  1990. case no_embedbody:
  1991. {
  1992. s.append("BEGINC++\n");
  1993. IValue * value = child0->queryValue();
  1994. if (value)
  1995. value->getUTF8Value(s);
  1996. s.append("ENDC++\n");
  1997. break;
  1998. }
  1999. case no_nofold:
  2000. case no_nohoist:
  2001. case no_nocombine:
  2002. case no_selectfields:
  2003. case no_pure:
  2004. if (expandProcessed)
  2005. defaultToECL(expr, s, inType);
  2006. else
  2007. toECL(child0, s, false, inType);
  2008. break;
  2009. case no_clustersize:
  2010. if (expandProcessed)
  2011. defaultToECL(expr, s, inType);
  2012. else
  2013. s.append(getEclOpString(no));
  2014. break;
  2015. case no_map:
  2016. {
  2017. unsigned kids = expr->numChildren();
  2018. s.append(getEclOpString(no));
  2019. s.append('(');
  2020. for (unsigned idx = 0; idx < kids; idx++)
  2021. {
  2022. if (idx)
  2023. {
  2024. s.append(",");
  2025. if (!xgmmlGraphText)
  2026. s.append("\n\t ");
  2027. }
  2028. IHqlExpression *child = expr->queryChild(idx);
  2029. if (xgmmlGraphText && expr->isDataset() && idx != kids-1)
  2030. child = child->queryChild(0);
  2031. toECL(child, s, child->getPrecedence() < 0, inType);
  2032. }
  2033. s.append(')');
  2034. break;
  2035. }
  2036. case no_newtransform:
  2037. {
  2038. if (expandProcessed)
  2039. {
  2040. defaultToECL(expr, s, inType);
  2041. break;
  2042. }
  2043. // assertex(expandProcessed || !insideNewTransform);
  2044. bool wasInsideNewTransform = insideNewTransform;
  2045. insideNewTransform = true;
  2046. s.append("{ ");
  2047. unsigned kids = expr->numChildren();
  2048. for (unsigned idx = 0; idx < kids; idx++)
  2049. {
  2050. if (idx) s.append(", ");
  2051. IHqlExpression *child = expr->queryChild(idx);
  2052. if (!child->isAttribute())
  2053. getTypeString(child->queryChild(0)->queryType(), s);
  2054. toECL(child, s.append(' '), child->getPrecedence() < 0, inType);
  2055. }
  2056. s.append(" }");
  2057. insideNewTransform = wasInsideNewTransform;
  2058. break;
  2059. }
  2060. case no_transform:
  2061. {
  2062. if (isNamedSymbol)
  2063. {
  2064. s.append(getEclOpString(no)).newline();
  2065. unsigned kids = expr->numChildren();
  2066. for (unsigned idx = 0; idx < kids; idx++)
  2067. {
  2068. IHqlExpression *child = expr->queryChild(idx);
  2069. toECL(child, s.append('\t'), child->getPrecedence() < 0, inType);
  2070. s.append(';').newline();
  2071. }
  2072. s.append("\tEND");
  2073. }
  2074. else
  2075. {
  2076. s.append("TRANSFORM(");
  2077. getTypeString(expr->queryType(), s);
  2078. s.append(",");
  2079. if (tryToRegenerate)
  2080. s.newline();
  2081. unsigned kids = expr->numChildren();
  2082. for (unsigned idx = 0; idx < kids; idx++)
  2083. {
  2084. if (queryAddDotDotDot(s, startLength))
  2085. break;
  2086. IHqlExpression *child = expr->queryChild(idx);
  2087. if (tryToRegenerate)
  2088. s.append("\t");
  2089. toECL(child, s, child->getPrecedence() < 0, inType);
  2090. s.append(';');
  2091. if (tryToRegenerate)
  2092. s.newline();
  2093. }
  2094. s.append(")");
  2095. }
  2096. break;
  2097. }
  2098. case no_newaggregate:
  2099. case no_newusertable:
  2100. {
  2101. s.append(getEclOpString(no));
  2102. s.append('(');
  2103. assertex(child0);
  2104. bool addComma = !xgmmlGraphText;
  2105. if (!xgmmlGraphText)
  2106. toECL(child0, s, false, inType);
  2107. pushScope(child0);
  2108. unsigned start = 2;
  2109. if (expandProcessed)
  2110. start = 1;
  2111. else if (isEclAlias(child1))
  2112. {
  2113. if (addComma)
  2114. s.append(", ");
  2115. toECL(child1, s, false, inType);
  2116. addComma = true;
  2117. start = 3;
  2118. }
  2119. childrenToECL(expr, s, inType, addComma, start);
  2120. popScope();
  2121. s.append(')');
  2122. break;
  2123. }
  2124. case no_newkeyindex:
  2125. {
  2126. s.append(getEclOpString(no));
  2127. s.append('(');
  2128. bool addComma = false;
  2129. if (!xgmmlGraphText)
  2130. {
  2131. toECL(child0, s, false, inType);
  2132. addComma = true;
  2133. }
  2134. pushScope(child0);
  2135. unsigned kids = expr->numChildren();
  2136. unsigned payloadFields = numPayloadFields(expr);
  2137. for (unsigned idx = 1; idx < kids; idx++)
  2138. {
  2139. IHqlExpression * child = queryChild(expr, idx);
  2140. if (child && ((idx != 2) || expandProcessed))
  2141. {
  2142. if (addComma) s.append(", ");
  2143. addComma = true;
  2144. //Normally this is called when file position special field has been removed.
  2145. if ((idx == 1) && (payloadFields != 0) && !expandProcessed)
  2146. {
  2147. OwnedHqlExpr keyedRecord;
  2148. OwnedHqlExpr payloadRecord;
  2149. splitPayload(keyedRecord, payloadRecord, child, payloadFields);
  2150. toECL(keyedRecord, s, false, inType);
  2151. toECL(payloadRecord, s.append(", "), false, inType);
  2152. }
  2153. else
  2154. toECL(child, s, false, inType);
  2155. }
  2156. }
  2157. popScope();
  2158. s.append(')');
  2159. break;
  2160. }
  2161. case no_keyindex:
  2162. {
  2163. unsigned payloadFields = numPayloadFields(expr);
  2164. s.append(getEclOpString(no));
  2165. s.append('(');
  2166. bool addComma = false;
  2167. if (!xgmmlGraphText)
  2168. {
  2169. toECL(child0, s, false, inType);
  2170. addComma = true;
  2171. }
  2172. pushScope(child0);
  2173. unsigned kids = expr->numChildren();
  2174. for (unsigned idx = 1; idx < kids; idx++)
  2175. {
  2176. IHqlExpression * child = queryChild(expr, idx);
  2177. if (child)
  2178. {
  2179. if (addComma) s.append(", ");
  2180. addComma = true;
  2181. if ((idx == 1) && (payloadFields != 1) && !expandProcessed)
  2182. {
  2183. OwnedHqlExpr keyedRecord;
  2184. OwnedHqlExpr payloadRecord;
  2185. splitPayload(keyedRecord, payloadRecord, child, payloadFields);
  2186. toECL(keyedRecord, s, false, inType);
  2187. toECL(payloadRecord, s.append(", "), false, inType);
  2188. }
  2189. else
  2190. toECL(child, s, false, inType);
  2191. }
  2192. }
  2193. popScope();
  2194. s.append(')');
  2195. break;
  2196. }
  2197. case no_preservemeta:
  2198. if (xgmmlGraphText)
  2199. {
  2200. curDatasetDepth--;
  2201. toECL(child0, s, false, inType);
  2202. curDatasetDepth++;
  2203. }
  2204. else if (tryToRegenerate)
  2205. defaultToECL(child0, s, inType);
  2206. else
  2207. defaultToECL(expr, s, inType);
  2208. break;
  2209. case no_callsideeffect:
  2210. if (xgmmlGraphText)
  2211. s.append("...");
  2212. else
  2213. defaultToECL(expr, s, inType);
  2214. break;
  2215. case no_hqlproject:
  2216. case no_iterate:
  2217. {
  2218. s.append(getEclOpString(no));
  2219. s.append('(');
  2220. // Left
  2221. if (!xgmmlGraphText)
  2222. toECL(child0, s, false, inType);
  2223. pushScope(NULL);
  2224. // Transform
  2225. if(child1)
  2226. {
  2227. // I need to feed Left to the transform function definition.
  2228. mapDatasetRecord(child0);
  2229. if (!xgmmlGraphText)
  2230. s.append(", ");
  2231. toECL(child1, s, false, inType);
  2232. popMapping();
  2233. }
  2234. childrenToECL(expr, s, inType, true, 2);
  2235. popScope();
  2236. s.append(')');
  2237. break;
  2238. }
  2239. case no_fetch:
  2240. case no_join:
  2241. case no_selfjoin:
  2242. {
  2243. unsigned kids = expr->numChildren();
  2244. s.append(getEclOpString(no));
  2245. s.append('(');
  2246. if (!xgmmlGraphText)
  2247. {
  2248. toECL(child0, s, false, inType);
  2249. // Right
  2250. s.append(", ");
  2251. toECL(queryJoinRhs(expr), s, false, inType);
  2252. }
  2253. pushScope(NULL);
  2254. // Condition
  2255. if(kids > 2)
  2256. {
  2257. if (!xgmmlGraphText)
  2258. s.append(", ");
  2259. toECL(expr->queryChild(2), s, false, inType);
  2260. }
  2261. // Transform
  2262. if(kids > 3)
  2263. {
  2264. // I need to feed Left and Right to the transform function definition.
  2265. mapDatasetRecord(child0);
  2266. mapDatasetRecord(queryJoinRhs(expr));
  2267. toECL(expr->queryChild(3), s.append(", "), false, inType);
  2268. popMapping();
  2269. popMapping();
  2270. }
  2271. // Join type
  2272. if(kids > 4)
  2273. {
  2274. for (unsigned i=4; i < kids; i++)
  2275. {
  2276. IHqlExpression * next = queryChild(expr, i);
  2277. if (next)
  2278. toECL(next, s.append(", "), false, inType);
  2279. }
  2280. }
  2281. s.append(')');
  2282. popScope();
  2283. break;
  2284. }
  2285. case no_sizeof:
  2286. {
  2287. IHqlExpression* child = expr->queryChild(0);
  2288. s.append("sizeof(");
  2289. if (child->getOperator()==no_null)
  2290. child->queryType()->getECLType(s);
  2291. else
  2292. toECL(child,s,false,inType);
  2293. if (child1)
  2294. toECL(child1, s.append(", "), false, inType);
  2295. s.append(")");
  2296. break;
  2297. }
  2298. case no_evaluate:
  2299. {
  2300. s.append(getEclOpString(no));
  2301. s.append('(');
  2302. toECL(child0, s, false, inType);
  2303. s.append(", ");
  2304. pushScope(child0);
  2305. toECL(child1, s, false, inType);
  2306. popScope();
  2307. s.append(')');
  2308. break;
  2309. }
  2310. case no_setmeta:
  2311. {
  2312. IAtom * kind = expr->queryChild(0)->queryName();
  2313. if (kind == debugAtom)
  2314. s.append("#OPTION");
  2315. else if (kind == constAtom)
  2316. s.append("#CONSTANT");
  2317. else if (kind == storedAtom)
  2318. s.append("#STORED");
  2319. else if (kind == workunitAtom)
  2320. s.append("#WORKUNIT");
  2321. else if (kind == webserviceAtom)
  2322. s.append("#WEBSERVICE");
  2323. else
  2324. s.append("#META:").append(kind);
  2325. s.append(" (");
  2326. unsigned kids = expr->numChildren();
  2327. for (unsigned idx = 1; idx < kids; idx++)
  2328. {
  2329. if (idx != 1)
  2330. s.append(", ");
  2331. toECL(expr->queryChild(idx), s, false, inType);
  2332. }
  2333. s.append(")");
  2334. break;
  2335. }
  2336. case NO_AGGREGATE:
  2337. {
  2338. // standard function-style operators
  2339. unsigned kids = expr->numChildren();
  2340. s.append(getEclOpString(no));
  2341. if (child0)
  2342. {
  2343. s.append('(');
  2344. toECL(child0, s, false, inType);
  2345. pushScope(child0);
  2346. for (unsigned idx = 1; idx < kids; idx++)
  2347. {
  2348. IHqlExpression * cur = expr->queryChild(idx);
  2349. if (expandProcessed || !cur->isAttribute())
  2350. {
  2351. if (idx != 0)
  2352. s.append(", ");
  2353. toECL(cur, s, false, inType);
  2354. }
  2355. }
  2356. popScope();
  2357. s.append(')');
  2358. }
  2359. break;
  2360. }
  2361. case no_pat_featureactual:
  2362. {
  2363. toECL(child0, s, false, inType);
  2364. s.append("{");
  2365. toECL(child1, s, false, inType);
  2366. s.append("}");
  2367. break;
  2368. }
  2369. case no_comma:
  2370. toECL(child0, s, false, inType);
  2371. s.append(",");
  2372. toECL(child1, s, false, inType);
  2373. break;
  2374. case no_compound:
  2375. if (!expandProcessed)
  2376. {
  2377. toECL(child0, s, false, inType);
  2378. s.append(",");
  2379. if (!xgmmlGraphText)
  2380. s.newline();
  2381. toECL(child1, s, false, inType);
  2382. }
  2383. else
  2384. defaultToECL(expr, s, inType);
  2385. break;
  2386. case no_choosen:
  2387. {
  2388. // standard function-style operators
  2389. unsigned kids = expr->numChildren();
  2390. s.append(getEclOpString(no));
  2391. s.append('(');
  2392. unsigned noCommaArg = 1;
  2393. if (!xgmmlGraphText || !child0->queryDataset())
  2394. {
  2395. toECL(child0, s, false, inType);
  2396. noCommaArg = 0;
  2397. }
  2398. pushScope(child0);
  2399. for (unsigned idx = 1; idx < kids; idx++)
  2400. {
  2401. if (idx != noCommaArg)
  2402. s.append(", ");
  2403. IHqlExpression * cur = expr->queryChild(idx);
  2404. if ((idx == 1) && isChooseNAllLimit(cur))
  2405. s.append("ALL");
  2406. else
  2407. toECL(cur, s, false, inType);
  2408. }
  2409. popScope();
  2410. s.append(')');
  2411. break;
  2412. }
  2413. case no_matchattr:
  2414. {
  2415. unsigned index;
  2416. if (expr->isDatarow())
  2417. index = (unsigned)getIntValue(child1);
  2418. else
  2419. index = (unsigned)getIntValue(child0);
  2420. s.append('$').append(index+1);
  2421. break;
  2422. }
  2423. case no_setresult:
  2424. #if 0
  2425. if (xgmmlGraphText && scope.ordinality() == 0 && child0->getOperator() == no_select)
  2426. {
  2427. pushScope(child0->queryChild(0));
  2428. defaultToECL(expr, s, inType);
  2429. popScope();
  2430. }
  2431. else
  2432. #endif
  2433. defaultToECL(expr, s, inType);
  2434. break;
  2435. case no_getresult:
  2436. {
  2437. IHqlExpression * name = queryAttributeChild(expr, namedAtom, 0);
  2438. switch (getIntValue(queryAttributeChild(expr, sequenceAtom, 0)))
  2439. {
  2440. case ResultSequencePersist:
  2441. s.append("PERSIST(");
  2442. break;
  2443. case ResultSequenceStored:
  2444. s.append("STORED(");
  2445. break;
  2446. case ResultSequenceInternal:
  2447. s.append("INTERNAL(");
  2448. break;
  2449. default:
  2450. s.append("RESULT(");
  2451. if (!name)
  2452. s.append(getIntValue(queryAttributeChild(expr, sequenceAtom, 0)+1));
  2453. break;
  2454. }
  2455. if (name)
  2456. name->toString(s);
  2457. s.append(")");
  2458. break;
  2459. }
  2460. case no_metaactivity:
  2461. if (expr->hasAttribute(pullAtom))
  2462. s.append("PULL");
  2463. else if (expr->hasAttribute(traceAtom))
  2464. s.append("TRACE");
  2465. else
  2466. s.append("no_metaactivity:unknown");
  2467. defaultChildrenToECL(expr, s, inType);
  2468. break;
  2469. case no_getgraphresult:
  2470. case no_setgraphresult:
  2471. if (expandProcessed || tryToRegenerate)
  2472. defaultToECL(expr, s, inType);
  2473. else
  2474. {
  2475. s.append(getOpString(no));
  2476. toECL(expr->queryChild(2), s, true, inType);
  2477. }
  2478. break;
  2479. case no_alias:
  2480. case no_activerow:
  2481. case no_outofline:
  2482. case no_inline:
  2483. if (expandProcessed)
  2484. defaultToECL(expr, s, inType);
  2485. else
  2486. toECL(child0, s, false, inType);
  2487. break;
  2488. case no_loopcounter:
  2489. if (expandProcessed)
  2490. defaultToECL(expr, s, inType);
  2491. else
  2492. s.append(getOpString(no));
  2493. break;
  2494. case no_omitted:
  2495. if (expandProcessed)
  2496. defaultToECL(expr, s, inType);
  2497. break;
  2498. case no_compound_selectnew:
  2499. if (expandProcessed)
  2500. defaultToECL(expr, s, inType);
  2501. else if (child0->getOperator() == no_select)
  2502. toECL(child0->queryChild(1), s, false, inType);
  2503. else
  2504. toECL(child0, s, false, inType);
  2505. break;
  2506. case no_random:
  2507. defaultToECL(expr, s, inType);
  2508. //s.append("()"); not needed since it always has a hidden parameter which causes () to be generated.
  2509. break;
  2510. case no_subgraph:
  2511. {
  2512. if (tryToRegenerate)
  2513. {
  2514. childrenToECL(expr, s, false, false, 0);
  2515. }
  2516. else
  2517. {
  2518. s.append(getEclOpString(expr->getOperator())).append("(");
  2519. ForEachChild(i, expr)
  2520. {
  2521. s.newline().append("\t");
  2522. toECL(expr->queryChild(i), s, false, inType);
  2523. }
  2524. s.append(")");
  2525. break;
  2526. }
  2527. }
  2528. case no_sequence:
  2529. if (expr->queryName())
  2530. s.append(expr->queryName());
  2531. else
  2532. s.append("SEQ");
  2533. s.append("(").append(expr->querySequenceExtra()).append(")");
  2534. break;
  2535. case no_virtualscope:
  2536. case no_concretescope:
  2537. case no_forwardscope:
  2538. {
  2539. IHqlScope * scope = expr->queryScope();
  2540. #ifdef SHOW_MODULE_STATUS
  2541. if (expandProcessed)
  2542. {
  2543. IHqlScope * concrete = scope->queryConcreteScope();
  2544. if (scope == concrete)
  2545. s.append("[concrete]");
  2546. else if (!concrete)
  2547. s.append("[abstract]");
  2548. else
  2549. s.append("[virtual with concrete]");
  2550. }
  2551. #endif
  2552. defaultToECL(expr, s, inType);
  2553. s.newline();
  2554. HqlExprArray syms;
  2555. scope->getSymbols(syms);
  2556. syms.sort(compareSymbolsByName);
  2557. ForEachItemIn(i, syms)
  2558. {
  2559. toECL(&syms.item(i), s.append("\t"), false, false);
  2560. s.append(";").newline();
  2561. }
  2562. s.append("END;").newline();
  2563. break;
  2564. }
  2565. case no_type:
  2566. {
  2567. IHqlScope * scope = expr->queryScope();
  2568. s.append("TYPE").newline();
  2569. HqlExprArray syms;
  2570. scope->getSymbols(syms);
  2571. syms.sort(compareSymbolsByName);
  2572. ForEachItemIn(i, syms)
  2573. {
  2574. toECL(&syms.item(i), s, false, true);
  2575. }
  2576. s.append("END");
  2577. break;
  2578. }
  2579. case no_libraryscopeinstance:
  2580. if (xgmmlGraphText)
  2581. {
  2582. IHqlExpression * module = expr->queryDefinition()->queryChild(0);
  2583. s.append("LIBRARY(");
  2584. toECL(module->queryAttribute(nameAtom)->queryChild(0), s, false, inType);
  2585. s.append(')');
  2586. }
  2587. else
  2588. {
  2589. s.append(getEclOpString(no));
  2590. s.append('(');
  2591. childrenToECL(expr, s, inType, false, 0);
  2592. s.append(')');
  2593. }
  2594. break;
  2595. case no_typedef:
  2596. {
  2597. getTypeString(expr->queryType(), s);
  2598. if (expr->numChildren())
  2599. {
  2600. s.append("{");
  2601. childrenToECL(expr, s, inType, false, 0);
  2602. s.append("}");
  2603. }
  2604. break;
  2605. }
  2606. case no_split:
  2607. case no_compound_diskread:
  2608. if (xgmmlGraphText && isEclAlias(child0))
  2609. {
  2610. curDatasetDepth--;
  2611. toECL(child0, s, false, inType);
  2612. curDatasetDepth++;
  2613. }
  2614. else if (tryToRegenerate)
  2615. toECL(child0, s, false, inType);
  2616. else
  2617. defaultToECL(expr, s, inType);
  2618. break;
  2619. case no_assert_ds:
  2620. if (xgmmlGraphText)
  2621. {
  2622. pushScope(child0);
  2623. childrenToECL(expr, s, inType, false, 1);
  2624. popScope();
  2625. }
  2626. else
  2627. defaultToECL(expr, s, inType);
  2628. break;
  2629. case no_compound_indexread:
  2630. case no_compound_disknormalize:
  2631. case no_compound_diskaggregate:
  2632. case no_compound_diskcount:
  2633. case no_compound_diskgroupaggregate:
  2634. case no_compound_indexnormalize:
  2635. case no_compound_indexaggregate:
  2636. case no_compound_indexcount:
  2637. case no_compound_indexgroupaggregate:
  2638. case no_compound_childread:
  2639. case no_compound_childnormalize:
  2640. case no_compound_childaggregate:
  2641. case no_compound_childcount:
  2642. case no_compound_childgroupaggregate:
  2643. case no_compound_inline:
  2644. if (tryToRegenerate)
  2645. toECL(child0, s, false, inType);
  2646. else
  2647. defaultToECL(expr, s, inType);
  2648. break;
  2649. //case no_table:
  2650. //case no_count:
  2651. //case no_if:
  2652. case no_simplified:
  2653. s.append(getEclOpString(no));
  2654. s.append('(');
  2655. getTypeString(expr->queryType(), s);
  2656. s.append(')');
  2657. break;
  2658. default:
  2659. defaultToECL(expr, s, inType);
  2660. break;
  2661. }
  2662. }
  2663. if (paren)
  2664. s.append(')');
  2665. curDatasetDepth = savedDatasetDepth;
  2666. }
  2667. void HqltHql::defaultToECL(IHqlExpression *expr, StringBuffer &s, bool inType)
  2668. {
  2669. // standard function-style operators
  2670. s.append(getEclOpString(expr->getOperator()));
  2671. defaultChildrenToECL(expr, s, inType);
  2672. }
  2673. void HqltHql::defaultChildrenToECL(IHqlExpression *expr, StringBuffer &s, bool inType)
  2674. {
  2675. // standard function-style operators
  2676. IHqlExpression * child0 = expr->queryChild(0);
  2677. if (child0)
  2678. {
  2679. s.append('(');
  2680. bool needComma = false;
  2681. if (!xgmmlGraphText || (!child0->queryDataset() && !isInternalAttribute(child0)))
  2682. {
  2683. toECL(child0, s, false, inType);
  2684. needComma = true;
  2685. }
  2686. if (child0->queryDataset())
  2687. pushScope(child0);
  2688. childrenToECL(expr, s, inType, needComma, 1);
  2689. if (child0->queryDataset())
  2690. popScope();
  2691. s.append(')');
  2692. }
  2693. }
  2694. void HqltHql::sortlistToEcl(IHqlExpression *expr, StringBuffer &s, bool addCurleys, bool inType)
  2695. {
  2696. unsigned startLength = s.length();
  2697. if (addCurleys)
  2698. s.append("{ ");
  2699. bool needComma = false;
  2700. ForEachChild(idx, expr)
  2701. {
  2702. IHqlExpression * child = queryChild(expr, idx);
  2703. if (child && (expandProcessed || !isInternalAttribute(expr)))
  2704. {
  2705. if (needComma) queryNewline(s.append(", "));
  2706. if (queryAddDotDotDot(s, startLength))
  2707. break;
  2708. needComma = true;
  2709. toECL(child, s, false, inType);
  2710. }
  2711. }
  2712. if (addCurleys)
  2713. s.append(" }");
  2714. }
  2715. StringBuffer &HqltHql::getFieldTypeString(IHqlExpression * e, StringBuffer &s)
  2716. {
  2717. ITypeInfo * type = e->queryType();
  2718. ITypeInfo * cur = type;
  2719. for(;;)
  2720. {
  2721. typemod_t mod = cur->queryModifier();
  2722. if (mod == typemod_none)
  2723. break;
  2724. if (mod == typemod_attr)
  2725. {
  2726. IHqlExpression * attr = (IHqlExpression *)cur->queryModifierExtra();
  2727. if (!isInternalAttribute(attr))
  2728. s.append(attr->queryName()).append(" ");
  2729. }
  2730. cur = cur->queryTypeBase();
  2731. }
  2732. switch (type->getTypeCode())
  2733. {
  2734. case type_groupedtable:
  2735. s.append("GROUPED ");
  2736. type = type->queryChildType();
  2737. //fall through
  2738. case type_table:
  2739. case type_dictionary:
  2740. {
  2741. s.append(type->getTypeCode()==type_dictionary ? "DICTIONARY(" : "DATASET(");
  2742. getTypeString(type->queryChildType()->queryChildType(), s);
  2743. ForEachChild(i, e)
  2744. {
  2745. IHqlExpression * cur = e->queryChild(i);
  2746. if (cur->isAttribute())
  2747. {
  2748. IAtom * name = cur->queryName();
  2749. if (name == countAtom || name == sizeofAtom)
  2750. {
  2751. toECL(cur, s.append(", "), false, false);
  2752. }
  2753. }
  2754. }
  2755. return s.append(")");
  2756. }
  2757. case type_row:
  2758. return getTypeString(type->queryChildType(), s);
  2759. default:
  2760. return getTypeString(type, s);
  2761. }
  2762. }
  2763. StringBuffer &HqltHql::getTypeString(ITypeInfo * i, StringBuffer &s)
  2764. {
  2765. type_t t = i->getTypeCode();
  2766. switch (t)
  2767. {
  2768. case type_transform:
  2769. i = i->queryChildType();
  2770. //fallthrough
  2771. case type_record:
  2772. case type_row:
  2773. {
  2774. ITypeInfo * original = queryModifier(i, typemod_original);
  2775. IHqlExpression * expr;
  2776. StringBuffer name;
  2777. if (original)
  2778. {
  2779. expr = (IHqlExpression *)original->queryModifierExtra();
  2780. toECL(expr, name, false, false);
  2781. }
  2782. else
  2783. {
  2784. i->getECLType(name);
  2785. expr = queryMapped(queryExpression(queryRecordType(i)));
  2786. }
  2787. StringBuffer tmp;
  2788. if(expr->queryName()==lower(unnamedId))
  2789. {
  2790. HqlExprArray * visited = findVisitedArray();
  2791. for (unsigned idx = 0; idx < visited->ordinality(); idx++)
  2792. {
  2793. IHqlExpression * e = &(visited->item(idx));
  2794. IHqlExpression * extra = static_cast<IHqlExpression *>(e->queryTransformExtra());
  2795. if(e->queryChild(1) && extra)
  2796. {
  2797. if(expr->queryType() == e->queryChild(1)->queryType())
  2798. {
  2799. appendId(tmp, e->queryId());
  2800. break;
  2801. }
  2802. }
  2803. }
  2804. if (!tmp.length())
  2805. {
  2806. //unusual - an inline record definition e.g. { string x } myTransform(...) := transform
  2807. toECL(expr, tmp, false, false);
  2808. }
  2809. }
  2810. else if (isPublicSymbol(expr))
  2811. {
  2812. doAlias(expr, name, false);
  2813. }
  2814. else if (!expr->queryTransformExtra())
  2815. {
  2816. if (isSymbolDefined(expr))
  2817. {
  2818. clashCounter++;
  2819. name.append("___").append(clashCounter);
  2820. }
  2821. OwnedHqlExpr extra = createId(createIdAtom(name.str()));
  2822. expr->setTransformExtra(extra); // LINKs !
  2823. addVisited(expr);
  2824. tmp.append(name);
  2825. tmp.append(" := ");
  2826. toECL(expr->queryBody(), tmp, false, false, 0, true);
  2827. tmp.append(";").newline().newline();
  2828. addExport(tmp);
  2829. tmp.clear();
  2830. }
  2831. else
  2832. {
  2833. IHqlExpression * prev = (IHqlExpression *)expr->queryTransformExtra();
  2834. IIdAtom * prevId = prev->queryId();
  2835. appendId(name.clear(), prevId);
  2836. }
  2837. if(tmp.length())
  2838. {
  2839. s.append(tmp);
  2840. }
  2841. else
  2842. {
  2843. s.append(name);
  2844. }
  2845. break;
  2846. }
  2847. case type_alien:
  2848. {
  2849. IHqlExpression * expr = queryExpression(i);
  2850. if (expr)
  2851. {
  2852. toECL(expr, s, false, false);
  2853. return s;
  2854. }
  2855. break;
  2856. }
  2857. // case type_row:
  2858. case type_table:
  2859. // case type_groupedtable:
  2860. break;
  2861. case type_filepos:
  2862. getTypeString(i->queryChildType(), s);
  2863. break;
  2864. default:
  2865. ITypeInfo * original = queryModifier(i, typemod_original);
  2866. IHqlExpression * originalExpr = NULL;
  2867. if (original)
  2868. originalExpr = (IHqlExpression *)original->queryModifierExtra();
  2869. if (originalExpr && (originalExpr->getOperator() == no_typedef))
  2870. toECL(originalExpr, s, false, false);
  2871. else if (t == type_set)
  2872. {
  2873. s.append("set of ");
  2874. i = i->queryChildType();
  2875. if (i)
  2876. getTypeString(i, s);
  2877. else
  2878. s.append("any");
  2879. }
  2880. else
  2881. i->getECLType(s);
  2882. break;
  2883. }
  2884. return s;
  2885. }
  2886. const char * HqltHql::getEclOpString(node_operator op)
  2887. {
  2888. switch(op)
  2889. {
  2890. case no_ave:
  2891. case no_avegroup:
  2892. return "AVE";
  2893. case no_concat:
  2894. return "+";
  2895. case no_ne:
  2896. return "!=";
  2897. case no_not:
  2898. return "NOT ";
  2899. case no_or:
  2900. return "OR";
  2901. case no_and:
  2902. return "AND";
  2903. case no_filepos:
  2904. return "FILEPOSITION";
  2905. case no_file_logicalname:
  2906. return "LOGICALFILENAME";
  2907. case no_compound_diskread:
  2908. return "DISKREAD";
  2909. case no_compound_indexread:
  2910. return "INDEXREAD";
  2911. case no_keyedlimit:
  2912. if (expandProcessed)
  2913. return "KEYEDLIMIT";
  2914. return ::getOpString(op);
  2915. default:
  2916. return ::getOpString(op);
  2917. }
  2918. }
  2919. static bool addExplicitType(IHqlExpression * expr)
  2920. {
  2921. ITypeInfo * type = stripFunctionType(expr->queryType());
  2922. if (!type)
  2923. return false;
  2924. switch (type->getTypeCode())
  2925. {
  2926. case type_transform:
  2927. return true;
  2928. case type_dictionary:
  2929. case type_row:
  2930. case type_table:
  2931. case type_groupedtable:
  2932. case type_alien:
  2933. return false;
  2934. }
  2935. return true;
  2936. }
  2937. void HqltHql::doFunctionDefinition(StringBuffer & newdef, IHqlExpression * funcdef, const char * name, bool inType)
  2938. {
  2939. assertex(funcdef->getOperator() == no_funcdef);
  2940. if (addExplicitType(funcdef))
  2941. {
  2942. ITypeInfo * returnType = funcdef->queryType()->queryChildType();
  2943. StringBuffer tmp;
  2944. getTypeString(returnType, tmp);
  2945. if(tmp.length())
  2946. newdef.append(tmp).append(' ');
  2947. }
  2948. newdef.append(name).append('(');
  2949. IHqlExpression * formals = funcdef->queryChild(1);
  2950. IHqlExpression * defaults = funcdef->queryChild(2);
  2951. assertex( !defaults || formals->numChildren() ==defaults->numChildren());
  2952. bool first = true;
  2953. ForEachChild(idx, formals)
  2954. {
  2955. IHqlExpression * curParam = formals->queryChild(idx);
  2956. if (expandProcessed || !curParam->hasAttribute(_hidden_Atom))
  2957. {
  2958. if (first)
  2959. first = false;
  2960. else
  2961. newdef.append(", ");
  2962. toECL(curParam, newdef, false, hasNamedSymbol(curParam) ? inType : true);
  2963. if (defaults)
  2964. {
  2965. IHqlExpression * defexpr = defaults->queryChild(idx);
  2966. if (defexpr->getOperator() != no_omitted)
  2967. {
  2968. newdef.append("=");
  2969. toECL(defexpr, newdef, false, false);
  2970. }
  2971. }
  2972. }
  2973. }
  2974. newdef.append(')');
  2975. toECL(funcdef->queryChild(0), newdef.append(" := "), false, false, 0, true);
  2976. }
  2977. StringBuffer &HqltHql::doAlias(IHqlExpression * expr, StringBuffer &name, bool inType)
  2978. {
  2979. bool wasInsideNewTransform = insideNewTransform;
  2980. insideNewTransform = false;
  2981. // Start fresh
  2982. name.clear();
  2983. StringBuffer tmp;
  2984. StringBuffer exports;
  2985. scope.append(NULL);
  2986. bool undefined = isPublicSymbol(expr) ? !expr->queryTransformExtra() : (findVisitedArray()->find(*expr) == NotFound);
  2987. if (undefined || inType)
  2988. {
  2989. IHqlExpression * body = expr->queryBody(true);
  2990. StringBuffer newdef;
  2991. bool nameClash = false;
  2992. IHqlExpression * funcdef = expr->queryFunctionDefinition();
  2993. if (!funcdef && expr->getOperator() == no_funcdef)
  2994. {
  2995. //True when doAlias() is called on members of a alien type or scope
  2996. //This is a complete mess!
  2997. funcdef = expr;
  2998. }
  2999. if(isExported(expr) || isShared(expr))
  3000. {
  3001. if (isExported(expr))
  3002. exports.append("EXPORT ");
  3003. else
  3004. exports.append("SHARED ");
  3005. m_export_level++;
  3006. nameClash = (!expr->queryTransformExtra() && isExportDefined(expr) && !funcdef);
  3007. }
  3008. else
  3009. nameClash = (!expr->queryTransformExtra() && isSymbolDefined(expr) && !funcdef);
  3010. if (nameClash)
  3011. {
  3012. StringBuffer temp;
  3013. makeUniqueName(expr, temp);
  3014. clashCounter++;
  3015. temp.append("___").append(clashCounter);
  3016. OwnedHqlExpr extra = createId(createIdAtom(temp.str()));
  3017. expr->setTransformExtra(extra); // LINKs !
  3018. }
  3019. #ifdef SHOW_SYMBOL_LOCATION
  3020. if (expandProcessed)
  3021. newdef.append(expr->queryFullContainerId()).append("(").append(expr->getStartLine()).append(",").append(expr->getStartColumn()).append("):");
  3022. #endif
  3023. newdef.append(exports);
  3024. lookupSymbolName(expr, name);
  3025. bool wasFunctionDefined = funcdef && isFunctionDefined(funcdef) && !inType;
  3026. //Add the export name before the body is processed to prevent clashing names (e.g., badrecord2.xhql)
  3027. if (exports.length())
  3028. m_export_names.append(*new StringBufferItem(name));
  3029. if(funcdef && !expandProcessed)
  3030. {
  3031. if(!wasFunctionDefined || inType)
  3032. {
  3033. if(!expr->queryTransformExtra())
  3034. {
  3035. OwnedHqlExpr extra = createId(createIdAtom(name.str()));
  3036. expr->setTransformExtra(extra);
  3037. addVisited(expr);
  3038. addVisited(funcdef);
  3039. funcdef->setTransformExtra(extra);
  3040. }
  3041. doFunctionDefinition(newdef, funcdef, name.str(), inType);
  3042. }
  3043. else
  3044. {
  3045. // ???? Huh?
  3046. newdef.clear();
  3047. }
  3048. }
  3049. else if(!inType)
  3050. {
  3051. OwnedHqlExpr extra = createId(createIdAtom(name.str()));
  3052. expr->setTransformExtra(extra); // LINKs !
  3053. addVisited(expr);
  3054. // Special cases
  3055. node_operator op = body->getOperator();
  3056. switch(op)
  3057. {
  3058. case no_record:
  3059. {
  3060. newdef.append(name.str()).append(" := ");
  3061. toECL(body, newdef, false, false, 0, true);
  3062. break;
  3063. }
  3064. default:
  3065. if (addExplicitType(expr))
  3066. getTypeString(expr->queryType(), tmp.clear());
  3067. if(tmp.length())
  3068. newdef.append(tmp).append(' ');
  3069. newdef.append(name.str());
  3070. bool isNamed = true;
  3071. if (expr->isDataset())
  3072. {
  3073. if (expandProcessed && op != no_field && op != no_rows && !isTargetSelector(expr))
  3074. isNamed = false;
  3075. }
  3076. toECL (body, newdef.append(" := "), false, inType, 0, isNamed);
  3077. break;
  3078. }
  3079. }
  3080. else
  3081. {
  3082. getTypeString(expr->queryType(), tmp.clear());
  3083. if(tmp.length())
  3084. newdef.append(tmp).append(' ');
  3085. newdef.append(name.str());
  3086. toECL (body, newdef.append(" := "), false, false, 0, true);
  3087. }
  3088. #ifdef SHOW_FUNC_DEFINTION
  3089. if (expandProcessed && expr->getOperator() == no_funcdef)
  3090. {
  3091. newdef.append("{");
  3092. defaultToECL(expr->queryChild(0),newdef,inType);
  3093. newdef.append("}");
  3094. }
  3095. #endif
  3096. if(newdef.length())
  3097. {
  3098. newdef.append(';').newline();
  3099. if(inType)
  3100. {
  3101. name.clear().append(' ').append(newdef);
  3102. }
  3103. else
  3104. {
  3105. addExport(tmp.clear().append(newdef).newline());
  3106. if(exports.length())
  3107. {
  3108. if(m_exports.isItem(m_export_level))
  3109. {
  3110. m_definitions.append(m_exports.item(m_export_level));
  3111. m_exports.item(m_export_level).clear();
  3112. clearVisited();
  3113. }
  3114. }
  3115. }
  3116. }
  3117. // If we got here then we must have finished with the current export
  3118. if(exports.length())
  3119. {
  3120. m_export_level--;
  3121. }
  3122. }
  3123. else
  3124. {
  3125. lookupSymbolName(expr, name);
  3126. }
  3127. scope.pop();
  3128. insideNewTransform = wasInsideNewTransform;
  3129. return name;
  3130. }
  3131. void HqltHql::defineCallTarget(IHqlExpression * call, StringBuffer & name)
  3132. {
  3133. // OK we got us an external call. Let's try and define it.
  3134. //This is a mess! (To put it politely)
  3135. IHqlExpression * funcdef;
  3136. if (call->getOperator() == no_externalcall)
  3137. {
  3138. funcdef = call->queryExternalDefinition();
  3139. }
  3140. else
  3141. {
  3142. funcdef = call->queryBody()->queryFunctionDefinition();
  3143. }
  3144. IHqlExpression * prevName = static_cast<IHqlExpression *>(call->queryTransformExtra());
  3145. if (funcdef && !prevName && !isServiceDefined(call))
  3146. {
  3147. makeUniqueName(call, name);
  3148. StringBuffer newdef;
  3149. m_service_names.append(*new StringBufferItem(name));
  3150. OwnedHqlExpr extra = createId(createIdAtom(name.str()));
  3151. call->setTransformExtra(extra);
  3152. addVisited(call);
  3153. if(hasNamedSymbol(call))
  3154. {
  3155. if(isExported(call))
  3156. {
  3157. newdef.append("EXPORT ");
  3158. }
  3159. else if(isShared(call))
  3160. {
  3161. newdef.append("SHARED ");
  3162. }
  3163. }
  3164. else if (!tryToRegenerate)
  3165. newdef.append("EXPORT "); //not really right - the information is lost about whether the service definition is exported or not.
  3166. newdef.append(name).append(" := ").newline();
  3167. if (call->getOperator() == no_externalcall)
  3168. {
  3169. newdef.append("SERVICE").newline();
  3170. getTypeString(call->queryType(), newdef);
  3171. newdef.append(" ");
  3172. lookupSymbolName(call, newdef);
  3173. }
  3174. if (funcdef->isFunctionDefinition())
  3175. {
  3176. newdef.append("(");
  3177. toECL(funcdef->queryChild(1), newdef, false, true);
  3178. newdef.append(") : ");
  3179. IHqlExpression *child = funcdef->queryChild(0);
  3180. toECL ( child, newdef, child->getPrecedence() < 0, false);
  3181. }
  3182. else
  3183. toECL ( funcdef, newdef, false, false);
  3184. newdef.append(';').newline();
  3185. if (call->getOperator() == no_externalcall)
  3186. {
  3187. newdef.append("END;").newline().newline();
  3188. }
  3189. m_services.append(newdef);
  3190. }
  3191. else
  3192. {
  3193. if (prevName)
  3194. appendId(name, prevName->queryId());
  3195. else
  3196. lookupSymbolName(call, name);
  3197. }
  3198. if (call->getOperator() == no_externalcall)
  3199. {
  3200. name.append('.');
  3201. lookupSymbolName(call, name);
  3202. }
  3203. }
  3204. static StringBuffer &toECL(StringBuffer &s, HqltHql & hqlthql, HqlExprArray & queries, bool recurse, bool isNamedSymbol = false)
  3205. {
  3206. int startpos = s.length();
  3207. try
  3208. {
  3209. ForEachItemIn(idx, queries)
  3210. {
  3211. hqlthql.toECL((IHqlExpression *) &queries.item(idx), s, false, false, 0, isNamedSymbol);
  3212. if(s.length() && s.charAt(s.length() - 1) != ';')
  3213. {
  3214. s.append(';').newline();
  3215. }
  3216. }
  3217. if (recurse)
  3218. {
  3219. StringBuffer definitions;
  3220. hqlthql.gatherServices(definitions);
  3221. hqlthql.gatherDefinitions(definitions);
  3222. s.insert(startpos, definitions.str());
  3223. }
  3224. }
  3225. #ifdef _DEBUG
  3226. catch(int*****************){}
  3227. #else
  3228. catch(...)
  3229. {
  3230. IERRLOG("toECL() threw an exception");
  3231. s.setLength(startpos);
  3232. }
  3233. #endif
  3234. return s;
  3235. }
  3236. static StringBuffer &toECLDefinition(StringBuffer &s, HqltHql & hqlthql, HqlExprArray & queries, bool recurse)
  3237. {
  3238. int startpos = s.length();
  3239. try
  3240. {
  3241. ForEachItemIn(idx, queries)
  3242. {
  3243. StringBuffer name;
  3244. hqlthql.doAlias((IHqlExpression *) &queries.item(idx), name, false);
  3245. }
  3246. if (recurse)
  3247. {
  3248. StringBuffer definitions;
  3249. hqlthql.gatherServices(definitions);
  3250. hqlthql.gatherDefinitions(definitions);
  3251. s.insert(startpos, definitions.str());
  3252. }
  3253. }
  3254. #ifdef _DEBUG
  3255. catch(int*****************){}
  3256. #else
  3257. catch(...)
  3258. {
  3259. IERRLOG("toECLDefinition() threw an exception");
  3260. s.setLength(startpos);
  3261. }
  3262. #endif
  3263. return s;
  3264. }
  3265. StringBuffer &toECL(IHqlExpression * expr, StringBuffer &s, bool recurse, bool xgmmlGraphText)
  3266. {
  3267. HqltHql hqlthql(recurse, xgmmlGraphText);
  3268. HqlExprArray queries;
  3269. unwindCommaCompound(queries, expr);
  3270. return toECL(s, hqlthql, queries, recurse);
  3271. }
  3272. StringBuffer &regenerateECL(IHqlExpression * expr, StringBuffer &s)
  3273. {
  3274. HqltHql hqlthql(true, false);
  3275. hqlthql.setIgnoreModuleNames(true);
  3276. hqlthql.setTryToRegenerate(true);
  3277. HqlExprArray queries;
  3278. unwindCommaCompound(queries, expr);
  3279. return toECL(s, hqlthql, queries, true);
  3280. }
  3281. StringBuffer &regenerateDefinition(IHqlExpression * expr, StringBuffer &s)
  3282. {
  3283. if (!isEclAlias(expr))
  3284. throw makeStringExceptionV(ERR_INTERNALEXCEPTION, "Internal: regenerateDefinition requires ECL alias expression");
  3285. HqltHql hqlthql(true, false);
  3286. hqlthql.setIgnoreModuleNames(true);
  3287. HqlExprArray queries;
  3288. unwindCommaCompound(queries, expr);
  3289. return toECLDefinition(s, hqlthql, queries, true);
  3290. }
  3291. StringBuffer &toUserECL(StringBuffer &s, IHqlExpression * expr, bool recurse)
  3292. {
  3293. HqltHql hqlthql(recurse, false);
  3294. hqlthql.setIgnoreModuleNames(true);
  3295. HqlExprArray queries;
  3296. unwindCommaCompound(queries, expr);
  3297. return toECL(s, hqlthql, queries, recurse);
  3298. }
  3299. void splitECL(IHqlExpression * expr, StringBuffer &s, StringBuffer &d)
  3300. {
  3301. #ifndef _DEBUG
  3302. int startpos = s.length();
  3303. #endif
  3304. try
  3305. {
  3306. HqltHql hqlthql(true, false);
  3307. hqlthql.toECL(expr, s, false, false);
  3308. hqlthql.gatherServices(d);
  3309. hqlthql.gatherDefinitions(d);
  3310. }
  3311. #ifdef _DEBUG
  3312. catch(int*****************){}
  3313. #else
  3314. catch(...)
  3315. {
  3316. IERRLOG("toECL() threw an exception");
  3317. s.setLength(startpos);
  3318. }
  3319. #endif
  3320. }
  3321. StringBuffer &expandDotLiteral(StringBuffer &s, const char *f)
  3322. {
  3323. unsigned lines = 0;
  3324. unsigned chars = 0;
  3325. char c;
  3326. while ((c = *f++))
  3327. {
  3328. switch (c)
  3329. {
  3330. case '\t':
  3331. s.append(" ");
  3332. break;
  3333. case '\r':
  3334. break;
  3335. case '\n':
  3336. s.append("\\l"); // Means left justify.
  3337. if (lines++ > 10)
  3338. return s;
  3339. break;
  3340. case '}':
  3341. case '{':
  3342. case '<':
  3343. case '>': // Special chars in dot graphs
  3344. case '\\':
  3345. case '\"':
  3346. case '\'':
  3347. s.append('\\');
  3348. // fall into...
  3349. default:
  3350. if (chars++ > 1000)
  3351. return s;
  3352. s.append(c);
  3353. break;
  3354. }
  3355. }
  3356. return s;
  3357. }
  3358. StringBuffer & doGetExprECL(IHqlExpression * expr, StringBuffer & out, bool minimalSelectors, bool xgmmlGraphText, unsigned _maxDepth)
  3359. {
  3360. const bool recurse = false;
  3361. HqltHql hqlthql(recurse, xgmmlGraphText);
  3362. hqlthql.setExpandNamed(false);
  3363. hqlthql.setIgnoreModuleNames(true);
  3364. hqlthql.setMinimalSelectors(minimalSelectors);
  3365. if (_maxDepth)
  3366. hqlthql.setMaxRecurseDepth(_maxDepth);
  3367. HqlExprArray queries;
  3368. unwindCommaCompound(queries, expr);
  3369. toECL(out, hqlthql, queries, recurse);
  3370. const char * text = out.str();
  3371. unsigned len = out.length();
  3372. while (len)
  3373. {
  3374. char c = text[len-1];
  3375. if ((c != ';') && (c != '\n') &&(c != '\r'))
  3376. break;
  3377. len--;
  3378. }
  3379. out.setLength(len);
  3380. return out;
  3381. }
  3382. StringBuffer & getExprECL(IHqlExpression * expr, StringBuffer & out, bool minimalSelectors, bool xgmmlGraphText)
  3383. {
  3384. return doGetExprECL(expr, out, minimalSelectors, xgmmlGraphText, 0);
  3385. }
  3386. StringBuffer &getRecordECL(IHqlExpression * expr, StringBuffer & out)
  3387. {
  3388. HqltHql hqlthql(true, false);
  3389. hqlthql.setIgnoreVirtualAttrs(true);
  3390. hqlthql.setLowerCaseIds(true);
  3391. HqlExprArray queries;
  3392. unwindCommaCompound(queries, expr);
  3393. return toECL(out, hqlthql, queries, true, false);
  3394. }
  3395. StringBuffer & processedTreeToECL(IHqlExpression * expr, StringBuffer &s)
  3396. {
  3397. HqltHql hqlthql(true, false);
  3398. hqlthql.setExpandProcessed(true);
  3399. HqlExprArray queries;
  3400. unwindCommaCompound(queries, expr);
  3401. return toECL(s, hqlthql, queries, true);
  3402. }
  3403. StringBuffer & getExprIdentifier(StringBuffer & out, IHqlExpression * expr)
  3404. {
  3405. if (expr->queryName())
  3406. return out.append(expr->queryName());
  3407. return doGetExprECL(expr, out, false, false, 1);
  3408. }
  3409. void dbglogUnboundedText(size32_t len, const char * ecl)
  3410. {
  3411. const size32_t chunkSize = 32768;
  3412. while (len > chunkSize)
  3413. {
  3414. const char * next = strchr(ecl+chunkSize, '\n');
  3415. if (!next || !next[1])
  3416. break;
  3417. unsigned size = next-ecl;
  3418. if (ecl[size-1] == '\r')
  3419. size--;
  3420. DBGLOG("%.*s", size, ecl);
  3421. len -= (next+1-ecl);
  3422. ecl = next+1;
  3423. }
  3424. DBGLOG("%s", ecl);
  3425. }
  3426. void dbglogExpr(IHqlExpression * expr)
  3427. {
  3428. if (expr)
  3429. {
  3430. StringBuffer s;
  3431. processedTreeToECL(expr, s);
  3432. dbglogUnboundedText(s.length(), s.str());
  3433. }
  3434. }