hqltcppc2.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  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 "hqlfunc.hpp"
  22. #include "hqlcpputil.hpp"
  23. #include "hqlfold.hpp"
  24. #include "hqlutil.hpp"
  25. #include "hqlstmt.hpp"
  26. #include "hqlwcpp.hpp"
  27. #include "hqlcpp.ipp"
  28. #include "hqltcppc.ipp"
  29. #include "hqlhtcpp.ipp"
  30. #include "hqlcerrors.hpp"
  31. #include "hqlcatom.hpp"
  32. #include "hqlpmap.hpp"
  33. #include "hqlthql.hpp"
  34. #include "hqlattr.hpp"
  35. #include "hqlusage.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, IAtom * serializeForm)
  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->queryAttribute(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 = queryAttributeChild(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->queryAttribute(choosenAtom))
  176. return true;
  177. if (queryAttributeChild(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, false);
  184. maxChildSize = offsetMap->getMaxSize();
  185. #ifdef _DEBUG
  186. assertex(!recordRequiresSerialization(column->queryRecord(), internalAtom));
  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, IAtom * serializeForm)
  201. {
  202. OwnedHqlExpr endMarker = loopctx.getTempDeclare(sizetType, NULL);
  203. HqlExprArray args;
  204. args.append(*LINK(helper));
  205. OwnedHqlExpr beginCall = translator.bindTranslatedFunctionCall(deserializerBeginNestedId, args);
  206. loopctx.addAssign(endMarker, beginCall);
  207. args.append(*LINK(helper));
  208. args.append(*LINK(endMarker));
  209. OwnedHqlExpr loopCall = createBoolExpr(no_not, translator.bindTranslatedFunctionCall(deserializerFinishedNestedId, args));
  210. loopctx.addLoop(loopCall, NULL, false);
  211. }
  212. void CColumnInfo::buildDeserializeToBuilder(HqlCppTranslator & translator, BuildCtx & ctx, IHqlCppDatasetBuilder * builder, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  213. {
  214. BuildCtx loopctx(ctx);
  215. buildDeserializeChildLoop(translator, loopctx, selector, helper, serializeForm);
  216. builder->buildDeserializeRow(loopctx, helper, serializeForm);
  217. }
  218. void CChildDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  219. {
  220. IHqlExpression * record = column->queryRecord();
  221. assertex(!recordRequiresLinkCount(record)); // Why would it?
  222. if (column->isDictionary())
  223. {
  224. if (serializeForm == diskAtom)
  225. {
  226. //If we ever generate the meta definition for an internal serialization format then the following needs to be implemented
  227. UNIMPLEMENTED_X("deserialize serialized dictionary from disk");
  228. return;
  229. }
  230. }
  231. if (isConditional())
  232. checkAssignOk(translator, ctx, selector, queryZero(), sizeof(size32_t));
  233. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  234. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  235. //Read the all flag and the size
  236. OwnedHqlExpr sizeSizet = getSizetConstant(sizeof(size32_t));
  237. callDeserializeGetN(translator, ctx, helper, sizeSizet, addressSize);
  238. OwnedHqlExpr targetSize = convertAddressToValue(addressSize, sizetType);
  239. OwnedHqlExpr simpleSize = translator.ensureSimpleTranslatedExpr(ctx, targetSize);
  240. OwnedHqlExpr unboundSize = createTranslated(simpleSize);
  241. checkAssignOk(translator, ctx, selector, unboundSize, sizeof(size32_t));
  242. callDeserializeGetN(translator, ctx, helper, simpleSize, addressData);
  243. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  244. OwnedHqlExpr srcSize = adjustValue(simpleSize, sizeof(size32_t));
  245. ctx.associateExpr(sizeOfExpr, srcSize);
  246. }
  247. void CChildDatasetColumnInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  248. {
  249. if (column->isDictionary())
  250. {
  251. if (serializeForm == diskAtom)
  252. {
  253. //If we ever generate the meta definition for an internal serialization format then the following needs to be implemented
  254. UNIMPLEMENTED_X("deserialize serialized dictionary from disk");
  255. }
  256. }
  257. CColumnInfo::buildSerialize(translator, ctx, selector, helper, serializeForm);
  258. }
  259. bool CChildDatasetColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  260. {
  261. OwnedHqlExpr sizeOfDataset = callDeserializerGetSize(translator, ctx, state.helper);
  262. callDeserializerSkipInputTranslatedSize(translator, ctx, state.helper, sizeOfDataset);
  263. return true;
  264. }
  265. IHqlExpression * CChildDatasetColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  266. {
  267. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  268. OwnedHqlExpr length = convertAddressToValue(addressSize, sizetType);
  269. OwnedHqlExpr boundSize = translator.getBoundSize(column->queryType(), length, NULL);
  270. return createValue(no_translated, LINK(sizetType), adjustValue(boundSize, sizeof(size32_t)));
  271. }
  272. void CChildDatasetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  273. {
  274. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  275. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  276. OwnedHqlExpr lengthTarget = convertAddressToValue(addressSize, sizetType);
  277. ITypeInfo * columnType = column->queryType();
  278. IHqlExpression * record = column->queryRecord();
  279. OwnedHqlExpr value = addDatasetLimits(translator, ctx, selector, _value);
  280. ITypeInfo * valueType = value->queryType();
  281. assertRecordTypesMatch(valueType, columnType);
  282. CHqlBoundExpr bound;
  283. translator.buildDataset(ctx, value, bound, FormatBlockedDataset);
  284. translator.normalizeBoundExpr(ctx, bound);
  285. ensureSimpleLength(translator, ctx, bound);
  286. OwnedHqlExpr length = translator.getBoundLength(bound);
  287. OwnedHqlExpr size = createValue(no_translated, LINK(sizetType), translator.getBoundSize(bound));
  288. checkAssignOk(translator, ctx, selector, size, sizeof(size32_t));
  289. translator.assignBoundToTemp(ctx, lengthTarget, length);
  290. translator.buildBlockCopy(ctx, addressData, bound);
  291. //Use the size just calculated for the field
  292. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  293. OwnedHqlExpr boundSize = translator.getBoundSize(bound);
  294. OwnedHqlExpr srcSize = adjustValue(boundSize, sizeof(size32_t));
  295. ctx.associateExpr(sizeOfExpr, srcSize);
  296. }
  297. AColumnInfo * CChildDatasetColumnInfo::lookupColumn(IHqlExpression * search)
  298. {
  299. throwError1(HQLERR_LookupNotActiveDataset, str(search->queryName()));
  300. return NULL;
  301. }
  302. //---------------------------------------------------------------------------
  303. CChildLimitedDatasetColumnInfo::CChildLimitedDatasetColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column, RecordOffsetMap & map, unsigned defaultMaxRecordSize) : CColumnInfo(_container, _prior, _column)
  304. {
  305. IHqlExpression * count = column->queryAttribute(countAtom);
  306. if (count)
  307. countField.setown(foldHqlExpression(column->queryAttribute(countAtom)->queryChild(0)));
  308. else
  309. {
  310. IHqlExpression * size = column->queryAttribute(sizeofAtom);
  311. if (size)
  312. sizeField.setown(foldHqlExpression(size->queryChild(0)));
  313. else
  314. countField.setown(createConstantOne());
  315. }
  316. if (countField)
  317. countField.setown(ensureExprType(countField, sizetType));
  318. if (sizeField)
  319. sizeField.setown(ensureExprType(sizeField, sizetType));
  320. ColumnToOffsetMap * offsetMap = map.queryMapping(column->queryRecord(), defaultMaxRecordSize, false);
  321. maxChildSize = offsetMap->getMaxSize();
  322. fixedChildSize = offsetMap->isFixedWidth() ? maxChildSize : UNKNOWN_LENGTH;
  323. }
  324. void CChildLimitedDatasetColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  325. {
  326. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), 0);
  327. if (countField)
  328. {
  329. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), selector->queryExpr()->queryChild(0));
  330. CHqlBoundExpr boundCount;
  331. translator.buildExpr(ctx, mappedCount, boundCount);
  332. bound.count.set(boundCount.expr);
  333. }
  334. else
  335. {
  336. OwnedHqlExpr mappedSize = replaceSelector(sizeField, querySelfReference(), selector->queryExpr()->queryChild(0));
  337. CHqlBoundExpr boundSize;
  338. translator.buildExpr(ctx, mappedSize, boundSize);
  339. bound.length.set(boundSize.expr);
  340. }
  341. bound.expr.setown(convertAddressToValue(addressData, queryType()));
  342. }
  343. void CChildLimitedDatasetColumnInfo::gatherSize(SizeStruct & target)
  344. {
  345. if (isFixedSize())
  346. {
  347. unsigned fixedSize;
  348. if (sizeField && sizeField->queryValue())
  349. fixedSize = (unsigned)getIntValue(sizeField);
  350. else
  351. {
  352. fixedSize = (unsigned)getIntValue(countField) * fixedChildSize;
  353. }
  354. if (isConditional())
  355. addVariableSize(fixedSize, target);
  356. else
  357. target.addFixed(fixedSize);
  358. }
  359. else
  360. {
  361. addVariableSize(0, target);
  362. }
  363. }
  364. IHqlExpression * CChildLimitedDatasetColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  365. {
  366. CHqlBoundExpr bound;
  367. buildColumnExpr(translator, ctx, selector, bound);
  368. OwnedHqlExpr length = translator.getBoundLength(bound);
  369. return createTranslated(length);
  370. }
  371. bool CChildLimitedDatasetColumnInfo::isFixedSize()
  372. {
  373. if (sizeField && sizeField->queryValue())
  374. return true;
  375. if (countField && countField->queryValue() && (fixedChildSize != UNKNOWN_LENGTH))
  376. return true;
  377. return false; //MORE:
  378. }
  379. void CChildLimitedDatasetColumnInfo::buildDeserializeChildLoop(HqlCppTranslator & translator, BuildCtx & loopctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  380. {
  381. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), selector->queryExpr()->queryChild(0));
  382. CHqlBoundExpr bound;
  383. translator.buildTempExpr(loopctx, mappedCount, bound);
  384. OwnedHqlExpr test = createValue(no_postdec, LINK(bound.expr));
  385. loopctx.addLoop(test, NULL, false);
  386. }
  387. bool CChildLimitedDatasetColumnInfo::prepareReadAhead(HqlCppTranslator & translator, ReadAheadState & state)
  388. {
  389. OwnedHqlExpr self = container->getRelativeSelf();
  390. if (sizeField)
  391. {
  392. OwnedHqlExpr mappedSize = replaceSelector(sizeField, querySelfReference(), self);
  393. gatherSelectExprs(state.requiredValues, mappedSize);
  394. }
  395. else if (countField)
  396. {
  397. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), self);
  398. gatherSelectExprs(state.requiredValues, mappedCount);
  399. }
  400. return true;
  401. }
  402. bool CChildLimitedDatasetColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  403. {
  404. try
  405. {
  406. OwnedHqlExpr self = container->getRelativeSelf();
  407. if (sizeField)
  408. {
  409. OwnedHqlExpr mappedSize = replaceSelector(sizeField, querySelfReference(), self);
  410. OwnedHqlExpr replacedSize = quickFullReplaceExpressions(mappedSize, state.requiredValues, state.mappedValues);
  411. if (containsSelector(replacedSize, queryRootSelf()))
  412. return false;
  413. callDeserializerSkipInputSize(translator, ctx, state. helper, replacedSize);
  414. return true;
  415. }
  416. else
  417. {
  418. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), self);
  419. OwnedHqlExpr replacedCount = quickFullReplaceExpressions(mappedCount, state.requiredValues, state.mappedValues);
  420. if (containsSelector(replacedCount, queryRootSelf()))
  421. return false;
  422. if (fixedChildSize != UNKNOWN_LENGTH)
  423. {
  424. OwnedHqlExpr scaledSize = multiplyValue(replacedCount, fixedChildSize);
  425. callDeserializerSkipInputSize(translator, ctx, state. helper, scaledSize);
  426. return true;
  427. }
  428. BuildCtx loopctx(ctx);
  429. CHqlBoundExpr bound;
  430. translator.buildTempExpr(loopctx, replacedCount, bound);
  431. OwnedHqlExpr test = createValue(no_postdec, LINK(bound.expr));
  432. loopctx.addLoop(test, NULL, false);
  433. StringBuffer helperCpp;
  434. translator.generateExprCpp(helperCpp, state.helper);
  435. StringBuffer prefetcherInstanceName;
  436. translator.ensureRowPrefetcher(prefetcherInstanceName, ctx, column->queryRecord());
  437. StringBuffer s;
  438. loopctx.addQuoted(s.clear().append(helperCpp).append(".noteStartChild();"));
  439. loopctx.addQuoted(s.clear().append(prefetcherInstanceName).append("->readAhead(").append(helperCpp).append(");"));
  440. loopctx.addQuoted(s.clear().append(helperCpp).append(".noteFinishChild();"));
  441. return true;
  442. }
  443. }
  444. catch (IException * e)
  445. {
  446. //yuk yuk yuk!! Couldn't resolve the dataset count/size for some strange reason
  447. e->Release();
  448. }
  449. return false;
  450. }
  451. void CChildLimitedDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
  452. {
  453. assertex(!column->isDictionary());
  454. if (sizeField || !countField)
  455. {
  456. ctx.addQuotedLiteral("rtlFailUnexpected();");
  457. return;
  458. }
  459. //NB: The serialized form of a dataset with an external count is not the same as a normal dataset
  460. IHqlExpression * record = column->queryRecord();
  461. if (recordRequiresSerialization(record, serializeForm) || !translator.isFixedRecordSize(record))
  462. {
  463. Owned<IHqlCppDatasetBuilder> builder = translator.createBlockedDatasetBuilder(column->queryRecord());
  464. builder->buildDeclare(ctx);
  465. buildDeserializeToBuilder(translator, ctx, builder, selector, helper, serializeForm);
  466. CHqlBoundExpr bound;
  467. builder->buildFinish(ctx, bound);
  468. setColumnFromBuilder(translator, ctx, selector, builder);
  469. }
  470. else
  471. CColumnInfo::buildDeserialize(translator, ctx, selector, helper, serializeForm);
  472. }
  473. void CChildLimitedDatasetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value)
  474. {
  475. if (sizeField)
  476. translator.throwError(HQLERR_CannotCreateSizedChildDataset);
  477. if (countField)
  478. {
  479. IHqlExpression * record = column->queryRecord();
  480. OwnedHqlExpr mappedCount = replaceSelector(countField, querySelfReference(), selector->queryExpr()->queryChild(0));
  481. Owned<IHqlCppDatasetBuilder> builder = translator.createLimitedDatasetBuilder(record, mappedCount);
  482. builder->buildDeclare(ctx);
  483. translator.buildDatasetAssign(ctx, builder, value);
  484. setColumnFromBuilder(translator, ctx, selector, builder);
  485. }
  486. }
  487. void CChildLimitedDatasetColumnInfo::setColumnFromBuilder(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlCppDatasetBuilder * builder)
  488. {
  489. CHqlBoundExpr bound;
  490. builder->buildFinish(ctx, bound);
  491. if (bound.length)
  492. bound.length.setown(translator.ensureSimpleTranslatedExpr(ctx, bound.length));
  493. OwnedHqlExpr size = createValue(no_translated, LINK(sizetType), translator.getBoundSize(bound));
  494. checkAssignOk(translator, ctx, selector, size, 0);
  495. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), 0);
  496. translator.buildBlockCopy(ctx, addressData, bound);
  497. //Use the size just calculated for the field
  498. OwnedHqlExpr sizeOfExpr = createValue(no_sizeof, LINK(sizetType), LINK(selector->queryExpr()));
  499. OwnedHqlExpr srcSize = translator.getBoundSize(bound);
  500. ctx.associateExpr(sizeOfExpr, srcSize);
  501. }
  502. AColumnInfo * CChildLimitedDatasetColumnInfo::lookupColumn(IHqlExpression * search)
  503. {
  504. throwError1(HQLERR_LookupNotActiveDataset, str(search->queryName()));
  505. return NULL;
  506. }
  507. //--------------------------------------------------------------------------------------------
  508. CChildLinkedDatasetColumnInfo::CChildLinkedDatasetColumnInfo(CContainerInfo * _container, CMemberInfo * _prior, IHqlExpression * _column, RecordOffsetMap & map, unsigned defaultMaxRecordSize) : CColumnInfo(_container, _prior, _column)
  509. {
  510. ColumnToOffsetMap * offsetMap = map.queryMapping(column->queryRecord(), defaultMaxRecordSize, false);
  511. maxChildSize = offsetMap->getMaxSize();
  512. }
  513. void CChildLinkedDatasetColumnInfo::buildColumnExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound)
  514. {
  515. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  516. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  517. bound.count.setown(convertAddressToValue(addressSize, sizetType));
  518. bound.expr.setown(convertAddressToValue(addressData, queryType()));
  519. }
  520. void CChildLinkedDatasetColumnInfo::gatherSize(SizeStruct & target)
  521. {
  522. unsigned thisSize = sizeof(size32_t) + sizeof(const byte * *);
  523. if (isConditional())
  524. addVariableSize(thisSize, target); // the size is used for ensure if condition is true
  525. else
  526. target.addFixed(thisSize);
  527. }
  528. IHqlExpression * CChildLinkedDatasetColumnInfo::buildSizeOfUnbound(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector)
  529. {
  530. return getSizetConstant(sizeof(size32_t) + sizeof(const byte * *));
  531. }
  532. void CChildLinkedDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeFormat)
  533. {
  534. //There is no need to check for enough space in the row because that has been done in CIfBlockInfo::buildDeserialize
  535. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  536. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  537. IHqlExpression * record = column->queryRecord();
  538. CHqlBoundTarget boundTarget;
  539. boundTarget.count.setown(convertAddressToValue(addressSize, sizetType));
  540. boundTarget.expr.setown(convertAddressToValue(addressData, queryType()));
  541. IIdAtom * func = NULL;
  542. HqlExprArray args;
  543. args.append(*translator.createSerializer(ctx, record, serializeFormat, deserializerAtom));
  544. if (column->isDictionary())
  545. {
  546. if (serializeFormat == diskAtom)
  547. {
  548. func = deserializeChildDictionaryFromDatasetFromStreamId;
  549. StringBuffer lookupHelperName;
  550. translator.buildDictionaryHashClass(record, lookupHelperName);
  551. args.append(*createQuoted(lookupHelperName.str(), makeBoolType()));
  552. }
  553. else
  554. func = deserializeChildDictionaryFromStreamId;
  555. }
  556. else
  557. func = deserializeChildRowsetFromStreamId;
  558. args.append(*LINK(helper));
  559. OwnedHqlExpr call = translator.bindFunctionCall(func, args, queryType());
  560. translator.buildExprAssign(ctx, boundTarget, call);
  561. }
  562. bool CChildLinkedDatasetColumnInfo::buildReadAhead(HqlCppTranslator & translator, BuildCtx & ctx, ReadAheadState & state)
  563. {
  564. OwnedHqlExpr sizeOfDataset = callDeserializerGetSize(translator, ctx, state.helper);
  565. callDeserializerSkipInputTranslatedSize(translator, ctx, state.helper, sizeOfDataset);
  566. return true;
  567. }
  568. void CChildLinkedDatasetColumnInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeFormat)
  569. {
  570. IHqlExpression * record = column->queryRecord();
  571. IIdAtom * func = NULL;
  572. HqlExprArray args;
  573. args.append(*LINK(helper));
  574. args.append(*translator.createSerializer(ctx, record, serializeFormat, serializerAtom));
  575. args.append(*LINK(selector->queryExpr()));
  576. if (column->isDictionary())
  577. {
  578. if (serializeFormat == diskAtom)
  579. func = serializeChildDictionaryToDatasetToStreamId;
  580. else
  581. func = serializeChildDictionaryToStreamId;
  582. }
  583. else
  584. func = serializeChildRowsetToStreamId;
  585. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(func, args);
  586. translator.buildStmt(ctx, call);
  587. }
  588. bool CChildLinkedDatasetColumnInfo::modifyColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value, node_operator op)
  589. {
  590. if (hasDatasetLimits() || (op != no_assign_addfiles))
  591. return false;
  592. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  593. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  594. ITypeInfo * resultType = queryType();
  595. ITypeInfo * valueType = value->queryType();
  596. assertex(recordTypesMatch(valueType, resultType));
  597. CHqlBoundTarget boundTarget;
  598. boundTarget.count.setown(convertAddressToValue(addressSize, sizetType));
  599. boundTarget.expr.setown(convertAddressToValue(addressData, queryType()));
  600. HqlExprArray args;
  601. args.append(*LINK(value));
  602. OwnedHqlExpr call = translator.bindFunctionCall(appendRowsToRowsetId, args, resultType);
  603. translator.buildDatasetAssign(ctx, boundTarget, call);
  604. return true;
  605. }
  606. void CChildLinkedDatasetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value)
  607. {
  608. checkConditionalAssignOk(translator, ctx, selector, sizeof(size32_t) + sizeof(const byte * *));
  609. OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0);
  610. OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t));
  611. ITypeInfo * resultType = queryType();
  612. LinkedHqlExpr value = _value;
  613. ITypeInfo * valueType = value->queryType();
  614. assertRecordTypesMatch(resultType, valueType);
  615. value.setown(addDatasetLimits(translator, ctx, selector, value));
  616. CHqlBoundTarget boundTarget;
  617. boundTarget.count.setown(convertAddressToValue(addressSize, sizetType));
  618. boundTarget.expr.setown(convertAddressToValue(addressData, queryType()));
  619. if (value->getOperator() == no_null)
  620. value.setown(createNullExpr(column));
  621. translator.buildDatasetAssign(ctx, boundTarget, value);
  622. }
  623. AColumnInfo * CChildLinkedDatasetColumnInfo::lookupColumn(IHqlExpression * search)
  624. {
  625. throwError1(HQLERR_LookupNotActiveDataset, str(search->queryName()));
  626. return NULL;
  627. }