rtlrecord.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2016 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. #ifndef rtlrecord_hpp
  14. #define rtlrecord_hpp
  15. #if defined(_WIN32)
  16. #include <malloc.h>
  17. #else
  18. #include <alloca.h>
  19. #endif
  20. #include "eclrtl_imp.hpp"
  21. #include "rtlds_imp.hpp"
  22. #include "rtlfield.hpp"
  23. //---------------------------------------------------------------------------
  24. // Record size handling.
  25. class CGlobalHelperClass : public RtlCInterface
  26. {
  27. public:
  28. inline CGlobalHelperClass(unsigned _activityId) { activityId = _activityId; ctx = NULL; }
  29. inline void onCreate(ICodeContext * _ctx) { ctx = _ctx; }
  30. protected:
  31. ICodeContext * ctx;
  32. unsigned activityId;
  33. };
  34. class COutputRowSerializer : implements IOutputRowSerializer, public CGlobalHelperClass
  35. {
  36. public:
  37. inline COutputRowSerializer(unsigned _activityId) : CGlobalHelperClass(_activityId) { }
  38. RTLIMPLEMENT_IINTERFACE
  39. virtual void serialize(IRowSerializerTarget & out, const byte * self) override = 0;
  40. };
  41. class COutputRowDeserializer : implements IOutputRowDeserializer, public RtlCInterface
  42. {
  43. public:
  44. inline COutputRowDeserializer(unsigned _activityId) { activityId = _activityId; ctx = NULL; }
  45. RTLIMPLEMENT_IINTERFACE
  46. inline void onCreate(ICodeContext * _ctx) { ctx = _ctx; }
  47. virtual size32_t deserialize(ARowBuilder & rowBuilder, IRowDeserializerSource & in) override = 0;
  48. protected:
  49. ICodeContext * ctx;
  50. unsigned activityId;
  51. };
  52. class CSourceRowPrefetcher : implements ISourceRowPrefetcher, public RtlCInterface
  53. {
  54. public:
  55. inline CSourceRowPrefetcher(unsigned _activityId) { activityId = _activityId; ctx = NULL; }
  56. RTLIMPLEMENT_IINTERFACE
  57. virtual void onCreate(ICodeContext * _ctx) { ctx = _ctx; }
  58. virtual void readAhead(IRowPrefetcherSource & in) override = 0;
  59. protected:
  60. ICodeContext * ctx;
  61. unsigned activityId;
  62. };
  63. class CFixedOutputRowSerializer : public COutputRowSerializer
  64. {
  65. public:
  66. inline CFixedOutputRowSerializer(unsigned _activityId, unsigned _fixedSize) : COutputRowSerializer(_activityId) { fixedSize = _fixedSize; }
  67. virtual void serialize(IRowSerializerTarget & out, const byte * self) { out.put(fixedSize, self); }
  68. protected:
  69. size32_t fixedSize;
  70. };
  71. class CFixedOutputRowDeserializer : public COutputRowDeserializer
  72. {
  73. public:
  74. inline CFixedOutputRowDeserializer(unsigned _activityId, unsigned _fixedSize) : COutputRowDeserializer(_activityId) { fixedSize = _fixedSize; }
  75. virtual size32_t deserialize(ARowBuilder & rowBuilder, IRowDeserializerSource & in) { in.read(fixedSize, rowBuilder.getSelf()); return fixedSize; }
  76. protected:
  77. size32_t fixedSize;
  78. };
  79. class CFixedSourceRowPrefetcher : public CSourceRowPrefetcher
  80. {
  81. public:
  82. inline CFixedSourceRowPrefetcher(unsigned _activityId, unsigned _fixedSize) : CSourceRowPrefetcher(_activityId) { fixedSize = _fixedSize; }
  83. virtual void readAhead(IRowPrefetcherSource & in) { in.skip(fixedSize); }
  84. protected:
  85. size32_t fixedSize;
  86. };
  87. //---------------------------------------------------------------------------
  88. class CXmlToRowTransformer : implements IXmlToRowTransformer, public CGlobalHelperClass
  89. {
  90. public:
  91. inline CXmlToRowTransformer(unsigned _activityId) : CGlobalHelperClass(_activityId) {}
  92. RTLIMPLEMENT_IINTERFACE
  93. };
  94. //---------------------------------------------------------------------------
  95. // Record size handling.
  96. class CNormalizeChildIterator : implements INormalizeChildIterator, public RtlCInterface
  97. {
  98. public:
  99. CNormalizeChildIterator(IOutputMetaData & _recordSize) : iter(0, NULL, _recordSize) {}
  100. RTLIMPLEMENT_IINTERFACE
  101. virtual byte * first(const void * parentRecord) override { init(parentRecord); return (byte *)iter.first(); }
  102. virtual byte * next() override { return (byte *)iter.next(); }
  103. virtual void init(const void * parentRecord) = 0;
  104. inline void setDataset(size32_t len, const void * data) { iter.setDataset(len, data); }
  105. protected:
  106. RtlVariableDatasetCursor iter;
  107. };
  108. class CNormalizeLinkedChildIterator : implements INormalizeChildIterator, public RtlCInterface
  109. {
  110. public:
  111. CNormalizeLinkedChildIterator() : iter(0, NULL) {}
  112. RTLIMPLEMENT_IINTERFACE
  113. virtual byte * first(const void * parentRecord) override { init(parentRecord); return (byte *)iter.first(); }
  114. virtual byte * next() override { return (byte *)iter.next(); }
  115. virtual void init(const void * parentRecord) = 0;
  116. inline void setDataset(unsigned _numRows, const byte * * _rows) { iter.setDataset(_numRows, _rows); }
  117. protected:
  118. RtlSafeLinkedDatasetCursor iter;
  119. };
  120. class CNormalizeStreamedChildIterator : implements INormalizeChildIterator, public RtlCInterface
  121. {
  122. public:
  123. CNormalizeStreamedChildIterator() {}
  124. RTLIMPLEMENT_IINTERFACE
  125. virtual byte * first(const void * parentRecord) override { init(parentRecord); return (byte *)iter.first(); }
  126. virtual byte * next() override { return (byte *)iter.next(); }
  127. virtual void init(const void * parentRecord) = 0;
  128. inline void setDataset(IRowStream * _streamed) { iter.init(_streamed); }
  129. protected:
  130. RtlStreamedDatasetCursor iter;
  131. };
  132. //These classes provides a relatively efficient way to access fields within a variable length record structure.
  133. // Probably convert to an interface with various concrete implementations for varying degrees of complexity
  134. //
  135. // Complications:
  136. // * ifblocks
  137. // * nested records.
  138. // * alien data types
  139. //
  140. class FieldNameToFieldNumMap;
  141. class IfBlockInfo;
  142. class ECLRTL_API RtlRecord
  143. {
  144. public:
  145. friend class RtlRow;
  146. RtlRecord(const RtlRecordTypeInfo & fields, bool expandFields);
  147. RtlRecord(const RtlFieldInfo * const * fields, bool expandFields);
  148. ~RtlRecord();
  149. void calcRowOffsets(size_t * variableOffsets, const void * _row, unsigned numFieldsUsed = (unsigned) -1) const;
  150. virtual size32_t getFixedSize() const
  151. {
  152. return numVarFields ? 0 : fixedOffsets[numFields];
  153. }
  154. size_t getOffset(size_t * variableOffsets, unsigned field) const
  155. {
  156. return fixedOffsets[field] + variableOffsets[whichVariableOffset[field]];
  157. }
  158. size_t getFixedOffset(unsigned field) const;
  159. size_t getRecordSize(size_t * variableOffsets) const
  160. {
  161. return getOffset(variableOffsets, numFields);
  162. }
  163. size32_t getRecordSize(const void *data) const;
  164. size32_t calculateOffset(const void *_row, unsigned field) const;
  165. size32_t getMinRecordSize() const;
  166. size32_t deserialize(ARowBuilder & rowBuilder, IRowDeserializerSource & in) const;
  167. void readAhead(IRowPrefetcherSource & in) const;
  168. inline unsigned getNumFields() const { return numFields; }
  169. unsigned getNumKeyedFields() const;
  170. inline unsigned getNumVarFields() const { return numVarFields; }
  171. inline unsigned getNumIfBlocks() const { return numIfBlocks > 0; }
  172. inline const RtlFieldInfo * queryField(unsigned field) const { return fields[field]; }
  173. const RtlFieldInfo * queryOriginalField(unsigned field) const;
  174. inline const RtlTypeInfo * queryType(unsigned field) const { return fields[field]->type; }
  175. const char * queryName(unsigned field) const;
  176. unsigned getFieldNum(const char *fieldName) const;
  177. const RtlRecord *queryNested(unsigned field) const;
  178. static bool excluded(const RtlFieldInfo *field, const byte *row, byte *conditions);
  179. protected:
  180. size_t * fixedOffsets; // fixed portion of the field offsets + 1 extra
  181. unsigned * whichVariableOffset;// which variable offset should be added to the fixed
  182. unsigned * variableFieldIds; // map variable field to real field id.
  183. unsigned * tableIds; // map nested table id to real field id.
  184. unsigned numFields;
  185. unsigned numVarFields;
  186. unsigned numTables;
  187. unsigned numIfBlocks;
  188. const RtlFieldInfo * const * fields;
  189. const RtlFieldInfo * const * originalFields;
  190. const RtlRecord **nestedTables;
  191. const char **names;
  192. const IfBlockInfo **ifblocks;
  193. mutable const FieldNameToFieldNumMap *nameMap;
  194. };
  195. class ECLRTL_API RtlRow
  196. {
  197. public:
  198. RtlRow(const RtlRecord & _info, const void * optRow, unsigned numOffsets, size_t * _variableOffsets);
  199. __int64 getInt(unsigned field) const;
  200. double getReal(unsigned field) const;
  201. void getString(size32_t & resultLen, char * & result, unsigned field) const;
  202. void getUtf8(size32_t & resultLen, char * & result, unsigned field) const;
  203. size_t getOffset(unsigned field) const
  204. {
  205. return info.getOffset(variableOffsets, field);
  206. }
  207. size_t getSize(unsigned field) const
  208. {
  209. return info.getOffset(variableOffsets, field+1) - info.getOffset(variableOffsets, field);
  210. }
  211. size_t getRecordSize() const
  212. {
  213. return info.getRecordSize(variableOffsets);
  214. }
  215. void setRow(const void * _row);
  216. void setRow(const void * _row, unsigned _numFields);
  217. const byte *queryRow() const
  218. {
  219. return row;
  220. }
  221. const byte * queryField(unsigned field) const
  222. {
  223. return queryRow() + getOffset(field);
  224. }
  225. explicit operator bool() { return row != nullptr; }
  226. protected:
  227. const RtlRecord & info;
  228. const byte * row;
  229. size_t * variableOffsets; // [0 + 1 entry for each variable size field ]
  230. };
  231. struct ECLRTL_API RtlDynRow : public RtlRow
  232. {
  233. public:
  234. RtlDynRow(const RtlRecord & _info, const void * optRow = NULL);
  235. ~RtlDynRow();
  236. };
  237. //The following template class is used from the generated code to avoid allocating the offset array
  238. template <unsigned NUM_VARIABLE_FIELDS>
  239. struct ECLRTL_API RtlStaticRow : RtlRow
  240. {
  241. public:
  242. RtlStaticRow(const RtlRecord & _info, const void * optRow = NULL) : RtlRow(_info, optRow, NUM_VARIABLE_FIELDS+1, off) {}
  243. public:
  244. size_t off[NUM_VARIABLE_FIELDS+1];
  245. };
  246. class ECLRTL_API RtlRecordSize : public IRecordSize, public RtlCInterface
  247. {
  248. public:
  249. RtlRecordSize(const RtlRecordTypeInfo & fields) : offsetInformation(fields, true) {}
  250. RTLIMPLEMENT_IINTERFACE
  251. virtual size32_t getRecordSize(const void * row) override
  252. {
  253. //Allocate a temporary offset array on the stack to avoid runtime overhead.
  254. unsigned numOffsets = offsetInformation.getNumVarFields() + 1;
  255. size_t * variableOffsets = (size_t *)alloca(numOffsets * sizeof(size_t));
  256. RtlRow offsetCalculator(offsetInformation, row, numOffsets, variableOffsets);
  257. return offsetCalculator.getRecordSize();
  258. }
  259. virtual size32_t getFixedSize() const override
  260. {
  261. return offsetInformation.getFixedSize();
  262. }
  263. // returns 0 for variable row size
  264. virtual size32_t getMinRecordSize() const override
  265. {
  266. return offsetInformation.getMinRecordSize();
  267. }
  268. protected:
  269. RtlRecord offsetInformation;
  270. };
  271. class CSourceRowPrefetcher;
  272. class ECLRTL_API COutputMetaData : implements IOutputMetaData, public RtlCInterface
  273. {
  274. public:
  275. RTLIMPLEMENT_IINTERFACE
  276. COutputMetaData();
  277. ~COutputMetaData();
  278. virtual void toXML(const byte * self, IXmlWriter & out) override
  279. {
  280. const RtlTypeInfo * type = queryTypeInfo();
  281. if (type)
  282. {
  283. RtlFieldStrInfo dummyField("",NULL,type);
  284. type->toXML(self, self, &dummyField, out);
  285. }
  286. }
  287. virtual unsigned getVersion() const override { return OUTPUTMETADATA_VERSION; }
  288. virtual unsigned getMetaFlags() override { return MDFhasserialize|MDFhasxml; }
  289. virtual void destruct(byte * self) override {}
  290. virtual IOutputMetaData * querySerializedDiskMeta() override { return this; }
  291. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId) override;
  292. virtual ISourceRowPrefetcher * createDiskPrefetcher(ICodeContext * ctx, unsigned activityId) override;
  293. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId) override;
  294. //Default internal serializers are the same as the disk versions
  295. virtual IOutputRowSerializer * createInternalSerializer(ICodeContext * ctx, unsigned activityId) override
  296. {
  297. return createDiskSerializer(ctx, activityId);
  298. }
  299. virtual IOutputRowDeserializer * createInternalDeserializer(ICodeContext * ctx, unsigned activityId) override
  300. {
  301. return createDiskDeserializer(ctx, activityId);
  302. }
  303. virtual void walkIndirectMembers(const byte * self, IIndirectMemberVisitor & visitor) override{ }
  304. virtual IOutputMetaData * queryChildMeta(unsigned i) override { return NULL; }
  305. virtual const RtlRecord &queryRecordAccessor(bool expand) const override final;
  306. virtual size32_t getRecordSize(const void * data) override;
  307. virtual size32_t getFixedSize() const override
  308. {
  309. return queryRecordAccessor(true).getFixedSize();
  310. }
  311. // returns 0 for variable row size
  312. virtual size32_t getMinRecordSize() const override
  313. {
  314. return queryRecordAccessor(true).getMinRecordSize();
  315. }
  316. protected:
  317. //This is the prefetch function that is actually generated by the code generator
  318. virtual CSourceRowPrefetcher * doCreateDiskPrefetcher(unsigned activityId) { return NULL; }
  319. ISourceRowPrefetcher * defaultCreateDiskPrefetcher(ICodeContext * ctx, unsigned activityId);
  320. mutable RtlRecord *recordAccessor[2];
  321. };
  322. /**
  323. * class CDynamicOutputMetaData
  324. *
  325. * An implementation of IOutputMetaData for use with a dynamically-created record type info structure
  326. *
  327. */
  328. class ECLRTL_API CDynamicOutputMetaData : public COutputMetaData
  329. {
  330. public:
  331. CDynamicOutputMetaData(const RtlRecordTypeInfo & fields) : typeInfo(fields)
  332. {
  333. }
  334. virtual const RtlTypeInfo * queryTypeInfo() const override { return &typeInfo; }
  335. protected:
  336. const RtlTypeInfo &typeInfo;
  337. };
  338. class ECLRTL_API CFixedOutputMetaData : public COutputMetaData
  339. {
  340. public:
  341. CFixedOutputMetaData(size32_t _fixedSize) { fixedSize = _fixedSize; }
  342. virtual size32_t getRecordSize(const void *rec) { return fixedSize; }
  343. virtual size32_t getMinRecordSize() const { return fixedSize; }
  344. virtual size32_t getFixedSize() const { return fixedSize; }
  345. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId);
  346. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId);
  347. virtual ISourceRowPrefetcher * createDiskPrefetcher(ICodeContext * ctx, unsigned activityId);
  348. protected:
  349. size32_t fixedSize;
  350. };
  351. class ECLRTL_API CVariableOutputMetaData : public COutputMetaData
  352. {
  353. public:
  354. CVariableOutputMetaData(size32_t _minSize) : minSize(_minSize) { }
  355. virtual size32_t getMinRecordSize() const { return minSize; }
  356. virtual size32_t getFixedSize() const { return 0; } // is variable
  357. protected:
  358. size32_t minSize;
  359. };
  360. class ECLRTL_API CActionOutputMetaData : public COutputMetaData
  361. {
  362. public:
  363. virtual size32_t getRecordSize(const void *) { return 0; }
  364. virtual size32_t getMinRecordSize() const { return 0; }
  365. virtual size32_t getFixedSize() const { return 0; } // is pseudo-variable
  366. virtual void toXML(const byte * self, IXmlWriter & out) { }
  367. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId);
  368. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId);
  369. virtual ISourceRowPrefetcher * createDiskPrefetcher(ICodeContext * ctx, unsigned activityId);
  370. };
  371. #endif