hqltcppc.cpp 117 KB

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