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