hqltcppc.cpp 126 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786
  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 "jliball.hpp"
  14. #include "hql.hpp"
  15. #include "platform.h"
  16. #include "jlib.hpp"
  17. #include "jexcept.hpp"
  18. #include "jmisc.hpp"
  19. #include "hql.hpp"
  20. #include "hqlexpr.hpp"
  21. #include "hqlattr.hpp"
  22. #include "hqlfunc.hpp"
  23. #include "hqlcpputil.hpp"
  24. #include "hqlfold.hpp"
  25. #include "hqlthql.hpp"
  26. #include "hqlstmt.hpp"
  27. #include "hqlwcpp.hpp"
  28. #include "hqlcpp.ipp"
  29. #include "hqltcppc.ipp"
  30. #include "hqlhtcpp.ipp"
  31. #include "hqlcerrors.hpp"
  32. #include "hqlcatom.hpp"
  33. #include "hqlccommon.hpp"
  34. #include "hqlpmap.hpp"
  35. #include "hqlutil.hpp"
  36. #include "hqlinline.hpp"
  37. #include "hqlusage.hpp"
  38. #define LIMIT_FOR_GET (NULL)
  39. //#define TraceExprPrintLog(x, expr) PrintLog(x ": %s", expr->toString(StringBuffer()).str());
  40. static void normalizeAdditions(IHqlExpression * expr, HqlExprAttr & var, HqlExprAttr & fixed)
  41. {
  42. switch (expr->getOperator())
  43. {
  44. case no_constant:
  45. extendAdd(fixed, expr);
  46. break;
  47. case no_add:
  48. normalizeAdditions(expr->queryChild(0), var, fixed);
  49. normalizeAdditions(expr->queryChild(1), var, fixed);
  50. break;
  51. default:
  52. extendAdd(var, expr);
  53. break;
  54. }
  55. }
  56. static bool needToNormalize(IHqlExpression * expr, bool insideAdd)
  57. {
  58. switch (expr->getOperator())
  59. {
  60. case no_constant:
  61. return insideAdd;
  62. case no_add:
  63. if (needToNormalize(expr->queryChild(0), true))
  64. return true;
  65. if (!insideAdd && expr->queryChild(1)->getOperator() == no_constant)
  66. return false;
  67. return needToNormalize(expr->queryChild(1), true);
  68. default:
  69. return false;
  70. }
  71. }
  72. IHqlExpression * normalizeAdditions(IHqlExpression * expr)
  73. {
  74. if (!needToNormalize(expr, false))
  75. return LINK(expr);
  76. HqlExprAttr var;
  77. HqlExprAttr fixed;
  78. normalizeAdditions(expr, var, fixed);
  79. if (fixed)
  80. extendAdd(var, fixed);
  81. return var.getClear();
  82. }
  83. IHqlExpression * ensureType(IHqlExpression * expr, ITypeInfo * type)
  84. {
  85. if (expr->queryType() != type)
  86. return createValue(no_implicitcast, LINK(type), expr);
  87. return expr;
  88. }
  89. static bool isVerySimpleLength(IHqlExpression * expr)
  90. {
  91. switch (expr->getOperator())
  92. {
  93. case no_variable:
  94. case no_constant:
  95. case no_select:
  96. return true;
  97. }
  98. return false;
  99. }
  100. bool isSimpleLength(IHqlExpression * expr)
  101. {
  102. switch (expr->getOperator())
  103. {
  104. case no_variable:
  105. case no_constant:
  106. case no_select:
  107. return true;
  108. case no_add:
  109. if (isVerySimpleLength(expr->queryChild(0)) &&
  110. (expr->queryChild(1)->getOperator() == no_constant))
  111. return true;
  112. break;
  113. case no_sub:
  114. if (isVerySimpleLength(expr->queryChild(0)))
  115. if (isSimpleLength(expr->queryChild(1)))
  116. return true;
  117. break;
  118. }
  119. return false;
  120. }
  121. void ensureSimpleLength(HqlCppTranslator & translator, BuildCtx & ctx, CHqlBoundExpr & bound)
  122. {
  123. OwnedHqlExpr length = translator.getBoundLength(bound);
  124. if (isSimpleLength(length))
  125. return;
  126. OwnedHqlExpr tempLen = createTranslatedOwned(translator.getBoundLength(bound));
  127. CHqlBoundExpr boundLength;
  128. translator.buildSimpleExpr(ctx, tempLen, boundLength);
  129. bound.length.set(boundLength.expr);
  130. }
  131. //---------------------------------------------------------------------------
  132. static IHqlExpression * createSizeExpression(IHqlExpression * varSize, unsigned fixedSize)
  133. {
  134. if (!varSize)
  135. return getSizetConstant(fixedSize);
  136. OwnedHqlExpr total = ensureType(LINK(varSize), sizetType);
  137. if (fixedSize)
  138. return adjustValue(total, (int)fixedSize);
  139. return total.getClear();
  140. }
  141. void SizeStruct::add(const SizeStruct & other)
  142. {
  143. assertex(self == other.self);
  144. addFixed(other.fixedSize);
  145. if (other.varSize)
  146. addVariableExpr(other.varMinSize, other.varSize);
  147. }
  148. void SizeStruct::addVariableExpr(unsigned _varMinSize, IHqlExpression * expr)
  149. {
  150. varMinSize += _varMinSize;
  151. if (varSize)
  152. varSize.setown(createValue(no_add, varSize.getClear(), LINK(expr)));
  153. else
  154. varSize.set(expr);
  155. }
  156. void SizeStruct::addVariable(unsigned _varMinSize, IHqlExpression * column)
  157. {
  158. OwnedHqlExpr expr = createValue(no_sizeof, makeIntType(4,false), LINK(column));
  159. addVariableExpr(_varMinSize, expr);
  160. }
  161. void SizeStruct::buildSizeExpr(HqlCppTranslator & translator, BuildCtx & ctx, BoundRow * row, CHqlBoundExpr & bound)
  162. {
  163. if (varSize)
  164. {
  165. OwnedHqlExpr temp = getSizeExpr(row);
  166. translator.buildCachedExpr(ctx, temp, bound);
  167. }
  168. else
  169. bound.expr.setown(getSizetConstant(fixedSize));
  170. }
  171. void SizeStruct::forceToTemp(node_operator op, IHqlExpression * selector)
  172. {
  173. varSize.setown(createValue(op, LINK(sizetType), LINK(selector)));
  174. fixedSize = 0;
  175. }
  176. IHqlExpression * SizeStruct::getSizeExpr(BoundRow * row) const
  177. {
  178. #if 0
  179. IHqlExpression * bound = row->queryDataset();
  180. if ((bound->getOperator() == no_translated) && queryRealChild(bound, 1))
  181. return createTranslated(bound->queryChild(1));
  182. #endif
  183. OwnedHqlExpr total;
  184. if (row)
  185. {
  186. assertex(self != NULL);
  187. OwnedHqlExpr mapped = normalizeAdditions(varSize);
  188. total.setown(row->bindToRow(mapped, self));
  189. }
  190. else
  191. total.set(varSize);
  192. return createSizeExpression(total, fixedSize);
  193. }
  194. bool SizeStruct::isWorthCommoning() const
  195. {
  196. if (varSize && varSize->getOperator() == no_add)
  197. {
  198. if (varSize->queryChild(0)->getOperator() == no_add)
  199. return true;
  200. }
  201. return false;
  202. }
  203. //---------------------------------------------------------------------------
  204. /* In param: _column is not linked */
  205. CMemberInfo::CMemberInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column)
  206. {
  207. container = _container;
  208. prior = _prior;
  209. column.set(_column);
  210. if (column->isRecord())
  211. column.setown(createRow(no_null, LINK(column)));
  212. hasVarOffset = false;
  213. isOffsetCached = false;
  214. seq = 0;
  215. }
  216. void CMemberInfo::addVariableSize(size32_t varMinSize, SizeStruct & size)
  217. {
  218. Owned<IHqlExpression> self = createSelectorExpr();
  219. size.addVariable(varMinSize, self);
  220. }
  221. void CMemberInfo::buildAddress(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  222. {
  223. bound.expr.setown(getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  224. }
  225. void CMemberInfo::calcAllCachedOffsets()
  226. {
  227. assertex(container);
  228. container->calcAllCachedOffsets();
  229. }
  230. void CMemberInfo::calcCachedOffsets(const SizeStruct & offset, SizeStruct & sizeSelf)
  231. {
  232. if (!isOffsetCached)
  233. {
  234. isOffsetCached = true;
  235. cachedOffset.set(offset);
  236. cachedSize.clear(offset.querySelf());
  237. calcCachedSize(offset, sizeSelf);
  238. }
  239. else
  240. {
  241. sizeSelf.set(cachedSize);
  242. }
  243. }
  244. void CMemberInfo::calcCachedSize(const SizeStruct & offset, SizeStruct & sizeSelf)
  245. {
  246. gatherSize(cachedSize);
  247. sizeSelf.set(cachedSize);
  248. }
  249. void CMemberInfo::getOffsets(SizeStruct & offset, SizeStruct & accessorOffset) const
  250. {
  251. offset.set(cachedOffset);
  252. accessorOffset.set(cachedAccessorOffset);
  253. }
  254. bool CMemberInfo::checkCompatibleIfBlock(HqlExprCopyArray & conditions)
  255. {
  256. return false;
  257. }
  258. StringBuffer & CMemberInfo::expandSelectPathText(StringBuffer & out, bool isLast) const
  259. {
  260. bool isField = (column->getOperator() == no_field);
  261. if (container)
  262. container->expandSelectPathText(out, isLast && !isField);
  263. if (isField)
  264. {
  265. out.append(column->queryName());
  266. if (!isLast)
  267. out.append('.');
  268. }
  269. return out;
  270. }
  271. unsigned CMemberInfo::getTotalFixedSize()
  272. {
  273. return cachedSize.getFixedSize();
  274. }
  275. unsigned CMemberInfo::getTotalMinimumSize()
  276. {
  277. return cachedSize.getMinimumSize();
  278. }
  279. void CContainerInfo::calcAllCachedOffsets()
  280. {
  281. if (container)
  282. CMemberInfo::calcAllCachedOffsets();
  283. else
  284. {
  285. OwnedHqlExpr self = getRelativeSelf();
  286. SizeStruct offset(self);
  287. SizeStruct size(self);
  288. calcCachedOffsets(offset, size);
  289. if (usesAccessClass())
  290. {
  291. SizeStruct finalAccessorOffset(self);
  292. OwnedHqlExpr sizeSelf = createValue(no_sizeof, LINK(sizetType), getRelativeSelf());
  293. if (bindOffsetsFromClass(finalAccessorOffset, false))
  294. {
  295. StringBuffer name;
  296. name.append("off[").append(nextSeq()).append("]");
  297. OwnedHqlExpr newOffset = createVariable(name, LINK(sizetType));
  298. finalAccessorOffset.set(0, newOffset);
  299. }
  300. accessorSize.set(finalAccessorOffset);
  301. cachedSize.set(0, sizeSelf);
  302. SizeStruct tempOffset;
  303. bindSizesFromOffsets(tempOffset, cachedSize);
  304. }
  305. }
  306. }
  307. void CContainerInfo::calcCachedChildrenOffsets(const SizeStruct & startOffset, SizeStruct & sizeSelf)
  308. {
  309. //Optimize one special case of ifblocks.
  310. //Sometimes you have a header with some fields, followed by a set of mutually exclusive ifblocks.
  311. //Spot any trailing mutually exclusive ifblocks and don't update
  312. HqlExprCopyArray conditions;
  313. unsigned maxOffsetUpdate = children.ordinality();
  314. while (maxOffsetUpdate > 0)
  315. {
  316. CMemberInfo & cur = children.item(maxOffsetUpdate-1);
  317. if (!cur.checkCompatibleIfBlock(conditions))
  318. break;
  319. maxOffsetUpdate--;
  320. }
  321. SizeStruct offset(startOffset);
  322. ForEachItemIn(idx, children)
  323. {
  324. CMemberInfo & cur = children.item(idx);
  325. SizeStruct sizeChild(offset.querySelf());
  326. cur.calcCachedOffsets(offset, sizeChild);
  327. if (offset.isWorthCommoning())
  328. {
  329. Owned<IHqlExpression> child = cur.createSelectorExpr();
  330. offset.forceToTemp(no_offsetof, child);
  331. }
  332. sizeSelf.add(sizeChild);
  333. if (idx < maxOffsetUpdate)
  334. offset.add(sizeChild);
  335. }
  336. }
  337. void CContainerInfo::calcCachedSize(const SizeStruct & offset, SizeStruct & sizeSelf)
  338. {
  339. SizeStruct childOffset(offset);
  340. if (childOffset.isWorthCommoning())
  341. {
  342. Owned<IHqlExpression> self = createSelectorExpr();
  343. childOffset.forceToTemp(no_offsetof, self);
  344. }
  345. calcCachedChildrenOffsets(childOffset, cachedSize);
  346. //Ensure that a record with no fields has a meta size > 0 (can be created by implicit project code)
  347. if (cachedSize.isEmpty())
  348. {
  349. IHqlExpression * record = column->queryRecord();
  350. if (record->hasAttribute(_nonEmpty_Atom))
  351. cachedSize.addFixed(1);
  352. }
  353. if (cachedSize.isFixedSize())
  354. sizeSelf.set(cachedSize);
  355. else
  356. addVariableSize(cachedSize.getMinimumSize(), sizeSelf);
  357. }
  358. bool CMemberInfo::bindOffsetsFromClass(SizeStruct & accessorOffset, bool prevVariableSize)
  359. {
  360. if (prevVariableSize)
  361. {
  362. seq = container->nextSeq();
  363. StringBuffer name;
  364. name.append("off[").append(seq).append("]");
  365. OwnedHqlExpr newOffset = createVariable(name, LINK(sizetType));
  366. cachedAccessorOffset.set(0, newOffset);
  367. }
  368. else
  369. cachedAccessorOffset.set(accessorOffset);
  370. if (!cachedAccessorOffset.isFixedSize())
  371. {
  372. Owned<IHqlExpression> child = createSelectorExpr();
  373. cachedOffset.forceToTemp(no_offsetof, child);
  374. }
  375. else
  376. assertex(!cachedOffset.queryVarSize() || cachedOffset.queryVarSize()->getOperator() != no_add);
  377. accessorOffset.set(cachedAccessorOffset);
  378. accessorOffset.addFixed(cachedSize.getFixedSize());
  379. return !cachedSize.isFixedSize();
  380. }
  381. bool CContainerInfo::bindOffsetsFromClass(SizeStruct & accessorOffset, bool prevVariableSize)
  382. {
  383. //MORE: ifblocks need further work if the offsets are not recalculated for trailing ifblocks
  384. ForEachItemIn(idx, children)
  385. {
  386. CMemberInfo & cur = children.item(idx);
  387. bool thisVariableSize = cur.bindOffsetsFromClass(accessorOffset, prevVariableSize);
  388. if (idx == 0)
  389. cur.getOffsets(cachedOffset, cachedAccessorOffset);
  390. prevVariableSize = thisVariableSize;
  391. }
  392. return prevVariableSize;
  393. }
  394. void CMemberInfo::bindSizesFromOffsets(SizeStruct & thisOffset, const SizeStruct & nextOffset)
  395. {
  396. if (!cachedSize.isFixedSize())
  397. {
  398. assertex(nextOffset.queryVarSize()->getOperator() != no_add);
  399. OwnedHqlExpr sub = createValue(no_sub, LINK(sizetType), nextOffset.getSizeExpr(NULL), cachedOffset.getSizeExpr(NULL));
  400. cachedSize.set(0, sub);
  401. }
  402. thisOffset.set(cachedOffset);
  403. }
  404. void CContainerInfo::bindSizesFromOffsets(SizeStruct & thisOffset, const SizeStruct & nextOffset)
  405. {
  406. SizeStruct curOffset(nextOffset);
  407. ForEachItemInRev(idx, children)
  408. {
  409. CMemberInfo & cur = children.item(idx);
  410. cur.bindSizesFromOffsets(curOffset, curOffset);
  411. }
  412. CMemberInfo::bindSizesFromOffsets(thisOffset, nextOffset);
  413. }
  414. unsigned CContainerInfo::getTotalFixedSize()
  415. {
  416. if (!isOffsetCached)
  417. calcAllCachedOffsets();
  418. if (cachedSize.isFixedSize())
  419. return cachedSize.getFixedSize();
  420. unsigned size = 0;
  421. ForEachItemIn(idx, children)
  422. size += children.item(idx).getTotalFixedSize();
  423. return size;
  424. }
  425. unsigned CContainerInfo::getTotalMinimumSize()
  426. {
  427. if (!isOffsetCached)
  428. calcAllCachedOffsets();
  429. if (cachedSize.isFixedSize())
  430. return cachedSize.getFixedSize();
  431. unsigned size = 0;
  432. ForEachItemIn(idx, children)
  433. size += children.item(idx).getTotalMinimumSize();
  434. return size;
  435. }
  436. void CIfBlockInfo::calcCachedSize(const SizeStruct & offset, SizeStruct & sizeSelf)
  437. {
  438. calcCachedChildrenOffsets(offset, cachedSize);
  439. if (cachedSize.isFixedSize())
  440. sizeSelf.set(cachedSize);
  441. else
  442. {
  443. addVariableSize(0, sizeSelf);
  444. // if (alwaysPresent)
  445. // sizeSelf.addFixed(cachedSize.getFixedSize());
  446. }
  447. }
  448. bool CIfBlockInfo::checkCompatibleIfBlock(HqlExprCopyArray & conditions)
  449. {
  450. ForEachItemIn(i, conditions)
  451. {
  452. if (!areExclusiveConditions(condition, &conditions.item(i)))
  453. return false;
  454. }
  455. conditions.append(*condition);
  456. return true;
  457. }
  458. unsigned CIfBlockInfo::getTotalFixedSize()
  459. {
  460. if (alwaysPresent)
  461. return CContainerInfo::getTotalFixedSize();
  462. return 0;
  463. }
  464. unsigned CIfBlockInfo::getTotalMinimumSize()
  465. {
  466. return 0;
  467. }
  468. void CBitfieldContainerInfo::calcCachedSize(const SizeStruct & offset, SizeStruct & sizeSelf)
  469. {
  470. cachedSize.addFixed(column->queryType()->getSize());
  471. sizeSelf.set(cachedSize);
  472. SizeStruct sizeBitfields(sizeSelf.querySelf());
  473. calcCachedChildrenOffsets(offset, sizeBitfields);
  474. assertex(sizeBitfields.isFixedSize() && sizeBitfields.getFixedSize() == 0);
  475. }
  476. void CMemberInfo::gatherSize(SizeStruct & target)
  477. {
  478. assertex(!"Should be implemented for non-containers");
  479. }
  480. void CMemberInfo::gatherOffset(SizeStruct & target, IHqlExpression * selector)
  481. {
  482. if (!isOffsetCached)
  483. calcAllCachedOffsets();
  484. target.set(cachedOffset);
  485. }
  486. void CMemberInfo::getSizeExpr(SizeStruct & target)
  487. {
  488. if (!isOffsetCached)
  489. calcAllCachedOffsets();
  490. target.set(cachedSize);
  491. }
  492. size32_t CMemberInfo::getContainerTrailingFixed()
  493. {
  494. SizeStruct size;
  495. assertex(container);
  496. container->addTrailingFixed(size, this);
  497. return size.getFixedSize();
  498. }
  499. void CMemberInfo::buildConditionFilter(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  500. {
  501. OwnedHqlExpr condition = getConditionSelect(translator, ctx, selector->queryRootRow());
  502. if (condition)
  503. translator.buildFilter(ctx, condition);
  504. }
  505. void CMemberInfo::buildOffset(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  506. {
  507. if (!cachedAccessorOffset.isEmpty())
  508. {
  509. OwnedHqlExpr value;
  510. if (cachedAccessorOffset.queryVarSize())
  511. {
  512. IHqlExpression * accessor = selector->queryRootRow()->ensureAccessor(translator, ctx);
  513. assertex(accessor);
  514. value.setown(createValue(no_select, LINK(sizetType), LINK(accessor), LINK(cachedAccessorOffset.queryVarSize())));
  515. }
  516. bound.expr.setown(createSizeExpression(value, cachedAccessorOffset.getFixedSize()));
  517. }
  518. else
  519. {
  520. SizeStruct totalSize;
  521. gatherOffset(totalSize, selector->queryExpr()); //this
  522. totalSize.buildSizeExpr(translator, ctx, selector->queryRootRow(), bound);
  523. }
  524. }
  525. void callDeserializeGetN(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * helper, IHqlExpression * boundSize, IHqlExpression * address)
  526. {
  527. HqlExprArray args;
  528. args.append(*LINK(helper));
  529. args.append(*LINK(boundSize));
  530. args.append(*LINK(address));
  531. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(deserializerReadNId, args);
  532. ctx.addExpr(call);
  533. }
  534. IHqlExpression * callDeserializerGetSize(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * helper)
  535. {
  536. HqlExprArray args;
  537. args.append(*LINK(helper));
  538. OwnedHqlExpr call = translator.bindFunctionCall(deserializerReadSizeId, args);
  539. OwnedHqlExpr sizeVariable = ctx.getTempDeclare(sizetType, call);
  540. return LINK(sizeVariable);
  541. }
  542. void callDeserializerSkipInputSize(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * helper, IHqlExpression * size)
  543. {
  544. CHqlBoundExpr bound;
  545. translator.buildExpr(ctx, size, bound);
  546. HqlExprArray args;
  547. args.append(*LINK(helper));
  548. args.append(*LINK(bound.expr));
  549. translator.callProcedure(ctx, deserializerSkipNId, args);
  550. }
  551. void callDeserializerSkipInputTranslatedSize(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * helper, IHqlExpression * size)
  552. {
  553. HqlExprArray args;
  554. args.append(*LINK(helper));
  555. args.append(*LINK(size));
  556. translator.callProcedure(ctx, deserializerSkipNId, args);
  557. }
  558. void CMemberInfo::associateSizeOf(BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * rawSize, size32_t extraSize)
  559. {
  560. //Use the size just calculated for the field
  561. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  562. OwnedHqlExpr srcSize = adjustValue(rawSize, extraSize);
  563. ctx.associateExpr(sizeOfExpr, srcSize);
  564. }
  565. void CMemberInfo::doBuildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IHqlExpression * boundSize)
  566. {
  567. if (!boundSize->isConstant())
  568. {
  569. OwnedHqlExpr unboundSize = createTranslated(boundSize);
  570. checkAssignOk(translator, ctx, selector, unboundSize, 0);
  571. }
  572. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryPhysicalType());
  573. callDeserializeGetN(translator, ctx, helper, boundSize, address);
  574. associateSizeOf(ctx, selector, boundSize, 0);
  575. }
  576. void CMemberInfo::doBuildSkipInput(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * helper, size32_t size)
  577. {
  578. HqlExprArray args;
  579. args.append(*LINK(helper));
  580. if (size == UNKNOWN_LENGTH)
  581. {
  582. OwnedHqlExpr sizeVariable = callDeserializerGetSize(translator, ctx, helper);
  583. callDeserializerSkipInputTranslatedSize(translator, ctx, helper, sizeVariable);
  584. }
  585. else
  586. {
  587. OwnedHqlExpr sizeExpr = getSizetConstant(size);
  588. callDeserializerSkipInputTranslatedSize(translator, ctx, helper, sizeExpr);
  589. }
  590. }
  591. IHqlExpression * CMemberInfo::createSelfPeekDeserializer(HqlCppTranslator & translator, IHqlExpression * helper)
  592. {
  593. IHqlExpression * size = column->queryProperty(EPsize);
  594. LinkedHqlExpr maxSize = size->queryChild(2);
  595. if (!maxSize || maxSize->isAttribute())
  596. maxSize.setown(getSizetConstant(MAX_RECORD_SIZE));
  597. HqlExprArray peekArgs;
  598. peekArgs.append(*LINK(helper));
  599. peekArgs.append(*LINK(maxSize));
  600. return translator.bindTranslatedFunctionCall(deserializerPeekId, peekArgs);
  601. }
  602. void CMemberInfo::gatherMaxRowSize(SizeStruct & totalSize, IHqlExpression * newSize, size32_t fixedExtra, IReferenceSelector * selector)
  603. {
  604. if (!isOffsetCached)
  605. calcAllCachedOffsets();
  606. totalSize.set(cachedOffset);
  607. totalSize.addFixed(fixedExtra);
  608. //Total size of the record is
  609. //offset+<size-this>+<any-following-fixed-size>
  610. if (newSize)
  611. {
  612. IHqlExpression * size = newSize;
  613. if (size->getOperator() == no_translated)
  614. size = size->queryChild(0);
  615. IValue * fixedNewSize = size->queryValue();
  616. if (fixedNewSize)
  617. totalSize.addFixed((size32_t)fixedNewSize->getIntValue());
  618. else
  619. totalSize.addVariableExpr(0, newSize);
  620. }
  621. BoundRow * row = selector->queryRootRow();
  622. if (!row->isSerialization())
  623. {
  624. if (container)
  625. container->addTrailingFixed(totalSize, this);
  626. }
  627. }
  628. void CMemberInfo::checkAssignOk(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * newSize, unsigned fixedExtra)
  629. {
  630. //If no size beyond the constant value then this can't be increasing the size of the row => no need to check
  631. if (matchesConstantValue(newSize, 0))
  632. return;
  633. CHqlBoundExpr bound;
  634. SizeStruct totalSize;
  635. gatherMaxRowSize(totalSize, newSize, fixedExtra, selector);
  636. BoundRow * row = selector->queryRootRow();
  637. if (row->isSerialization())
  638. {
  639. //<any-following-fixed-size> is unknown at this point.
  640. //equals (eventualMaximum - fixed-to-this-point)
  641. //note, offset - leadingFixed should never go negative
  642. container->subLeadingFixed(totalSize, this);
  643. totalSize.buildSizeExpr(translator, ctx, row, bound);
  644. //NOTE: The final fixed size is unknown at this point, and is implemented as a callback.
  645. bound.expr.setown(createValue(no_add, bound.expr->getType(), row->getFinalFixedSizeExpr(), LINK(bound.expr)));
  646. HqlExprArray args2;
  647. args2.append(*LINK(row->queryBound()));
  648. args2.append(*LINK(bound.expr));
  649. translator.callProcedure(ctx, ensureRowAvailableId, args2);
  650. }
  651. else
  652. {
  653. unsigned maxRowSize = row->getMaxSize();
  654. unsigned fixedSize = totalSize.getFixedSize();
  655. //This removes calls that can be constant folded - a bit confusing in the generated code sometimes..
  656. if (!row->queryBuilder() && !totalSize.queryVarSize())
  657. return;
  658. totalSize.buildSizeExpr(translator, ctx, row, bound);
  659. IValue * value = bound.expr->queryValue();
  660. if (value)
  661. {
  662. unsigned constSize = (unsigned)value->getIntValue();
  663. if (constSize <= getMinRecordSize(row->queryRecord()))
  664. return;
  665. }
  666. StringBuffer fieldname;
  667. fieldname.append(column->queryName()).toLowerCase();
  668. if (row->queryBuilder())
  669. {
  670. HqlExprArray args2;
  671. args2.append(*LINK(row->queryBuilder()));
  672. args2.append(*LINK(bound.expr));
  673. args2.append(*createConstant(unknownVarStringType->castFrom(fieldname.length(), fieldname.str())));
  674. OwnedHqlExpr call = translator.bindFunctionCall(ensureCapacityId, args2);
  675. bool combined = false;
  676. if (bound.expr->isConstant())
  677. {
  678. //Try and merge all calls to ensureCapacity with a constant value
  679. IHqlExpression * marker = row->queryBuilderEnsureMarker();
  680. HqlStmtExprAssociation * match = static_cast<HqlStmtExprAssociation *>(ctx.queryAssociation(marker, AssocStmt, NULL));
  681. if (match)
  682. {
  683. //Check the previous call to ensureCapacity() wasn't outside of a condition
  684. //otherwise modifying it could cause problems with the other branches
  685. if (ctx.hasAssociation(*match, false))
  686. {
  687. ctx.replaceExpr(match->stmt, call);
  688. combined = true;
  689. }
  690. }
  691. if (!combined)
  692. {
  693. IHqlStmt * stmt = ctx.addExpr(call);
  694. ctx.associateOwn(* new HqlStmtExprAssociation(marker, stmt));
  695. combined = true;
  696. }
  697. }
  698. if (!combined)
  699. ctx.addExpr(call);
  700. }
  701. else
  702. {
  703. OwnedHqlExpr max = getSizetConstant(maxRowSize);
  704. HqlExprArray args2;
  705. args2.append(*LINK(bound.expr));
  706. args2.append(*LINK(max));
  707. args2.append(*createConstant(unknownVarStringType->castFrom(fieldname.length(), fieldname.str())));
  708. translator.callProcedure(ctx, checkFieldOverflowId, args2);
  709. }
  710. }
  711. }
  712. void CMemberInfo::defaultSetColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  713. {
  714. CHqlBoundTarget boundTarget;
  715. boundTarget.expr.setown(getColumnRef(translator, ctx, selector));
  716. translator.buildExprAssign(ctx, boundTarget, value);
  717. }
  718. void CMemberInfo::ensureTargetAvailable(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, size32_t thisSize)
  719. {
  720. OwnedHqlExpr minSize = getSizetConstant(thisSize);
  721. checkAssignOk(translator, ctx, selector, minSize, 0);
  722. }
  723. IHqlExpression * CMemberInfo::getColumnAddress(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, ITypeInfo * columnType, size32_t delta)
  724. {
  725. ITypeInfo * type;
  726. if (isTypePassedByAddress(columnType) && !hasReferenceModifier(columnType))
  727. {
  728. type = makeReferenceModifier(LINK(columnType));
  729. }
  730. else
  731. type = makePointerType(LINK(columnType));
  732. CHqlBoundExpr bound;
  733. getColumnOffset(translator, ctx, selector, bound);
  734. bound.expr.setown(adjustValue(bound.expr, delta));
  735. IHqlExpression * rowAddr = getPointer(selector->queryRootRow()->queryBound());
  736. // IValue * value = bound.expr->queryValue();
  737. // if (value && value->getIntValue()== 0)
  738. // return createValue(no_typetransfer, type, rowAddr));
  739. return createValue(no_add, type, rowAddr, bound.expr.getClear());
  740. }
  741. void CMemberInfo::getColumnOffset(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & tgt)
  742. {
  743. if (!isOffsetCached)
  744. calcAllCachedOffsets();
  745. if (!cachedOffset.isWorthCommoning())
  746. buildOffset(translator, ctx, selector, tgt);
  747. else
  748. {
  749. OwnedHqlExpr expr = createValue(no_offsetof, LINK(sizetType), LINK(selector->queryExpr()));
  750. translator.buildExpr(ctx, expr, tgt);
  751. }
  752. }
  753. IHqlExpression * CMemberInfo::getColumnRef(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  754. {
  755. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryType());
  756. return convertAddressToValue(address, queryType());
  757. }
  758. IHqlExpression * CMemberInfo::getCondition(BuildCtx & ctx)
  759. {
  760. if (container)
  761. return container->getCondition(ctx);
  762. return NULL;
  763. }
  764. IHqlExpression * CMemberInfo::getConditionSelect(HqlCppTranslator & translator, BuildCtx & ctx, BoundRow * row)
  765. {
  766. OwnedHqlExpr cond = getCondition(ctx);
  767. cond.setown(row->bindToRow(cond, queryRootSelf()));
  768. if (row->isConditional())
  769. extendConditionOwn(cond, no_and, createTranslated(row->queryBound()));
  770. if (cond)
  771. {
  772. //Force the ifblock condition to be evaluated in a temporary - since it will be reused several times.
  773. CHqlBoundExpr bound;
  774. HqlExprAssociation * match = ctx.queryMatchExpr(cond);
  775. if (match)
  776. bound.expr.set(match->queryExpr());
  777. else
  778. translator.buildSimpleExpr(ctx, cond, bound);
  779. IValue * boundValue = bound.expr->queryValue();
  780. if (boundValue)
  781. {
  782. if (boundValue->getBoolValue())
  783. return NULL;
  784. return LINK(bound.expr);
  785. }
  786. return bound.getTranslatedExpr();
  787. }
  788. return cond.getClear();
  789. }
  790. ITypeInfo * CMemberInfo::queryPhysicalType()
  791. {
  792. return queryType();
  793. }
  794. IReferenceSelector * CMemberInfo::getSelector(BuildCtx & ctx, IReferenceSelector * parentSelector)
  795. {
  796. return parentSelector->select(ctx, column);
  797. }
  798. void CMemberInfo::getXPath(StringBuffer & out)
  799. {
  800. if (container)
  801. container->getContainerXPath(out);
  802. IHqlExpression * xpath = column->queryAttribute(xpathAtom);
  803. if (xpath)
  804. xpath->queryChild(0)->queryValue()->getStringValue(out);
  805. else
  806. {
  807. IHqlExpression * named = column->queryAttribute(namedAtom);
  808. if (named)
  809. named->queryChild(0)->queryValue()->getStringValue(out);
  810. else
  811. {
  812. StringBuffer temp;
  813. temp.append(str(column->queryName())).toLowerCase();
  814. out.append(temp);
  815. }
  816. }
  817. }
  818. IHqlExpression * CMemberInfo::createSelectorExpr()
  819. {
  820. return createSelectExpr(container->getRelativeSelf(), column.getLink());
  821. }
  822. IHqlExpression * CMemberInfo::makeConditional(HqlCppTranslator & translator, BuildCtx & ctx, BoundRow * row, IHqlExpression * value)
  823. {
  824. OwnedHqlExpr cond = getConditionSelect(translator, ctx, row);
  825. if (cond)
  826. {
  827. IValue * condValue = cond->queryValue();
  828. if (!condValue)
  829. return createValue(no_if, value->getType(), cond.getClear(), LINK(value), createNullExpr(value));
  830. else if (!condValue->getBoolValue())
  831. return createNullExpr(value);
  832. }
  833. return LINK(value);
  834. }
  835. bool CMemberInfo::hasFixedOffset()
  836. {
  837. return !hasVarOffset;
  838. }
  839. bool CMemberInfo::isConditional()
  840. {
  841. if (container)
  842. return container->isConditional();
  843. return false;
  844. }
  845. IHqlExpression * CMemberInfo::queryParentSelector(IHqlExpression * selector)
  846. {
  847. return selector->queryChild(0);
  848. }
  849. IHqlExpression * CMemberInfo::queryRootSelf()
  850. {
  851. return container->queryRootSelf();
  852. }
  853. ITypeInfo * CMemberInfo::queryType() const
  854. {
  855. return column->queryType();
  856. }
  857. bool CMemberInfo::requiresTemp()
  858. {
  859. return isConditional();
  860. }
  861. void CMemberInfo::setOffset(bool _hasVarOffset)
  862. {
  863. hasVarOffset = _hasVarOffset;
  864. }
  865. AColumnInfo * CMemberInfo::lookupColumn(IHqlExpression * search)
  866. {
  867. throwUnexpected();
  868. }
  869. //---------------------------------------------------------------------------
  870. /* In param: _column is NOT linked */
  871. CContainerInfo::CContainerInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) :
  872. CMemberInfo(_container, _prior, _column)
  873. {
  874. fixedSize = true;
  875. isDynamic = false;
  876. }
  877. void CContainerInfo::addChild(CMemberInfo * child)
  878. {
  879. isOffsetCached = false;
  880. children.append(*LINK(child));
  881. registerChild(child);
  882. }
  883. void CContainerInfo::buildClear(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, int direction)
  884. {
  885. BuildCtx condctx(ctx);
  886. buildConditionFilter(translator, condctx, selector);
  887. if (children.ordinality() == 0)
  888. {
  889. if (column->queryRecord()->hasAttribute(_nonEmpty_Atom))
  890. {
  891. //Clear on an empty record that has the _nonEmpty_attrbute clears the implicit byte
  892. Owned<ITypeInfo> dummyType = makeIntType(1, false);
  893. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, dummyType);
  894. OwnedHqlExpr dummyTarget = convertAddressToValue(address, dummyType);
  895. translator.buildAssignToTemp(ctx, dummyTarget, queryZero());
  896. }
  897. return;
  898. }
  899. ForEachItemIn(idx, children)
  900. {
  901. CMemberInfo & cur = children.item(idx);
  902. Owned<IReferenceSelector> ds = cur.getSelector(ctx, selector);
  903. cur.buildClear(translator, condctx, ds, direction);
  904. }
  905. }
  906. void CContainerInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  907. {
  908. ForEachItemIn(idx, children)
  909. {
  910. CMemberInfo & cur = children.item(idx);
  911. Owned<IReferenceSelector> ds = cur.getSelector(ctx, selector);
  912. cur.buildDeserialize(translator, ctx, ds, helper, serializeForm);
  913. }
  914. }
  915. void CContainerInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  916. {
  917. ForEachItemIn(idx, children)
  918. {
  919. CMemberInfo & cur = children.item(idx);
  920. Owned<IReferenceSelector> ds = cur.getSelector(ctx, selector);
  921. cur.buildSerialize(translator, ctx, ds, helper, serializeForm);
  922. }
  923. }
  924. void CContainerInfo::buildSizeOf(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  925. {
  926. if (!isOffsetCached)
  927. calcAllCachedOffsets();
  928. if (container && !usesAccessClass())
  929. usesAccessClass();
  930. if (!container && usesAccessClass())
  931. {
  932. IHqlExpression * accessor = selector->queryRootRow()->ensureAccessor(translator, ctx);
  933. assertex(accessor);
  934. if (accessorSize.queryVarSize())
  935. bound.expr.setown(createValue(no_select, LINK(sizetType), LINK(accessor), LINK(accessorSize.queryVarSize())));
  936. bound.expr.setown(createSizeExpression(bound.expr, accessorSize.getFixedSize()));
  937. }
  938. else
  939. cachedSize.buildSizeExpr(translator, ctx, selector->queryRootRow(), bound);
  940. }
  941. bool CContainerInfo::prepareReadAhead(HqlCppTranslator & translator, ReadAheadState & state)
  942. {
  943. ForEachItemIn(idx, children)
  944. {
  945. CMemberInfo & cur = children.item(idx);
  946. if (!cur.prepareReadAhead(translator, state))
  947. return false;
  948. }
  949. return true;
  950. }
  951. bool CContainerInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  952. {
  953. ForEachItemIn(idx, children)
  954. {
  955. CMemberInfo & cur = children.item(idx);
  956. if (!cur.buildReadAhead(translator, ctx, state))
  957. return false;
  958. }
  959. return true;
  960. }
  961. IHqlExpression * CContainerInfo::createSelectorExpr()
  962. {
  963. if (!container)
  964. return getRelativeSelf();
  965. return CMemberInfo::createSelectorExpr();
  966. }
  967. void CContainerInfo::setRow(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IReferenceSelector * source)
  968. {
  969. if (!recordTypesMatch(selector->queryType(), source->queryType()))
  970. throwError(HQLERR_RecordNotCompatible);
  971. CHqlBoundExpr targetAddress, sourceAddress, length;
  972. source->buildAddress(ctx, sourceAddress);
  973. IHqlExpression * sourceExpr = source->queryExpr();
  974. OwnedHqlExpr rowExpr = sourceExpr->isDataset() ? ensureActiveRow(sourceExpr) : LINK(sourceExpr);
  975. OwnedHqlExpr size = createSizeof(rowExpr);
  976. translator.buildExpr(ctx, size, length);
  977. ensureSimpleLength(translator, ctx, length);
  978. calcAllCachedOffsets();
  979. //If copying from one identical record to another then the source record must be large enough,
  980. //so only need to check it it is a child record....
  981. if (!cachedSize.isFixedSize())
  982. {
  983. OwnedHqlExpr translatedLength = length.getTranslatedExpr();
  984. checkAssignOk(translator, ctx, selector, translatedLength, 0);
  985. }
  986. buildAddress(translator, ctx, selector, targetAddress);
  987. HqlExprArray args;
  988. if (recordRequiresLinkCount(column->queryRecord()))
  989. {
  990. args.append(*LINK(targetAddress.expr));
  991. args.append(*LINK(length.expr));
  992. args.append(*LINK(sourceAddress.expr));
  993. args.append(*translator.buildMetaParameter(column));
  994. translator.callProcedure(ctx, rtlCopyRowLinkChildrenId, args);
  995. }
  996. else
  997. {
  998. args.append(*LINK(targetAddress.expr));
  999. args.append(*LINK(sourceAddress.expr));
  1000. args.append(*LINK(length.expr));
  1001. translator.callProcedure(ctx, memcpyId, args);
  1002. }
  1003. //Use the size just calculated for the field
  1004. associateSizeOf(ctx, selector, length.expr, 0);
  1005. }
  1006. void CContainerInfo::addTrailingFixed(SizeStruct & size, CMemberInfo * cur)
  1007. {
  1008. if (container)
  1009. container->addTrailingFixed(size, this);
  1010. unsigned max = children.ordinality();
  1011. unsigned match = children.find(*cur);
  1012. for (unsigned i=match+1; i < max; i++)
  1013. size.addFixed(children.item(i).getTotalMinimumSize());
  1014. }
  1015. void CContainerInfo::subLeadingFixed(SizeStruct & size, CMemberInfo * cur)
  1016. {
  1017. if (container)
  1018. container->subLeadingFixed(size, this);
  1019. unsigned match = children.find(*cur);
  1020. for (unsigned i=0; i < match; i++)
  1021. size.addFixed((unsigned)-(int)children.item(i).getTotalFixedSize());
  1022. }
  1023. IHqlExpression * CContainerInfo::getCondition(BuildCtx & ctx)
  1024. {
  1025. if (container)
  1026. return container->getCondition(ctx);
  1027. return NULL;
  1028. }
  1029. void CContainerInfo::getContainerXPath(StringBuffer & out)
  1030. {
  1031. if (container)
  1032. container->getContainerXPath(out);
  1033. if (column->getOperator() == no_field)
  1034. {
  1035. StringBuffer temp;
  1036. IHqlExpression * xpath = column->queryAttribute(xpathAtom);
  1037. if (xpath)
  1038. xpath->queryChild(0)->queryValue()->getStringValue(temp);
  1039. else
  1040. {
  1041. IHqlExpression * named = column->queryAttribute(namedAtom);
  1042. if (named)
  1043. named->queryChild(0)->queryValue()->getStringValue(temp);
  1044. else
  1045. temp.append(str(column->queryName())).toLowerCase();
  1046. }
  1047. unsigned len = temp.length();
  1048. if (len && (temp.charAt(len-1) != '/'))
  1049. temp.append('/');
  1050. out.append(temp);
  1051. }
  1052. }
  1053. unsigned CContainerInfo::nextSeq()
  1054. {
  1055. if (container)
  1056. return container->nextSeq();
  1057. return ++seq;
  1058. }
  1059. bool CContainerInfo::isConditional()
  1060. {
  1061. if (container)
  1062. return container->isConditional();
  1063. return false;
  1064. }
  1065. void CContainerInfo::registerChild(CMemberInfo * child)
  1066. {
  1067. container->registerChild(child);
  1068. }
  1069. //---------------------------------------------------------------------------
  1070. CRecordInfo::CRecordInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) :
  1071. CContainerInfo(_container, _prior, _column)
  1072. {
  1073. useAccessClass = false;
  1074. }
  1075. void CRecordInfo::buildAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  1076. {
  1077. CHqlBoundExpr temp;
  1078. buildExpr(translator, ctx, selector, temp);
  1079. translator.assign(ctx, target, temp);
  1080. }
  1081. void CRecordInfo::buildExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1082. {
  1083. OwnedHqlExpr size = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()), NULL);
  1084. CHqlBoundExpr boundSize;
  1085. translator.buildExpr(ctx, size, boundSize);
  1086. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryType());
  1087. bound.length.set(boundSize.expr);
  1088. bound.expr.setown(convertAddressToValue(address, queryType()));
  1089. }
  1090. void CRecordInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  1091. {
  1092. translator.buildCompoundAssign(ctx, selector->queryExpr(), value);
  1093. }
  1094. IHqlExpression * CRecordInfo::getRelativeSelf()
  1095. {
  1096. if (!cachedSelf)
  1097. {
  1098. if (container)
  1099. cachedSelf.setown(createSelectExpr(container->getRelativeSelf(), LINK(column)));
  1100. else
  1101. cachedSelf.setown(createSelector(no_self, column->queryRecord(), NULL));
  1102. }
  1103. return LINK(cachedSelf);
  1104. }
  1105. IHqlExpression * CRecordInfo::queryRootSelf()
  1106. {
  1107. if (container)
  1108. return container->queryRootSelf();
  1109. if (!cachedSelf)
  1110. cachedSelf.setown(createSelector(no_self, column->queryRecord(), NULL));
  1111. return cachedSelf;
  1112. }
  1113. AColumnInfo * CRecordInfo::lookupColumn(IHqlExpression * search)
  1114. {
  1115. return map.find(search);
  1116. }
  1117. void CRecordInfo::registerChild(CMemberInfo * child)
  1118. {
  1119. map.replaceOwn(*child);
  1120. }
  1121. //---------------------------------------------------------------------------
  1122. CIfBlockInfo::CIfBlockInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) :
  1123. CContainerInfo(_container, _prior, _column)
  1124. {
  1125. OwnedHqlExpr self = container->getRelativeSelf();
  1126. condition.setown(replaceSelector(column->queryChild(0), querySelfReference(), self));
  1127. alwaysPresent = (condition->queryValue() && condition->queryValue()->getBoolValue());
  1128. }
  1129. void CIfBlockInfo::buildAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  1130. {
  1131. throwUnexpected();
  1132. }
  1133. void CIfBlockInfo::buildExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1134. {
  1135. throwUnexpected();
  1136. }
  1137. void CIfBlockInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1138. {
  1139. //MORE: This should really associate offset of the ifblock with the offset of its first child as well.
  1140. CHqlBoundExpr boundOffset;
  1141. buildOffset(translator, ctx, selector, boundOffset);
  1142. //NB: Sizeof(ifblock) has an unusual representation...
  1143. OwnedHqlExpr sizeOfIfBlock = createValue(no_sizeof, makeIntType(4,false), createSelectExpr(LINK(selector->queryExpr()), LINK(column)));
  1144. CHqlBoundTarget cachedSize;
  1145. cachedSize.expr.setown(ctx.getTempDeclare(sizetType, queryZero()));
  1146. //MORE: Should also conditionally set a variable to the size of the ifblock to simplify subsequent generated code
  1147. OwnedHqlExpr cond = selector->queryRootRow()->bindToRow(condition, queryRootSelf());
  1148. CHqlBoundExpr bound;
  1149. translator.buildSimpleExpr(ctx, cond, bound);
  1150. BuildCtx condctx(ctx);
  1151. condctx.addFilter(bound.expr);
  1152. //MORE: This test could be avoided if the first child is *actually* variable length
  1153. ensureTargetAvailable(translator, condctx, selector, CContainerInfo::getTotalMinimumSize());
  1154. CContainerInfo::buildDeserialize(translator, condctx, selector, helper, serializeForm);
  1155. //Avoid recalculating the size outside of the ifblock()
  1156. translator.buildExprAssign(condctx, cachedSize, sizeOfIfBlock);
  1157. ctx.associateExpr(sizeOfIfBlock, cachedSize.expr);
  1158. }
  1159. void CIfBlockInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1160. {
  1161. OwnedHqlExpr cond = selector->queryRootRow()->bindToRow(condition, queryRootSelf());
  1162. CHqlBoundExpr bound;
  1163. translator.buildSimpleExpr(ctx, cond, bound);
  1164. BuildCtx condctx(ctx);
  1165. condctx.addFilter(bound.expr);
  1166. CContainerInfo::buildSerialize(translator, condctx, selector, helper, serializeForm);
  1167. }
  1168. bool CIfBlockInfo::prepareReadAhead(HqlCppTranslator & translator, ReadAheadState & state)
  1169. {
  1170. gatherSelectExprs(state.requiredValues, condition);
  1171. return CContainerInfo::prepareReadAhead(translator, state);
  1172. }
  1173. bool CIfBlockInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  1174. {
  1175. try
  1176. {
  1177. OwnedHqlExpr mappedCondition = quickFullReplaceExpressions(condition, state.requiredValues, state.mappedValues);
  1178. //Early check to see if all the values have been mapped, rather than relying on exception processing.
  1179. if (!containsSelector(mappedCondition, queryRootSelf()))
  1180. {
  1181. BuildCtx condctx(ctx);
  1182. translator.buildFilter(condctx, mappedCondition);
  1183. return CContainerInfo::buildReadAhead(translator, condctx, state);
  1184. }
  1185. }
  1186. catch (IException * e)
  1187. {
  1188. //yuk yuk yuk!! Could't resolve the test condition for very unusual reason, e.g., based on a variable length string.
  1189. e->Release();
  1190. }
  1191. return false;
  1192. }
  1193. void CIfBlockInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  1194. {
  1195. throwUnexpected();
  1196. }
  1197. IHqlExpression * CIfBlockInfo::getCondition(BuildCtx & ctx)
  1198. {
  1199. IHqlExpression * containerCond = container->getCondition(ctx);
  1200. if (alwaysPresent)
  1201. return containerCond;
  1202. if (containerCond)
  1203. return createBoolExpr(no_and, LINK(condition), containerCond);
  1204. return LINK(condition);
  1205. }
  1206. IHqlExpression * CIfBlockInfo::getRelativeSelf()
  1207. {
  1208. return container->getRelativeSelf();
  1209. }
  1210. IReferenceSelector * CIfBlockInfo::getSelector(BuildCtx & ctx, IReferenceSelector * parentSelector)
  1211. {
  1212. return LINK(parentSelector);
  1213. }
  1214. bool CIfBlockInfo::isConditional()
  1215. {
  1216. if (alwaysPresent)
  1217. return CMemberInfo::isConditional();
  1218. return true;
  1219. }
  1220. IHqlExpression * CIfBlockInfo::queryParentSelector(IHqlExpression * selector)
  1221. {
  1222. return selector;
  1223. }
  1224. //---------------------------------------------------------------------------
  1225. CColumnInfo::CColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CMemberInfo(_container, _prior, _column)
  1226. {
  1227. }
  1228. void CColumnInfo::buildAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  1229. {
  1230. BoundRow * row = selector->queryRootRow();
  1231. if (isConditional() || row->isConditional())
  1232. {
  1233. CHqlBoundExpr boundCondition;
  1234. OwnedHqlExpr condition = getConditionSelect(translator, ctx, row);
  1235. //calculate the address (and throw it away) so that indexing calculations aren't
  1236. //included in the conditional code.
  1237. calcCurrentOffset(translator, ctx, selector);
  1238. // now generate if (a) b else c
  1239. BuildCtx condctx(ctx);
  1240. IHqlStmt * stmt = NULL;
  1241. if (condition)
  1242. stmt = translator.buildFilterViaExpr(condctx, condition);
  1243. buildColumnAssign(translator, condctx, selector, target);
  1244. if (stmt)
  1245. {
  1246. condctx.selectElse(stmt);
  1247. IHqlExpression * dft = column->queryChild(0);
  1248. if (dft && !dft->isAttribute() && dft->isConstant())
  1249. translator.buildExprAssign(condctx, target, dft);
  1250. else
  1251. translator.buildClear(condctx, target);
  1252. }
  1253. }
  1254. else
  1255. {
  1256. buildColumnAssign(translator, ctx, selector, target);
  1257. }
  1258. }
  1259. void CColumnInfo::calcCurrentOffset(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  1260. {
  1261. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryPhysicalType());
  1262. }
  1263. void CColumnInfo::gatherSize(SizeStruct & target)
  1264. {
  1265. if (isConditional())
  1266. addVariableSize(queryType()->getSize(), target);
  1267. else
  1268. target.addFixed(queryType()->getSize());
  1269. }
  1270. void CColumnInfo::buildSizeOf(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1271. {
  1272. //Need to be careful that buildSizeOfUnbound() is called within a test for the dataset being present
  1273. //otherwise with alien datatypes it can incorrectly access the current row.
  1274. BoundRow * row = selector->queryRootRow();
  1275. if (!row->isConditional())
  1276. {
  1277. OwnedHqlExpr value = ensureType(buildSizeOfUnbound(translator, ctx, selector), sizetType);
  1278. value.setown(makeConditional(translator, ctx, row, value));
  1279. translator.buildExpr(ctx, value, bound);
  1280. }
  1281. else
  1282. {
  1283. OwnedHqlExpr cond = getConditionSelect(translator, ctx, row);
  1284. CHqlBoundTarget tempTarget;
  1285. translator.createTempFor(ctx, sizetType, tempTarget, typemod_none, FormatNatural);
  1286. BuildCtx subctx(ctx);
  1287. IHqlStmt * ifStmt = translator.buildFilterViaExpr(subctx, cond);
  1288. OwnedHqlExpr value = ensureType(buildSizeOfUnbound(translator, subctx, selector), sizetType);
  1289. translator.buildExprAssign(subctx, tempTarget, value);
  1290. subctx.selectElse(ifStmt);
  1291. translator.buildExprAssign(subctx, tempTarget, queryZero());
  1292. bound.setFromTarget(tempTarget);
  1293. }
  1294. }
  1295. IHqlExpression * CColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  1296. {
  1297. ITypeInfo * type = queryType();
  1298. unsigned typeSize = type->getSize();
  1299. return getSizetConstant(typeSize);
  1300. }
  1301. static __int64 maxIntValue[] = { I64C(0), I64C(0x7F), I64C(0x7FFF), I64C(0x7FFFFF), I64C(0x7FFFFFFF), I64C(0x7FFFFFFFFF), I64C(0x7FFFFFFFFFFF), I64C(0x7FFFFFFFFFFFFF), I64C(0x7FFFFFFFFFFFFFFF) };
  1302. void CColumnInfo::buildClear(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, int direction)
  1303. {
  1304. OwnedHqlExpr null;
  1305. ITypeInfo * type = queryType();
  1306. if (direction != 0)
  1307. {
  1308. switch (type->getTypeCode())
  1309. {
  1310. case type_int:
  1311. case type_swapint:
  1312. if (type->isSigned())
  1313. {
  1314. __int64 value = maxIntValue[type->getSize()];
  1315. if (direction == -1)
  1316. value = 0-(value+1);
  1317. null.setown(createConstant(type->castFrom(true, value)));
  1318. }
  1319. break;
  1320. case type_decimal:
  1321. if (type->isSigned())
  1322. {
  1323. size32_t size = type->getSize();
  1324. byte * temp = (byte *)alloca(size);
  1325. memset(temp, 0x99, size-1);
  1326. if ((type->getDigits() & 1) != 0)
  1327. temp[0] = 0x99;
  1328. else
  1329. temp[0] = 0x09;
  1330. if (direction == 1)
  1331. temp[size-1] = 0x90;
  1332. else
  1333. temp[size-1] = 0x9F;
  1334. null.setown(createConstant(createValueFromMem(LINK(type), temp)));
  1335. }
  1336. else if (direction == 1)
  1337. {
  1338. size32_t size = type->getSize();
  1339. byte * temp = (byte *)alloca(size);
  1340. memset(temp, 0x99, size);
  1341. if ((type->getDigits() & 1) != 0)
  1342. temp[0] = 0x99;
  1343. else
  1344. temp[0] = 0x09;
  1345. null.setown(createConstant(createValueFromMem(LINK(type), temp)));
  1346. }
  1347. break;
  1348. case type_real:
  1349. //MORE: ? assign +/-inf?
  1350. break;
  1351. case type_string:
  1352. case type_data:
  1353. case type_varstring:
  1354. {
  1355. size32_t size = type->getSize();
  1356. size32_t len = type->getStringLen();
  1357. if (size == UNKNOWN_LENGTH)
  1358. {
  1359. assertex(direction < 0);
  1360. null.setown(createConstant(type->castFrom(0, (const char *)NULL)));
  1361. }
  1362. else
  1363. {
  1364. MemoryAttr buffer(size);
  1365. memset(buffer.bufferBase(), direction < 0 ? 0x00 : 0xff, size);
  1366. null.setown(createConstant(type->castFrom(len, (const char *)buffer.get())));
  1367. }
  1368. break;
  1369. }
  1370. case type_unicode:
  1371. case type_varunicode:
  1372. {
  1373. assertex(direction < 0);
  1374. size32_t size = type->getSize();
  1375. size32_t len = type->getStringLen();
  1376. if (size == UNKNOWN_LENGTH)
  1377. {
  1378. null.setown(createConstant(type->castFrom(0, (const UChar *)NULL)));
  1379. }
  1380. else
  1381. {
  1382. MemoryAttr buffer(size);
  1383. memset(buffer.bufferBase(), 0x00, size);
  1384. null.setown(createConstant(type->castFrom(len, (const UChar *)buffer.get())));
  1385. }
  1386. break;
  1387. }
  1388. }
  1389. }
  1390. if (!null)
  1391. null.setown(createNullExpr(column));
  1392. setColumn(translator, ctx, selector, null);
  1393. }
  1394. void CColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1395. {
  1396. CHqlBoundExpr boundSize;
  1397. OwnedHqlExpr unboundSize = ensureType(buildSizeOfUnbound(translator, ctx, selector), sizetType);
  1398. translator.buildExpr(ctx, unboundSize, boundSize);
  1399. doBuildDeserialize(translator, ctx, selector, helper, boundSize.expr);
  1400. }
  1401. void CColumnInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1402. {
  1403. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  1404. CHqlBoundExpr boundSize;
  1405. translator.buildExpr(ctx, sizeOfExpr, boundSize);
  1406. HqlExprArray args;
  1407. args.append(*LINK(helper));
  1408. args.append(*LINK(boundSize.expr));
  1409. args.append(*getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  1410. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(serializerPutId, args);
  1411. ctx.addExpr(call);
  1412. }
  1413. bool CColumnInfo::prepareReadAhead(HqlCppTranslator & translator, ReadAheadState & state)
  1414. {
  1415. return true;
  1416. }
  1417. bool CColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  1418. {
  1419. size32_t columnSize = queryType()->getSize();
  1420. if ((columnSize != UNKNOWN_LENGTH) && state.requiredValues.ordinality())
  1421. {
  1422. OwnedHqlExpr selector = createSelectorExpr();
  1423. unsigned match = state.requiredValues.find(*selector);
  1424. if (match != NotFound)
  1425. {
  1426. OwnedHqlExpr tempVariable = ctx.getTempDeclare(queryType(), NULL);
  1427. HqlExprArray args;
  1428. args.append(*LINK(state.helper));
  1429. args.append(*getSizetConstant(columnSize));
  1430. args.append(*getPointer(tempVariable));
  1431. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(deserializerReadNId, args);
  1432. ctx.addExpr(call);
  1433. OwnedHqlExpr translated = createTranslated(tempVariable);
  1434. state.setMapping(match, translated);
  1435. return true;
  1436. }
  1437. }
  1438. doBuildSkipInput(translator, ctx, state.helper, column->queryType()->getSize());
  1439. return true;
  1440. }
  1441. void CColumnInfo::buildExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1442. {
  1443. BoundRow * row = selector->queryRootRow();
  1444. if (isConditional() || row->isConditional())
  1445. {
  1446. OwnedHqlExpr condition = getConditionSelect(translator, ctx, row);
  1447. if (condition)
  1448. {
  1449. //Unusual, but if this is inside a fileview translation helper there is no context, so use blocked
  1450. //format to avoid temporaries that require an allocator.
  1451. //A better fix long term would be to pass the format to get() and buildExpr
  1452. ExpressionFormat format = ctx.queryMatchExpr(codeContextMarkerExpr) ? FormatNatural : FormatBlockedDataset;
  1453. //MORE: Can conditionally code retrieval be improved for some types of field...
  1454. CHqlBoundTarget tempTarget;
  1455. translator.createTempFor(ctx, queryLogicalType(), tempTarget, typemod_none, format);
  1456. buildAssign(translator, ctx, selector, tempTarget);
  1457. bound.setFromTarget(tempTarget);
  1458. return;
  1459. }
  1460. }
  1461. buildColumnExpr(translator, ctx, selector, bound);
  1462. }
  1463. bool CColumnInfo::isFixedSize()
  1464. {
  1465. return (queryType()->getSize() != UNKNOWN_LENGTH);
  1466. }
  1467. void CColumnInfo::buildColumnAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  1468. {
  1469. CHqlBoundExpr bound;
  1470. buildColumnExpr(translator, ctx, selector, bound);
  1471. translator.assign(ctx, target, bound);
  1472. }
  1473. void CColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1474. {
  1475. bound.expr.setown(getColumnRef(translator, ctx, selector));
  1476. }
  1477. void CColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  1478. {
  1479. if (isConditional())
  1480. {
  1481. OwnedHqlExpr size = getSizetConstant(queryType()->getSize());
  1482. checkAssignOk(translator, ctx, selector, size, 0);
  1483. CHqlBoundTarget tgt;
  1484. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryType());
  1485. tgt.expr.setown(convertAddressToValue(address, queryType()));
  1486. translator.buildExprAssign(ctx, tgt, value);
  1487. }
  1488. else
  1489. defaultSetColumn(translator, ctx, selector, value);
  1490. }
  1491. //---------------------------------------------------------------------------
  1492. CSpecialIntColumnInfo::CSpecialIntColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  1493. {
  1494. }
  1495. void CSpecialIntColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1496. {
  1497. ITypeInfo * type = queryType();
  1498. IIdAtom * func = readIntId[type->getSize()][type->isSigned()];
  1499. HqlExprArray args;
  1500. args.append(*getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  1501. bound.expr.setown(translator.bindTranslatedFunctionCall(func, args));
  1502. ITypeInfo * promoted = type->queryPromotedType();
  1503. if (promoted != bound.expr->queryType())
  1504. bound.expr.setown(createValue(no_typetransfer, LINK(promoted), bound.expr.getClear()));
  1505. }
  1506. void CSpecialIntColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  1507. {
  1508. ITypeInfo * type = queryType();
  1509. ITypeInfo * promoted = type->queryPromotedType();
  1510. IIdAtom * func = writeIntId[type->getSize()];
  1511. if (isConditional())
  1512. {
  1513. OwnedHqlExpr size = getSizetConstant(type->getSize());
  1514. checkAssignOk(translator, ctx, selector, size, 0);
  1515. }
  1516. HqlExprArray args;
  1517. CHqlBoundExpr bound;
  1518. args.append(*getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  1519. ITypeInfo * valueType = value->queryType();
  1520. LinkedHqlExpr castValue = value;
  1521. if (valueType->getTypeCode() != type_int || type->getTypeCode() != type_int)
  1522. castValue.setown(ensureExprType(value, promoted));
  1523. translator.buildExpr(ctx, castValue, bound);
  1524. args.append(*bound.expr.getLink());
  1525. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(func, args);
  1526. ctx.addExpr(call);
  1527. }
  1528. //---------------------------------------------------------------------------
  1529. CPackedIntColumnInfo::CPackedIntColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  1530. {
  1531. }
  1532. void CPackedIntColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1533. {
  1534. ITypeInfo * type = queryType();
  1535. IIdAtom * func = type->isSigned() ? getPackedSignedId : getPackedUnsignedId;
  1536. HqlExprArray args;
  1537. args.append(*getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  1538. bound.expr.setown(translator.bindTranslatedFunctionCall(func, args));
  1539. ITypeInfo * promoted = type->queryPromotedType();
  1540. if (promoted != bound.expr->queryType())
  1541. bound.expr.setown(createValue(no_typetransfer, LINK(promoted), bound.expr.getClear()));
  1542. }
  1543. void CPackedIntColumnInfo::gatherSize(SizeStruct & target)
  1544. {
  1545. addVariableSize(1, target);
  1546. }
  1547. IHqlExpression * CPackedIntColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  1548. {
  1549. HqlExprArray args;
  1550. args.append(*getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  1551. return createValue(no_translated, LINK(sizetType), translator.bindTranslatedFunctionCall(getPackedSizeId, args));
  1552. }
  1553. void CPackedIntColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1554. {
  1555. OwnedHqlExpr size = getSizetConstant(queryType()->queryPromotedType()->getSize()+1); // an over-estimate, but more efficient than working out exactly.
  1556. checkAssignOk(translator, ctx, selector, size, 0);
  1557. HqlExprArray args;
  1558. args.append(*LINK(helper));
  1559. args.append(*getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  1560. translator.buildTranslatedFunctionCall(ctx, deserializerReadPackedIntId, args);
  1561. }
  1562. bool CPackedIntColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  1563. {
  1564. Owned<ITypeInfo> tempType = makeDataType(queryType()->queryPromotedType()->getSize()+1); // an over-estimate
  1565. OwnedHqlExpr tempVar = ctx.getTempDeclare(tempType, NULL);
  1566. HqlExprArray args;
  1567. args.append(*LINK(state.helper));
  1568. args.append(*getPointer(tempVar));
  1569. translator.buildTranslatedFunctionCall(ctx, deserializerReadPackedIntId, args);
  1570. return true;
  1571. }
  1572. void CPackedIntColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  1573. {
  1574. ITypeInfo * type = queryType();
  1575. IIdAtom * func = type->isSigned() ? setPackedSignedId : setPackedUnsignedId;
  1576. OwnedHqlExpr size = getSizetConstant(type->queryPromotedType()->getSize()+1); // an over-estimate, but more efficient than working out exactly.
  1577. checkAssignOk(translator, ctx, selector, size, 0);
  1578. HqlExprArray args;
  1579. CHqlBoundExpr bound;
  1580. args.append(*getColumnAddress(translator, ctx, selector, queryPhysicalType()));
  1581. OwnedHqlExpr castValue = ensureExprType(value, type);
  1582. translator.buildExpr(ctx, castValue, bound);
  1583. args.append(*LINK(bound.expr));
  1584. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(func, args);
  1585. ctx.addExpr(call);
  1586. }
  1587. //---------------------------------------------------------------------------
  1588. CSpecialStringColumnInfo::CSpecialStringColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  1589. {
  1590. }
  1591. void CSpecialStringColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1592. {
  1593. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, sizetType);
  1594. OwnedHqlExpr addressStr = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  1595. bound.length.setown(convertAddressToValue(address, sizetType));
  1596. bound.expr.setown(convertAddressToValue(addressStr, queryType()));
  1597. #if 0
  1598. //Following improves code for transforms, disable until I finish regression testing
  1599. ensureSimpleLength(translator, ctx, bound);
  1600. OwnedHqlExpr boundSize = translator.getBoundSize(bound);
  1601. associateSizeOf(ctx, selector, boundSize, sizeof(size32_t));
  1602. #endif
  1603. }
  1604. void CSpecialStringColumnInfo::gatherSize(SizeStruct & target)
  1605. {
  1606. addVariableSize(sizeof(size32_t), target);
  1607. }
  1608. void CSpecialStringColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1609. {
  1610. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, sizetType);
  1611. OwnedHqlExpr addressStr = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  1612. OwnedHqlExpr targetLength = convertAddressToValue(address, sizetType);
  1613. OwnedHqlExpr sizeSizet = getSizetConstant(sizeof(size32_t));
  1614. callDeserializeGetN(translator, ctx, helper, sizeSizet, address);
  1615. if (queryType()->getTypeCode() == type_utf8)
  1616. {
  1617. BoundRow * row = selector->queryRootRow();
  1618. CHqlBoundExpr boundOffset;
  1619. getColumnOffset(translator, ctx, selector, boundOffset);
  1620. SizeStruct fixedRowSize;
  1621. CHqlBoundExpr boundFixedRowSize;
  1622. gatherMaxRowSize(fixedRowSize, NULL, sizeof(size32_t), selector);
  1623. fixedRowSize.buildSizeExpr(translator, ctx, row, boundFixedRowSize);
  1624. assertex(!row->isSerialization() && row->queryBuilder());
  1625. IIdAtom * func = deserializerReadUtf8Id;
  1626. HqlExprArray args;
  1627. args.append(*LINK(helper));
  1628. args.append(*LINK(row->queryBuilder()));
  1629. args.append(*adjustValue(boundOffset.expr, sizeof(size32_t)));
  1630. args.append(*LINK(boundFixedRowSize.expr));
  1631. args.append(*LINK(targetLength));
  1632. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(func, args);
  1633. OwnedHqlExpr sizeVariable = ctx.getTempDeclare(sizetType, call);
  1634. associateSizeOf(ctx, selector, sizeVariable, sizeof(size32_t));
  1635. }
  1636. else
  1637. {
  1638. CHqlBoundExpr bound;
  1639. bound.length.setown(translator.ensureSimpleTranslatedExpr(ctx, targetLength));
  1640. bound.expr.setown(convertAddressToValue(addressStr, queryType()));
  1641. OwnedHqlExpr boundSize = translator.getBoundSize(bound);
  1642. if (queryType()->getTypeCode() == type_qstring)
  1643. boundSize.setown(translator.ensureSimpleTranslatedExpr(ctx, boundSize));
  1644. OwnedHqlExpr unboundSize = createTranslated(boundSize);
  1645. checkAssignOk(translator, ctx, selector, unboundSize, sizeof(size32_t));
  1646. callDeserializeGetN(translator, ctx, helper, boundSize, addressStr);
  1647. associateSizeOf(ctx, selector, boundSize, sizeof(size32_t));
  1648. }
  1649. }
  1650. bool CSpecialStringColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  1651. {
  1652. OwnedHqlExpr lengthVariable = callDeserializerGetSize(translator, ctx, state.helper);
  1653. if (column->queryType()->getTypeCode() == type_utf8)
  1654. {
  1655. HqlExprArray args;
  1656. args.append(*LINK(state.helper));
  1657. args.append(*LINK(lengthVariable));
  1658. translator.callProcedure(ctx, deserializerSkipUtf8Id, args);
  1659. }
  1660. else
  1661. {
  1662. OwnedHqlExpr size = translator.getBoundSize(column->queryType(), lengthVariable, NULL);
  1663. callDeserializerSkipInputTranslatedSize(translator, ctx, state.helper, size);
  1664. }
  1665. return true;
  1666. }
  1667. IHqlExpression * CSpecialStringColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  1668. {
  1669. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, sizetType);
  1670. OwnedHqlExpr addressStr = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  1671. OwnedHqlExpr length = convertAddressToValue(address, sizetType);
  1672. assertex(length->queryType()->queryTypeBase() == sizetType);
  1673. OwnedHqlExpr boundSize = translator.getBoundSize(column->queryType(), length, addressStr);
  1674. return createValue(no_translated, LINK(sizetType), adjustValue(boundSize, sizeof(size32_t)));
  1675. }
  1676. void CSpecialStringColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  1677. {
  1678. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, sizetType, 0);
  1679. OwnedHqlExpr addressStr = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  1680. ITypeInfo * columnType = column->queryType();
  1681. CHqlBoundExpr bound;
  1682. OwnedHqlExpr value = ensureExprType(_value, columnType);
  1683. translator.buildExpr(ctx, value, bound);
  1684. ensureSimpleLength(translator, ctx, bound);
  1685. OwnedHqlExpr length = createValue(no_translated, LINK(sizetType), translator.getBoundLength(bound));
  1686. OwnedHqlExpr size = createValue(no_translated, LINK(sizetType), translator.getBoundSize(bound));
  1687. checkAssignOk(translator, ctx, selector, size, sizeof(size32_t));
  1688. CHqlBoundTarget boundTarget;
  1689. boundTarget.expr.setown(convertAddressToValue(address, sizetType));
  1690. translator.buildExprAssign(ctx, boundTarget, length);
  1691. translator.buildBlockCopy(ctx, addressStr, bound);
  1692. //Use the size just calulated for the field
  1693. OwnedHqlExpr boundSize = translator.getBoundSize(bound);
  1694. associateSizeOf(ctx, selector, boundSize, sizeof(size32_t));
  1695. }
  1696. //---------------------------------------------------------------------------
  1697. CSpecialVStringColumnInfo::CSpecialVStringColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  1698. {
  1699. }
  1700. void CSpecialVStringColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1701. {
  1702. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryType(), 0);
  1703. bound.expr.setown(convertAddressToValue(address, queryType()));
  1704. }
  1705. void CSpecialVStringColumnInfo::gatherSize(SizeStruct & target)
  1706. {
  1707. size32_t varMinSize = (queryType()->getTypeCode() == type_varunicode) ? sizeof(UChar) : 1;
  1708. addVariableSize(varMinSize, target);
  1709. }
  1710. IHqlExpression * CSpecialVStringColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  1711. {
  1712. CHqlBoundExpr bound;
  1713. buildColumnExpr(translator, ctx, selector, bound);
  1714. IHqlExpression * length = translator.getBoundSize(bound);
  1715. return createTranslatedOwned(length);
  1716. }
  1717. void CSpecialVStringColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1718. {
  1719. BoundRow * row = selector->queryRootRow();
  1720. CHqlBoundExpr boundOffset;
  1721. getColumnOffset(translator, ctx, selector, boundOffset);
  1722. SizeStruct fixedRowSize;
  1723. CHqlBoundExpr boundFixedRowSize;
  1724. gatherMaxRowSize(fixedRowSize, NULL, 0, selector);
  1725. fixedRowSize.buildSizeExpr(translator, ctx, row, boundFixedRowSize);
  1726. assertex(!row->isSerialization() && row->queryBuilder());
  1727. IIdAtom * func;
  1728. switch (queryType()->getTypeCode())
  1729. {
  1730. case type_varstring:
  1731. func = deserializerReadVStrId;
  1732. break;
  1733. case type_varunicode:
  1734. func = deserializerReadVUniId;
  1735. break;
  1736. default:
  1737. throwUnexpected();
  1738. }
  1739. HqlExprArray args;
  1740. args.append(*LINK(helper));
  1741. args.append(*LINK(row->queryBuilder()));
  1742. args.append(*LINK(boundOffset.expr));
  1743. args.append(*LINK(boundFixedRowSize.expr));
  1744. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(func, args);
  1745. OwnedHqlExpr sizeVariable = ctx.getTempDeclare(sizetType, call);
  1746. associateSizeOf(ctx, selector, sizeVariable, 0);
  1747. }
  1748. bool CSpecialVStringColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  1749. {
  1750. HqlExprArray args;
  1751. args.append(*LINK(state.helper));
  1752. IIdAtom * func;
  1753. switch (queryType()->getTypeCode())
  1754. {
  1755. case type_varstring:
  1756. func = deserializerSkipVStrId;
  1757. break;
  1758. case type_varunicode:
  1759. func = deserializerSkipVUniId;
  1760. break;
  1761. default:
  1762. throwUnexpected();
  1763. }
  1764. translator.callProcedure(ctx, func, args);
  1765. return true;
  1766. }
  1767. void CSpecialVStringColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  1768. {
  1769. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryType(), 0);
  1770. OwnedHqlExpr target = convertAddressToValue(address, queryType());
  1771. ITypeInfo * columnType = column->queryType();
  1772. OwnedHqlExpr value = ensureExprType(_value, columnType);
  1773. //Allow a direct assignment from a string, rather than creating a temp varstring.
  1774. switch (value->getOperator())
  1775. {
  1776. case no_cast: case no_implicitcast:
  1777. ITypeInfo * type = value->queryType();
  1778. ITypeInfo * prevType = value->queryChild(0)->queryType();
  1779. if ((type->getTypeCode() == type_varstring) && (prevType->getTypeCode() == type_string) &&
  1780. (type->queryCharset() == prevType->queryCharset()))
  1781. value.set(value->queryChild(0));
  1782. break;
  1783. }
  1784. CHqlBoundExpr bound;
  1785. translator.buildExpr(ctx, value, bound);
  1786. // ensureSimpleLength(translator, ctx, bound);
  1787. OwnedHqlExpr length = translator.getBoundLength(bound);
  1788. OwnedHqlExpr targetSize = adjustValue(length, 1);
  1789. if (isUnicodeType(columnType))
  1790. targetSize.setown(createValue(no_mul, targetSize->getType(), LINK(targetSize), getSizetConstant(2)));
  1791. OwnedHqlExpr translatedLength = createTranslated(targetSize);
  1792. checkAssignOk(translator, ctx, selector, translatedLength, 0);
  1793. HqlExprArray args;
  1794. if (columnType->getTypeCode() == type_varunicode)
  1795. {
  1796. translator.buildBlockCopy(ctx, address, bound);
  1797. }
  1798. else if (bound.expr->queryType()->getTypeCode() == type_varstring)
  1799. {
  1800. args.append(*target.getLink());
  1801. args.append(*translator.getElementPointer(bound.expr));
  1802. translator.callProcedure(ctx, strcpyId, args);
  1803. }
  1804. else
  1805. {
  1806. args.append(*LINK(targetSize));
  1807. args.append(*target.getLink());
  1808. args.append(*LINK(length));
  1809. args.append(*translator.getElementPointer(bound.expr));
  1810. translator.callProcedure(ctx, str2VStrId, args);
  1811. associateSizeOf(ctx, selector, LINK(targetSize), 0);
  1812. }
  1813. }
  1814. //---------------------------------------------------------------------------
  1815. CAlienColumnInfo::CAlienColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  1816. {
  1817. self.setown(container->getRelativeSelf());
  1818. }
  1819. void CAlienColumnInfo::buildAddress(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1820. {
  1821. Linked<ITypeInfo> physicalType = queryPhysicalType();
  1822. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, physicalType, 0);
  1823. OwnedHqlExpr value = convertAddressToValue(address, physicalType);
  1824. bound.expr.set(value->queryChild(0));
  1825. }
  1826. IHqlExpression * CAlienColumnInfo::doBuildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper)
  1827. {
  1828. ITypeInfo * type = queryType();
  1829. IHqlAlienTypeInfo * alien = queryAlienType(type);
  1830. unsigned size = alien->getPhysicalTypeSize();
  1831. if (size != UNKNOWN_LENGTH)
  1832. return getSizetConstant(size);
  1833. BoundRow * cursor = selector->queryRootRow();
  1834. IHqlExpression * lengthAttr = alien->queryLengthFunction();
  1835. if (!lengthAttr->isFunctionDefinition())
  1836. {
  1837. OwnedHqlExpr absoluteLength = replaceSelector(lengthAttr, querySelfReference(), self);
  1838. OwnedHqlExpr value = cursor->bindToRow(absoluteLength, queryRootSelf());
  1839. return ensureExprType(value, sizetType);
  1840. }
  1841. HqlExprArray args;
  1842. if (lengthAttr->queryChild(0))
  1843. {
  1844. OwnedHqlExpr address;
  1845. Owned<ITypeInfo> physicalType = getPhysicalSourceType();
  1846. if (helper)
  1847. address.setown(createSelfPeekDeserializer(translator, helper));
  1848. else
  1849. address.setown(getColumnAddress(translator, ctx, selector, physicalType, 0));
  1850. OwnedHqlExpr value = convertAddressToValue(address, physicalType);
  1851. args.append(*createTranslated(value));
  1852. }
  1853. OwnedHqlExpr expr = createBoundFunction(NULL, lengthAttr, args, NULL, true);
  1854. OwnedHqlExpr absoluteExpr = replaceSelector(expr, querySelfReference(), self);
  1855. OwnedHqlExpr value = cursor->bindToRow(absoluteExpr, queryRootSelf());
  1856. return ensureExprType(value, sizetType);
  1857. }
  1858. IHqlExpression * CAlienColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  1859. {
  1860. return doBuildSizeOfUnbound(translator, ctx, selector, NULL);
  1861. }
  1862. void CAlienColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  1863. {
  1864. OwnedHqlExpr unboundSize = doBuildSizeOfUnbound(translator, ctx, selector, helper);
  1865. CHqlBoundExpr boundSize;
  1866. if (unboundSize->isConstant())
  1867. translator.buildSimpleExpr(ctx, unboundSize, boundSize);
  1868. else
  1869. translator.buildTempExpr(ctx, unboundSize, boundSize);
  1870. doBuildDeserialize(translator, ctx, selector, helper, boundSize.expr);
  1871. }
  1872. bool CAlienColumnInfo::prepareReadAhead(HqlCppTranslator & translator, ReadAheadState & state)
  1873. {
  1874. return false; // too complicated to do safetly. It really needs a rethink...
  1875. }
  1876. bool CAlienColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  1877. {
  1878. throwUnexpected();
  1879. }
  1880. void CAlienColumnInfo::gatherSize(SizeStruct & target)
  1881. {
  1882. unsigned size = getPhysicalSize();
  1883. if (isConditional())
  1884. addVariableSize(0, target);
  1885. else
  1886. {
  1887. if (size != UNKNOWN_LENGTH)
  1888. target.addFixed(size);
  1889. else
  1890. addVariableSize(0, target);
  1891. }
  1892. }
  1893. unsigned CAlienColumnInfo::getPhysicalSize()
  1894. {
  1895. ITypeInfo * type = queryType();
  1896. IHqlAlienTypeInfo * alien = queryAlienType(type);
  1897. unsigned size = alien->getPhysicalTypeSize();
  1898. if (size == UNKNOWN_LENGTH)
  1899. {
  1900. IHqlExpression * lengthAttr = queryStripCasts(alien->queryLengthFunction());
  1901. if (lengthAttr->isConstant() && !lengthAttr->isFunction())
  1902. {
  1903. OwnedHqlExpr folded = foldHqlExpression(lengthAttr);
  1904. if (folded->queryValue())
  1905. size = (unsigned)folded->queryValue()->getIntValue();
  1906. }
  1907. }
  1908. return size;
  1909. }
  1910. ITypeInfo * CAlienColumnInfo::queryPhysicalType()
  1911. {
  1912. IHqlAlienTypeInfo * alien = queryAlienType(queryType());
  1913. return alien->queryPhysicalType();
  1914. }
  1915. ITypeInfo * CAlienColumnInfo::getPhysicalSourceType()
  1916. {
  1917. ITypeInfo * physicalType = queryPhysicalType();
  1918. if (physicalType->getSize() == UNKNOWN_LENGTH)
  1919. return getStretchedType(INFINITE_LENGTH, physicalType);
  1920. return LINK(physicalType);
  1921. }
  1922. IHqlExpression * CAlienColumnInfo::getAlienGetFunction(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  1923. {
  1924. ITypeInfo * columnType = queryType();
  1925. IHqlAlienTypeInfo * alien = queryAlienType(columnType);
  1926. IHqlExpression * getFunction = alien->queryLoadFunction();
  1927. Owned<ITypeInfo> physicalType = getPhysicalSourceType();
  1928. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, physicalType, 0);
  1929. OwnedHqlExpr physical = convertAddressToValue(address, physicalType);
  1930. HqlExprArray args;
  1931. args.append(*createTranslated(physical));
  1932. OwnedHqlExpr bound = createBoundFunction(NULL, getFunction, args, NULL, true);
  1933. OwnedHqlExpr absoluteBound = replaceSelector(bound, querySelfReference(), self);
  1934. return selector->queryRootRow()->bindToRow(absoluteBound, queryRootSelf());
  1935. }
  1936. bool CAlienColumnInfo::isFixedSize()
  1937. {
  1938. return getPhysicalSize() != UNKNOWN_LENGTH;
  1939. }
  1940. void CAlienColumnInfo::buildColumnAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  1941. {
  1942. OwnedHqlExpr expr = getAlienGetFunction(translator, ctx, selector);
  1943. translator.buildExprAssign(ctx, target, expr);
  1944. }
  1945. void CAlienColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  1946. {
  1947. BoundRow * cursor = selector->queryRootRow();
  1948. ITypeInfo * columnType = queryType();
  1949. IHqlAlienTypeInfo * alien = queryAlienType(columnType);
  1950. IHqlExpression * getFunction = alien->queryLoadFunction();
  1951. Owned<ITypeInfo> physicalType = getPhysicalSourceType();
  1952. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, physicalType);
  1953. OwnedHqlExpr physical = convertAddressToValue(address, physicalType);
  1954. HqlExprArray args;
  1955. args.append(*createTranslated(physical));
  1956. OwnedHqlExpr expr = createBoundFunction(NULL, getFunction, args, NULL, true);
  1957. OwnedHqlExpr absoluteExpr = replaceSelector(expr, querySelfReference(), self);
  1958. OwnedHqlExpr selectedExpr = cursor->bindToRow(absoluteExpr, queryRootSelf());
  1959. translator.buildExpr(ctx, selectedExpr, bound);
  1960. }
  1961. void CAlienColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  1962. {
  1963. BoundRow * cursor = selector->queryRootRow();
  1964. ITypeInfo * columnType = queryType();
  1965. IHqlAlienTypeInfo * alien = queryAlienType(columnType);
  1966. IHqlExpression * setFunction = alien->queryStoreFunction();
  1967. HqlExprArray args;
  1968. CHqlBoundExpr bound;
  1969. translator.buildExpr(ctx, value, bound);
  1970. args.append(*bound.getTranslatedExpr());
  1971. OwnedHqlExpr call = createBoundFunction(NULL, setFunction, args, NULL, true);
  1972. Linked<ITypeInfo> physicalType = queryPhysicalType();
  1973. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, physicalType, 0);
  1974. IHqlExpression * tgt = convertAddressToValue(address, physicalType);
  1975. OwnedHqlExpr absoluteCall = replaceSelector(call, querySelfReference(), self);
  1976. OwnedHqlExpr selectedCall = cursor->bindToRow(absoluteCall, queryRootSelf());
  1977. if (physicalType->getSize() == UNKNOWN_LENGTH)
  1978. {
  1979. CHqlBoundExpr boundCall;
  1980. translator.buildExpr(ctx, selectedCall, boundCall);
  1981. OwnedHqlExpr size = translator.getBoundSize(boundCall);
  1982. OwnedHqlExpr translatedSize = createTranslated(size);
  1983. checkAssignOk(translator, ctx, selector, translatedSize, 0);
  1984. translator.buildBlockCopy(ctx, tgt, boundCall);
  1985. //Use the size just calulated for sizeof(target)
  1986. associateSizeOf(ctx, selector, size, 0);
  1987. }
  1988. else
  1989. {
  1990. if (isConditional())
  1991. {
  1992. OwnedHqlExpr size = getSizetConstant(physicalType->getSize());
  1993. checkAssignOk(translator, ctx, selector, size, 0);
  1994. }
  1995. CHqlBoundTarget boundTarget;
  1996. boundTarget.expr.set(tgt);
  1997. translator.buildExprAssign(ctx, boundTarget, selectedCall);
  1998. }
  1999. tgt->Release();
  2000. }
  2001. //---------------------------------------------------------------------------
  2002. CBitfieldContainerInfo::CBitfieldContainerInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) :
  2003. CContainerInfo(_container, _prior, _column)
  2004. {
  2005. }
  2006. //AColumnInfo
  2007. void CBitfieldContainerInfo::buildAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  2008. {
  2009. throwUnexpected();
  2010. }
  2011. void CBitfieldContainerInfo::buildClear(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, int direction)
  2012. {
  2013. BuildCtx condctx(ctx);
  2014. BoundRow * cursor = selector->queryRootRow();
  2015. OwnedHqlExpr condition = getConditionSelect(translator, ctx, cursor);
  2016. if (condition)
  2017. translator.buildFilter(condctx, condition);
  2018. OwnedHqlExpr null = createNullExpr(column);
  2019. setColumn(translator, condctx, selector, null);
  2020. }
  2021. void CBitfieldContainerInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  2022. {
  2023. OwnedHqlExpr size = getSizetConstant(column->queryType()->getSize());
  2024. doBuildDeserialize(translator, ctx, selector, helper, size);
  2025. }
  2026. bool CBitfieldContainerInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  2027. {
  2028. doBuildSkipInput(translator, ctx, state.helper, column->queryType()->getSize());
  2029. return true;
  2030. }
  2031. IHqlExpression* CBitfieldContainerInfo::queryParentSelector(IHqlExpression* selector)
  2032. {
  2033. return selector;
  2034. }
  2035. void CBitfieldContainerInfo::buildExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2036. {
  2037. throwUnexpected();
  2038. }
  2039. IReferenceSelector * CBitfieldContainerInfo::getSelector(BuildCtx & ctx, IReferenceSelector * parentSelector)
  2040. {
  2041. return LINK(parentSelector);
  2042. }
  2043. void CBitfieldContainerInfo::noteLastBitfield()
  2044. {
  2045. if (children.ordinality())
  2046. children.tos().noteLastBitfield();
  2047. }
  2048. void CBitfieldContainerInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  2049. {
  2050. defaultSetColumn(translator, ctx, selector, value);
  2051. }
  2052. CMemberInfo * CBitfieldContainerInfo::lastBitfield()
  2053. {
  2054. if (children.ordinality())
  2055. return &(CMemberInfo &)children.tos();
  2056. return NULL;
  2057. }
  2058. void CBitfieldContainerInfo::gatherSize(SizeStruct & size)
  2059. {
  2060. size.addFixed(column->queryType()->getSize());
  2061. }
  2062. IHqlExpression * CBitfieldContainerInfo::getRelativeSelf()
  2063. {
  2064. return container->getRelativeSelf();
  2065. }
  2066. bool CBitfieldContainerInfo::isFixedSize()
  2067. {
  2068. return true;
  2069. }
  2070. //---------------------------------------------------------------------------
  2071. CBitfieldInfo::CBitfieldInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  2072. {
  2073. bitOffset = 0;
  2074. isLastBitfield = false;
  2075. }
  2076. void CBitfieldInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2077. {
  2078. ITypeInfo * columnType = queryType();
  2079. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, queryStorageType(), 0);
  2080. OwnedHqlExpr value = convertAddressToValue(address, queryStorageType());
  2081. if (bitOffset > 0)
  2082. value.setown(createValue(no_rshift, LINK(value), getSizetConstant((int)bitOffset)));
  2083. unsigned __int64 mask = ((unsigned __int64)1<<columnType->getBitSize())-1;
  2084. IValue * maskValue = columnType->queryChildType()->castFrom(false, (__int64)mask);
  2085. bound.expr.setown(createValue(no_band, LINK(value), createConstant(maskValue)));
  2086. }
  2087. IHqlExpression * CBitfieldInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2088. {
  2089. return createConstant(0);
  2090. }
  2091. void CBitfieldInfo::gatherSize(SizeStruct & target)
  2092. {
  2093. target.addFixed(0); //!!
  2094. }
  2095. bool CBitfieldInfo::isFixedSize()
  2096. {
  2097. return true;
  2098. }
  2099. unsigned CBitfieldInfo::queryBitfieldPackSize() const
  2100. {
  2101. const CBitfieldContainerInfo * packing = static_cast<const CBitfieldContainerInfo *>(container);
  2102. return packing->queryStorageType()->getSize();
  2103. }
  2104. void CBitfieldInfo::setBitOffset(unsigned _bitOffset)
  2105. {
  2106. bitOffset = _bitOffset;
  2107. }
  2108. void CBitfieldInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  2109. {
  2110. ITypeInfo * columnType = queryType();
  2111. ITypeInfo * storageType = queryStorageType();
  2112. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, storageType, 0);
  2113. IHqlExpression * columnRef = convertAddressToValue(address, storageType);
  2114. unsigned bitSize = columnType->getBitSize();
  2115. unsigned __int64 mask = (((unsigned __int64)1)<<bitSize)-1;
  2116. unsigned __int64 shiftMask = 0;
  2117. if (bitSize + bitOffset < sizeof(__int64) * 8)
  2118. shiftMask = (((unsigned __int64)1)<<(bitSize+bitOffset));
  2119. shiftMask -= (((unsigned __int64)1)<<bitOffset);
  2120. IValue * oldMaskValue = storageType->castFrom(false, (__int64)shiftMask);
  2121. IHqlExpression * oldMask = createConstant(oldMaskValue);
  2122. IHqlExpression * transColumn = createTranslatedOwned(columnRef);
  2123. IHqlExpression * oldValue = createValue(no_band, transColumn, createValue(no_bnot,oldMask));
  2124. IValue * newMaskValue = storageType->castFrom(false, (__int64)mask);
  2125. IHqlExpression * newMask = createConstant(newMaskValue);
  2126. OwnedHqlExpr newValue = createValue(no_band, LINK(storageType), ensureExprType(value, storageType), newMask);
  2127. if (bitOffset > 0)
  2128. newValue.setown(createValue(no_lshift, LINK(storageType), newValue.getClear(), getSizetConstant(bitOffset)));
  2129. if (newValue->isConstant())
  2130. newValue.setown(foldHqlExpression(translator.queryErrorProcessor(), newValue));
  2131. OwnedHqlExpr final = createValue(no_bor, LINK(storageType), oldValue, newValue.getClear());
  2132. CHqlBoundTarget boundTarget;
  2133. boundTarget.expr.set(columnRef);
  2134. translator.buildExprAssign(ctx, boundTarget, final);
  2135. }
  2136. //---------------------------------------------------------------------------
  2137. void CRowReferenceColumnInfo::gatherSize(SizeStruct & target)
  2138. {
  2139. if (isConditional())
  2140. addVariableSize(queryType()->getSize(), target);
  2141. else
  2142. target.addFixed(sizeof(void *));
  2143. }
  2144. IHqlExpression * CRowReferenceColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2145. {
  2146. size32_t typeSize = sizeof(void *);
  2147. return getSizetConstant(typeSize);
  2148. }
  2149. //---------------------------------------------------------------------------
  2150. CVirtualColumnInfo::CVirtualColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  2151. {
  2152. }
  2153. void CVirtualColumnInfo::buildAddress(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2154. {
  2155. UNIMPLEMENTED;
  2156. }
  2157. IHqlExpression * CVirtualColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2158. {
  2159. return getSizetConstant(0);
  2160. }
  2161. void CVirtualColumnInfo::gatherSize(SizeStruct & target)
  2162. {
  2163. //Zero size
  2164. }
  2165. bool CVirtualColumnInfo::isFixedSize()
  2166. {
  2167. return true;
  2168. }
  2169. void CVirtualColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2170. {
  2171. IHqlExpression * virtualAttr = column->queryAttribute(virtualAtom);
  2172. OwnedHqlExpr value = getVirtualReplacement(column, virtualAttr->queryChild(0), selector->queryRootRow()->querySelector());
  2173. OwnedHqlExpr cast = ensureExprType(value, column->queryType()->queryPromotedType());
  2174. translator.buildExpr(ctx, cast, bound);
  2175. }
  2176. void CVirtualColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  2177. {
  2178. UNIMPLEMENTED;
  2179. }
  2180. //---------------------------------------------------------------------------
  2181. //******* For CSV the offset is the field number, not a byte offset ***********
  2182. CCsvColumnInfo::CCsvColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column, IAtom * _encoding) : CColumnInfo(_container, _prior, _column)
  2183. {
  2184. encoding = _encoding;
  2185. }
  2186. void CCsvColumnInfo::buildAddress(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2187. {
  2188. UNIMPLEMENTED;
  2189. }
  2190. IHqlExpression * CCsvColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2191. {
  2192. return getSizetConstant(1);
  2193. }
  2194. void CCsvColumnInfo::gatherSize(SizeStruct & target)
  2195. {
  2196. if (isConditional())
  2197. addVariableSize(1, target);
  2198. else
  2199. target.addFixed(1);
  2200. }
  2201. bool CCsvColumnInfo::isFixedSize()
  2202. {
  2203. return true;
  2204. }
  2205. void CCsvColumnInfo::getName(HqlCppTranslator & translator, BuildCtx & ctx, StringBuffer & out, const char * prefix, IReferenceSelector * selector)
  2206. {
  2207. CHqlBoundExpr boundIndex;
  2208. buildOffset(translator, ctx, selector, boundIndex);
  2209. BoundRow * cursor = selector->queryRootRow();
  2210. out.append(prefix);
  2211. cursor->queryBound()->toString(out);
  2212. out.append("[");
  2213. translator.generateExprCpp(out, boundIndex.expr).append("]");
  2214. }
  2215. void CCsvColumnInfo::buildColumnAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  2216. {
  2217. OwnedHqlExpr value = getColumnExpr(translator, ctx, selector);
  2218. translator.buildExprAssign(ctx, target, value);
  2219. }
  2220. void CCsvColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2221. {
  2222. OwnedHqlExpr value = getColumnExpr(translator, ctx, selector);
  2223. translator.buildExpr(ctx, value, bound);
  2224. }
  2225. IHqlExpression * CCsvColumnInfo::getColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2226. {
  2227. StringBuffer lenText, dataText;
  2228. getName(translator, ctx, lenText, "len", selector);
  2229. getName(translator, ctx, dataText, "data", selector);
  2230. Owned<ITypeInfo> type = makeStringType(UNKNOWN_LENGTH, NULL, NULL);
  2231. ITypeInfo * columnType = column->queryType();
  2232. if (encoding == NULL)
  2233. {
  2234. //This is slightly weird legacy semantics - treat the input as UTF8 if a unicode field is used.
  2235. if (isUnicodeType(columnType))
  2236. type.setown(makeUtf8Type(UNKNOWN_LENGTH, NULL));
  2237. }
  2238. else if (encoding == ebcdicAtom || encoding == asciiAtom)
  2239. {
  2240. type.setown(makeStringType(UNKNOWN_LENGTH, getCharset(encoding), NULL));
  2241. }
  2242. else if (encoding == unicodeAtom)
  2243. {
  2244. type.setown(makeUtf8Type(UNKNOWN_LENGTH, NULL));
  2245. }
  2246. type.setown(makeReferenceModifier(type.getClear()));
  2247. if (isUnicodeType(type))
  2248. {
  2249. //This is an ugly fix to change the size to the number of utf8-characters.
  2250. //Better would be to either perform the mapping (and validation) in the engines, or
  2251. //give it a string of encoding utf8 and extend the code generator to correctly handle those
  2252. //string/unicode conversions by using the codepage to codepage mapping function.
  2253. StringBuffer temp;
  2254. temp.appendf("rtlUtf8Length(%s,%s)", lenText.str(), dataText.str());
  2255. lenText.swapWith(temp);
  2256. }
  2257. OwnedHqlExpr length = createQuoted(lenText.str(), LINK(sizetType));
  2258. OwnedHqlExpr data = createQuoted(dataText.str(), type.getClear());
  2259. OwnedHqlExpr value = createTranslated(data, length);
  2260. if (columnType->getTypeCode() == type_boolean)
  2261. {
  2262. HqlExprArray args;
  2263. args.append(*LINK(value));
  2264. value.setown(translator.bindFunctionCall(csvStr2BoolId,args));
  2265. }
  2266. else
  2267. value.setown(ensureExprType(value, columnType));
  2268. return value.getClear();
  2269. }
  2270. void CCsvColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  2271. {
  2272. UNIMPLEMENTED;
  2273. }
  2274. //---------------------------------------------------------------------------
  2275. static IIdAtom * getXmlReadFunction(ITypeInfo * type, bool hasDefault)
  2276. {
  2277. type = type->queryPromotedType();
  2278. if (hasDefault)
  2279. {
  2280. switch (type->getTypeCode())
  2281. {
  2282. case type_unicode:
  2283. case type_varunicode:
  2284. return columnReadUnicodeXId;
  2285. case type_utf8:
  2286. return columnReadUtf8XId;
  2287. case type_int:
  2288. case type_swapint:
  2289. case type_packedint:
  2290. return columnReadIntId;
  2291. case type_data:
  2292. return columnReadDataXId;
  2293. case type_boolean:
  2294. return columnReadBoolId;
  2295. default:
  2296. return columnReadStringXId;
  2297. }
  2298. }
  2299. else
  2300. {
  2301. switch (type->getTypeCode())
  2302. {
  2303. case type_unicode:
  2304. case type_varunicode:
  2305. return columnGetUnicodeXId;
  2306. case type_utf8:
  2307. return columnGetUtf8XId;
  2308. case type_int:
  2309. case type_swapint:
  2310. case type_packedint:
  2311. return columnGetIntId;
  2312. case type_data:
  2313. return columnGetDataXId;
  2314. case type_boolean:
  2315. return columnGetBoolId;
  2316. default:
  2317. return columnGetStringXId;
  2318. }
  2319. }
  2320. }
  2321. CXmlColumnInfo::CXmlColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  2322. {
  2323. }
  2324. void CXmlColumnInfo::buildAddress(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2325. {
  2326. UNIMPLEMENTED;
  2327. }
  2328. IHqlExpression * CXmlColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2329. {
  2330. UNIMPLEMENTED;
  2331. }
  2332. void CXmlColumnInfo::gatherSize(SizeStruct & target)
  2333. {
  2334. addVariableSize(0, target);
  2335. }
  2336. bool CXmlColumnInfo::isFixedSize()
  2337. {
  2338. return false;
  2339. }
  2340. void CXmlColumnInfo::buildFixedStringAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target, IHqlExpression * defaultValue, IIdAtom * func)
  2341. {
  2342. StringBuffer row,path;
  2343. selector->queryRootRow()->queryBound()->toString(row);
  2344. getXPath(path);
  2345. translator.noteXpathUsed(path);
  2346. HqlExprArray args;
  2347. args.append(*createQuoted(row, makeBoolType()));
  2348. args.append(*target.getTranslatedExpr());
  2349. args.append(*createConstant(path.str()));
  2350. if (defaultValue)
  2351. args.append(*LINK(defaultValue));
  2352. OwnedHqlExpr call = translator.bindFunctionCall(func, args);
  2353. translator.buildStmt(ctx, call);
  2354. }
  2355. void CXmlColumnInfo::buildColumnAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target)
  2356. {
  2357. Linked<ITypeInfo> type = queryPhysicalType();
  2358. if (type->getSize() != UNKNOWN_LENGTH)
  2359. {
  2360. IIdAtom * func = NULL;
  2361. IHqlExpression * defaultValue = queryAttributeChild(column, xmlDefaultAtom, 0);
  2362. if (!defaultValue)
  2363. defaultValue = queryAttributeChild(column, defaultAtom, 0);
  2364. switch (type->getTypeCode())
  2365. {
  2366. case type_string:
  2367. if (type->queryCharset()->queryName() == asciiAtom)
  2368. func = defaultValue ? columnReadStringId : columnGetStringId;
  2369. break;
  2370. case type_data:
  2371. func = defaultValue ? columnReadDataId : columnGetDataId;
  2372. break;
  2373. case type_qstring:
  2374. func = defaultValue ? columnReadQStringId : columnGetQStringId;
  2375. break;
  2376. }
  2377. if (func)
  2378. {
  2379. buildFixedStringAssign(translator, ctx, selector, target, defaultValue, func);
  2380. return;
  2381. }
  2382. }
  2383. OwnedHqlExpr call = getCallExpr(translator, ctx, selector);
  2384. translator.buildExprAssign(ctx, target, call);
  2385. }
  2386. void CXmlColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  2387. {
  2388. OwnedHqlExpr call = getCallExpr(translator, ctx, selector);
  2389. translator.buildExpr(ctx, call, bound);
  2390. }
  2391. void HqlCppTranslator::buildXmlReadChildrenIterator(BuildCtx & ctx, const char * iterTag, IHqlExpression * rowName, SharedHqlExpr & subRowExpr)
  2392. {
  2393. StringBuffer s, iterName, subRowName;
  2394. unique_id_t id = getUniqueId();
  2395. appendUniqueId(iterName.append("iter"), id);
  2396. appendUniqueId(subRowName.append("row"), id);
  2397. //XmlChildIterator iterNNN;
  2398. s.clear().append("XmlChildIterator ").append(iterName).append(";");
  2399. ctx.addQuoted(s);
  2400. //iterNN.init(row->getChildIterator("Name/Row"))
  2401. s.clear().append(iterName).append(".initOwn(");
  2402. generateExprCpp(s, rowName).append("->getChildIterator(");
  2403. s.append("\"");
  2404. if (iterTag)
  2405. appendStringAsCPP(s, strlen(iterTag), iterTag, false);
  2406. s.append("\"));");
  2407. ctx.addQuoted(s);
  2408. //IColumnProvider * rowNNN;
  2409. s.clear().append("IColumnProvider * ").append(subRowName).append(";");
  2410. ctx.addQuoted(s);
  2411. //rowNNN = iterNN.first();
  2412. s.clear().append(subRowName).append(" = ").append(iterName).append(".first();");
  2413. ctx.addQuoted(s);
  2414. s.clear().append(subRowName).append(" = ").append(iterName).append(".next()");
  2415. OwnedHqlExpr nextExpr = createQuoted(s.str(), makeVoidType());
  2416. //<Name><Row><.....fields.....></Row>
  2417. subRowExpr.setown(createQuoted(subRowName, makeBoolType()));
  2418. ctx.addLoop(subRowExpr, nextExpr, false);
  2419. }
  2420. IHqlExpression * CXmlColumnInfo::getXmlDatasetExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2421. {
  2422. IHqlExpression * expr = column;
  2423. IHqlExpression * rowName = selector->queryRootRow()->queryBound();
  2424. StringBuffer prefix;
  2425. if (container)
  2426. container->getContainerXPath(prefix);
  2427. StringBuffer s;
  2428. StringBuffer fieldTag, rowTag, iterTag;
  2429. extractXmlName(fieldTag, &rowTag, NULL, expr, "Row", true);
  2430. iterTag.append(prefix);
  2431. if (fieldTag.length())
  2432. iterTag.append(fieldTag).append("/");
  2433. iterTag.append(rowTag);
  2434. //Create the builder for generating a temporary set.
  2435. IHqlExpression * record = expr->queryRecord();
  2436. Owned<IHqlCppDatasetBuilder> builder;
  2437. builder.setown(translator.createLinkedDatasetBuilder(record));
  2438. builder->buildDeclare(ctx);
  2439. //Generate the code to process a child iterator
  2440. OwnedHqlExpr subRowExpr;
  2441. BuildCtx loopctx(ctx);
  2442. translator.buildXmlReadChildrenIterator(loopctx, iterTag.str(), rowName, subRowExpr);
  2443. BoundRow * targetRow = builder->buildCreateRow(loopctx);
  2444. IHqlExpression * path = selector->queryExpr();
  2445. StringBuffer subPrefix;
  2446. BoundRow * selfCursor = translator.bindSelf(loopctx, path, targetRow->queryBound(), targetRow->queryBuilder());
  2447. translator.bindXmlTableCursor(loopctx, path, subRowExpr, no_none, NULL, false);
  2448. OwnedHqlExpr active = ensureActiveRow(path);
  2449. translator.buildAssign(loopctx, selfCursor->querySelector(), active);
  2450. translator.finishSelf(loopctx, selfCursor, targetRow);
  2451. builder->finishRow(loopctx, targetRow);
  2452. CHqlBoundTarget temp;
  2453. translator.createTempFor(ctx, expr, temp);
  2454. builder->buildFinish(ctx, temp);
  2455. return temp.getTranslatedExpr();
  2456. }
  2457. IHqlExpression * CXmlColumnInfo::getXmlSetExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2458. {
  2459. IHqlExpression * expr = column;
  2460. IHqlExpression * rowName = selector->queryRootRow()->queryBound();
  2461. StringBuffer prefix;
  2462. if (container)
  2463. container->getContainerXPath(prefix);
  2464. ITypeInfo * elementType = expr->queryType()->queryChildType();
  2465. StringBuffer s;
  2466. StringBuffer fieldTag, itemTag, valueTag, iterTag, fullFieldPath;
  2467. extractXmlName(fieldTag, &itemTag, &valueTag, expr, "Item", true);
  2468. fullFieldPath.append(prefix).append(fieldTag);
  2469. iterTag.append(prefix);
  2470. if (fieldTag.length() != 0)
  2471. iterTag.append(fieldTag).append("/");
  2472. iterTag.append(itemTag);
  2473. bool checkForAll = (fieldTag.length() != 0);
  2474. //Create the builder for generating a temporary set.
  2475. CHqlBoundTarget temp;
  2476. translator.createTempFor(ctx, expr, temp);
  2477. Owned<IHqlCppSetBuilder> builder = translator.createTempSetBuilder(elementType, temp.isAll);
  2478. builder->buildDeclare(ctx);
  2479. LinkedHqlExpr defaultValue = queryAttributeChild(column, xmlDefaultAtom, 0);
  2480. if (!defaultValue)
  2481. defaultValue.set(queryAttributeChild(column, defaultAtom, 0));
  2482. bool defaultIsAllValue = defaultValue && (defaultValue->getOperator() == no_all);
  2483. if (checkForAll)
  2484. {
  2485. //assign isAll...
  2486. HqlExprArray isAllArgs;
  2487. isAllArgs.append(*LINK(rowName));
  2488. isAllArgs.append(*createConstant(fullFieldPath.str()));
  2489. if (defaultValue)
  2490. isAllArgs.append(*createConstant(defaultIsAllValue));
  2491. OwnedHqlExpr isAll = translator.bindFunctionCall(defaultValue ? columnReadSetIsAllId : columnGetSetIsAllId, isAllArgs);
  2492. builder->setAll(ctx, isAll);
  2493. }
  2494. else
  2495. builder->setAll(ctx, queryBoolExpr(false));
  2496. //Generate the code to process a child iterator
  2497. OwnedHqlExpr subRowExpr;
  2498. BuildCtx loopctx(ctx);
  2499. translator.buildXmlReadChildrenIterator(loopctx, iterTag.str(), rowName, subRowExpr);
  2500. HqlExprArray args;
  2501. args.append(*LINK(subRowExpr));
  2502. args.append(*createConstant(valueTag.str()));
  2503. OwnedHqlExpr call = translator.bindFunctionCall(getXmlReadFunction(elementType, false), args);
  2504. Owned<IReferenceSelector> elemselector = builder->buildCreateElement(loopctx);
  2505. elemselector->set(loopctx, call);
  2506. builder->finishElement(loopctx);
  2507. builder->buildFinish(ctx, temp);
  2508. return temp.getTranslatedExpr();
  2509. }
  2510. IHqlExpression * CXmlColumnInfo::getCallExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  2511. {
  2512. Linked<ITypeInfo> type = queryPhysicalType();
  2513. IIdAtom * func = NULL;
  2514. IHqlExpression * defaultValue = queryAttributeChild(column, xmlDefaultAtom, 0);
  2515. if (!defaultValue)
  2516. defaultValue = queryAttributeChild(column, defaultAtom, 0);
  2517. switch (type->getTypeCode())
  2518. {
  2519. case type_dictionary:
  2520. case type_table:
  2521. case type_groupedtable:
  2522. return getXmlDatasetExpr(translator, ctx, selector);
  2523. case type_set:
  2524. return getXmlSetExpr(translator, ctx, selector);
  2525. case type_string:
  2526. if ((type->getSize() != UNKNOWN_LENGTH) && type->queryCharset()->queryName() == asciiAtom)
  2527. func = defaultValue ? columnReadStringId : columnGetStringId;
  2528. break;
  2529. case type_data:
  2530. if (type->getSize() != UNKNOWN_LENGTH)
  2531. func = defaultValue ? columnReadDataId : columnGetDataId;
  2532. break;
  2533. case type_qstring:
  2534. if (type->getSize() != UNKNOWN_LENGTH)
  2535. func = defaultValue ? columnReadQStringId : columnGetQStringId;
  2536. break;
  2537. }
  2538. if (func)
  2539. {
  2540. CHqlBoundTarget tempTarget;
  2541. translator.createTempFor(ctx, type, tempTarget, typemod_none, FormatNatural);
  2542. buildFixedStringAssign(translator, ctx, selector, tempTarget, defaultValue, func);
  2543. return tempTarget.getTranslatedExpr();
  2544. }
  2545. StringBuffer row,path;
  2546. selector->queryRootRow()->queryBound()->toString(row);
  2547. getXPath(path);
  2548. translator.noteXpathUsed(path);
  2549. HqlExprArray args;
  2550. args.append(*createQuoted(row, makeBoolType()));
  2551. args.append(*createConstant(path.str()));
  2552. if (defaultValue)
  2553. args.append(*LINK(defaultValue));
  2554. OwnedHqlExpr call = translator.bindFunctionCall(getXmlReadFunction(type, defaultValue != NULL), args);
  2555. return ensureExprType(call, type);
  2556. }
  2557. void CXmlColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  2558. {
  2559. UNIMPLEMENTED;
  2560. }
  2561. //---------------------------------------------------------------------------
  2562. inline int doAlign(unsigned value, unsigned align) { return (value + align-1) & ~(align-1); }
  2563. ColumnToOffsetMap::ColumnToOffsetMap(IHqlExpression * _key, IHqlExpression * _record, unsigned _id, unsigned _packing, unsigned _maxRecordSize, bool _translateVirtuals, bool _useAccessClass)
  2564. : root(NULL, NULL, _record), key(_key), id(_id)
  2565. {
  2566. record = _record;
  2567. prior = NULL;
  2568. maxAlign = _packing;
  2569. packing = _packing;
  2570. fixedSizeRecord = true;
  2571. translateVirtuals = _translateVirtuals;
  2572. defaultMaxRecordSize = _maxRecordSize;
  2573. containsIfBlock = false;
  2574. cachedDefaultMaxSizeUsed = false;
  2575. cachedMaxSize = UNKNOWN_LENGTH;
  2576. root.setOffset(false);
  2577. if (_useAccessClass)
  2578. root.setUseAccessClass();
  2579. }
  2580. void ColumnToOffsetMap::init(RecordOffsetMap & map)
  2581. {
  2582. expandRecord(record, &root, map);
  2583. }
  2584. void ColumnToOffsetMap::completeActiveBitfields()
  2585. {
  2586. if (prior)
  2587. prior->noteLastBitfield();
  2588. packer.reset();
  2589. }
  2590. CMemberInfo * ColumnToOffsetMap::addColumn(CContainerInfo * container, IHqlExpression * column, RecordOffsetMap & map)
  2591. {
  2592. CMemberInfo * created = NULL;
  2593. switch (column->getOperator())
  2594. {
  2595. case no_attr:
  2596. case no_attr_expr:
  2597. case no_attr_link:
  2598. if (column->queryName() == packingAtom)
  2599. packing = (unsigned)column->queryChild(0)->queryValue()->getIntValue();
  2600. break;
  2601. case no_record:
  2602. completeActiveBitfields();
  2603. return expandRecord(column, container, map);
  2604. case no_ifblock:
  2605. {
  2606. completeActiveBitfields();
  2607. CIfBlockInfo * next = new CIfBlockInfo(container, prior, column);
  2608. next->setOffset(!fixedSizeRecord);
  2609. expandRecord(column->queryChild(1), next, map);
  2610. created = next;
  2611. containsIfBlock = true;
  2612. }
  2613. break;
  2614. default:
  2615. {
  2616. if (column->queryType()->getTypeCode() != type_bitfield)
  2617. completeActiveBitfields();
  2618. if (translateVirtuals && column->hasAttribute(virtualAtom) && (column->queryType()->getSize() != UNKNOWN_LENGTH))
  2619. created = new CVirtualColumnInfo(container, prior, column);
  2620. else
  2621. created = createColumn(container, column, map);
  2622. break;
  2623. }
  2624. }
  2625. if (created)
  2626. {
  2627. container->addChild(created);
  2628. prior = created;
  2629. if (!created->isFixedSize())
  2630. fixedSizeRecord = false;
  2631. }
  2632. return created;
  2633. }
  2634. bool ColumnToOffsetMap::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * helper)
  2635. {
  2636. //prepare() allows Ifblock and a count/size on a dataset to tag the fields they depend on which need to be read.
  2637. //The fallback (implemented in base class) is to call deserialize on a temporary row instead. Ugly, but better than failing.
  2638. ReadAheadState state(helper);
  2639. if (queryRootColumn()->prepareReadAhead(translator, state))
  2640. {
  2641. state.addDummyMappings();
  2642. return queryRootColumn()->buildReadAhead(translator, ctx, state);
  2643. }
  2644. return false;
  2645. }
  2646. void ColumnToOffsetMap::buildAccessor(StringBuffer & accessorName, HqlCppTranslator & translator, BuildCtx & declarectx, IHqlExpression * selector)
  2647. {
  2648. StringBuffer typeName;
  2649. translator.buildRtlType(typeName, record->queryType());
  2650. BuildCtx ctx(declarectx);
  2651. ctx.setNextPriority(TypeInfoPrio);
  2652. ctx.addGroup();
  2653. StringBuffer s;
  2654. s.clear().append("RtlRecord rec").append(queryId()).append("(").append(typeName).append(",true);");
  2655. ctx.addQuoted(s);
  2656. if (translator.queryOptions().spanMultipleCpp)
  2657. {
  2658. ctx.set(mainprototypesAtom);
  2659. ctx.addQuoted(s.clear().append("extern RtlRecord rec").append(queryId()).append(";"));
  2660. }
  2661. BuildCtx classctx(ctx);
  2662. unsigned numVarOffsets = getVarSizeFieldCount(record, true);
  2663. accessorName.append("access").append(queryId());
  2664. s.clear().append("struct ").append(accessorName).append(" : public RtlStaticRow<").append(numVarOffsets).append(">");
  2665. classctx.addQuotedCompound(s.str(), ";");
  2666. s.clear().append(accessorName).append("(const void * _row) : RtlStaticRow<").append(numVarOffsets).append(">(rec").append(queryId()).append(", _row) {}");
  2667. classctx.addQuoted(s.str());
  2668. }
  2669. CMemberInfo * ColumnToOffsetMap::createColumn(CContainerInfo * container, IHqlExpression * column, RecordOffsetMap & map)
  2670. {
  2671. ITypeInfo * type = column->queryType();
  2672. ITypeInfo * promoted = type->queryPromotedType();
  2673. unsigned align = promoted ? promoted->getAlignment() : 1;
  2674. if (align > packing)
  2675. align = packing;
  2676. if (align > maxAlign)
  2677. maxAlign = align;
  2678. bool isFixedOffset = !fixedSizeRecord;
  2679. CMemberInfo * created = NULL;
  2680. switch (type->getTypeCode())
  2681. {
  2682. //MORE: Alien types could be based on bitfields. If so need a column as a child
  2683. //of the alien column representing the stored value.....
  2684. case type_bitfield:
  2685. {
  2686. CBitfieldContainerInfo * bitContainer;
  2687. unsigned thisBitOffset, thisBits;
  2688. if (!packer.checkSpaceAvailable(thisBitOffset, thisBits, type))
  2689. {
  2690. if (prior)
  2691. prior->noteLastBitfield();
  2692. ITypeInfo * storeType = type->queryChildType();
  2693. //Use createUniqueId() to ensure that bitfield containers of the same type can be distinguished.
  2694. OwnedHqlExpr value = createValue(no_field, LINK(storeType), createUniqueId());
  2695. bitContainer = new CBitfieldContainerInfo(container, prior, value);
  2696. bitContainer->setOffset(!fixedSizeRecord);
  2697. }
  2698. else
  2699. bitContainer = (CBitfieldContainerInfo *)prior;
  2700. CBitfieldInfo & entry = * new CBitfieldInfo(bitContainer, bitContainer->lastBitfield(), column);
  2701. entry.setBitOffset(thisBitOffset);
  2702. bitContainer->addChild(&entry);
  2703. if (bitContainer != prior)
  2704. created = bitContainer;
  2705. break;
  2706. }
  2707. case type_row:
  2708. {
  2709. if (hasReferenceModifier(type))
  2710. created = new CRowReferenceColumnInfo(container, prior, column);
  2711. else
  2712. {
  2713. CRecordInfo * next = new CRecordInfo(container, prior, column);
  2714. expandRecord(column->queryRecord(), next, map);
  2715. created = next;
  2716. }
  2717. break;
  2718. }
  2719. case type_groupedtable:
  2720. case type_table:
  2721. case type_dictionary:
  2722. {
  2723. IHqlExpression * count = NULL;
  2724. IHqlExpression * size = NULL;
  2725. ForEachChild(i, column)
  2726. {
  2727. IHqlExpression * cur = column->queryChild(i);
  2728. if (cur->isAttribute())
  2729. {
  2730. IAtom * name = cur->queryName();
  2731. if (name == countAtom)
  2732. count = cur->queryChild(0);
  2733. else if (name == sizeofAtom)
  2734. size = cur->queryChild(0);
  2735. }
  2736. }
  2737. if (column->hasAttribute(_linkCounted_Atom))
  2738. created = new CChildLinkedDatasetColumnInfo(container, prior, column, map, defaultMaxRecordSize);
  2739. else if (count || size)
  2740. created = new CChildLimitedDatasetColumnInfo(container, prior, column, map, defaultMaxRecordSize);
  2741. else
  2742. created = new CChildDatasetColumnInfo(container, prior, column, map, defaultMaxRecordSize);
  2743. break;
  2744. }
  2745. case type_string:
  2746. case type_data:
  2747. case type_unicode:
  2748. case type_qstring:
  2749. case type_utf8:
  2750. if (type->getSize() == UNKNOWN_LENGTH)
  2751. created = new CSpecialStringColumnInfo(container, prior, column);
  2752. else
  2753. created = new CColumnInfo(container, prior, column);
  2754. break;
  2755. case type_varstring:
  2756. case type_varunicode:
  2757. if (type->getSize() == UNKNOWN_LENGTH)
  2758. created = new CSpecialVStringColumnInfo(container, prior, column);
  2759. else
  2760. created = new CColumnInfo(container, prior, column);
  2761. break;
  2762. case type_int:
  2763. case type_swapint:
  2764. switch (type->getSize())
  2765. {
  2766. case 1: case 2: case 4: case 8:
  2767. created = new CColumnInfo(container, prior, column);
  2768. break;
  2769. default:
  2770. created = new CSpecialIntColumnInfo(container, prior, column);
  2771. break;
  2772. }
  2773. break;
  2774. case type_packedint:
  2775. created = new CPackedIntColumnInfo(container, prior, column);
  2776. break;
  2777. case type_set:
  2778. created = new CChildSetColumnInfo(container, prior, column);
  2779. break;
  2780. default:
  2781. {
  2782. if (type->getTypeCode() == type_alien)
  2783. created = new CAlienColumnInfo(container, prior, column);
  2784. else
  2785. created = new CColumnInfo(container, prior, column);
  2786. break;
  2787. }
  2788. }
  2789. if (created)
  2790. created->setOffset(isFixedOffset);
  2791. return created;
  2792. }
  2793. unsigned ColumnToOffsetMap::getFixedRecordSize()
  2794. {
  2795. SizeStruct size;
  2796. root.getSizeExpr(size);
  2797. assertex(size.isFixedSize());
  2798. return size.getFixedSize();
  2799. }
  2800. AColumnInfo * ColumnToOffsetMap::queryRootColumn()
  2801. {
  2802. return &root;
  2803. }
  2804. void ColumnToOffsetMap::ensureMaxSizeCached()
  2805. {
  2806. if (cachedMaxSize == UNKNOWN_LENGTH)
  2807. {
  2808. bool isKnownSize;
  2809. cachedMaxSize = getMaxRecordSize(record, defaultMaxRecordSize, isKnownSize, cachedDefaultMaxSizeUsed);
  2810. }
  2811. }
  2812. unsigned ColumnToOffsetMap::getMaxSize()
  2813. {
  2814. ensureMaxSizeCached();
  2815. return cachedMaxSize;
  2816. }
  2817. bool ColumnToOffsetMap::isMaxSizeSpecified()
  2818. {
  2819. if (isFixedWidth())
  2820. return true;
  2821. ensureMaxSizeCached();
  2822. return !cachedDefaultMaxSizeUsed;
  2823. }
  2824. CMemberInfo * ColumnToOffsetMap::expandRecord(IHqlExpression * record, CContainerInfo * container, RecordOffsetMap & map)
  2825. {
  2826. assertex(record->getOperator() == no_record);
  2827. unsigned max = record->numChildren();
  2828. unsigned idx;
  2829. bool fixedSize = true;
  2830. prior = NULL;
  2831. for (idx = 0; idx < max; idx++)
  2832. {
  2833. CMemberInfo * created = addColumn(container, record->queryChild(idx), map);
  2834. if (created)
  2835. {
  2836. if (!created->isFixedSize())
  2837. fixedSize = false;
  2838. }
  2839. }
  2840. container->setFixedSize(fixedSize);
  2841. completeActiveBitfields();
  2842. return prior;
  2843. }
  2844. DynamicColumnToOffsetMap::DynamicColumnToOffsetMap(unsigned _maxRecordSize) : ColumnToOffsetMap(NULL, queryNullRecord(), 0, 0, _maxRecordSize, false, false)
  2845. {
  2846. root.setDynamic();
  2847. }
  2848. void DynamicColumnToOffsetMap::addColumn(IHqlExpression * column, RecordOffsetMap & map)
  2849. {
  2850. CMemberInfo * created = ColumnToOffsetMap::addColumn(&root, column, map);
  2851. if (created)
  2852. {
  2853. if (!created->isFixedSize())
  2854. root.setFixedSize(false);
  2855. }
  2856. }
  2857. //---------------------------------------------------------------------------
  2858. static bool cachedCanReadFromCsv(IHqlExpression * record)
  2859. {
  2860. record = record->queryBody();
  2861. if (record->queryTransformExtra())
  2862. return true;
  2863. record->setTransformExtra(record);
  2864. ForEachChild(i, record)
  2865. {
  2866. IHqlExpression * cur = record->queryChild(i);
  2867. switch (cur->getOperator())
  2868. {
  2869. case no_ifblock:
  2870. if (!cachedCanReadFromCsv(cur->queryChild(1)))
  2871. return false;
  2872. break;
  2873. case no_record:
  2874. if (!cachedCanReadFromCsv(cur))
  2875. return false;
  2876. break;
  2877. case no_field:
  2878. {
  2879. ITypeInfo * type = cur->queryType();
  2880. switch (type->getTypeCode())
  2881. {
  2882. case type_row:
  2883. if (!cachedCanReadFromCsv(cur->queryRecord()))
  2884. return false;
  2885. break;
  2886. case type_dictionary:
  2887. case type_table:
  2888. case type_groupedtable:
  2889. case type_set:
  2890. return false;
  2891. }
  2892. break;
  2893. }
  2894. }
  2895. }
  2896. return true;
  2897. }
  2898. bool canReadFromCsv(IHqlExpression * record)
  2899. {
  2900. TransformMutexBlock block;
  2901. return cachedCanReadFromCsv(record);
  2902. }
  2903. CsvColumnToOffsetMap::CsvColumnToOffsetMap(IHqlExpression * _record, unsigned _maxRecordSize, bool _translateVirtuals, IAtom * _encoding)
  2904. : ColumnToOffsetMap(NULL, _record, 0, 1, _maxRecordSize, _translateVirtuals, false)
  2905. {
  2906. encoding = _encoding;
  2907. }
  2908. CMemberInfo * CsvColumnToOffsetMap::createColumn(CContainerInfo * container, IHqlExpression * column, RecordOffsetMap & map)
  2909. {
  2910. CMemberInfo * created = NULL;
  2911. ITypeInfo * type = column->queryType();
  2912. switch (type->getTypeCode())
  2913. {
  2914. case type_row:
  2915. {
  2916. Owned<CRecordInfo> next = new CRecordInfo(container, prior, column);
  2917. expandRecord(column->queryRecord(), next, map);
  2918. created = next.getClear();
  2919. break;
  2920. }
  2921. case type_table:
  2922. case type_groupedtable:
  2923. case type_set:
  2924. throwError(HQLERR_CsvNotSupportTableSet);
  2925. break;
  2926. default:
  2927. created = new CCsvColumnInfo(container, prior, column, encoding);
  2928. break;
  2929. }
  2930. return created;
  2931. }
  2932. //---------------------------------------------------------------------------
  2933. XmlColumnToOffsetMap::XmlColumnToOffsetMap(IHqlExpression * _record, unsigned _maxRecordSize, bool _translateVirtuals)
  2934. : ColumnToOffsetMap(NULL, _record, 0, 1, _maxRecordSize, _translateVirtuals, false)
  2935. {
  2936. }
  2937. CMemberInfo * XmlColumnToOffsetMap::createColumn(CContainerInfo * container, IHqlExpression * column, RecordOffsetMap & map)
  2938. {
  2939. CMemberInfo * created = NULL;
  2940. ITypeInfo * type = column->queryType();
  2941. switch (type->getTypeCode())
  2942. {
  2943. case type_row:
  2944. {
  2945. CRecordInfo * next = new CRecordInfo(container, prior, column);
  2946. expandRecord(column->queryRecord(), next, map);
  2947. created = next;
  2948. break;
  2949. }
  2950. default:
  2951. created = new CXmlColumnInfo(container, prior, column);
  2952. break;
  2953. }
  2954. return created;
  2955. }
  2956. //---------------------------------------------------------------------------
  2957. BoundRow::BoundRow(const BoundRow & other, IHqlExpression * _newBound) : HqlExprAssociation(other.represents)
  2958. {
  2959. dataset.set(other.dataset);
  2960. bound.set(_newBound ? _newBound : other.bound.get());
  2961. columnMap = LINK(other.columnMap);
  2962. conditional = other.conditional;
  2963. side = other.side;
  2964. kind = other.kind;
  2965. assertex(bound->queryType()->getTypeCode() != type_void);
  2966. resultAlias = false;
  2967. inherited = other.inherited;
  2968. assertex(!other.accessor); // not currently supported in child queries.
  2969. accessor.set(other.accessor);
  2970. accessorStmt = other.accessorStmt;
  2971. }
  2972. BoundRow::BoundRow(const BoundRow & other, ColumnToOffsetMap * rawMap, IHqlExpression * _newBound) : HqlExprAssociation(other.represents)
  2973. {
  2974. dataset.set(other.dataset);
  2975. bound.set(_newBound ? _newBound : other.bound.get());
  2976. columnMap = LINK(rawMap);
  2977. conditional = other.conditional;
  2978. side = other.side;
  2979. kind = other.kind;
  2980. assertex(bound->queryType()->getTypeCode() != type_void);
  2981. resultAlias = false;
  2982. inherited = other.inherited;
  2983. assertex(!rawMap->usesAccessor());
  2984. }
  2985. BoundRow::BoundRow(IHqlExpression * _dataset, IHqlExpression * _bound, IHqlExpression * _accessor, ColumnToOffsetMap * _columnMap) : HqlExprAssociation(_dataset)
  2986. {
  2987. assertex(_columnMap);
  2988. dataset.set(_dataset);
  2989. bound.set(_bound);
  2990. accessor.set(_accessor);
  2991. assertex(!accessor);
  2992. columnMap = LINK(_columnMap);
  2993. conditional = false;
  2994. side = no_none;
  2995. kind = AssocRow;
  2996. assertex(bound->queryType()->getTypeCode() != type_void);
  2997. resultAlias = false;
  2998. inherited = false;
  2999. assertex(!accessor == !columnMap->usesAccessor());
  3000. }
  3001. BoundRow::BoundRow(IHqlExpression * _dataset, IHqlExpression * _bound, IHqlExpression * _accessor, ColumnToOffsetMap * _columnMap, node_operator _side, IHqlExpression * selSeq) : HqlExprAssociation(NULL)
  3002. {
  3003. assertex(_columnMap);
  3004. dataset.set(_dataset);
  3005. bound.set(_bound);
  3006. accessor.set(_accessor);
  3007. columnMap = LINK(_columnMap);
  3008. conditional = false;
  3009. kind = AssocCursor;
  3010. side = _side;
  3011. if (side == no_none)
  3012. represents.set(_dataset->queryNormalizedSelector());
  3013. else if ((side != no_self) || selSeq)
  3014. represents.setown(createSelector(side, dataset, selSeq));
  3015. else
  3016. {
  3017. OwnedHqlExpr uid = createUniqueSelectorSequence();
  3018. represents.setown(createSelector(no_self, dataset, uid));
  3019. }
  3020. assertex(bound->queryType()->getTypeCode() != type_void);
  3021. resultAlias = false;
  3022. inherited = false;
  3023. // assertex(!columnMap->usesAccessor());
  3024. }
  3025. BoundRow::~BoundRow()
  3026. {
  3027. ::Release(columnMap);
  3028. }
  3029. /* In: not linked. Return: linked */
  3030. IHqlExpression * BoundRow::bindToRow(IHqlExpression * expr, IHqlExpression * exprSelector)
  3031. {
  3032. if (kind == AssocCursor)
  3033. {
  3034. OwnedHqlExpr replacement = ensureActiveRow(represents);
  3035. return replaceSelector(expr, exprSelector, replacement);
  3036. }
  3037. OwnedHqlExpr wrapped = createRow(no_newrow, LINK(represents));
  3038. return replaceSelector(expr, exprSelector, wrapped);
  3039. }
  3040. IHqlExpression * BoundRow::getMappedSelector(BuildCtx & ctx, IReferenceSelector * selector)
  3041. {
  3042. return NULL;
  3043. }
  3044. IHqlExpression * BoundRow::getFinalFixedSizeExpr()
  3045. {
  3046. return getSizetConstant(columnMap->getTotalFixedSize());
  3047. }
  3048. bool BoundRow::isBinary()
  3049. {
  3050. return (columnMap->getFormat() == MapFormatBinary);
  3051. }
  3052. IHqlExpression * BoundRow::queryBuilderEnsureMarker()
  3053. {
  3054. if (!builderEnsureMarker)
  3055. builderEnsureMarker.setown(createAttribute(ensureCapacityAtom, LINK(represents)));
  3056. return builderEnsureMarker;
  3057. }
  3058. void BoundRow::prepareAccessor(HqlCppTranslator & translator, BuildCtx & ctx)
  3059. {
  3060. translator.buildRowAccessor(columnMap);
  3061. StringBuffer className;
  3062. className.append("access").append(columnMap->queryId());
  3063. accessor.setown(createVariable(makeConstantModifier(makeClassType(className))));
  3064. OwnedHqlExpr rowPointer = getPointer(bound);
  3065. accessorStmt = ctx.addDeclare(accessor, rowPointer);
  3066. accessorStmt->setIncluded(false);
  3067. }
  3068. IHqlExpression * BoundRow::ensureAccessor(HqlCppTranslator & translator, BuildCtx & ctx)
  3069. {
  3070. accessorStmt->setIncluded(true);
  3071. return accessor;
  3072. }
  3073. AColumnInfo * BoundRow::queryRootColumn()
  3074. {
  3075. return columnMap->queryRootColumn();
  3076. }
  3077. unsigned BoundRow::getMaxSize()
  3078. {
  3079. return columnMap->getMaxSize();
  3080. }
  3081. //---------------------------------------------------------------------------
  3082. NonLocalIndirectRow::NonLocalIndirectRow(const BoundRow & other, ColumnToOffsetMap * rawMap, SerializationRow * _serialization) : BoundRow(other, rawMap, nullptr)
  3083. {
  3084. serialization = _serialization;
  3085. }
  3086. IHqlExpression * NonLocalIndirectRow::getMappedSelector(BuildCtx & ctx, IReferenceSelector * selector)
  3087. {
  3088. return serialization->ensureSerialized(ctx, NULL, selector);
  3089. }
  3090. //---------------------------------------------------------------------------
  3091. SerializationRow::SerializationRow(HqlCppTranslator & _translator, IHqlExpression * _dataset, IHqlExpression * _bound, DynamicColumnToOffsetMap * _columnMap, ActivityInstance * _activity) : BoundRow(_dataset, _bound, NULL, _columnMap, no_none, NULL), translator(_translator)
  3092. {
  3093. serializedMap = _columnMap;
  3094. extractBuilder = NULL;
  3095. finalFixedSizeExpr.setown(createUnknown(no_callback, LINK(sizetType), sizeAtom, new DelayedSizeGenerator(serializedMap)));
  3096. activity = _activity;
  3097. }
  3098. IHqlExpression * SerializationRow::ensureSerialized(BuildCtx & ctx, IHqlExpression * colocal, IReferenceSelector * selector)
  3099. {
  3100. return ensureSerialized(selector->queryExpr(), colocal, selector->isConditional());
  3101. }
  3102. IHqlExpression * SerializationRow::ensureSerialized(IHqlExpression * path, IHqlExpression * colocal, bool isConditional)
  3103. {
  3104. SharedHqlExpr * mapped = mapping.getValue(path);
  3105. if (mapped)
  3106. return LINK(mapped->get());
  3107. ITypeInfo * pathType = path->queryType();
  3108. Owned<ITypeInfo> unqualifiedType = getFullyUnqualifiedType(pathType);
  3109. Owned<ITypeInfo> serializeType = cloneEssentialFieldModifiers(pathType, unqualifiedType);
  3110. if (colocal && path->isDataset() &&
  3111. (hasLinkedRow(pathType) || hasOutOfLineModifier(pathType)))
  3112. serializeType.setown(setLinkCountedAttr(serializeType, true));
  3113. return addSerializedValue(path, serializeType, colocal, isConditional);
  3114. }
  3115. IHqlExpression * SerializationRow::addSerializedValue(IHqlExpression * path, ITypeInfo * type, IHqlExpression * colocal, bool isConditional)
  3116. {
  3117. IIdAtom * id = NULL;
  3118. if (path->getOperator() == no_select)
  3119. id = path->queryChild(1)->queryId();
  3120. Owned<ITypeInfo> newType = getSimplifiedType(type, isConditional, (colocal == NULL), internalAtom);
  3121. OwnedHqlExpr newSelect = createField(id, newType);
  3122. OwnedHqlExpr deserialized;
  3123. if (colocal)
  3124. {
  3125. extractBuilder->buildAssign(newSelect, path);
  3126. deserialized.set(newSelect);
  3127. }
  3128. else
  3129. {
  3130. OwnedHqlExpr srcValue = ::ensureSerialized(path, internalAtom);
  3131. extractBuilder->buildAssign(newSelect, srcValue);
  3132. Linked<ITypeInfo> evaluateType = type;
  3133. if (evaluateType->getTypeCode() == type_dictionary)
  3134. evaluateType.setown(setLinkCountedAttr(evaluateType, true));
  3135. deserialized.setown(ensureDeserialized(newSelect, evaluateType, internalAtom));
  3136. if (deserialized != newSelect)
  3137. deserialized.setown(createAlias(deserialized, NULL)); // force it to be evaluated once per start
  3138. }
  3139. mapping.setValue(path, deserialized);
  3140. return LINK(deserialized);
  3141. }
  3142. IHqlExpression * SerializationRow::createField(IIdAtom * id, ITypeInfo * type)
  3143. {
  3144. if (!id)
  3145. {
  3146. StringBuffer fieldName;
  3147. fieldName.append("__f").append(numFields()).append("__");
  3148. id = createIdAtom(fieldName);
  3149. }
  3150. IHqlExpression * attr = hasLinkCountedModifier(type) ? getLinkCountedAttr() : NULL;
  3151. OwnedHqlExpr newField = ::createField(id, LINK(type), attr, NULL);
  3152. if (serializedMap->queryRootColumn()->lookupColumn(newField))
  3153. return createField(NULL, type); // name clash -> create a new unnamed field
  3154. queryRecord()->addOperand(LINK(newField));
  3155. serializedMap->addColumn(newField, translator.queryRecordMap());
  3156. return createSelectExpr(LINK(querySelector()), LINK(newField));
  3157. }
  3158. SerializationRow * SerializationRow::create(HqlCppTranslator & _translator, IHqlExpression * _bound, ActivityInstance * activity)
  3159. {
  3160. OwnedHqlExpr id = createDataset(no_anon, LINK(queryNullRecord()), createAttribute(serializationAtom, createUniqueId()));
  3161. Owned<DynamicColumnToOffsetMap> map = new DynamicColumnToOffsetMap(_translator.queryOptions().maxRecordSize); //NB: This is not cached, but it may be shared...
  3162. return new SerializationRow(_translator, id, _bound, map, activity);
  3163. }
  3164. BoundRow * SerializationRow::clone(IHqlExpression * _newBound)
  3165. {
  3166. return new SerializationRow(translator, dataset, _newBound, serializedMap, activity);
  3167. }
  3168. size32_t SerializationRow::getTotalMinimumSize() const
  3169. {
  3170. return serializedMap->getTotalMinimumSize();
  3171. }
  3172. bool SerializationRow::isFixedSize() const
  3173. {
  3174. return serializedMap->isFixedWidth();
  3175. }
  3176. unsigned SerializationRow::numFields() const
  3177. {
  3178. return serializedMap->numRootFields();
  3179. }
  3180. IHqlExpression * SerializationRow::queryRecord()
  3181. {
  3182. if (!record)
  3183. record.setown(createRecord());
  3184. return record;
  3185. }
  3186. void SerializationRow::finalize()
  3187. {
  3188. if (record)
  3189. record.setown(record.getClear()->closeExpr());
  3190. }