hqltcppc2.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #include "jliball.hpp"
  15. #include "hql.hpp"
  16. #include "platform.h"
  17. #include "jlib.hpp"
  18. #include "jexcept.hpp"
  19. #include "jmisc.hpp"
  20. #include "hql.hpp"
  21. #include "hqlexpr.hpp"
  22. #include "hqlfunc.hpp"
  23. #include "hqlcpputil.hpp"
  24. #include "hqlfold.hpp"
  25. #include "hqlutil.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 "hqlpmap.hpp"
  34. #include "hqlthql.hpp"
  35. #include "hqlattr.hpp"
  36. //#define TraceExprPrintLog(x, expr) PrintLog(x ": %s", expr->toString(StringBuffer()).str());
  37. //---------------------------------------------------------------------------
  38. CChildSetColumnInfo::CChildSetColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column) : CColumnInfo(_container, _prior, _column)
  39. {
  40. }
  41. void CChildSetColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  42. {
  43. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, boolType, 0);
  44. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, sizeof(bool));
  45. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(bool)+sizeof(size32_t));
  46. bound.isAll.setown(convertAddressToValue(address, boolType));
  47. bound.length.setown(convertAddressToValue(addressSize, sizetType));
  48. bound.expr.setown(convertAddressToValue(addressData, queryType()));
  49. }
  50. void CChildSetColumnInfo::gatherSize(SizeStruct & target)
  51. {
  52. addVariableSize(sizeof(bool) + sizeof(size32_t), target);
  53. }
  54. IHqlExpression * CChildSetColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  55. {
  56. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, sizeof(bool));
  57. OwnedHqlExpr length = convertAddressToValue(addressSize, sizetType);
  58. OwnedHqlExpr boundSize = translator.getBoundSize(column->queryType(), length, NULL);
  59. return createValue(no_translated, LINK(sizetType), adjustValue(boundSize, sizeof(bool)+sizeof(size32_t)));
  60. }
  61. void CChildSetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper)
  62. {
  63. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, boolType, 0);
  64. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, sizeof(bool));
  65. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(bool)+sizeof(size32_t));
  66. size32_t sizeExtra = sizeof(bool)+sizeof(size32_t);
  67. //Read the all flag and the size
  68. OwnedHqlExpr sizeAllSizet = getSizetConstant(sizeExtra);
  69. callDeserializeGetN(translator, ctx, helper, sizeAllSizet, address);
  70. OwnedHqlExpr targetSize = convertAddressToValue(addressSize, sizetType);
  71. OwnedHqlExpr unboundSize = createTranslated(targetSize);
  72. checkAssignOk(translator, ctx, selector, unboundSize, sizeExtra);
  73. callDeserializeGetN(translator, ctx, helper, targetSize, addressData);
  74. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  75. OwnedHqlExpr srcSize = adjustValue(targetSize, sizeExtra);
  76. ctx.associateExpr(sizeOfExpr, srcSize);
  77. }
  78. bool CChildSetColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  79. {
  80. OwnedHqlExpr sizeAllFlag = getSizetConstant(1);
  81. callDeserializerSkipInputTranslatedSize(translator, ctx, state.helper, sizeAllFlag);
  82. OwnedHqlExpr sizeOfItems = callDeserializerGetSize(translator, ctx, state.helper);
  83. callDeserializerSkipInputTranslatedSize(translator, ctx, state.helper, sizeOfItems);
  84. return true;
  85. }
  86. void CChildSetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  87. {
  88. OwnedHqlExpr address = getColumnAddress(translator, ctx, selector, boolType, 0);
  89. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, sizeof(bool));
  90. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(bool)+sizeof(size32_t));
  91. OwnedHqlExpr isAllTarget = convertAddressToValue(address, boolType);
  92. OwnedHqlExpr lengthTarget = convertAddressToValue(addressSize, sizetType);
  93. ITypeInfo * columnType = column->queryType();
  94. ITypeInfo * elementType = columnType->queryChildType();
  95. OwnedHqlExpr value = ensureExprType(_value, columnType);
  96. OwnedHqlExpr inlineSize;
  97. switch (value->getOperator())
  98. {
  99. case no_list:
  100. if ((value->numChildren() != 0) && ::isFixedSize(elementType))
  101. inlineSize.setown(getSizetConstant(value->numChildren() * elementType->getSize()));
  102. break;
  103. }
  104. if (inlineSize)
  105. {
  106. checkAssignOk(translator, ctx, selector, inlineSize, sizeof(size32_t)+sizeof(bool));
  107. Owned<IHqlCppSetBuilder> builder = translator.createInlineSetBuilder(elementType, isAllTarget, inlineSize, addressData);
  108. builder->buildDeclare(ctx);
  109. translator.buildSetAssign(ctx, builder, value);
  110. CHqlBoundTarget boundTarget;
  111. boundTarget.length.set(lengthTarget);
  112. builder->buildFinish(ctx, boundTarget);
  113. }
  114. else
  115. {
  116. CHqlBoundExpr bound;
  117. if ((value->getOperator() == no_list) && value->numChildren())
  118. {
  119. CHqlBoundTarget tempTarget;
  120. translator.createTempFor(ctx, columnType, tempTarget, typemod_none, FormatNatural);
  121. translator.buildExprAssign(ctx, tempTarget, value);
  122. bound.setFromTarget(tempTarget);
  123. }
  124. else
  125. translator.buildExpr(ctx, value, bound);
  126. ensureSimpleLength(translator, ctx, bound);
  127. OwnedHqlExpr isAll = bound.getIsAll();
  128. OwnedHqlExpr length = translator.getBoundLength(bound);
  129. OwnedHqlExpr size = createValue(no_translated, LINK(sizetType), translator.getBoundSize(bound));
  130. checkAssignOk(translator, ctx, selector, size, sizeof(size32_t)+sizeof(bool));
  131. translator.assignBoundToTemp(ctx, isAllTarget, isAll);
  132. translator.assignBoundToTemp(ctx, lengthTarget, length);
  133. translator.buildBlockCopy(ctx, addressData, bound);
  134. ensureSimpleLength(translator, ctx, bound);
  135. OwnedHqlExpr boundSize = translator.getBoundSize(bound);
  136. associateSizeOf(ctx, selector, boundSize, sizeof(size32_t)+sizeof(bool));
  137. }
  138. }
  139. //---------------------------------------------------------------------------
  140. IHqlExpression * CMemberInfo::addDatasetLimits(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  141. {
  142. LinkedHqlExpr value = _value;
  143. IHqlExpression * choosen = column->queryProperty(choosenAtom);
  144. if (choosen)
  145. {
  146. LinkedHqlExpr choosenValue = choosen->queryChild(0);
  147. if (!choosenValue->queryValue())
  148. {
  149. OwnedHqlExpr self = container->getRelativeSelf();
  150. OwnedHqlExpr absoluteExpr = replaceSelector(choosenValue, querySelfReference(), self);
  151. choosenValue.setown(selector->queryRootRow()->bindToRow(absoluteExpr, querySelfReference()));
  152. }
  153. else
  154. {
  155. if (hasNoMoreRowsThan(value, getIntValue(choosenValue)))
  156. choosenValue.clear();
  157. }
  158. if (choosenValue)
  159. value.setown(createDataset(no_choosen, LINK(value), LINK(choosenValue)));
  160. }
  161. IHqlExpression * maxCount = queryPropertyChild(column, maxCountAtom, 0);
  162. if (maxCount && !hasNoMoreRowsThan(value, getIntValue(maxCount)))
  163. {
  164. //Generate a limit test if there isn't a limit that ensures it is small enough
  165. StringBuffer failText, columnText;
  166. expandSelectPathText(columnText, true).toLowerCase();
  167. failText.appendf("Too many rows assigned to field %s", columnText.str());
  168. OwnedHqlExpr fail = translator.createFailAction(failText.str(), maxCount, NULL, translator.queryCurrentActivityId(ctx));
  169. value.setown(createDataset(no_limit, LINK(value), createComma(LINK(maxCount), LINK(fail))));
  170. }
  171. return value.getClear();
  172. }
  173. bool CMemberInfo::hasDatasetLimits() const
  174. {
  175. if (column->queryProperty(choosenAtom))
  176. return true;
  177. if (queryPropertyChild(column, maxCountAtom, 0))
  178. return true;
  179. return false;
  180. }
  181. CChildDatasetColumnInfo::CChildDatasetColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column, RecordOffsetMap & map, unsigned defaultMaxRecordSize) : CColumnInfo(_container, _prior, _column)
  182. {
  183. ColumnToOffsetMap * offsetMap = map.queryMapping(column->queryRecord(), defaultMaxRecordSize);
  184. maxChildSize = offsetMap->getMaxSize();
  185. #ifdef _DEBUG
  186. assertex(!recordRequiresSerialization(column->queryRecord()));
  187. #endif
  188. }
  189. void CChildDatasetColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  190. {
  191. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  192. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  193. bound.length.setown(convertAddressToValue(addressSize, sizetType));
  194. bound.expr.setown(convertAddressToValue(addressData, queryType()));
  195. }
  196. void CChildDatasetColumnInfo::gatherSize(SizeStruct & target)
  197. {
  198. addVariableSize(sizeof(size32_t), target);
  199. }
  200. void CColumnInfo::buildDeserializeChildLoop(HqlCppTranslator & translator, BuildCtx & loopctx, IReferenceSelector * selector, IHqlExpression * helper)
  201. {
  202. OwnedHqlExpr endMarker = loopctx.getTempDeclare(sizetType, NULL);
  203. HqlExprArray args;
  204. args.append(*LINK(helper));
  205. OwnedHqlExpr beginCall = translator.bindTranslatedFunctionCall(deserializerBeginNestedAtom, args);
  206. loopctx.addAssign(endMarker, beginCall);
  207. args.append(*LINK(helper));
  208. args.append(*LINK(endMarker));
  209. OwnedHqlExpr loopCall = createBoolExpr(no_not, translator.bindTranslatedFunctionCall(deserializerFinishedNestedAtom, args));
  210. loopctx.addLoop(loopCall, NULL, false);
  211. }
  212. void CColumnInfo::buildDeserializeToBuilder(HqlCppTranslator & translator, BuildCtx & ctx, IHqlCppDatasetBuilder * builder, IReferenceSelector * selector, IHqlExpression * helper)
  213. {
  214. BuildCtx loopctx(ctx);
  215. buildDeserializeChildLoop(translator, loopctx, selector, helper);
  216. BoundRow * selfRow = builder->buildDeserializeRow(loopctx, helper);
  217. builder->finishRow(loopctx, selfRow);
  218. }
  219. void CColumnInfo::buildDeserializeDatasetUsingBuilder(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper)
  220. {
  221. Owned<IHqlCppDatasetBuilder> builder = translator.createBlockedDatasetBuilder(column->queryRecord());
  222. builder->buildDeclare(ctx);
  223. buildDeserializeToBuilder(translator, ctx, builder, selector, helper);
  224. CHqlBoundExpr bound;
  225. builder->buildFinish(ctx, bound);
  226. OwnedHqlExpr translated = bound.getTranslatedExpr();
  227. setColumn(translator, ctx, selector, translated);
  228. }
  229. void CChildDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper)
  230. {
  231. IHqlExpression * record = column->queryRecord();
  232. if (recordRequiresSerialization(record))
  233. {
  234. buildDeserializeDatasetUsingBuilder(translator, ctx, selector, helper);
  235. return;
  236. }
  237. if (isConditional())
  238. checkAssignOk(translator, ctx, selector, queryZero(), sizeof(size32_t));
  239. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  240. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  241. //Read the all flag and the size
  242. OwnedHqlExpr sizeSizet = getSizetConstant(sizeof(size32_t));
  243. callDeserializeGetN(translator, ctx, helper, sizeSizet, addressSize);
  244. OwnedHqlExpr targetSize = convertAddressToValue(addressSize, sizetType);
  245. OwnedHqlExpr simpleSize = translator.ensureSimpleTranslatedExpr(ctx, targetSize);
  246. OwnedHqlExpr unboundSize = createTranslated(simpleSize);
  247. checkAssignOk(translator, ctx, selector, unboundSize, sizeof(size32_t));
  248. callDeserializeGetN(translator, ctx, helper, simpleSize, addressData);
  249. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  250. OwnedHqlExpr srcSize = adjustValue(simpleSize, sizeof(size32_t));
  251. ctx.associateExpr(sizeOfExpr, srcSize);
  252. }
  253. bool CChildDatasetColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  254. {
  255. OwnedHqlExpr sizeOfDataset = callDeserializerGetSize(translator, ctx, state.helper);
  256. callDeserializerSkipInputTranslatedSize(translator, ctx, state.helper, sizeOfDataset);
  257. return true;
  258. }
  259. IHqlExpression * CChildDatasetColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  260. {
  261. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  262. OwnedHqlExpr length = convertAddressToValue(addressSize, sizetType);
  263. OwnedHqlExpr boundSize = translator.getBoundSize(column->queryType(), length, NULL);
  264. return createValue(no_translated, LINK(sizetType), adjustValue(boundSize, sizeof(size32_t)));
  265. }
  266. void CChildDatasetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  267. {
  268. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  269. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  270. OwnedHqlExpr lengthTarget = convertAddressToValue(addressSize, sizetType);
  271. ITypeInfo * columnType = column->queryType();
  272. OwnedHqlExpr value = LINK(_value); //ensureExprType(_value, columnType);
  273. ITypeInfo * valueType = value->queryType();
  274. assertex(recordTypesMatch(valueType, columnType));
  275. bool assignInline = false; // canEvaluateInline(value); // MORE: What is the test
  276. // bool assignInline = canAssignInline(&ctx, value) && !canEvaluateInline(&ctx, value);
  277. value.setown(addDatasetLimits(translator, ctx, selector, value));
  278. IHqlExpression * record = column->queryRecord();
  279. if (assignInline)
  280. {
  281. OwnedHqlExpr inlineSize = getSizetConstant(0);
  282. checkAssignOk(translator, ctx, selector, inlineSize, sizeof(size32_t));
  283. //Can only assign inline if we know the maximum length that will be assigned is 0.
  284. Owned<IHqlCppDatasetBuilder> builder = translator.createInlineDatasetBuilder(record, inlineSize, addressData);
  285. builder->buildDeclare(ctx);
  286. translator.buildDatasetAssign(ctx, builder, value);
  287. CHqlBoundTarget boundTarget;
  288. boundTarget.length.set(lengthTarget);
  289. builder->buildFinish(ctx, boundTarget);
  290. }
  291. else
  292. {
  293. CHqlBoundExpr bound;
  294. translator.buildDataset(ctx, value, bound, FormatBlockedDataset);
  295. translator.normalizeBoundExpr(ctx, bound);
  296. ensureSimpleLength(translator, ctx, bound);
  297. OwnedHqlExpr length = translator.getBoundLength(bound);
  298. OwnedHqlExpr size = createValue(no_translated, LINK(sizetType), translator.getBoundSize(bound));
  299. checkAssignOk(translator, ctx, selector, size, sizeof(size32_t));
  300. translator.assignBoundToTemp(ctx, lengthTarget, length);
  301. translator.buildBlockCopy(ctx, addressData, bound);
  302. //Use the size just calculated for the field
  303. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  304. OwnedHqlExpr boundSize = translator.getBoundSize(bound);
  305. OwnedHqlExpr srcSize = adjustValue(boundSize, sizeof(size32_t));
  306. ctx.associateExpr(sizeOfExpr, srcSize);
  307. }
  308. }
  309. AColumnInfo * CChildDatasetColumnInfo::lookupColumn(IHqlExpression * search)
  310. {
  311. throwError1(HQLERR_LookupNotActiveDataset, search->queryName()->str());
  312. return NULL;
  313. }
  314. //---------------------------------------------------------------------------
  315. CChildLimitedDatasetColumnInfo::CChildLimitedDatasetColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column, RecordOffsetMap & map, unsigned defaultMaxRecordSize) : CColumnInfo(_container, _prior, _column)
  316. {
  317. IHqlExpression * count = column->queryProperty(countAtom);
  318. if (count)
  319. countField.setown(foldHqlExpression(column->queryProperty(countAtom)->queryChild(0)));
  320. else
  321. {
  322. IHqlExpression * size = column->queryProperty(sizeofAtom);
  323. if (size)
  324. sizeField.setown(foldHqlExpression(size->queryChild(0)));
  325. else
  326. countField.setown(createConstantOne());
  327. }
  328. if (countField)
  329. countField.setown(ensureExprType(countField, sizetType));
  330. if (sizeField)
  331. sizeField.setown(ensureExprType(sizeField, sizetType));
  332. ColumnToOffsetMap * offsetMap = map.queryMapping(column->queryRecord(), defaultMaxRecordSize);
  333. maxChildSize = offsetMap->getMaxSize();
  334. fixedChildSize = offsetMap->isFixedWidth() ? maxChildSize : UNKNOWN_LENGTH;
  335. }
  336. void CChildLimitedDatasetColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  337. {
  338. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), 0);
  339. if (countField)
  340. {
  341. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), selector->queryExpr()->queryChild(0));
  342. CHqlBoundExpr boundCount;
  343. translator.buildExpr(ctx, mappedCount, boundCount);
  344. bound.count.set(boundCount.expr);
  345. }
  346. else
  347. {
  348. OwnedHqlExpr mappedSize = replaceSelector(sizeField, querySelfReference(), selector->queryExpr()->queryChild(0));
  349. CHqlBoundExpr boundSize;
  350. translator.buildExpr(ctx, mappedSize, boundSize);
  351. bound.length.set(boundSize.expr);
  352. }
  353. bound.expr.setown(convertAddressToValue(addressData, queryType()));
  354. }
  355. void CChildLimitedDatasetColumnInfo::gatherSize(SizeStruct & target)
  356. {
  357. if (isFixedSize())
  358. {
  359. unsigned fixedSize;
  360. if (sizeField && sizeField->queryValue())
  361. fixedSize = (unsigned)getIntValue(sizeField);
  362. else
  363. {
  364. fixedSize = (unsigned)getIntValue(countField) * fixedChildSize;
  365. }
  366. if (isConditional())
  367. addVariableSize(fixedSize, target);
  368. else
  369. target.addFixed(fixedSize);
  370. }
  371. else
  372. {
  373. addVariableSize(0, target);
  374. }
  375. }
  376. IHqlExpression * CChildLimitedDatasetColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  377. {
  378. CHqlBoundExpr bound;
  379. buildColumnExpr(translator, ctx, selector, bound);
  380. OwnedHqlExpr length = translator.getBoundLength(bound);
  381. return createTranslated(length);
  382. }
  383. bool CChildLimitedDatasetColumnInfo::isFixedSize()
  384. {
  385. if (sizeField && sizeField->queryValue())
  386. return true;
  387. if (countField && countField->queryValue() && (fixedChildSize != UNKNOWN_LENGTH))
  388. return true;
  389. return false; //MORE:
  390. }
  391. void CChildLimitedDatasetColumnInfo::buildDeserializeChildLoop(HqlCppTranslator & translator, BuildCtx & loopctx, IReferenceSelector * selector, IHqlExpression * helper)
  392. {
  393. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), selector->queryExpr()->queryChild(0));
  394. CHqlBoundExpr bound;
  395. translator.buildTempExpr(loopctx, mappedCount, bound);
  396. OwnedHqlExpr test = createValue(no_postdec, LINK(bound.expr));
  397. loopctx.addLoop(test, NULL, false);
  398. }
  399. bool CChildLimitedDatasetColumnInfo::prepareReadAhead(HqlCppTranslator & translator, ReadAheadState & state)
  400. {
  401. OwnedHqlExpr self = container->getRelativeSelf();
  402. if (sizeField)
  403. {
  404. OwnedHqlExpr mappedSize = replaceSelector(sizeField, querySelfReference(), self);
  405. gatherSelectExprs(state.requiredValues, mappedSize);
  406. }
  407. else if (countField)
  408. {
  409. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), self);
  410. gatherSelectExprs(state.requiredValues, mappedCount);
  411. }
  412. return true;
  413. }
  414. bool CChildLimitedDatasetColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  415. {
  416. try
  417. {
  418. OwnedHqlExpr self = container->getRelativeSelf();
  419. if (sizeField)
  420. {
  421. OwnedHqlExpr mappedSize = replaceSelector(sizeField, querySelfReference(), self);
  422. OwnedHqlExpr replacedSize = quickFullReplaceExpressions(mappedSize, state.requiredValues, state.mappedValues);
  423. if (containsSelector(replacedSize, queryRootSelf()))
  424. return false;
  425. callDeserializerSkipInputSize(translator, ctx, state. helper, replacedSize);
  426. return true;
  427. }
  428. else
  429. {
  430. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), self);
  431. OwnedHqlExpr replacedCount = quickFullReplaceExpressions(mappedCount, state.requiredValues, state.mappedValues);
  432. if (containsSelector(replacedCount, queryRootSelf()))
  433. return false;
  434. if (fixedChildSize != UNKNOWN_LENGTH)
  435. {
  436. OwnedHqlExpr scaledSize = multiplyValue(replacedCount, fixedChildSize);
  437. callDeserializerSkipInputSize(translator, ctx, state. helper, scaledSize);
  438. return true;
  439. }
  440. BuildCtx loopctx(ctx);
  441. CHqlBoundExpr bound;
  442. translator.buildTempExpr(loopctx, replacedCount, bound);
  443. OwnedHqlExpr test = createValue(no_postdec, LINK(bound.expr));
  444. loopctx.addLoop(test, NULL, false);
  445. StringBuffer prefetcherInstanceName;
  446. translator.ensureRowPrefetcher(prefetcherInstanceName, ctx, column->queryRecord());
  447. StringBuffer s;
  448. s.append(prefetcherInstanceName).append("->readAhead(");
  449. translator.generateExprCpp(s, state.helper).append(");");
  450. loopctx.addQuoted(s);
  451. return true;
  452. }
  453. }
  454. catch (IException * e)
  455. {
  456. //yuk yuk yuk!! Couldn't resolve the dataset count/size for some strange reason
  457. e->Release();
  458. }
  459. return false;
  460. }
  461. void CChildLimitedDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper)
  462. {
  463. if (sizeField || !countField)
  464. {
  465. ctx.addQuoted("rtlFailUnexpected();");
  466. return;
  467. }
  468. //NB: The serialized form of a dataset with an external count is not the same as a normal dataset
  469. IHqlExpression * record = column->queryRecord();
  470. if (recordRequiresSerialization(record) || !translator.isFixedRecordSize(record))
  471. {
  472. Owned<IHqlCppDatasetBuilder> builder = translator.createBlockedDatasetBuilder(column->queryRecord());
  473. builder->buildDeclare(ctx);
  474. buildDeserializeToBuilder(translator, ctx, builder, selector, helper);
  475. CHqlBoundExpr bound;
  476. builder->buildFinish(ctx, bound);
  477. setColumnFromBuilder(translator, ctx, selector, builder);
  478. }
  479. else
  480. CColumnInfo::buildDeserialize(translator, ctx, selector, helper);
  481. }
  482. void CChildLimitedDatasetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  483. {
  484. if (sizeField)
  485. translator.throwError(HQLERR_CannotCreateSizedChildDataset);
  486. if (countField)
  487. {
  488. IHqlExpression * record = column->queryRecord();
  489. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), selector->queryExpr()->queryChild(0));
  490. Owned<IHqlCppDatasetBuilder> builder = translator.createLimitedDatasetBuilder(record, mappedCount);
  491. builder->buildDeclare(ctx);
  492. translator.buildDatasetAssign(ctx, builder, value);
  493. setColumnFromBuilder(translator, ctx, selector, builder);
  494. }
  495. }
  496. void CChildLimitedDatasetColumnInfo::setColumnFromBuilder(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlCppDatasetBuilder * builder)
  497. {
  498. CHqlBoundExpr bound;
  499. builder->buildFinish(ctx, bound);
  500. if (bound.length)
  501. bound.length.setown(translator.ensureSimpleTranslatedExpr(ctx, bound.length));
  502. OwnedHqlExpr size = createValue(no_translated, LINK(sizetType), translator.getBoundSize(bound));
  503. checkAssignOk(translator, ctx, selector, size, 0);
  504. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), 0);
  505. translator.buildBlockCopy(ctx, addressData, bound);
  506. //Use the size just calculated for the field
  507. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  508. OwnedHqlExpr srcSize = translator.getBoundSize(bound);
  509. ctx.associateExpr(sizeOfExpr, srcSize);
  510. }
  511. AColumnInfo * CChildLimitedDatasetColumnInfo::lookupColumn(IHqlExpression * search)
  512. {
  513. throwError1(HQLERR_LookupNotActiveDataset, search->queryName()->str());
  514. return NULL;
  515. }
  516. //--------------------------------------------------------------------------------------------
  517. CChildLinkedDatasetColumnInfo::CChildLinkedDatasetColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column, RecordOffsetMap & map, unsigned defaultMaxRecordSize) : CColumnInfo(_container, _prior, _column)
  518. {
  519. ColumnToOffsetMap * offsetMap = map.queryMapping(column->queryRecord(), defaultMaxRecordSize);
  520. maxChildSize = offsetMap->getMaxSize();
  521. }
  522. void CChildLinkedDatasetColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  523. {
  524. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  525. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  526. bound.count.setown(convertAddressToValue(addressSize, sizetType));
  527. bound.expr.setown(convertAddressToValue(addressData, queryType()));
  528. }
  529. void CChildLinkedDatasetColumnInfo::gatherSize(SizeStruct & target)
  530. {
  531. unsigned thisSize = sizeof(size32_t) + sizeof(byte * *);
  532. if (isConditional())
  533. addVariableSize(thisSize, target); // the size is used for ensure if condition is true
  534. else
  535. target.addFixed(thisSize);
  536. }
  537. IHqlExpression * CChildLinkedDatasetColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  538. {
  539. return getSizetConstant(sizeof(size32_t) + sizeof(byte * *));
  540. }
  541. void CChildLinkedDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper)
  542. {
  543. if (isConditional())
  544. checkAssignOk(translator, ctx, selector, queryZero(), sizeof(size32_t) + sizeof(byte * *));
  545. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  546. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  547. IHqlExpression * record = column->queryRecord();
  548. CHqlBoundTarget boundTarget;
  549. boundTarget.count.setown(convertAddressToValue(addressSize, sizetType));
  550. boundTarget.expr.setown(convertAddressToValue(addressData, queryType()));
  551. HqlExprArray args;
  552. args.append(*translator.createRowSerializer(ctx, record, deserializerAtom));
  553. args.append(*LINK(helper));
  554. OwnedHqlExpr call = translator.bindFunctionCall(deserializerRowsetHelperAtom, args, queryType());
  555. translator.buildExprAssign(ctx, boundTarget, call);
  556. }
  557. bool CChildLinkedDatasetColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  558. {
  559. OwnedHqlExpr sizeOfDataset = callDeserializerGetSize(translator, ctx, state.helper);
  560. callDeserializerSkipInputTranslatedSize(translator, ctx, state.helper, sizeOfDataset);
  561. return true;
  562. }
  563. void CChildLinkedDatasetColumnInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper)
  564. {
  565. IHqlExpression * record = column->queryRecord();
  566. HqlExprArray args;
  567. args.append(*LINK(helper));
  568. args.append(*translator.createRowSerializer(ctx, record, serializerAtom));
  569. args.append(*LINK(selector->queryExpr()));
  570. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(serializerRowsetHelperAtom, args);
  571. translator.buildStmt(ctx, call);
  572. }
  573. bool CChildLinkedDatasetColumnInfo::modifyColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value, node_operator op)
  574. {
  575. if (hasDatasetLimits() || (op != no_assign_addfiles))
  576. return false;
  577. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  578. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  579. ITypeInfo * resultType = queryType();
  580. ITypeInfo * valueType = value->queryType();
  581. assertex(recordTypesMatch(valueType, resultType));
  582. CHqlBoundTarget boundTarget;
  583. boundTarget.count.setown(convertAddressToValue(addressSize, sizetType));
  584. boundTarget.expr.setown(convertAddressToValue(addressData, queryType()));
  585. HqlExprArray args;
  586. args.append(*LINK(value));
  587. OwnedHqlExpr call = translator.bindFunctionCall(appendRowsToRowsetAtom, args, resultType);
  588. translator.buildDatasetAssign(ctx, boundTarget, call);
  589. return true;
  590. }
  591. void CChildLinkedDatasetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  592. {
  593. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  594. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  595. ITypeInfo * resultType = queryType();
  596. LinkedHqlExpr value = _value;
  597. ITypeInfo * valueType = value->queryType();
  598. assertex(recordTypesMatch(valueType, resultType));
  599. value.setown(addDatasetLimits(translator, ctx, selector, value));
  600. CHqlBoundTarget boundTarget;
  601. boundTarget.count.setown(convertAddressToValue(addressSize, sizetType));
  602. boundTarget.expr.setown(convertAddressToValue(addressData, queryType()));
  603. if (value->getOperator() == no_null)
  604. value.setown(createNullExpr(resultType));
  605. translator.buildDatasetAssign(ctx, boundTarget, value);
  606. }
  607. AColumnInfo * CChildLinkedDatasetColumnInfo::lookupColumn(IHqlExpression * search)
  608. {
  609. throwError1(HQLERR_LookupNotActiveDataset, search->queryName()->str());
  610. return NULL;
  611. }