Advertisement
zamotivator

Untitled

Jul 13th, 2012
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.20 KB | None | 0 0
  1. diff --git a/include/array/RLE.h b/include/array/RLE.h
  2. index eb10d99..741e221 100644
  3. --- a/include/array/RLE.h
  4. +++ b/include/array/RLE.h
  5. @@ -60,164 +60,6 @@ typedef std::map<position_t, Value> ValueMap;
  6.  
  7. extern bool checkChunkMagic(ConstChunk const& chunk);
  8.  
  9. -class RLEBitmap
  10. -{
  11. - size_t nSegments;
  12. - position_t* occ; // occ[0] is last occurrence of 0 in first sequence of 0,
  13. - // occ[1] - last coccurence of 1 of first sequnce of 1,...:
  14. - // case 1:
  15. - // 0,0,1,1,1,1,0,0,1,0,0,0,1,1,1
  16. - // occ= 1,5,7,8,11,14
  17. - // case 2:
  18. - // 1,1,0,0,1,0,0,0,0,0,0
  19. - // occ= -1,1,3,4,10
  20. -
  21. - std::vector<position_t> container;
  22. -
  23. - public:
  24. - /**
  25. - * Check if bit at specified position is set
  26. - */
  27. - bool isSet(position_t pos) const {
  28. - size_t l = 0, r = nSegments;
  29. - while (l < r) {
  30. - size_t m = (l + r) >> 1;
  31. - if (occ[m] < pos) {
  32. - l = m + 1;
  33. - } else {
  34. - r = m;
  35. - }
  36. - }
  37. - assert(r < nSegments);
  38. - return r & 1;
  39. - }
  40. -
  41. - struct Segment {
  42. - position_t start;
  43. - position_t length;
  44. - };
  45. -
  46. - /**
  47. - * Get next i-th segment of set bits
  48. - */
  49. - bool getSetSegment(size_t i, Segment& segm) const {
  50. - i <<= 1;
  51. - if (i+1 < nSegments) {
  52. - segm.start = occ[i] + 1;
  53. - segm.length = occ[i+1] - segm.start + 1;
  54. - return true;
  55. - }
  56. - return false;
  57. - }
  58. -
  59. - /**
  60. - * Get next i-th segment of clear bits
  61. - */
  62. - bool getClearSegment(size_t i, Segment& segm) const {
  63. - if (occ[0] < 0) {
  64. - i += 1;
  65. - }
  66. - i <<= 1;
  67. - if (i < nSegments) {
  68. - segm.start = i == 0 ? 0 : occ[i-1] + 1;
  69. - segm.length = occ[i] - segm.start + 1;
  70. - return true;
  71. - }
  72. - return false;
  73. - }
  74. -
  75. -
  76. - /**
  77. - * Find segment of clear bits with position greater or equal than specified.
  78. - * @return segment index which should be used in getClearSegment
  79. - */
  80. - size_t findClearSegment(position_t pos) const {
  81. - size_t l = 0, r = nSegments;
  82. - while (l < r) {
  83. - size_t m = (l + r) >> 1;
  84. - if (occ[m] < pos) {
  85. - l = m + 1;
  86. - } else {
  87. - r = m;
  88. - }
  89. - }
  90. - return (r + 1) >> 1;
  91. - }
  92. -
  93. - /**
  94. - * Find segment of set bits with position greater or equal than specified.
  95. - * @return segment index which should be used in getClearSegment
  96. - */
  97. - size_t findSetSegment(position_t pos) const {
  98. - size_t l = 0, r = nSegments;
  99. - while (l < r) {
  100. - size_t m = (l + r) >> 1;
  101. - if (occ[m] < pos) {
  102. - l = m + 1;
  103. - } else {
  104. - r = m;
  105. - }
  106. - }
  107. - return r >> 1;
  108. - }
  109. -
  110. -
  111. - /**
  112. - * Method to be called to save bitmap in chunk body
  113. - */
  114. - void pack(char* dst) {
  115. - *(size_t*)dst = nSegments;
  116. - dst += sizeof(size_t);
  117. - memcpy(dst, occ, nSegments*sizeof(position_t));
  118. - }
  119. -
  120. - /**
  121. - * Get size needed to pack bitmap (used to dermine size of chunk)
  122. - */
  123. - size_t packedSize() {
  124. - return sizeof(size_t) + nSegments*sizeof(position_t);
  125. - }
  126. -
  127. - /**
  128. - * Assignment operator
  129. - */
  130. - RLEBitmap& operator=(RLEBitmap const& other);
  131. -
  132. - /**
  133. - * Default constructor
  134. - */
  135. - RLEBitmap() {
  136. - nSegments = 0;
  137. - occ = NULL;
  138. - }
  139. -
  140. - /**
  141. - * Copy constructor
  142. - */
  143. - RLEBitmap(RLEBitmap const& other) {
  144. - *this = other;
  145. - }
  146. -
  147. - /**
  148. - * Constructor for initializing Bitmap with raw chunk data
  149. - */
  150. - RLEBitmap(char const* src) {
  151. - nSegments = *(size_t*)src;
  152. - occ = (position_t*)(src + sizeof(size_t));
  153. - }
  154. -
  155. - /**
  156. - * Constructor of bitmap from ValueMap (which is used to be filled by ChunkIterator)
  157. - */
  158. - RLEBitmap(ValueMap& vm, uint64_t chunkSize, bool defaultVal);
  159. -
  160. - /**
  161. - * Constructor of RLE bitmap from dense bit vector
  162. - */
  163. - RLEBitmap(char* data, size_t chunkSize);
  164. -};
  165. -
  166. -
  167. class RLEEmptyBitmap;
  168. class ConstRLEEmptyBitmap
  169. {
  170. @@ -431,6 +273,15 @@ public:
  171. boost::shared_ptr<RLEEmptyBitmap> merge(ConstRLEEmptyBitmap const& other);
  172.  
  173. /**
  174. + * Merge THIS with other bitmap
  175. + */
  176. + boost::shared_ptr<RLEEmptyBitmap> cut(
  177. + Coordinates const& lowerOrigin,
  178. + Coordinates const& upperOrigin,
  179. + Coordinates const& lowerResult,
  180. + Coordinates const& upperResult) const;
  181. +
  182. + /**
  183. * Merge THIS with MERGEBITS and return the result as a new RLEEmptyBitmap
  184. * MERGEBITS must have one BIT for each "1" in THIS.
  185. */
  186. @@ -560,11 +411,6 @@ class RLEEmptyBitmap : public ConstRLEEmptyBitmap
  187. RLEEmptyBitmap(char* data, size_t numBits);
  188.  
  189. /**
  190. - * Constructor for initializing Bitmap with specified ranges
  191. - */
  192. - RLEEmptyBitmap(Coordinates const& chunkSize, Coordinates const& origin, Coordinates const& first, Coordinates const& last);
  193. -
  194. - /**
  195. * Constructor for initializing Bitmap from specified chunk
  196. */
  197. RLEEmptyBitmap(ConstChunk const& chunk);
  198. @@ -919,7 +765,7 @@ public:
  199. setBits += _payload->checkBit(_cs->valueIndex) ? tail : 0;
  200. } else {
  201. position_t beg = _cs->valueIndex + _currPpos - _cs->pPosition;
  202. - position_t end = _cs->pPosition + _cs->length();
  203. + position_t end = _cs->valueIndex + _cs->length();
  204. while (beg < end) {
  205. setBits += _payload->checkBit(beg++);
  206. }
  207. diff --git a/src/array/MemArray.cpp b/src/array/MemArray.cpp
  208. index bc547c9..175b5ea 100644
  209. --- a/src/array/MemArray.cpp
  210. +++ b/src/array/MemArray.cpp
  211. @@ -2005,7 +2005,10 @@ namespace scidb
  212. emptyBitmap = shared_ptr<RLEEmptyBitmap>(new RLEEmptyBitmap(logicalChunkSize));
  213. }
  214. if (hasOverlap && (iterationMode & IGNORE_OVERLAPS)) {
  215. - emptyBitmap = emptyBitmap->merge(RLEEmptyBitmap(chunkIntervals, origin, data->getFirstPosition(false), data->getLastPosition(false)));
  216. + emptyBitmap = emptyBitmap->cut(data->getFirstPosition(true),
  217. + data->getLastPosition(true),
  218. + data->getFirstPosition(false),
  219. + data->getLastPosition(false));
  220. }
  221. //assert(emptyBitmap->count() == payload.count() || (hasOverlap && emptyBitmap->count() < payload.count()));
  222. assert(emptyBitmap->count() <= payload.count());
  223. @@ -2113,7 +2116,10 @@ namespace scidb
  224. } else {
  225. emptyBitmap = data->getEmptyBitmap();
  226. if (hasOverlap && (iterationMode & IGNORE_OVERLAPS)) {
  227. - emptyBitmap = emptyBitmap->merge(RLEEmptyBitmap(chunkIntervals, origin, data->getFirstPosition(false), data->getLastPosition(false)));
  228. + emptyBitmap = emptyBitmap->cut(data->getFirstPosition(true),
  229. + data->getLastPosition(true),
  230. + data->getFirstPosition(false),
  231. + data->getLastPosition(false));
  232. }
  233. }
  234. emptyBitmapIterator = emptyBitmap->getIterator();
  235. diff --git a/src/array/RLE.cpp b/src/array/RLE.cpp
  236. index ff8319a..7a901dc 100644
  237. --- a/src/array/RLE.cpp
  238. +++ b/src/array/RLE.cpp
  239. @@ -21,10 +21,13 @@
  240. * END_COPYRIGHT
  241. */
  242.  
  243. +#include <sstream>
  244. +#include <fstream>
  245. #include "array/Array.h"
  246. #include "query/TypeSystem.h"
  247. #include "system/Config.h"
  248. #include "system/SciDBConfigOptions.h"
  249. +#include "system/Utils.h"
  250.  
  251. using namespace boost;
  252. using namespace std;
  253. @@ -48,70 +51,6 @@ namespace scidb
  254. return true;
  255. }
  256.  
  257. - RLEBitmap& RLEBitmap::operator=(RLEBitmap const& other)
  258. - {
  259. - nSegments = other.nSegments;
  260. - if (other.occ == &other.container[0]) {
  261. - container = other.container;
  262. - occ = &container[0];
  263. - } else {
  264. - occ = other.occ;
  265. - }
  266. - return *this;
  267. - }
  268. -
  269. - RLEBitmap::RLEBitmap(ValueMap& vm, uint64_t chunkSize, bool defaultVal)
  270. - {
  271. - bool currVal = false;
  272. - position_t currPos = -1;
  273. - for (ValueMap::const_iterator i = vm.begin(); i != vm.end(); ++i) {
  274. - assert(i->first > currPos);
  275. - if (i->second.getBool() != currVal || (i->first != currPos+1 && currVal != defaultVal)) {
  276. - if (i->first != currPos+1) { // hole
  277. - if (currVal != defaultVal) {
  278. - container.push_back(currPos); // sequence of currVal (where currVal != defaultVal)
  279. - if (i->second.getBool() != defaultVal) {
  280. - container.push_back(i->first-1); // sequence of defaultVal
  281. - }
  282. - } else {
  283. - container.push_back(i->first-1); // sequence of defaultVal (where defaultVal != i->second)
  284. - }
  285. - } else {
  286. - container.push_back(currPos);
  287. - }
  288. - }
  289. - currVal = i->second.getBool();
  290. - currPos = i->first;
  291. - }
  292. - if (currVal == defaultVal) {
  293. - container.push_back(chunkSize-1);
  294. - } else {
  295. - container.push_back(currPos);
  296. - if (currPos != position_t(chunkSize-1)) {
  297. - container.push_back(chunkSize-1);
  298. - }
  299. - }
  300. - nSegments = container.size();
  301. - occ = &container[0];
  302. - }
  303. -
  304. - RLEBitmap::RLEBitmap(char* data, size_t chunkSize)
  305. - {
  306. - bool currVal = false;
  307. - for (size_t i = 0; i < chunkSize; i++) {
  308. - bool newVal = (data[i >> 3] & (1 << (i & 7))) != 0;
  309. - if (newVal != currVal) {
  310. - container.push_back(i-1);
  311. - currVal = newVal;
  312. - }
  313. - }
  314. - if (container.back() != position_t(chunkSize-1)) {
  315. - container.push_back(chunkSize-1);
  316. - }
  317. - nSegments = container.size();
  318. - occ = &container[0];
  319. - }
  320. -
  321. size_t ConstRLEEmptyBitmap::packedSize() const {
  322. return sizeof(Header) + nSegs*sizeof(Segment);
  323. }
  324. @@ -395,64 +334,261 @@ namespace scidb
  325. ppos += len;
  326. }
  327. return ppos;
  328. - }
  329. -
  330. - RLEEmptyBitmap::RLEEmptyBitmap(Coordinates const& chunkSize, Coordinates const& origin, Coordinates const& first, Coordinates const& last)
  331. + }
  332. +
  333. + class CutBuilder : boost::noncopyable
  334. {
  335. - //This constructor is used to create fully dense bitmasks for chunks that are assumed to be 100% dense,
  336. - //AND they are missing a tail section (say chunk size is 100 and array ends at 120) or maybe they
  337. - //are missing overlap. I personally think we should NEVER need to call this constructor. There is no reason
  338. - //why we need to build such masks. We can always start with empty masks and go from there. But this bad
  339. - //behavior is hard to get rid of quickly. I will try to get rid of it slowly -poliocough, 5/2/12
  340. -
  341. - //Why is this behavior bad? Assume you have a 4x4 chunk that's truncated to be 3x3. What does the bitmask look
  342. - //like?. Uncompressed, it looks like this:
  343. - //
  344. - // 1110
  345. - // 1110
  346. - // 1110
  347. - // 0000
  348. - //
  349. - //So this bitmask contains 3 segments. One segment for each row of 1s.
  350. - //Now imagine this is a 5-dimensional array with chunk sizes of thousands. We could create a very large bitmask.
  351. - //for no reason at all!
  352. -
  353. - uint64_t nElems = 1;
  354. - size_t n = chunkSize.size();
  355. - size_t lastTruncatedDim = 0;
  356. - for (size_t i = 0; i < n; i++)
  357. + public:
  358. + typedef ConstRLEEmptyBitmap::Segment Segment;
  359. +
  360. + private:
  361. + boost::shared_ptr<RLEEmptyBitmap> _resultBitmap;
  362. +
  363. + Segment const * _sourceArray;
  364. +
  365. + size_t _sourceCount;
  366. + size_t _sourceIndex;
  367. +
  368. + Segment _sourceSegment;
  369. + Segment _resultSegment;
  370. +
  371. + public:
  372. + CutBuilder(Segment* sourceArray, size_t sourceCount) :
  373. + _resultBitmap(new RLEEmptyBitmap()),
  374. + _sourceArray(sourceArray),
  375. + _sourceCount(sourceCount),
  376. + _sourceIndex(0)
  377. {
  378. - if(chunkSize[i]!= last[i]-first[i]+1)
  379. - {
  380. - lastTruncatedDim=i;
  381. + if (!endSource()) {
  382. + _sourceSegment = _sourceArray[0];
  383. + _resultSegment.lPosition = _sourceSegment.lPosition;
  384. + _resultSegment.pPosition = _sourceSegment.pPosition;
  385. + _resultSegment.length = 0;
  386. }
  387. - nElems *= chunkSize[i];
  388. }
  389.  
  390. - //Turns out, the number of segments is the product of all dimensions UP TO the LAST truncated dimension:
  391. - uint64_t numSegments = 1;
  392. - for(size_t i =0; i<lastTruncatedDim; i++)
  393. + position_t logical() const
  394. {
  395. - numSegments *= (last[i]-first[i]+1);
  396. + SCIDB_ASSERT(!endSource());
  397. + return _sourceSegment.lPosition;
  398. }
  399.  
  400. -#ifndef SCIDB_CLIENT
  401. - size_t memUsage = numSegments*sizeof(Segment);
  402. - if (memUsage > scidb::Config::getInstance()->getOption<int>(CONFIG_MEM_ARRAY_THRESHOLD)*MB)
  403. + position_t length() const
  404. {
  405. - //We are stupid! We just made one chunk bitmask that is larger than MEM_ARRAY_THRESHOLD.
  406. - //We should kill ourselves and warn the user of our stupidity!
  407. - throw SYSTEM_EXCEPTION(SCIDB_SE_INTERNAL, SCIDB_LE_ILLEGAL_OPERATION) << "Truncated chunk bitmask constructor error";
  408. + SCIDB_ASSERT(!endSource());
  409. + return _sourceSegment.length;
  410. }
  411. -#endif //if it doesn't happen on the server - it shouldn't happen on the client
  412.  
  413. - reserve(numSegments);
  414. + void skipSource(position_t count)
  415. + {
  416. + SCIDB_ASSERT(!endSource());
  417. + SCIDB_ASSERT(count <= _sourceSegment.length);
  418. + _sourceSegment.lPosition += count;
  419. + _sourceSegment.pPosition += count;
  420. + _sourceSegment.length -= count;
  421. + }
  422.  
  423. - nNonEmptyElements = addRange(0, 0, nElems, 0, chunkSize, origin, first, last);
  424. - nSegs = container.size();
  425. - seg = &container[0];
  426. + void skipResult(position_t count)
  427. + {
  428. + if (_resultSegment.length > 0 && count > 0) {
  429. + _resultBitmap->addSegment(_resultSegment);
  430. + _resultSegment.length = 0;
  431. + }
  432. + }
  433. +
  434. + void flush()
  435. + {
  436. + skipResult(1);
  437. + }
  438. +
  439. + void copy(position_t count)
  440. + {
  441. + SCIDB_ASSERT(!endSource());
  442. + SCIDB_ASSERT(count <= _sourceSegment.length);
  443. + if (_resultSegment.length == 0) {
  444. + _resultSegment.lPosition = _sourceSegment.lPosition;
  445. + _resultSegment.pPosition = _sourceSegment.pPosition;
  446. + }
  447. + _resultSegment.length += count;
  448. + skipSource(count);
  449. + }
  450. +
  451. + void nextSourceSegment()
  452. + {
  453. + SCIDB_ASSERT(!endSource());
  454. + SCIDB_ASSERT(_sourceSegment.length == 0);
  455. + ++_sourceIndex;
  456. + if (!endSource()) {
  457. + Segment const& previous = _sourceSegment;
  458. + Segment const& current = _sourceArray[_sourceIndex];
  459. + SCIDB_ASSERT(previous.lPosition >= current.lPosition);
  460. + SCIDB_ASSERT(previous.pPosition >= current.pPosition);
  461. + }
  462. + }
  463. +
  464. + bool endSource() const
  465. + {
  466. + return _sourceIndex == _sourceCount;
  467. + }
  468. +
  469. + boost::shared_ptr<RLEEmptyBitmap> result() const
  470. + {
  471. + return _resultBitmap;
  472. + }
  473. + };
  474. +
  475. + class CutDimension : boost::noncopyable
  476. + {
  477. + private:
  478. + position_t _prefix;
  479. + position_t _suffix;
  480. + position_t _interval;
  481. + position_t _copy;
  482. + boost::shared_ptr<CutDimension> _nested;
  483. +
  484. + private:
  485. + CutDimension()
  486. + {
  487. + }
  488. +
  489. + position_t init(Coordinates const& lowerOrigin,
  490. + Coordinates const& upperOrigin,
  491. + Coordinates const& lowerResult,
  492. + Coordinates const& upperResult,
  493. + size_t index)
  494. + {
  495. + SCIDB_ASSERT(lowerOrigin[index] <= lowerResult[index]);
  496. + SCIDB_ASSERT(lowerResult[index] <= upperResult[index]);
  497. + SCIDB_ASSERT(upperResult[index] <= upperOrigin[index]);
  498. + _prefix = lowerResult[index] - lowerOrigin[index];
  499. + _suffix = upperOrigin[index] - upperResult[index];
  500. + _interval = upperOrigin[index] + 1 - lowerOrigin[index];
  501. + ++index;
  502. + position_t multiplier = _interval;
  503. + if (index < lowerOrigin.size()) {
  504. + _nested = boost::shared_ptr<CutDimension>(new CutDimension());
  505. + multiplier *= _nested->init(lowerOrigin, lowerResult,
  506. + upperResult, upperOrigin,
  507. + index);
  508. + if (!bool(_nested->_nested) && _prefix == 0 && _suffix == 0) {
  509. + /* nested dimension fully included */
  510. + _nested.reset();
  511. + }
  512. + }
  513. + _copy = _interval - _prefix - _suffix;
  514. + return multiplier;
  515. + }
  516. +
  517. + public:
  518. + CutDimension(Coordinates const& lowerOrigin,
  519. + Coordinates const& upperOrigin,
  520. + Coordinates const& lowerResult,
  521. + Coordinates const& upperResult)
  522. + {
  523. + size_t const n(lowerOrigin.size());
  524. + SCIDB_ASSERT(n > 0);
  525. + SCIDB_ASSERT(n == upperOrigin.size());
  526. + SCIDB_ASSERT(n == lowerResult.size());
  527. + SCIDB_ASSERT(n == upperResult.size());
  528. + init(lowerOrigin, lowerResult, upperResult, upperOrigin, 0);
  529. + }
  530. +
  531. + void cut(CutBuilder& builder) const
  532. + {
  533. + if (builder.length() == 0) {
  534. + return;
  535. + }
  536. +
  537. + position_t resultOffset = builder.logical() % _interval;
  538. + builder.skipResult(resultOffset);
  539. +
  540. + position_t prefixLeft = 0;
  541. + if (resultOffset < _prefix) {
  542. + prefixLeft = min(_prefix - resultOffset, builder.length());
  543. + }
  544. + builder.skipSource(prefixLeft);
  545. + builder.skipResult(prefixLeft);
  546. +
  547. + if (builder.length() == 0) {
  548. + return;
  549. + }
  550. +
  551. +
  552. + if (_nested) {
  553. + position_t left = _copy;
  554. + SCIDB_ASSERT(left > 0);
  555. +
  556. + while(builder.length() > 0 && left > 0) {
  557. + _nested->cut(builder);
  558. + left -= _nested->_interval;
  559. + }
  560. + } else {
  561. + builder.copy(min(_copy, builder.length()));
  562. + }
  563. +
  564. + if (builder.length() == 0) {
  565. + return ;
  566. + }
  567. +
  568. + position_t left = min(_suffix, builder.length());
  569. + builder.skipSource(left);
  570. + builder.skipResult(left);
  571. + }
  572. + };
  573. +
  574. +
  575. + boost::shared_ptr<RLEEmptyBitmap> ConstRLEEmptyBitmap::cut(
  576. + Coordinates const& lowerOrigin,
  577. + Coordinates const& upperOrigin,
  578. + Coordinates const& lowerResult,
  579. + Coordinates const& upperResult) const
  580. + {
  581. + CutBuilder builder(seg, nSegs);
  582. + CutDimension cut(lowerOrigin, upperOrigin, lowerResult, upperResult);
  583. +
  584. + while(!builder.endSource()) {
  585. + cut.cut(builder);
  586. + SCIDB_ASSERT(builder.length() == 0);
  587. + builder.nextSourceSegment();
  588. + }
  589. + builder.flush();
  590. +
  591. + if (true) {
  592. + boost::shared_ptr<RLEEmptyBitmap> result = builder.result();
  593. + std::ofstream f("/tmp/zabivator", std::ios_base::app | std::ios_base::out);
  594. + std::ostringstream ori;
  595. + std::ostringstream res;
  596. + ori << "OR [";
  597. + res << "RE [";
  598. + for (std::size_t i = 0; i < lowerOrigin.size(); ++i) {
  599. + if (i > 0) {
  600. + ori << ";";
  601. + res << ";";
  602. + }
  603. + ori << lowerOrigin[i] << "," << upperOrigin[i];
  604. + res << lowerResult[i] << "," << upperResult[i];
  605. + }
  606. + ori << "] " << nSegs;
  607. + res << "] " << result->nSegs;
  608. + for (size_t i = 0; i < nSegs; ++i) {
  609. + ori << " (logical=" << seg[i].lPosition;
  610. + ori << ", physical=" << seg[i].pPosition;
  611. + ori << ", length=" << seg[i].length;
  612. + ori << ")";
  613. + }
  614. + for (size_t i = 0; i < result->nSegs; ++i) {
  615. + res << "(logical=" << result->seg[i].lPosition;
  616. + res << ", physical=" << result->seg[i].pPosition;
  617. + res << ", length=" << result->seg[i].length;
  618. + res << ")";
  619. + }
  620. + ori << "\n";
  621. + res << "\n";
  622. + f << (ori.str() + res.str() + "\n") << std::flush;
  623. + }
  624. +
  625. + return builder.result();
  626. }
  627. -
  628.  
  629. RLEEmptyBitmap::RLEEmptyBitmap(ValueMap& vm, bool all)
  630. {
  631. diff --git a/src/query/ops/between/BetweenArray.cpp b/src/query/ops/between/BetweenArray.cpp
  632. index b76202c..2470a99 100644
  633. --- a/src/query/ops/between/BetweenArray.cpp
  634. +++ b/src/query/ops/between/BetweenArray.cpp
  635. @@ -147,7 +147,11 @@ namespace scidb
  636. while (i < nDims && coord[i] >= chunk.firstPos[i]) {
  637. if (coord[i] > chunk.lastPos[i]) {
  638. do {
  639. - if (i == 0) {
  640. + if (i == 0) {
  641. + size_t left = emptyBitmap->count() - pos;
  642. + if (left > 0) {
  643. + appender.add(falseVal, left);
  644. + }
  645. goto EndOfTile;
  646. }
  647. i -= 1;
  648. diff --git a/tests/harness/testcases/r/other/NID_basics.expected b/tests/harness/testcases/r/other/NID_basics.expected
  649. index 6347cb7..5059ecb 100644
  650. --- a/tests/harness/testcases/r/other/NID_basics.expected
  651. +++ b/tests/harness/testcases/r/other/NID_basics.expected
  652. @@ -425,7 +425,7 @@ SCIDB QUERY : <bernoulli (filter (Timeseries_Example, Total_Qty > 150 ), 0.85, 1
  653. [Query was executed successfully, ignoring data output by this query.]
  654.  
  655. SCIDB QUERY : <between (filter (Timeseries_Example, Total_Qty > 150 ), 'Foo', 'T_003', 'Wump', 'T_006' )>
  656. -{1,3}[[{1,3}(12.75,250)],[{2,3}(61.75,200)]];[[{2,5}(9.5,250)]];[[{3,3}(7.25,300),{3,4}(6,300)]]
  657. +{1,3}[[{1,3}(12.5,200)],[{2,3}(62.5,200)]];[[{2,5}(61,175)]];[[{3,3}(7.5,200),{3,4}(8,250)]]
  658.  
  659. SCIDB QUERY : <cast ( filter (Timeseries_Example, Total_Qty > 150 ), EMPTY < Avg_Price : double NULL, Total_Qty : int64 NULL > [ TS(string)=*,4,0, Symbol(string)=*,14,0 ])>
  660. {0,1}[[{0,1}(110.5,200)]];[[{0,3}(112.5,200)]];[[{0,5}(111,175)]];[[{0,7}(113,200),{0,8}(112.75,250)]];[[{1,0}(10.25,300)]];[[{1,3}(12.5,200)]];[[{1,7}(13,200),{1,8}(12.75,250)]];[[{2,1}(60.5,200)]];[[{2,3}(62.5,200)]];[[{2,5}(61,175),{2,6}(61.75,200)]];[[{3,1}(9.5,250)]];[[{3,3}(7.5,200),{3,4}(8,250)]];[[{3,8}(7.25,300),{3,9}(6,300)]]
  661. diff --git a/tests/harness/testcases/r/other/UB_basics.expected b/tests/harness/testcases/r/other/UB_basics.expected
  662. index e0580f4..8585d9d 100644
  663. --- a/tests/harness/testcases/r/other/UB_basics.expected
  664. +++ b/tests/harness/testcases/r/other/UB_basics.expected
  665. @@ -425,7 +425,7 @@ SCIDB QUERY : <bernoulli (filter (Timeseries_Example, Total_Qty > 150 ), 0.85, 1
  666. [Query was executed successfully, ignoring data output by this query.]
  667.  
  668. SCIDB QUERY : <between (filter (Timeseries_Example, Total_Qty > 150 ), 'Foo', 'T_003', 'Wump', 'T_006' )>
  669. -{1,3}[[{1,3}(12.75,250)],[{2,3}(61.75,200)]];[[{2,5}(9.5,250)]];[[{3,3}(7.25,300),{3,4}(6,300)]]
  670. +{1,3}[[{1,3}(12.5,200)],[{2,3}(62.5,200)]];[[{2,5}(61,175)]];[[{3,3}(7.5,200),{3,4}(8,250)]]
  671.  
  672. SCIDB QUERY : <cast ( filter (Timeseries_Example, Total_Qty > 150 ), EMPTY < Avg_Price : double NULL, Total_Qty : int64 NULL > [ TS(string)=*,4,0, Symbol(string)=*,14,0 ])>
  673. {0,1}[[{0,1}(110.5,200)]];[[{0,3}(112.5,200)]];[[{0,5}(111,175)]];[[{0,7}(113,200),{0,8}(112.75,250)]];[[{1,0}(10.25,300)]];[[{1,3}(12.5,200)]];[[{1,7}(13,200),{1,8}(12.75,250)]];[[{2,1}(60.5,200)]];[[{2,3}(62.5,200)]];[[{2,5}(61,175),{2,6}(61.75,200)]];[[{3,1}(9.5,250)]];[[{3,3}(7.5,200),{3,4}(8,250)]];[[{3,8}(7.25,300),{3,9}(6,300)]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement