hqlthql.cpp 107 KB

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