fvwugen.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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 "hqlexpr.hpp"
  15. #include "fvwugen.ipp"
  16. #include "fvsource.ipp"
  17. /*
  18. The format of the generated query is as follows:
  19. unsigned8 startPos := 0 : stored('__startPos__');
  20. unsigned4 numRecords := 100 : stored('__numRecords__');
  21. src := dataset(..., rec); //Need to add holepos or filepos to structure
  22. filter := src(curPos >= startPos); //curPos == holepos or filepos depending on source.
  23. limited := choosen(filter, numRecords);
  24. simple := table(src, {simplify-record});
  25. output(simple);
  26. */
  27. IIdAtom * fileposId;
  28. IIdAtom * recordlenName;
  29. IAtom * insertedAtom;
  30. MODULE_INIT(INIT_PRIORITY_STANDARD)
  31. {
  32. fileposId = createIdAtom("__filepos__");
  33. recordlenName = createIdAtom("__recordlen__");
  34. insertedAtom = createLowerCaseAtom("inserted");
  35. return true;
  36. }
  37. IHqlExpression * addFilter(IHqlExpression * dataset, IHqlExpression * limitField)
  38. {
  39. IHqlExpression * lower = createConstant(limitField->queryType()->castFrom(true, (__int64)0));
  40. lower = createValue(no_colon, lower, createValue(no_stored, createConstant(LOWER_LIMIT_ID)));
  41. lower = createSymbol(createIdAtom(LOWER_LIMIT_ID), lower, ob_private);
  42. dataset = createDataset(no_filter, LINK(dataset), createBoolExpr(no_ge, LINK(limitField), lower));
  43. IHqlExpression * upper = createConstant((int)DISKREAD_PAGE_SIZE);
  44. upper = createValue(no_colon, upper, createValue(no_stored, createConstant(RECORD_LIMIT_ID)));
  45. upper = createSymbol(createIdAtom(RECORD_LIMIT_ID), upper, ob_private);
  46. dataset = createDataset(no_choosen, dataset, upper);
  47. dataset = createSymbol(createIdAtom("_Filtered_"), dataset, ob_private);
  48. return dataset;
  49. }
  50. IHqlExpression * addOutput(IHqlExpression * dataset)
  51. {
  52. return createValue(no_output, makeVoidType(), LINK(dataset));
  53. }
  54. IHqlExpression * addSimplifyProject(IHqlExpression * dataset)
  55. {
  56. IHqlExpression * record = dataset->queryRecord();
  57. IHqlExpression * projectRecord = getFileViewerRecord(record, false);
  58. if (!projectRecord)
  59. return LINK(dataset);
  60. projectRecord = createSymbol(createIdAtom("_TargetRecord_"), projectRecord, ob_private);
  61. return createDataset(no_newusertable, LINK(dataset), createComma(projectRecord, getSimplifiedTransform(projectRecord, record, dataset)));
  62. }
  63. IHqlExpression * buildWorkUnitViewerEcl(IHqlExpression * record, const char * wuid, unsigned sequence, const char * name)
  64. {
  65. OwnedHqlExpr newRecord = createSymbol(createIdAtom("_SourceRecord_"), LINK(record), ob_private);
  66. IHqlExpression * arg = name ? createConstant(name) : createConstant((int)sequence);
  67. OwnedHqlExpr dataset = createDataset(no_workunit_dataset, newRecord.getLink(), createComma(createConstant(wuid), arg));
  68. OwnedHqlExpr projected = addSimplifyProject(dataset);
  69. OwnedHqlExpr output = addOutput(projected);
  70. return output.getClear();
  71. }
  72. IHqlExpression * buildDiskFileViewerEcl(const char * logicalName, IHqlExpression * record)
  73. {
  74. //Add filepos to the incomming record structure...
  75. IHqlExpression * filePosAttr = createAttribute(virtualAtom, createAttribute(filepositionAtom));
  76. OwnedHqlExpr filepos = createField(fileposId, makeIntType(8, false), NULL, filePosAttr);
  77. IHqlExpression * sizeofAttr = createAttribute(virtualAtom, createAttribute(sizeofAtom));
  78. OwnedHqlExpr reclen = createField(recordlenName, makeIntType(2, false), NULL, sizeofAttr);
  79. HqlExprArray fields;
  80. unwindChildren(fields, record);
  81. fields.append(*filepos.getLink());
  82. fields.append(*reclen.getLink());
  83. OwnedHqlExpr newRecord = createRecord(fields);
  84. newRecord.setown(createSymbol(createIdAtom("_SourceRecord_"), newRecord.getLink(), ob_private));
  85. OwnedHqlExpr dataset = createNewDataset(createConstant(logicalName), newRecord.getLink(), createValue(no_thor), NULL, NULL, NULL);
  86. OwnedHqlExpr filtered = addFilter(dataset, filepos);
  87. OwnedHqlExpr projected = addSimplifyProject(filtered);
  88. OwnedHqlExpr output = addOutput(projected);
  89. return output.getClear();
  90. }
  91. //---------------------------------------------------------------------------
  92. IHqlExpression * buildDiskOutputEcl(const char * logicalName, IHqlExpression * record)
  93. {
  94. OwnedHqlExpr dataset = createNewDataset(createConstant(logicalName), LINK(record), createValue(no_thor), NULL, NULL, NULL);
  95. return addOutput(dataset);
  96. }
  97. //---------------------------------------------------------------------------
  98. //Add holepos/filepos/sizeof to the query, so that the browse has something to work on.
  99. static HqlTransformerInfo positionTransformerInfo("PositionTransformer");
  100. PositionTransformer::PositionTransformer() : NewHqlTransformer(positionTransformerInfo)
  101. {
  102. insertedAttr.setown(createAttribute(insertedAtom));
  103. }
  104. IHqlExpression * PositionTransformer::createTransformed(IHqlExpression * _expr)
  105. {
  106. OwnedHqlExpr transformed = NewHqlTransformer::createTransformed(_expr);
  107. switch (transformed->getOperator())
  108. {
  109. case no_table:
  110. {
  111. IHqlExpression * mode = transformed->queryChild(2);
  112. HqlExprArray fields;
  113. HqlExprArray args;
  114. if (mode->getOperator() == no_thor)
  115. {
  116. unwindChildren(fields, transformed->queryChild(1));
  117. IHqlExpression * filePosAttr = createComma(createAttribute(virtualAtom, createAttribute(filepositionAtom)), insertedAttr.getLink());
  118. IHqlExpression * sizeofAttr = createComma(createAttribute(virtualAtom, createAttribute(sizeofAtom)), insertedAttr.getLink());
  119. fields.append(*createField(fileposId, makeIntType(8, false), NULL, filePosAttr));
  120. fields.append(*createField(recordlenName, makeIntType(2, false), NULL, sizeofAttr));
  121. unwindChildren(args, transformed);
  122. args.replace(*createRecord(fields), 1);
  123. return transformed->clone(args);
  124. }
  125. }
  126. break;
  127. case no_iterate:
  128. case no_hqlproject:
  129. {
  130. HqlExprArray args;
  131. HqlExprArray assigns;
  132. IHqlExpression * transform = transformed->queryChild(1);
  133. unwindChildren(args, transformed);
  134. unwindChildren(assigns, transform);
  135. IHqlExpression * inRecord = transformed->queryChild(0)->queryRecord();
  136. IHqlExpression * outRecord = transform->queryRecord();
  137. HqlExprArray fields;
  138. unwindChildren(fields, outRecord);
  139. ForEachChild(idx, inRecord)
  140. {
  141. IHqlExpression * child = inRecord->queryChild(idx);
  142. if (child->hasAttribute(insertedAtom))
  143. {
  144. IHqlExpression * newTarget = createField(child->queryId(), child->getType(), LINK(child), insertedAttr.getLink());
  145. fields.append(*newTarget);
  146. assigns.append(*createValue(no_assign, makeVoidType(), newTarget, createSelectExpr(createValue(no_left), LINK(newTarget))));
  147. }
  148. }
  149. IHqlExpression * newRecord = createRecord(fields);
  150. args.replace(*createValue(no_transform, newRecord->getType(), assigns), 1);
  151. return transformed->clone(args);
  152. }
  153. break;
  154. case no_join:
  155. //only ok if join first
  156. case no_rollup:
  157. case no_newaggregate:
  158. case no_aggregate:
  159. fail();
  160. break;
  161. case no_usertable:
  162. case no_selectfields:
  163. {
  164. IHqlExpression * grouping = transformed->queryChild(2);
  165. if (grouping && (grouping->getOperator() != no_attr))
  166. fail();
  167. IHqlExpression * record = transformed->queryRecord();
  168. HqlExprArray fields;
  169. unwindChildren(fields, transformed->queryChild(1));
  170. ForEachChild(idx, record)
  171. {
  172. IHqlExpression * child = record->queryChild(idx);
  173. if (child->hasAttribute(insertedAtom))
  174. fields.append(*createField(child->queryId(), child->getType(), LINK(child), insertedAttr.getLink()));
  175. }
  176. HqlExprArray args;
  177. unwindChildren(args, transformed);
  178. args.replace(*createRecord(fields), 1);
  179. return transformed->clone(args);
  180. }
  181. case no_output:
  182. {
  183. IHqlExpression * file = transformed->queryChild(2);
  184. if (file && (file->getOperator() != no_attr))
  185. {
  186. IHqlExpression * child = transformed->queryChild(0);
  187. assertex(child->getOperator() == no_selectfields);
  188. HqlExprArray args;
  189. unwindChildren(args, child);
  190. HqlExprArray fields;
  191. IHqlExpression * record = child->queryChild(1);
  192. if (record->getOperator() == no_null)
  193. {
  194. //MORE: This might will not work for ifblocks, and may not cope with
  195. // alien(self.x), or nested records.
  196. IHqlExpression * record = child->queryRecord();
  197. ForEachChild(idx, record)
  198. {
  199. IHqlExpression * child = record->queryChild(idx);
  200. if (!child->hasAttribute(insertedAtom))
  201. fields.append(*createField(child->queryId(), child->getType(), LINK(child)));
  202. }
  203. }
  204. else
  205. {
  206. ForEachChild(idx, record)
  207. {
  208. IHqlExpression * child = record->queryChild(idx);
  209. if (!child->hasAttribute(insertedAtom))
  210. fields.append(*LINK(child));
  211. }
  212. }
  213. args.replace(*createRecord(fields), 1);
  214. IHqlExpression * dataset = createRecord(args);
  215. args.kill();
  216. unwindChildren(args, transformed);
  217. args.replace(*dataset, 0);
  218. return transformed->clone(args);
  219. }
  220. }
  221. break;
  222. default:
  223. if (definesColumnList(transformed))
  224. throw 2;
  225. break;
  226. }
  227. return transformed.getClear();
  228. }
  229. void PositionTransformer::fail()
  230. {
  231. throw 1;
  232. }
  233. IHqlExpression * addQueryPositionFields(IHqlExpression * selectFields)
  234. {
  235. PositionTransformer transformer;
  236. try
  237. {
  238. return transformer.transformRoot(selectFields);
  239. }
  240. catch (int)
  241. {
  242. return NULL;
  243. }
  244. }
  245. IHqlExpression * buildQueryViewerEcl(IHqlExpression * selectFields)
  246. {
  247. OwnedHqlExpr transformed = addQueryPositionFields(selectFields);
  248. if (!transformed)
  249. return NULL;
  250. IHqlSimpleScope * scope = transformed->queryRecord()->querySimpleScope();
  251. OwnedHqlExpr filterField = scope->lookupSymbol(fileposId);
  252. OwnedHqlExpr filtered = addFilter(transformed, filterField);
  253. OwnedHqlExpr output = addOutput(filtered);
  254. return output.getClear();
  255. }