rtlnewkey.cpp 82 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207
  1. /*##############################################################################
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR getValue OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. ############################################################################## */
  12. #include <initializer_list>
  13. #include "jlib.hpp"
  14. #include "jsort.hpp"
  15. #include "jexcept.hpp"
  16. #include "rtlnewkey.hpp"
  17. #include "eclrtl_imp.hpp"
  18. #include "rtlrecord.hpp"
  19. #include "rtlkey.hpp"
  20. //move to jstring as part of HPCC-18547
  21. /*
  22. * Read a single quoted string from in until the terminating quote is found
  23. *
  24. * @param out The resulting string with special quote characters resolved.
  25. * @param in A reference to the start of the string. Updated to point to the end of the string.
  26. */
  27. static void readString(StringBuffer &out, const char * &in)
  28. {
  29. for (;;)
  30. {
  31. char c = *in++;
  32. if (!c)
  33. throw MakeStringException(0, "Invalid filter - missing closing '");
  34. if (c=='\'')
  35. break;
  36. if (c=='\\')
  37. {
  38. c = *in++;
  39. switch (c)
  40. {
  41. case '\'':
  42. case '\\':
  43. break;
  44. default:
  45. UNIMPLEMENTED; // HPCC-18547
  46. }
  47. }
  48. out.append(c);
  49. }
  50. }
  51. /*
  52. * Read a single string from in until a matching terminator is found
  53. *
  54. * @param out The resulting string.
  55. * @param in A reference to the start of the string. Updated to point to the end of the string.
  56. * @param term Characters that can serve as terminators.
  57. */
  58. static void readUntilTerminator(StringBuffer & out, const char * & in, const char * terminators)
  59. {
  60. const char * start = in;
  61. const char * pbrk = strpbrk(start, terminators);
  62. if (!pbrk)
  63. throw makeStringExceptionV(0, "Invalid filter - expected terminator '%s'", terminators);
  64. out.append(pbrk - start, start);
  65. in = pbrk;
  66. }
  67. void deserializeSet(ISetCreator & creator, const char * filter)
  68. {
  69. while (*filter)
  70. {
  71. char startRange = *filter++;
  72. if (startRange != '(' && startRange != '[')
  73. throw MakeStringException(0, "Invalid filter string: expected [ or ( at start of range");
  74. StringBuffer upperString, lowerString;
  75. if (*filter=='\'')
  76. {
  77. filter++;
  78. readString(lowerString, filter);
  79. }
  80. else
  81. readUntilTerminator(lowerString, filter, ",])");
  82. if (*filter == ',')
  83. {
  84. filter++;
  85. if (*filter=='\'')
  86. {
  87. filter++;
  88. readString(upperString, filter);
  89. }
  90. else
  91. readUntilTerminator(upperString, filter, "])");
  92. }
  93. else
  94. upperString.set(lowerString);
  95. char endRange = *filter++;
  96. if (endRange != ')' && endRange != ']')
  97. throw MakeStringException(0, "Invalid filter string: expected ] or ) at end of range");
  98. if (*filter==',')
  99. filter++;
  100. else if (*filter)
  101. throw MakeStringException(0, "Invalid filter string: expected , between ranges");
  102. TransitionMask lowerMask = (startRange == '(') ? CMPgt : CMPge;
  103. TransitionMask upperMask = (endRange == ')') ? CMPlt : CMPle;
  104. creator.addRange(lowerMask, lowerString, upperMask, upperString);
  105. }
  106. }
  107. // A class wrapped for adding ranges to IValueSets
  108. class ValueSetCreator : implements ISetCreator
  109. {
  110. public:
  111. ValueSetCreator(IValueSet & _set) : set(_set) {}
  112. virtual void addRange(TransitionMask lowerMask, const StringBuffer & lowerString, TransitionMask upperMask, const StringBuffer & upperString) override
  113. {
  114. Owned<ValueTransition> lower = lowerString ? set.createUtf8Transition(lowerMask, rtlUtf8Length(lowerString.length(), lowerString), lowerString) : nullptr;
  115. Owned<ValueTransition> upper = upperString ? set.createUtf8Transition(upperMask, rtlUtf8Length(upperString.length(), upperString), upperString) : nullptr;
  116. set.addRange(lower, upper);
  117. }
  118. protected:
  119. IValueSet & set;
  120. };
  121. void deserializeSet(IValueSet & set, const char * filter)
  122. {
  123. ValueSetCreator creator(set);
  124. deserializeSet(creator, filter);
  125. }
  126. //---------------------------------------------------------------------------------------------------------------------
  127. /*
  128. * This class represents a value and a comparison condition and is used for representing ranges of values
  129. *
  130. * A lowerbound will always have the CMPgt bit set in the mask, and upper bound will have CMPlt set in the mask.
  131. * The value is always represented in the same way as a field of that type would be in a record.
  132. */
  133. class ValueTransition : implements CInterface
  134. {
  135. public:
  136. ValueTransition(TransitionMask _mask, const RtlTypeInfo & type, const void *_value)
  137. {
  138. mask = _mask;
  139. dbgassertex(_value || isMinimum() || isMaximum());
  140. if (_value)
  141. {
  142. size32_t size = type.size((const byte *)_value, nullptr);
  143. value.allocateN(size, false);
  144. memcpy(value, _value, size);
  145. }
  146. }
  147. ValueTransition(TransitionMask _mask) : mask(_mask)
  148. {
  149. dbgassertex(isMaximum() || isMinimum());
  150. }
  151. MemoryBuffer &serialize(const RtlTypeInfo & type, MemoryBuffer &mb) const
  152. {
  153. mb.append((byte)mask);
  154. size32_t size = type.size(value, nullptr);
  155. memcpy(mb.reserve(size), value, size);
  156. return mb;
  157. }
  158. int compareRaw(const RtlTypeInfo & type, const byte * field) const
  159. {
  160. if (!value)
  161. {
  162. if (mask & CMPmin)
  163. return +1;
  164. if (mask & CMPmax)
  165. return -1;
  166. }
  167. return type.compare(field, value.get());
  168. }
  169. int compare(const RtlTypeInfo & type, const byte * field) const
  170. {
  171. int c = compareRaw(type, field);
  172. if (c == 0)
  173. {
  174. if (mask & CMPeq)
  175. return 0;
  176. //Lower bound
  177. if (mask & CMPgt)
  178. return -1;
  179. //Check against upper bound
  180. if (mask & CMPlt)
  181. return +1;
  182. throwUnexpected();
  183. }
  184. return c;
  185. }
  186. int compareRaw(const RtlTypeInfo & type, const ValueTransition & other) const
  187. {
  188. if (!value || !other.value)
  189. {
  190. if (isMinimum())
  191. return other.isMinimum() ? 0 : -1;
  192. if (isMaximum())
  193. return other.isMaximum() ? 0 : +1;
  194. if (other.isMinimum())
  195. return +1;
  196. if (other.isMaximum())
  197. return -1;
  198. throwUnexpected();
  199. }
  200. return type.compare(value, other.value);
  201. }
  202. StringBuffer & describe(const RtlTypeInfo & type, StringBuffer & out) const
  203. {
  204. if (mask & CMPgt)
  205. {
  206. if (mask & CMPeq)
  207. out.append("[");
  208. else
  209. out.append("(");
  210. }
  211. if (value)
  212. {
  213. size32_t len;
  214. rtlDataAttr text;
  215. type.getUtf8(len, text.refstr(), value);
  216. size32_t size = rtlUtf8Size(len, text.getstr());
  217. if (type.isNumeric())
  218. {
  219. out.append(size, text.getstr());
  220. }
  221. else
  222. {
  223. out.append("'");
  224. appendUtf8AsECL(out, size, text.getstr());
  225. out.append("'");
  226. }
  227. }
  228. if (mask & CMPlt)
  229. {
  230. if (mask & CMPeq)
  231. out.append("]");
  232. else
  233. out.append(")");
  234. }
  235. return out;
  236. }
  237. bool isPreviousBound(const RtlTypeInfo & type, const ValueTransition & other) const
  238. {
  239. if (isInclusiveBound() || other.isInclusiveBound())
  240. {
  241. if (compareRaw(type, other) == 0)
  242. return true;
  243. }
  244. if (isInclusiveBound() && other.isInclusiveBound())
  245. {
  246. //MORE: if isPreviousValue(other)
  247. //if (oneless(hival, t.getValue()))
  248. }
  249. return false;
  250. }
  251. //If this transition isn't shared then modify it directly, otherwise clone. Always return a linked object.
  252. ValueTransition * modifyTransition(const RtlTypeInfo & type, TransitionMask newMask)
  253. {
  254. assertex(value);
  255. if (IsShared())
  256. {
  257. return new ValueTransition(newMask, type, value);
  258. }
  259. else
  260. {
  261. mask = newMask;
  262. return LINK(this);
  263. }
  264. }
  265. ValueTransition * modifyInverse(const RtlTypeInfo & type)
  266. {
  267. TransitionMask newMask = (TransitionMask)(mask ^ (CMPgt|CMPlt|CMPeq));
  268. return modifyTransition(type, newMask);
  269. }
  270. bool isLowerBound() const { return (mask & CMPgt) != 0; }
  271. bool isUpperBound() const { return (mask & CMPlt) != 0; }
  272. bool isInclusiveBound() const { return (mask & CMPeq) != 0; }
  273. bool isMinimum() const { return (mask & CMPmin) != 0; }
  274. bool isMaximum() const { return (mask & CMPmax) != 0; }
  275. private:
  276. TransitionMask mask;
  277. OwnedMalloc<byte> value;
  278. };
  279. typedef CIArrayOf<ValueTransition> ValueTransitionArray;
  280. //---------------------------------------------------------------------------------------------------------------------
  281. /*
  282. * The ValueSet class represents a set of ranges of values.
  283. *
  284. * The transitions always come in pairs - an upper and lower bound. Each bound can be inclusive or exclusive.
  285. */
  286. class ValueSet : public CInterfaceOf<IValueSet>
  287. {
  288. public:
  289. ValueSet(const RtlTypeInfo & _type) : type(_type)
  290. {
  291. }
  292. // Methods for creating a value set
  293. virtual ValueTransition * createTransition(TransitionMask mask, unsigned __int64 value) const override
  294. {
  295. MemoryBuffer buff;
  296. MemoryBufferBuilder builder(buff, 0);
  297. type.buildInt(builder, 0, nullptr, value);
  298. return new ValueTransition(mask, type, buff.toByteArray());
  299. }
  300. virtual ValueTransition * createStringTransition(TransitionMask mask, size32_t len, const char * value) const override
  301. {
  302. MemoryBuffer buff;
  303. MemoryBufferBuilder builder(buff, 0);
  304. type.buildString(builder, 0, nullptr, len, value);
  305. return new ValueTransition(mask, type, buff.toByteArray());
  306. }
  307. virtual ValueTransition * createUtf8Transition(TransitionMask mask, size32_t len, const char * value) const override
  308. {
  309. MemoryBuffer buff;
  310. MemoryBufferBuilder builder(buff, 0);
  311. type.buildUtf8(builder, 0, nullptr, len, value);
  312. return new ValueTransition(mask, type, buff.toByteArray());
  313. }
  314. virtual void addRange(ValueTransition * lower, ValueTransition * upper) override
  315. {
  316. Owned<ValueTransition> minBound;
  317. Owned<ValueTransition> maxBound;
  318. if (!lower)
  319. {
  320. minBound.setown(new ValueTransition(CMPminmask));
  321. lower = minBound;
  322. }
  323. if (!upper)
  324. {
  325. maxBound.setown(new ValueTransition(CMPmaxmask));
  326. upper = maxBound;
  327. }
  328. if (!lower->isLowerBound() || !upper->isUpperBound())
  329. throw MakeStringException(1, "Invalid range bounds");
  330. //If lower > upper then it is an empty range
  331. int rc = lower->compareRaw(type, *upper);
  332. if (rc > 0)
  333. return;
  334. //Check for exclusive ranges for a single value
  335. if (rc == 0)
  336. {
  337. if (!lower->isInclusiveBound() || !upper->isInclusiveBound())
  338. return;
  339. }
  340. // binchop to find last transition > val...
  341. unsigned int low = 0;
  342. unsigned high = transitions.ordinality();
  343. while (low < high)
  344. {
  345. unsigned mid = low + (high - low) / 2;
  346. int rc = lower->compareRaw(type, transitions.item(mid));
  347. if (rc <= 0)
  348. high = mid;
  349. else
  350. low = mid+1;
  351. }
  352. unsigned idx;
  353. if (transitions.isItem(low))
  354. {
  355. ValueTransition & next = transitions.item(low);
  356. if (lower->compareRaw(type, next) == 0)
  357. {
  358. if (next.isLowerBound())
  359. {
  360. if (!next.isInclusiveBound() && lower->isInclusiveBound())
  361. transitions.replace(*LINK(lower), low);
  362. idx = low+1;
  363. }
  364. else
  365. {
  366. if (next.isInclusiveBound() || lower->isInclusiveBound())
  367. {
  368. transitions.remove(low);
  369. idx = low;
  370. }
  371. else
  372. {
  373. transitions.add(*LINK(lower), low+1);
  374. idx = low + 2;
  375. }
  376. }
  377. }
  378. else
  379. {
  380. if (next.isLowerBound())
  381. {
  382. transitions.add(*LINK(lower), low);
  383. idx = low + 1;
  384. }
  385. else
  386. {
  387. //previous must exist and be lower => ignore this one
  388. idx = low;
  389. }
  390. }
  391. }
  392. else
  393. {
  394. transitions.append(*LINK(lower));
  395. transitions.append(*LINK(upper));
  396. return;
  397. }
  398. //Walk the remaining transitions until you find one that is higher than the current one (or run out)
  399. while (transitions.isItem(idx))
  400. {
  401. ValueTransition & cur = transitions.item(idx);
  402. int rc = cur.compareRaw(type, *upper);
  403. if (rc > 0)
  404. {
  405. if (cur.isUpperBound())
  406. return;
  407. break;
  408. }
  409. if (rc == 0)
  410. {
  411. if (cur.isUpperBound())
  412. {
  413. if (!cur.isInclusiveBound() && upper->isInclusiveBound())
  414. transitions.replace(*LINK(upper), idx);
  415. return;
  416. }
  417. //Upper value matches the next lower bound - could either remove the next item if either is inclusive, otherwise add
  418. if (cur.isInclusiveBound() || upper->isInclusiveBound())
  419. {
  420. transitions.remove(idx);
  421. return;
  422. }
  423. break;
  424. }
  425. transitions.remove(idx);
  426. }
  427. if (transitions.isItem(idx))
  428. {
  429. ValueTransition & cur = transitions.item(idx);
  430. assertex(cur.isLowerBound());
  431. if (upper->isPreviousBound(type, cur))
  432. {
  433. transitions.remove(idx);
  434. return;
  435. }
  436. }
  437. transitions.add(*LINK(upper), idx);
  438. }
  439. virtual void addAll() override
  440. {
  441. reset();
  442. addRange(nullptr, nullptr);
  443. }
  444. virtual void killRange(ValueTransition * lower, ValueTransition * upper) override
  445. {
  446. Owned<ValueTransition> minBound;
  447. Owned<ValueTransition> maxBound;
  448. if (!lower)
  449. {
  450. minBound.setown(new ValueTransition(CMPminmask));
  451. lower = minBound;
  452. }
  453. if (!upper)
  454. {
  455. maxBound.setown(new ValueTransition(CMPmaxmask));
  456. upper = maxBound;
  457. }
  458. if (!lower->isLowerBound() || !upper->isUpperBound())
  459. throw MakeStringException(1, "Invalid range bounds");
  460. //If lower > upper then it is an empty range
  461. int rc = lower->compareRaw(type, *upper);
  462. if (rc > 0)
  463. return;
  464. //Check for exclusive ranges for a single value
  465. if (rc == 0)
  466. {
  467. if (!lower->isInclusiveBound() || !upper->isInclusiveBound())
  468. return;
  469. }
  470. // binchop to find last transition > val...
  471. unsigned int low = 0;
  472. unsigned high = transitions.ordinality();
  473. while (low < high)
  474. {
  475. unsigned mid = low + (high - low) / 2;
  476. int rc = lower->compareRaw(type, transitions.item(mid));
  477. if (rc <= 0)
  478. high = mid;
  479. else
  480. low = mid+1;
  481. }
  482. unsigned idx = low;
  483. if (!transitions.isItem(low))
  484. return;
  485. //First terminate any set that overlaps the start of the range
  486. ValueTransition & next = transitions.item(low);
  487. if (lower->compareRaw(type, next) == 0)
  488. {
  489. if (next.isLowerBound())
  490. {
  491. // Range [x..y] remove [x..]
  492. if (!lower->isInclusiveBound() && next.isInclusiveBound())
  493. {
  494. //[x,y] - (x,z) = [x],{ (x,y)-(x,z)
  495. transitions.add(*lower->modifyTransition(type, CMPle), low+1);
  496. idx = low+2;
  497. }
  498. else
  499. transitions.remove(low);
  500. }
  501. else
  502. {
  503. //[x..y]-[y..z) -> [x..y)
  504. if (lower->isInclusiveBound() && next.isInclusiveBound())
  505. {
  506. //Convert to an exclusive bound. This must be different from the lower bound
  507. //(otherwise it would have matched that bound 1st)
  508. ValueTransition * newTransition = next.modifyTransition(type, CMPlt);
  509. transitions.replace(*newTransition, low);
  510. idx = low+1;
  511. }
  512. else
  513. idx = low+1;
  514. }
  515. }
  516. else
  517. {
  518. if (next.isUpperBound())
  519. {
  520. transitions.add(*lower->modifyTransition(type, lower->isInclusiveBound() ? CMPlt : CMPle), idx);
  521. idx++;
  522. }
  523. }
  524. //Walk the remaining transitions until you find one that is higher than the current one (or run out)
  525. while (transitions.isItem(idx))
  526. {
  527. ValueTransition & cur = transitions.item(idx);
  528. int rc = cur.compareRaw(type, *upper);
  529. if (rc > 0)
  530. {
  531. if (cur.isUpperBound())
  532. transitions.add(*upper->modifyTransition(type, upper->isInclusiveBound() ? CMPgt : CMPge), idx);
  533. return;
  534. }
  535. if (rc == 0)
  536. {
  537. if (cur.isUpperBound())
  538. {
  539. //[x..y] remove [y..y)
  540. if (cur.isInclusiveBound() && !upper->isInclusiveBound())
  541. transitions.add(*upper->modifyTransition(type, CMPge), idx);
  542. else
  543. transitions.remove(idx);
  544. return;
  545. }
  546. else
  547. {
  548. if (!upper->isInclusiveBound())
  549. return;
  550. }
  551. }
  552. transitions.remove(idx);
  553. }
  554. }
  555. virtual void reset() override
  556. {
  557. transitions.kill();
  558. }
  559. virtual void invertSet() override
  560. {
  561. if (transitions.empty())
  562. {
  563. addAll();
  564. return;
  565. }
  566. unsigned idx = 0;
  567. ValueTransitionArray newTransitions;
  568. if (!transitions.item(0).isMinimum())
  569. newTransitions.append(*new ValueTransition(CMPminmask));
  570. else
  571. idx++;
  572. bool unboundedUpper = transitions.tos().isMaximum();
  573. unsigned max = transitions.ordinality();
  574. if (unboundedUpper)
  575. max--;
  576. for (; idx < max; idx ++)
  577. newTransitions.append(*transitions.item(idx).modifyInverse(type));
  578. if (!unboundedUpper)
  579. newTransitions.append(*new ValueTransition(CMPmaxmask));
  580. transitions.swapWith(newTransitions);
  581. }
  582. virtual void unionSet(const IValueSet * _other) override
  583. {
  584. //Iterate through the ranges in other and add them to this set
  585. const ValueSet * other = static_cast<const ValueSet *>(_other);
  586. for (unsigned i=0; i < other->transitions.ordinality(); i+=2)
  587. addRange(&other->transitions.item(i), &other->transitions.item(i+1));
  588. }
  589. virtual void excludeSet(const IValueSet * _other) override
  590. {
  591. //Iterate through the ranges in other and add them to this set
  592. const ValueSet * other = static_cast<const ValueSet *>(_other);
  593. for (unsigned i=0; i < other->transitions.ordinality(); i+=2)
  594. killRange(&other->transitions.item(i), &other->transitions.item(i+1));
  595. }
  596. virtual void intersectSet(IValueSet const * _other) override
  597. {
  598. const ValueSet * other = static_cast<const ValueSet *>(_other);
  599. //Iterate through the ranges in other and remove them from this set
  600. unsigned curOther = 0;
  601. unsigned otherMax = other->numTransitions();
  602. ValueTransitionArray newTransitions;
  603. for (unsigned i = 0; i < numTransitions(); i+=2)
  604. {
  605. ValueTransition & lower = transitions.item(i);
  606. ValueTransition & upper = transitions.item(i+1);
  607. for (;;)
  608. {
  609. if (curOther == otherMax)
  610. goto done; // break out of both loops.
  611. ValueTransition & otherLower = other->transitions.item(curOther);
  612. ValueTransition & otherUpper = other->transitions.item(curOther+1);
  613. //If upper is lower than the other lower bound then no rows overlap, skip this range
  614. int rc1 = upper.compareRaw(type, otherLower);
  615. if (rc1 < 0 ||
  616. ((rc1 == 0) && (!upper.isInclusiveBound() || !otherLower.isInclusiveBound())))
  617. break;
  618. //If other upper is lower than the lower bound then no rows overlap, skip other range
  619. int rc2 = otherUpper.compareRaw(type, lower);
  620. if (rc2 < 0 ||
  621. ((rc2 == 0) && (!otherUpper.isInclusiveBound() || !lower.isInclusiveBound())))
  622. {
  623. curOther += 2;
  624. continue;
  625. }
  626. //Lower bound of the intersection is the higher of the two lower bounds
  627. int rc3 = lower.compareRaw(type, otherLower);
  628. if (rc3 < 0 || ((rc3 == 0) && lower.isInclusiveBound()))
  629. newTransitions.append(OLINK(otherLower));
  630. else
  631. newTransitions.append(OLINK(lower));
  632. //Upper bound of the intersection is the lower of the two bounds - and move onto next range that is consumed
  633. int rc4 = upper.compareRaw(type, otherUpper);
  634. if (rc4 < 0 || ((rc4 == 0) && !upper.isInclusiveBound()))
  635. {
  636. newTransitions.append(OLINK(upper));
  637. break;
  638. }
  639. else
  640. {
  641. newTransitions.append(OLINK(otherUpper));
  642. curOther += 2;
  643. }
  644. }
  645. }
  646. done:
  647. transitions.swapWith(newTransitions);
  648. }
  649. virtual ValueTransition * createRawTransition(TransitionMask mask, const void * value) const override
  650. {
  651. return new ValueTransition(mask, type, value);
  652. }
  653. virtual void addRawRange(const void * lower, const void * upper) override
  654. {
  655. Owned<ValueTransition> lowerBound = lower ? createRawTransition(CMPge, lower) : nullptr;
  656. Owned<ValueTransition> upperBound = upper ? createRawTransition(CMPle, upper) : nullptr;
  657. addRange(lowerBound, upperBound);
  658. }
  659. virtual void killRawRange(const void * lower, const void * upper) override
  660. {
  661. Owned<ValueTransition> lowerBound = lower ? createRawTransition(CMPge, lower) : nullptr;
  662. Owned<ValueTransition> upperBound = upper ? createRawTransition(CMPle, upper) : nullptr;
  663. killRange(lowerBound, upperBound);
  664. }
  665. // Methods for using a value set
  666. virtual unsigned numRanges() const override;
  667. //find the last range where the lower bound <= the field, returns 0 if the field matches the lower bound, > 0 otherwise.
  668. //matchRange is set to the range number, set to numRanges if there is no possible match. Uses a binary chop
  669. virtual int findCandidateRange(const byte * field, unsigned & matchRange) const override;
  670. //find the last range where the lower bound <= the field, returns 0 if the field matches the lower bound, > 0 otherwise.
  671. //starts searching from curRange (which is likely to match). Uses a sequential search.
  672. virtual int checkCandidateRange(const byte * field, unsigned & curRange) const override;
  673. // Does this field match any range?
  674. virtual bool matches(const byte * field) const override;
  675. // Does this field match this particular range?
  676. virtual bool matches(const byte * field, unsigned range) const override;
  677. virtual StringBuffer & serialize(StringBuffer & out) const override
  678. {
  679. //Does this need to include the type information?
  680. return describe(out);
  681. }
  682. virtual const RtlTypeInfo & queryType() const override
  683. {
  684. return type;
  685. }
  686. protected:
  687. inline int compareRaw(const byte * field, ValueTransition * transition) const __attribute__((always_inline))
  688. {
  689. return transition->compareRaw(type, field);
  690. }
  691. inline int compare(const byte * field, ValueTransition * transition) const __attribute__((always_inline))
  692. {
  693. return transition->compare(type, field);
  694. }
  695. ValueTransition * queryTransition(unsigned i) const { return &transitions.item(i); }
  696. unsigned numTransitions() const { return transitions.ordinality(); }
  697. StringBuffer & describe(StringBuffer & out) const
  698. {
  699. for (unsigned i = 0; i < transitions.ordinality(); i += 2)
  700. {
  701. if (i != 0)
  702. out.append(",");
  703. ValueTransition & lower = transitions.item(i);
  704. ValueTransition & upper = transitions.item(i+1);
  705. lower.describe(type, out);
  706. if (lower.compareRaw(type, upper) != 0)
  707. {
  708. out.append(",");
  709. upper.describe(type, out);
  710. }
  711. else
  712. out.append("]");
  713. }
  714. return out;
  715. }
  716. bool hasLowerBound() const
  717. {
  718. if (transitions.empty())
  719. return false;
  720. return transitions.item(0).isMinimum();
  721. }
  722. bool hasUpperBound() const
  723. {
  724. if (transitions.empty())
  725. return false;
  726. return transitions.tos().isMaximum();
  727. }
  728. protected:
  729. const RtlTypeInfo & type;
  730. ValueTransitionArray transitions;
  731. };
  732. unsigned ValueSet::numRanges() const
  733. {
  734. return transitions.ordinality() / 2;
  735. }
  736. bool ValueSet::matches(const byte * field) const
  737. {
  738. //NOTE: It is guaranteed that transitions with the same value are merged if possible - which allows the loop to terminate early on equality.
  739. unsigned high = numRanges();
  740. unsigned low = 0;
  741. while (low < high)
  742. {
  743. unsigned mid = low + (high-low)/2;
  744. unsigned lower = mid * 2;
  745. //Using compareRaw allows early termination for equalities that actually fail to match.
  746. int rc = compareRaw(field, queryTransition(lower));
  747. if (rc < 0)
  748. {
  749. high = mid;
  750. }
  751. else if (rc == 0)
  752. {
  753. if (queryTransition(lower)->isInclusiveBound())
  754. return true;
  755. else
  756. return false;
  757. }
  758. else
  759. {
  760. unsigned upper = lower + 1;
  761. rc = compareRaw(field, queryTransition(upper));
  762. if (rc < 0)
  763. return true;
  764. if (rc == 0)
  765. {
  766. if (queryTransition(upper)->isInclusiveBound())
  767. return true;
  768. else
  769. return false;
  770. }
  771. low = mid+1;
  772. }
  773. }
  774. return false;
  775. }
  776. bool ValueSet::matches(const byte * field, unsigned range) const
  777. {
  778. if (range >= numRanges())
  779. return false;
  780. unsigned lower = range * 2;
  781. int rc = compare(field, queryTransition(lower));
  782. if (rc < 0)
  783. return false;
  784. if (rc == 0)
  785. return true;
  786. unsigned upper = lower + 1;
  787. rc = compare(field, queryTransition(upper));
  788. return (rc <= 0);
  789. }
  790. //find the last range where the lower bound <= the field, returns 0 if the field matches the lower bound, > 0 otherwise.
  791. //matchRange is set to the range number, set to numRanges if there is no possible match. Uses a binary chop
  792. int ValueSet::findCandidateRange(const byte * field, unsigned & matchRange) const
  793. {
  794. //NOTE: It is guaranteed that transitions are merged if possible - which allows the loop to terminate early.
  795. unsigned high = numRanges();
  796. unsigned low = 0;
  797. int rc = 0;
  798. while (low < high)
  799. {
  800. unsigned mid = low + (high - low) / 2;
  801. unsigned lower = mid * 2;
  802. rc = compare(field, queryTransition(lower));
  803. if (rc <= 0)
  804. high = mid;
  805. else
  806. low = mid + 1;
  807. }
  808. matchRange = low;
  809. return rc;
  810. }
  811. //find the last range where the lower bound <= the field, returns 0 if the field matches the lower bound, > 0 otherwise.
  812. //starts searching from curRange (which is likely to match). Uses a sequential search.
  813. int ValueSet::checkCandidateRange(const byte * field, unsigned & curRange) const
  814. {
  815. unsigned cur = curRange;
  816. while (cur < numRanges())
  817. {
  818. unsigned lower = cur * 2;
  819. int rc = compare(field, queryTransition(lower));
  820. if (rc >= 0)
  821. {
  822. curRange = cur;
  823. return rc;
  824. }
  825. cur++;
  826. }
  827. curRange = numRanges();
  828. return 0;
  829. }
  830. IValueSet * createValueSet(const RtlTypeInfo & _type) { return new ValueSet(_type); }
  831. //---------------------------------------------------------------------------------------------------------------------
  832. /*
  833. * Base implementation class for field filters.
  834. */
  835. class FieldFilter : public CInterfaceOf<IFieldFilter>
  836. {
  837. public:
  838. FieldFilter(unsigned _field, const RtlTypeInfo & _type) : field(_field), type(_type) {}
  839. //More complex index matching
  840. virtual int compareRow(const RtlRow & left, const RtlRow & right) const override
  841. {
  842. return type.compare(left.queryField(field), right.queryField(field));
  843. }
  844. protected:
  845. unsigned field;
  846. const RtlTypeInfo & type;
  847. };
  848. /*
  849. * A field filter that can match a set of values.
  850. */
  851. class SetFieldFilter : public FieldFilter
  852. {
  853. public:
  854. SetFieldFilter(unsigned _field, IValueSet * _values) : FieldFilter(_field, _values->queryType()), values(_values) {}
  855. //Simple row matching
  856. virtual bool matches(const RtlRow & row) const override;
  857. //More complex index matching
  858. virtual unsigned numRanges() const override;
  859. virtual int findCandidateRange(const RtlRow & row, unsigned & matchRange) const override;
  860. virtual int checkCandidateRange(const RtlRow & row, unsigned & curRange) const override;
  861. virtual bool withinUpperRange(const RtlRow & row, unsigned range) const override; // is the row within the current upper limit?
  862. virtual bool matches(const RtlRow & row, unsigned range) const override;
  863. protected:
  864. Linked<IValueSet> values;
  865. };
  866. bool SetFieldFilter::matches(const RtlRow & row) const
  867. {
  868. return values->matches(row.queryField(field));
  869. }
  870. unsigned SetFieldFilter::numRanges() const
  871. {
  872. return values->numRanges();
  873. }
  874. int SetFieldFilter::findCandidateRange(const RtlRow & row, unsigned & matchRange) const
  875. {
  876. UNIMPLEMENTED;
  877. return 0;
  878. }
  879. int SetFieldFilter::checkCandidateRange(const RtlRow & row, unsigned & curRange) const
  880. {
  881. UNIMPLEMENTED;
  882. return 0;
  883. }
  884. bool SetFieldFilter::withinUpperRange(const RtlRow & row, unsigned range) const
  885. {
  886. UNIMPLEMENTED;
  887. return false;
  888. }
  889. bool SetFieldFilter::matches(const RtlRow & row, unsigned range) const
  890. {
  891. UNIMPLEMENTED;
  892. return 0;
  893. }
  894. IFieldFilter * createFieldFilter(unsigned fieldId, IValueSet * values)
  895. {
  896. return new SetFieldFilter(fieldId, values);
  897. }
  898. IFieldFilter * createEmptyFieldFilter(unsigned fieldId, const RtlTypeInfo & type)
  899. {
  900. Owned<IValueSet> values = createValueSet(type);
  901. return new SetFieldFilter(fieldId, values);
  902. }
  903. IFieldFilter * createFieldFilter(unsigned fieldId, const RtlTypeInfo & type, const void * value)
  904. {
  905. Owned<IValueSet> values = createValueSet(type);
  906. values->addRawRange(value, value);
  907. return new SetFieldFilter(fieldId, values);
  908. }
  909. //---------------------------------------------------------------------------------------------------------------------
  910. /*
  911. * A field filter that can match any value.
  912. */
  913. class WildFieldFilter : public FieldFilter
  914. {
  915. public:
  916. WildFieldFilter(unsigned _field, const RtlTypeInfo & _type) : FieldFilter(_field, _type) {}
  917. //Simple row matching
  918. virtual bool matches(const RtlRow & row) const override
  919. {
  920. return true;
  921. }
  922. //More complex index matching
  923. virtual unsigned numRanges() const override
  924. {
  925. return 0;
  926. }
  927. virtual int findCandidateRange(const RtlRow & row, unsigned & matchRange) const override
  928. {
  929. matchRange = 0;
  930. return 0;
  931. }
  932. virtual int checkCandidateRange(const RtlRow & row, unsigned & curRange) const override
  933. {
  934. curRange = 0;
  935. return 0;
  936. }
  937. virtual bool withinUpperRange(const RtlRow & row, unsigned range) const override
  938. {
  939. return true;
  940. }
  941. virtual bool matches(const RtlRow & row, unsigned range) const override
  942. {
  943. return true;
  944. }
  945. };
  946. extern ECLRTL_API IFieldFilter * createWildFieldFilter(unsigned fieldId);
  947. //---------------------------------------------------------------------------------------------------------------------
  948. void RowFilter::addFilter(IFieldFilter & filter)
  949. {
  950. //assertex(filter.queryField() == filters.ordinality()); //MORE - fill with wild filters and replace existing wild
  951. filters.append(filter);
  952. }
  953. bool RowFilter::matches(const RtlRow & row) const
  954. {
  955. ForEachItemIn(i, filters)
  956. {
  957. if (!filters.item(i).matches(row))
  958. return false;
  959. }
  960. return true;
  961. }
  962. int RowFilter::compareRows(const RtlRow & left, const RtlRow & right) const
  963. {
  964. ForEachItemIn(i, filters)
  965. {
  966. int rc = filters.item(i).compareRow(left, right);
  967. if (rc != 0)
  968. return rc;
  969. }
  970. return 0;
  971. }
  972. //---------------------------------------------------------------------------------------------------------------------
  973. class RowCursor;
  974. class IRowCursor
  975. {
  976. public:
  977. //Find the first row that is >= the search cursor
  978. virtual const byte * findFirst(RowCursor & search) = 0;
  979. //Find the first row that is larger than search within the first numSeekFields
  980. virtual const byte * findGT(const RtlRow & search, unsigned numSeekFields) = 0;
  981. //select the next row
  982. virtual const byte * next() = 0;
  983. };
  984. //This class represents the current set of values which have been matched in the filter sets.
  985. class RowCursor
  986. {
  987. public:
  988. RowCursor(RowFilter & _filter) : filter(_filter) {}
  989. void selectFirst()
  990. {
  991. numMatched = 0;
  992. }
  993. //Compare the incoming row against the search
  994. int compareGE(const RtlRow & row)
  995. {
  996. unsigned i;
  997. for (i = 0; i < numMatched; i++)
  998. {
  999. //Use sequential searches for the values that have previously been matched
  1000. int c = queryFilter(i).checkCandidateRange(row, matchPos(i));
  1001. if (c != 0)
  1002. {
  1003. numMatched = i + 1;
  1004. return c;
  1005. }
  1006. }
  1007. for (; i < numFilterFields(); i++)
  1008. {
  1009. int c = queryFilter(i).findCandidateRange(row, matchPos(i));
  1010. if (c != 0)
  1011. {
  1012. numMatched = i + 1;
  1013. return c;
  1014. }
  1015. }
  1016. numMatched = i;
  1017. return 0;
  1018. }
  1019. int compareRows(const RtlRow & left, const RtlRow & right) const
  1020. {
  1021. return filter.compareRows(left, right);
  1022. }
  1023. bool matchesCurrent(const RtlRow & row)
  1024. {
  1025. unsigned i;
  1026. for (i = 0; i < numMatched; i++)
  1027. {
  1028. if (!queryFilter(i).withinUpperRange(row, matchPos(i)))
  1029. {
  1030. //save away failure info
  1031. return false;
  1032. }
  1033. }
  1034. //Not sure which
  1035. for (; i < numFilterFields(); i++)
  1036. {
  1037. int c = queryFilter(i).findCandidateRange(row, matchPos(i));
  1038. if (!isValid(i))
  1039. {
  1040. numMatched = i + 1;
  1041. //Restart searching element i-1.
  1042. return false;
  1043. }
  1044. if (!queryFilter(i).matches(row, matchPos(i)))
  1045. {
  1046. numMatched = i + 1;
  1047. return false;
  1048. }
  1049. }
  1050. return true;
  1051. }
  1052. //One of the filters in the range 0..numMatches failed.
  1053. //Walk the fields in turn checking if they still match. The first that doesn't needs to be advanced if possible.
  1054. //If that field cannot be advanced then we need to search for the next row that is > the current leading fields.
  1055. //If there is Need to advance the filter to the next possibility
  1056. //The filter doesn't match => find the next set of potential matches.
  1057. unsigned nextCandidate(const RtlRow & row)
  1058. {
  1059. for (unsigned i = 0; i < numMatched; i++)
  1060. {
  1061. const IFieldFilter & cur = queryFilter(i);
  1062. if (!cur.withinUpperRange(row, matchPos(i)))
  1063. {
  1064. //Find the range that could include the row
  1065. cur.checkCandidateRange(row, matchPos(i));
  1066. if (isValid(i))
  1067. return 0;
  1068. if (i == 0)
  1069. return UINT_MAX;
  1070. //caller needs to find a new row that is larger that the current values for fields 0..i
  1071. //Now need to search for a value if
  1072. //Search for a new candidate value from this filter
  1073. return i+1;
  1074. }
  1075. }
  1076. throwUnexpected();
  1077. return false;
  1078. }
  1079. unsigned numFilterFields() const { return filter.numFilterFields(); }
  1080. protected:
  1081. unsigned & matchPos(unsigned i) { return matchPositions.element(i); }
  1082. unsigned matchPos(unsigned i) const { return matchPositions.item(i); }
  1083. bool isValid(unsigned i) const { return matchPos(i) < queryFilter(i).numRanges(); }
  1084. const IFieldFilter & queryFilter(unsigned i) const { return filter.queryFilter(i); }
  1085. protected:
  1086. UnsignedArray matchPositions;
  1087. unsigned numMatched = 0;
  1088. RowFilter & filter;
  1089. };
  1090. //---------------------------------------------------------------------------------------------
  1091. class KeySearcher
  1092. {
  1093. public:
  1094. KeySearcher(const RtlRecord & _info, RowFilter & _filter) : curRow(_info, nullptr), cursor(_filter)
  1095. {
  1096. }
  1097. bool first()
  1098. {
  1099. cursor.selectFirst();
  1100. return resolveValidRow(0);
  1101. }
  1102. bool next()
  1103. {
  1104. setCurrent(rows->next());
  1105. if (!curRow)
  1106. return false;
  1107. if (cursor.matchesCurrent(curRow))
  1108. return true;
  1109. //MORE: Check if the row is valid for the next transition
  1110. unsigned numSeekFields = cursor.nextCandidate(curRow);
  1111. return resolveValidRow(numSeekFields);
  1112. }
  1113. bool resolveValidRow(unsigned numSeekFields)
  1114. {
  1115. for (;;)
  1116. {
  1117. //No more possible candidates
  1118. if (numSeekFields == UINT_MAX)
  1119. return false;
  1120. if (numSeekFields != 0)
  1121. {
  1122. //Find the first row where the first numSeekFields are larger than the current values.
  1123. setCurrent(rows->findGT(curRow, numSeekFields)); // more - return the row pointer to avoid recalculation
  1124. }
  1125. else
  1126. setCurrent(rows->findFirst(cursor));
  1127. if (!curRow)
  1128. return false;
  1129. if (cursor.matchesCurrent(curRow))
  1130. return true;
  1131. numSeekFields = cursor.nextCandidate(curRow);
  1132. }
  1133. }
  1134. protected:
  1135. void setCurrent(const byte * row) { curRow.setRow(row, cursor.numFilterFields()); }
  1136. protected:
  1137. IRowCursor * rows = nullptr;
  1138. RtlDynRow curRow;
  1139. RowCursor cursor;
  1140. };
  1141. //Always has an even number of transitions
  1142. //Null transitions can be used at the start and end of the ranges to map anything
  1143. //equality conditions repeat the transition
  1144. class InMemoryRowCursor : public IRowCursor
  1145. {
  1146. virtual const byte * findFirst(RowCursor & search)
  1147. {
  1148. size_t high = numRows;
  1149. size_t low = 0;
  1150. while (low<high)
  1151. {
  1152. size_t mid = low + (high - low) / 2;
  1153. seekRow.setRow(rows[mid], search.numFilterFields());
  1154. int rc = search.compareGE(seekRow);
  1155. if (rc>0)
  1156. low = mid + 1;
  1157. else
  1158. high = mid;
  1159. }
  1160. cur = low;
  1161. if (low == numRows)
  1162. return nullptr;
  1163. return rows[cur];
  1164. }
  1165. //Find the first row that is larger than search within the first numSeekFields
  1166. //RowCursor is not the correct type
  1167. virtual const byte * findGT(const RowCursor & order, const RtlRow & search, unsigned numSeekFields)
  1168. {
  1169. size_t high = numRows;
  1170. size_t low = 0;
  1171. while (low<high)
  1172. {
  1173. size_t mid = low + (high - low) / 2;
  1174. seekRow.setRow(rows[mid], order.numFilterFields());
  1175. int rc = order.compareRows(seekRow, search);
  1176. if (rc >= 0)
  1177. low = mid + 1;
  1178. else
  1179. high = mid;
  1180. }
  1181. cur = low;
  1182. if (cur == numRows)
  1183. return nullptr;
  1184. return rows[cur];
  1185. }
  1186. virtual const byte * next() override
  1187. {
  1188. cur++;
  1189. if (cur == numRows)
  1190. return nullptr;
  1191. return rows[cur];
  1192. }
  1193. protected:
  1194. size_t numRows;
  1195. size_t cur;
  1196. const byte * * rows;
  1197. RtlDynRow seekRow;
  1198. };
  1199. /*
  1200. class KeyLocator
  1201. {
  1202. public:
  1203. KeyLocator(IValueSet & _filter) : filter(_filter)
  1204. {
  1205. }
  1206. bool first()
  1207. {
  1208. transitionIdx = 0;
  1209. startTransition = filter.queryTransition(transitionIdx);
  1210. if (!startTransition)
  1211. return false;
  1212. endTransition = filter.queryTransition(transitionIdx+1);
  1213. return nextValidRow();
  1214. }
  1215. bool next()
  1216. {
  1217. curRow = rows->next();
  1218. if (matches(*endTransition, curRow))
  1219. return true;
  1220. if (!nextTransition())
  1221. return false;
  1222. //MORE: Check if the row is valid for the next transition
  1223. return nextValidRow();
  1224. }
  1225. bool nextValidRow()
  1226. {
  1227. for (;;)
  1228. {
  1229. if (findFirst(startTransition))
  1230. {
  1231. if (matches(*endTransition, curRow))
  1232. return true;
  1233. }
  1234. if (!nextTransition())
  1235. return false;
  1236. }
  1237. }
  1238. protected:
  1239. bool nextTransition()
  1240. {
  1241. transitionIdx += 2;
  1242. return setTransition();
  1243. }
  1244. bool setTransition()
  1245. {
  1246. startTransition = filter.queryTransition(transitionIdx);
  1247. if (!startTransition)
  1248. return false;
  1249. endTransition = filter.queryTransition(transitionIdx+1);
  1250. return true;
  1251. }
  1252. bool findFirst(const ValueTransition * transition)
  1253. {
  1254. assertex(transition->queryMask() & CMPgt);
  1255. if (transition->queryMask() & CMPeq)
  1256. curRow = rows->findGE(transition);
  1257. else
  1258. curRow = rows->findGT(transition);
  1259. return curRow != nullptr;
  1260. }
  1261. protected:
  1262. unsigned transitionIdx = 0;
  1263. const ValueTransition * startTransition = nullptr;
  1264. const ValueTransition * endTransition = nullptr;
  1265. IRowCursor * rows = nullptr;
  1266. const byte * curRow = nullptr;
  1267. IValueSet & filter;
  1268. };
  1269. */
  1270. /*
  1271. Conclusions:
  1272. * Need compareLowest to be able to implement first()/ next with wildcards. Could implement with a typed lowest transition....
  1273. * Is it actually any different from start transition for most cases -
  1274. * index read is very efficient using a single memcmp when finding the next.
  1275. * Moving the compare into the transition makes the memcmp harder - although could be optimized + allow combining.
  1276. * The string sets should work on a field. The segmonitor should map row->field
  1277. * Could have multiple adjacent field fields once have variable length.
  1278. * Moving the compare into the transition makes index formats without decompression very tricky. Could possibly work around it by having a byte provider interface which could be called to get the next value.
  1279. *
  1280. *
  1281. */
  1282. #ifdef _USE_CPPUNIT
  1283. #include <cppunit/extensions/HelperMacros.h>
  1284. /*
  1285. class IStdException : extends std::exception
  1286. {
  1287. Owned<IException> jException;
  1288. public:
  1289. IStdException(IException *E) : jException(E) {};
  1290. };
  1291. */
  1292. static void addRange(IValueSet * set, const char * lower, const char * upper)
  1293. {
  1294. Owned<ValueTransition> lowerBound = lower ? set->createUtf8Transition(CMPge, rtlUtf8Length(strlen(lower), lower), lower) : nullptr;
  1295. Owned<ValueTransition> upperBound = upper ? set->createUtf8Transition(CMPle, rtlUtf8Length(strlen(upper), upper), upper) : nullptr;
  1296. set->addRange(lowerBound, upperBound);
  1297. };
  1298. class ValueSetTest : public CppUnit::TestFixture
  1299. {
  1300. CPPUNIT_TEST_SUITE(ValueSetTest);
  1301. CPPUNIT_TEST(testFilter);
  1302. CPPUNIT_TEST(testRange);
  1303. CPPUNIT_TEST(testSerialize);
  1304. CPPUNIT_TEST(testUnion);
  1305. CPPUNIT_TEST(testExclude);
  1306. CPPUNIT_TEST(testInverse);
  1307. CPPUNIT_TEST(testIntersect);
  1308. CPPUNIT_TEST(testStr2);
  1309. CPPUNIT_TEST_SUITE_END();
  1310. protected:
  1311. void checkSet(const IValueSet * set, const char * expected)
  1312. {
  1313. StringBuffer temp;
  1314. set->serialize(temp);
  1315. if (!streq(expected, temp))
  1316. CPPUNIT_ASSERT_EQUAL(expected, temp.str());
  1317. }
  1318. void testRange(RtlTypeInfo & type, const char * low, const char * high, const char * expected)
  1319. {
  1320. Owned<IValueSet> set = createValueSet(type);
  1321. addRange(set, low, high);
  1322. checkSet(set, expected);
  1323. }
  1324. void testRangeStr1(const char * low, const char * high, const char * expected)
  1325. {
  1326. RtlStringTypeInfo str1(type_string, 1);
  1327. testRange(str1, low, high, expected);
  1328. }
  1329. void testRangeInt2(const char * low, const char * high, const char * expected)
  1330. {
  1331. RtlIntTypeInfo int2(type_int, 2);
  1332. testRange(int2, low, high, expected);
  1333. }
  1334. void testRangeStrX(const char * low, const char * high, const char * expected)
  1335. {
  1336. RtlStringTypeInfo type(type_string|RFTMunknownsize, 0);
  1337. testRange(type, low, high, expected);
  1338. }
  1339. void testRangeUniX(const char * low, const char * high, const char * expected)
  1340. {
  1341. RtlUnicodeTypeInfo type(type_string|RFTMunknownsize, 0, "");
  1342. testRange(type, low, high, expected);
  1343. }
  1344. void testRange()
  1345. {
  1346. testRangeStr1("A","Z","['A','Z']");
  1347. testRangeStr1("X","z","['X','z']");
  1348. testRangeStr1("Z","X","");
  1349. testRangeStr1(nullptr, "z","(,'z']");
  1350. testRangeStr1("Z", nullptr,"['Z',)");
  1351. testRangeStr1("A", "A","['A']");
  1352. testRangeStr1(nullptr, nullptr,"(,)");
  1353. testRangeStr1("é", "é","['é']"); // Test utf8 translation
  1354. testRangeStr1("AB", "ZX","['A','Z']");
  1355. testRangeInt2("0","1","[0,1]");
  1356. testRangeInt2("-1","1","[-1,1]");
  1357. testRangeInt2("-32768","32767","[-32768,32767]");
  1358. testRangeInt2("32768","0","[-32768,0]");
  1359. testRangeStrX("A", "Z","['A','Z']");
  1360. testRangeStrX("AB", "ZX","['AB','ZX']");
  1361. testRangeStrX("éèabc", "ab","");
  1362. testRangeStrX("a'b", "éèabc", "['a\\'b','éèabc']");
  1363. testRangeUniX("A", "Z","['A','Z']");
  1364. testRangeUniX("AB", "ZX","['AB','ZX']");
  1365. testRangeUniX("éèabc", "ab","");
  1366. testRangeUniX("a'b", "éèabc", "['a\\'b','éèabc']");
  1367. }
  1368. void testSerialize(RtlTypeInfo & type, const char * filter, const char * expected = nullptr)
  1369. {
  1370. Owned<IValueSet> set = createValueSet(type);
  1371. deserializeSet(*set, filter);
  1372. checkSet(set, expected ? expected : filter);
  1373. }
  1374. void testUnion(RtlTypeInfo & type, const char * filter, const char * next, const char * expected)
  1375. {
  1376. Owned<IValueSet> set = createValueSet(type);
  1377. deserializeSet(*set, filter);
  1378. deserializeSet(*set, next);
  1379. checkSet(set, expected);
  1380. //test the arguments in the opposite order
  1381. Owned<IValueSet> set2 = createValueSet(type);
  1382. deserializeSet(*set2, next);
  1383. deserializeSet(*set2, filter);
  1384. checkSet(set, expected);
  1385. //test the arguments in the opposite order
  1386. Owned<IValueSet> set3a = createValueSet(type);
  1387. Owned<IValueSet> set3b = createValueSet(type);
  1388. deserializeSet(*set3a, next);
  1389. deserializeSet(*set3b, filter);
  1390. set3a->unionSet(set3b);
  1391. checkSet(set3a, expected);
  1392. }
  1393. void testSerialize()
  1394. {
  1395. RtlStringTypeInfo str1(type_string, 1);
  1396. RtlIntTypeInfo int2(type_int, 2);
  1397. RtlStringTypeInfo strx(type_string|RFTMunknownsize, 0);
  1398. testSerialize(int2, "[123]");
  1399. testSerialize(int2, "(123,234]");
  1400. testSerialize(int2, "[123,234)");
  1401. testSerialize(int2, "(123,234)");
  1402. testSerialize(int2, "(,234)");
  1403. testSerialize(int2, "(128,)");
  1404. testSerialize(int2, "(,)");
  1405. testSerialize(int2, "(123,234),(456,567)");
  1406. testSerialize(int2, "(456,567),(123,234)", "(123,234),(456,567)");
  1407. testSerialize(str1, "['A']");
  1408. testSerialize(str1, "[',']");
  1409. testSerialize(str1, "['\\'']");
  1410. testSerialize(strx, "['\\'\\'','}']");
  1411. testSerialize(str1, "[A]", "['A']");
  1412. testSerialize(int2, "(123]", "");
  1413. testSerialize(int2, "[123)", "");
  1414. testSerialize(int2, "[1,0]", "");
  1415. }
  1416. void testUnion()
  1417. {
  1418. RtlIntTypeInfo int2(type_int, 2);
  1419. testSerialize(int2, "[3,5],[5,7]", "[3,7]");
  1420. testSerialize(int2, "[3,5],(5,7]", "[3,7]");
  1421. testSerialize(int2, "[3,5),[5,7]", "[3,7]");
  1422. testSerialize(int2, "[3,5),(5,7]");
  1423. testSerialize(int2, "[4],[4]", "[4]");
  1424. testSerialize(int2, "[4,5],[4]", "[4,5]");
  1425. testSerialize(int2, "[4,5],[5]", "[4,5]");
  1426. testUnion(int2, "[3,5]", "[,1]", "(,1],[3,5]");
  1427. testUnion(int2, "[3,5]", "[,3]", "(,5]");
  1428. testUnion(int2, "[3,5]", "[,4]", "(,5]");
  1429. testUnion(int2, "[3,5]", "[,]", "(,)");
  1430. testUnion(int2, "[3,5]", "[1,)", "[1,)");
  1431. testUnion(int2, "[3,5]", "[3,)", "[3,)");
  1432. testUnion(int2, "[3,5]", "[5,)", "[3,)");
  1433. testUnion(int2, "[3,5]", "(5,)", "[3,)");
  1434. testUnion(int2, "[3,5]", "[6,)", "[3,5],[6,)");
  1435. testUnion(int2, "[3,5]", "(6,)", "[3,5],(6,)");
  1436. testUnion(int2, "[4,7],[12,15]", "[1,1]", "[1],[4,7],[12,15]");
  1437. testUnion(int2, "[4,7],[12,15]", "[1,4)", "[1,7],[12,15]");
  1438. testUnion(int2, "[4,7],[12,15]", "[1,4]", "[1,7],[12,15]");
  1439. testUnion(int2, "[4,7],[12,15]", "[1,5)", "[1,7],[12,15]");
  1440. testUnion(int2, "[4,7],[12,15]", "[1,7)", "[1,7],[12,15]");
  1441. testUnion(int2, "[4,7],[12,15]", "[1,7]", "[1,7],[12,15]");
  1442. testUnion(int2, "[4,7],[12,15]", "[1,8]", "[1,8],[12,15]");
  1443. testUnion(int2, "[4,7],[12,15]", "[1,12)", "[1,15]");
  1444. testUnion(int2, "[4,7],[12,15]", "[1,12]", "[1,15]");
  1445. testUnion(int2, "[4,7],[12,15]", "[1,14]", "[1,15]");
  1446. testUnion(int2, "[4,7],[12,15]", "[1,15]", "[1,15]");
  1447. testUnion(int2, "[4,7],[12,15]", "[1,16]", "[1,16]");
  1448. testUnion(int2, "[4,7],[12,15]", "[1,17]", "[1,17]");
  1449. testUnion(int2, "[4,7],[12,15]", "(4,5)", "[4,7],[12,15]");
  1450. testUnion(int2, "[4,7],[12,15]", "(4,7)", "[4,7],[12,15]");
  1451. testUnion(int2, "[4,7],[12,15]", "(4,7]", "[4,7],[12,15]");
  1452. testUnion(int2, "[4,7],[12,15]", "(4,8]", "[4,8],[12,15]");
  1453. testUnion(int2, "[4,7],[12,15]", "(4,12)", "[4,15]");
  1454. testUnion(int2, "[4,7],[12,15]", "(4,12]", "[4,15]");
  1455. testUnion(int2, "[4,7],[12,15]", "[4,4]", "[4,7],[12,15]");
  1456. testUnion(int2, "[4,7],[12,15]", "[4,5)", "[4,7],[12,15]");
  1457. testUnion(int2, "[4,7],[12,15]", "[4,7)", "[4,7],[12,15]");
  1458. testUnion(int2, "[4,7],[12,15]", "[4,7]", "[4,7],[12,15]");
  1459. testUnion(int2, "[4,7],[12,15]", "[4,8]", "[4,8],[12,15]");
  1460. testUnion(int2, "[4,7],[12,15]", "[4,12)", "[4,15]");
  1461. testUnion(int2, "[4,7],[12,15]", "[4,12]", "[4,15]");
  1462. testUnion(int2, "[4,7],[12,15]", "[4,14]", "[4,15]");
  1463. testUnion(int2, "[4,7],[12,15]", "[4,15]", "[4,15]");
  1464. testUnion(int2, "[4,7],[12,15]", "[4,16]", "[4,16]");
  1465. testUnion(int2, "[4,7],[12,15]", "[4,17]", "[4,17]");
  1466. testUnion(int2, "[4,7],[12,15]", "(5,7)", "[4,7],[12,15]");
  1467. testUnion(int2, "[4,7],[12,15]", "(5,7]", "[4,7],[12,15]");
  1468. testUnion(int2, "[4,7],[12,15]", "(5,8]", "[4,8],[12,15]");
  1469. testUnion(int2, "[4,7],[12,15]", "(5,12)", "[4,15]");
  1470. testUnion(int2, "[4,7],[12,15]", "(5,12]", "[4,15]");
  1471. testUnion(int2, "[4,7],[12,15]", "(5,14]", "[4,15]");
  1472. testUnion(int2, "[4,7],[12,15]", "(5,15]", "[4,15]");
  1473. testUnion(int2, "[4,7],[12,15]", "(5,17]", "[4,17]");
  1474. testUnion(int2, "[4,7],[12,15]", "(7,8]", "[4,8],[12,15]");
  1475. testUnion(int2, "[4,7],[12,15]", "(7,8)", "[4,8),[12,15]");
  1476. testUnion(int2, "[4,7],[12,15]", "(7,12)", "[4,15]");
  1477. testUnion(int2, "[4,7],[12,15]", "(7,12]", "[4,15]");
  1478. testUnion(int2, "[4,7],[12,15]", "(7,14]", "[4,15]");
  1479. testUnion(int2, "[4,7],[12,15]", "(7,15]", "[4,15]");
  1480. testUnion(int2, "[4,7],[12,15]", "(7,17]", "[4,17]");
  1481. testUnion(int2, "[4,7],[12,15]", "[7,7]", "[4,7],[12,15]");
  1482. testUnion(int2, "[4,7],[12,15]", "[7,8]", "[4,8],[12,15]");
  1483. testUnion(int2, "[4,7],[12,15]", "[7,12)", "[4,15]");
  1484. testUnion(int2, "[4,7],[12,15]", "[7,17]", "[4,17]");
  1485. testUnion(int2, "[4,7],[12,15]", "[8,8]", "[4,7],[8],[12,15]");
  1486. testUnion(int2, "[4,7],[12,15]", "[8,12)", "[4,7],[8,15]");
  1487. testUnion(int2, "[4,7],[12,15]", "[8,12]", "[4,7],[8,15]");
  1488. testUnion(int2, "[4,7],[12,15]", "[8,14]", "[4,7],[8,15]");
  1489. testUnion(int2, "[4,7],[12,15]", "[8,15]", "[4,7],[8,15]");
  1490. testUnion(int2, "[4,7],[12,15]", "[8,16]", "[4,7],[8,16]");
  1491. testUnion(int2, "[4,7],[12,15]", "[8,17]", "[4,7],[8,17]");
  1492. testUnion(int2, "[4,7],[12,15]", "(8,11)", "[4,7],(8,11),[12,15]");
  1493. testUnion(int2, "[4,7],[12,15]", "(8,12)", "[4,7],(8,15]");
  1494. testUnion(int2, "[4,7],[12,15]", "(8,12]", "[4,7],(8,15]");
  1495. testUnion(int2, "[4,7],[12,15]", "(8,14]", "[4,7],(8,15]");
  1496. testUnion(int2, "[4,7],[12,15]", "(8,15]", "[4,7],(8,15]");
  1497. testUnion(int2, "[4,7],[12,15]", "(8,16]", "[4,7],(8,16]");
  1498. testUnion(int2, "[4,7],[12,15]", "(8,17]", "[4,7],(8,17]");
  1499. testUnion(int2, "[4,7],[12,15]", "(12,14]", "[4,7],[12,15]");
  1500. testUnion(int2, "[4,7],[12,15]", "(12,15]", "[4,7],[12,15]");
  1501. testUnion(int2, "[4,7],[12,15]", "(12,16]", "[4,7],[12,16]");
  1502. testUnion(int2, "[4,7],[12,15]", "(12,17]", "[4,7],[12,17]");
  1503. testUnion(int2, "[4,7],[12,15]", "[12,12]", "[4,7],[12,15]");
  1504. testUnion(int2, "[4,7],[12,15]", "[12,14]", "[4,7],[12,15]");
  1505. testUnion(int2, "[4,7],[12,15]", "[12,15]", "[4,7],[12,15]");
  1506. testUnion(int2, "[4,7],[12,15]", "[12,16]", "[4,7],[12,16]");
  1507. testUnion(int2, "[4,7],[12,15]", "[12,17]", "[4,7],[12,17]");
  1508. testUnion(int2, "[4,7],[12,15]", "[14,14]", "[4,7],[12,15]");
  1509. testUnion(int2, "[4,7],[12,15]", "[14,15]", "[4,7],[12,15]");
  1510. testUnion(int2, "[4,7],[12,15]", "[14,16]", "[4,7],[12,16]");
  1511. testUnion(int2, "[4,7],[12,15]", "[14,17]", "[4,7],[12,17]");
  1512. testUnion(int2, "[4,7],[12,15]", "[15]", "[4,7],[12,15]");
  1513. testUnion(int2, "[4,7],[12,15]", "[15,16]", "[4,7],[12,16]");
  1514. testUnion(int2, "[4,7],[12,15]", "[15,17]", "[4,7],[12,17]");
  1515. testUnion(int2, "[4,7],[12,15]", "[15,17)", "[4,7],[12,17)");
  1516. testUnion(int2, "[4,7],[12,15]", "[16]", "[4,7],[12,15],[16]");
  1517. testUnion(int2, "[4,7],[12,15]", "[16,17]", "[4,7],[12,15],[16,17]");
  1518. testUnion(int2, "[4,7],[12,15]", "[17]", "[4,7],[12,15],[17]");
  1519. testUnion(int2, "(4,7),(12,15)", "[1,1]", "[1],(4,7),(12,15)");
  1520. testUnion(int2, "(4,7),(12,15)", "[1,4)", "[1,4),(4,7),(12,15)");
  1521. testUnion(int2, "(4,7),(12,15)", "[1,4]", "[1,7),(12,15)");
  1522. testUnion(int2, "(4,7),(12,15)", "[1,5)", "[1,7),(12,15)");
  1523. testUnion(int2, "(4,7),(12,15)", "[1,7)", "[1,7),(12,15)");
  1524. testUnion(int2, "(4,7),(12,15)", "[1,7]", "[1,7],(12,15)");
  1525. testUnion(int2, "(4,7),(12,15)", "[1,8]", "[1,8],(12,15)");
  1526. testUnion(int2, "(4,7),(12,15)", "[1,12)", "[1,12),(12,15)");
  1527. testUnion(int2, "(4,7),(12,15)", "[1,12]", "[1,15)");
  1528. testUnion(int2, "(4,7),(12,15)", "[1,14]", "[1,15)");
  1529. testUnion(int2, "(4,7),(12,15)", "[1,15]", "[1,15]");
  1530. testUnion(int2, "(4,7),(12,15)", "[1,16]", "[1,16]");
  1531. testUnion(int2, "(4,7),(12,15)", "[1,17]", "[1,17]");
  1532. testUnion(int2, "(4,7),(12,15)", "(4,5)", "(4,7),(12,15)");
  1533. testUnion(int2, "(4,7),(12,15)", "(4,7)", "(4,7),(12,15)");
  1534. testUnion(int2, "(4,7),(12,15)", "(4,7]", "(4,7],(12,15)");
  1535. testUnion(int2, "(4,7),(12,15)", "(4,8]", "(4,8],(12,15)");
  1536. testUnion(int2, "(4,7),(12,15)", "(4,12)", "(4,12),(12,15)");
  1537. testUnion(int2, "(4,7),(12,15)", "(4,12]", "(4,15)");
  1538. testUnion(int2, "(4,7),(12,15)", "[4,4]", "[4,7),(12,15)");
  1539. testUnion(int2, "(4,7),(12,15)", "[4,5)", "[4,7),(12,15)");
  1540. testUnion(int2, "(4,7),(12,15)", "[4,7)", "[4,7),(12,15)");
  1541. testUnion(int2, "(4,7),(12,15)", "[4,7]", "[4,7],(12,15)");
  1542. testUnion(int2, "(4,7),(12,15)", "[4,8]", "[4,8],(12,15)");
  1543. testUnion(int2, "(4,7),(12,15)", "[4,12)", "[4,12),(12,15)");
  1544. testUnion(int2, "(4,7),(12,15)", "[4,12]", "[4,15)");
  1545. testUnion(int2, "(4,7),(12,15)", "[4,14]", "[4,15)");
  1546. testUnion(int2, "(4,7),(12,15)", "[4,15]", "[4,15]");
  1547. testUnion(int2, "(4,7),(12,15)", "[4,16]", "[4,16]");
  1548. testUnion(int2, "(4,7),(12,15)", "[4,17]", "[4,17]");
  1549. testUnion(int2, "(4,7),(12,15)", "(5,7)", "(4,7),(12,15)");
  1550. testUnion(int2, "(4,7),(12,15)", "(5,7]", "(4,7],(12,15)");
  1551. testUnion(int2, "(4,7),(12,15)", "(5,8]", "(4,8],(12,15)");
  1552. testUnion(int2, "(4,7),(12,15)", "(5,12)", "(4,12),(12,15)");
  1553. testUnion(int2, "(4,7),(12,15)", "(5,12]", "(4,15)");
  1554. testUnion(int2, "(4,7),(12,15)", "(5,14]", "(4,15)");
  1555. testUnion(int2, "(4,7),(12,15)", "(5,15]", "(4,15]");
  1556. testUnion(int2, "(4,7),(12,15)", "(5,17]", "(4,17]");
  1557. testUnion(int2, "(4,7),(12,15)", "(7,8]", "(4,7),(7,8],(12,15)");
  1558. testUnion(int2, "(4,7),(12,15)", "(7,8)", "(4,7),(7,8),(12,15)");
  1559. testUnion(int2, "(4,7),(12,15)", "(7,12)", "(4,7),(7,12),(12,15)");
  1560. testUnion(int2, "(4,7),(12,15)", "(7,12]", "(4,7),(7,15)");
  1561. testUnion(int2, "(4,7),(12,15)", "(7,14]", "(4,7),(7,15)");
  1562. testUnion(int2, "(4,7),(12,15)", "(7,15]", "(4,7),(7,15]");
  1563. testUnion(int2, "(4,7),(12,15)", "(7,17]", "(4,7),(7,17]");
  1564. testUnion(int2, "(4,7),(12,15)", "[7,7]", "(4,7],(12,15)");
  1565. testUnion(int2, "(4,7),(12,15)", "[7,8]", "(4,8],(12,15)");
  1566. testUnion(int2, "(4,7),(12,15)", "[7,12)", "(4,12),(12,15)");
  1567. testUnion(int2, "(4,7),(12,15)", "[7,17]", "(4,17]");
  1568. testUnion(int2, "(4,7),(12,15)", "[8,8]", "(4,7),[8],(12,15)");
  1569. testUnion(int2, "(4,7),(12,15)", "[8,12)", "(4,7),[8,12),(12,15)");
  1570. testUnion(int2, "(4,7),(12,15)", "[8,12]", "(4,7),[8,15)");
  1571. testUnion(int2, "(4,7),(12,15)", "[8,14]", "(4,7),[8,15)");
  1572. testUnion(int2, "(4,7),(12,15)", "[8,15]", "(4,7),[8,15]");
  1573. testUnion(int2, "(4,7),(12,15)", "[8,16]", "(4,7),[8,16]");
  1574. testUnion(int2, "(4,7),(12,15)", "[8,17]", "(4,7),[8,17]");
  1575. testUnion(int2, "(4,7),(12,15)", "(8,11)", "(4,7),(8,11),(12,15)");
  1576. testUnion(int2, "(4,7),(12,15)", "(8,12)", "(4,7),(8,12),(12,15)");
  1577. testUnion(int2, "(4,7),(12,15)", "(8,12]", "(4,7),(8,15)");
  1578. testUnion(int2, "(4,7),(12,15)", "(8,14]", "(4,7),(8,15)");
  1579. testUnion(int2, "(4,7),(12,15)", "(8,15]", "(4,7),(8,15]");
  1580. testUnion(int2, "(4,7),(12,15)", "(8,16]", "(4,7),(8,16]");
  1581. testUnion(int2, "(4,7),(12,15)", "(8,17]", "(4,7),(8,17]");
  1582. testUnion(int2, "(4,7),(12,15)", "(12,14]", "(4,7),(12,15)");
  1583. testUnion(int2, "(4,7),(12,15)", "(12,15]", "(4,7),(12,15]");
  1584. testUnion(int2, "(4,7),(12,15)", "(12,16]", "(4,7),(12,16]");
  1585. testUnion(int2, "(4,7),(12,15)", "(12,17]", "(4,7),(12,17]");
  1586. testUnion(int2, "(4,7),(12,15)", "[12,12]", "(4,7),[12,15)");
  1587. testUnion(int2, "(4,7),(12,15)", "[12,14]", "(4,7),[12,15)");
  1588. testUnion(int2, "(4,7),(12,15)", "[12,15]", "(4,7),[12,15]");
  1589. testUnion(int2, "(4,7),(12,15)", "[12,16]", "(4,7),[12,16]");
  1590. testUnion(int2, "(4,7),(12,15)", "[12,17]", "(4,7),[12,17]");
  1591. testUnion(int2, "(4,7),(12,15)", "[14,14]", "(4,7),(12,15)");
  1592. testUnion(int2, "(4,7),(12,15)", "[14,15]", "(4,7),(12,15]");
  1593. testUnion(int2, "(4,7),(12,15)", "[14,16]", "(4,7),(12,16]");
  1594. testUnion(int2, "(4,7),(12,15)", "[14,17]", "(4,7),(12,17]");
  1595. testUnion(int2, "(4,7),(12,15)", "[15]", "(4,7),(12,15]");
  1596. testUnion(int2, "(4,7),(12,15)", "[15,16]", "(4,7),(12,16]");
  1597. testUnion(int2, "(4,7),(12,15)", "(15,16]", "(4,7),(12,15),(15,16]");
  1598. testUnion(int2, "(4,7),(12,15)", "[15,17]", "(4,7),(12,17]");
  1599. testUnion(int2, "(4,7),(12,15)", "[15,17)", "(4,7),(12,17)");
  1600. testUnion(int2, "(4,7),(12,15)", "[16]", "(4,7),(12,15),[16]");
  1601. testUnion(int2, "(4,7),(12,15)", "[16,17]", "(4,7),(12,15),[16,17]");
  1602. testUnion(int2, "(4,7),(12,15)", "[17]", "(4,7),(12,15),[17]");
  1603. }
  1604. void testExclude(RtlTypeInfo & type, const char * filter, const char * next, const char * expected)
  1605. {
  1606. Owned<IValueSet> set = createValueSet(type);
  1607. deserializeSet(*set, filter);
  1608. Owned<IValueSet> set2 = createValueSet(type);
  1609. deserializeSet(*set2, next);
  1610. set->excludeSet(set2);
  1611. checkSet(set, expected);
  1612. }
  1613. //Tests killRange which is used by excludeSet()
  1614. void testExclude()
  1615. {
  1616. RtlIntTypeInfo int2(type_int, 2);
  1617. testExclude(int2, "[4]", "(4,5]", "[4]");
  1618. testExclude(int2, "[4,7],[12,15]", "[1,1]", "[4,7],[12,15]");
  1619. testExclude(int2, "[4,7],[12,15]", "[1,4)", "[4,7],[12,15]");
  1620. testExclude(int2, "[4,7],[12,15]", "[1,4]", "(4,7],[12,15]");
  1621. testExclude(int2, "[4,7],[12,15]", "[1,5)", "[5,7],[12,15]");
  1622. testExclude(int2, "[4,7],[12,15]", "[1,7)", "[7],[12,15]");
  1623. testExclude(int2, "[4,7],[12,15]", "[1,7]", "[12,15]");
  1624. testExclude(int2, "[4,7],[12,15]", "(,)", "");
  1625. testExclude(int2, "[4,7],[12,15]", "(,12]", "(12,15]");
  1626. testExclude(int2, "[4,7],[12,15]", "(6,)", "[4,6]");
  1627. testExclude(int2, "[4,7],[12,15]", "[1,8]", "[12,15]");
  1628. testExclude(int2, "[4,7],[12,15]", "[1,12)", "[12,15]");
  1629. testExclude(int2, "[4,7],[12,15]", "[1,12]", "(12,15]");
  1630. testExclude(int2, "[4,7],[12,15]", "[1,14]", "(14,15]");
  1631. testExclude(int2, "[4,7],[12,15]", "[1,15]", "");
  1632. testExclude(int2, "[4,7],[12,15]", "[1,16]", "");
  1633. testExclude(int2, "[4,7],[12,15]", "(4,5)", "[4],[5,7],[12,15]");
  1634. testExclude(int2, "[4,7],[12,15]", "(4,7)", "[4],[7],[12,15]");
  1635. testExclude(int2, "[4,7],[12,15]", "(4,7]", "[4],[12,15]");
  1636. testExclude(int2, "[4,7],[12,15]", "(4,8]", "[4],[12,15]");
  1637. testExclude(int2, "[4,7],[12,15]", "(4,12)", "[4],[12,15]");
  1638. testExclude(int2, "[4,7],[12,15]", "(4,12]", "[4],(12,15]");
  1639. testExclude(int2, "[4,7],[12,15]", "[4,4]", "(4,7],[12,15]");
  1640. testExclude(int2, "[4,7],[12,15]", "[4,5)", "[5,7],[12,15]");
  1641. testExclude(int2, "[4,7],[12,15]", "[4,7)", "[7],[12,15]");
  1642. testExclude(int2, "[4,7],[12,15]", "[4,7]", "[12,15]");
  1643. testExclude(int2, "[4,7],[12,15]", "[4,8]", "[12,15]");
  1644. testExclude(int2, "[4,7],[12,15]", "[4,12)", "[12,15]");
  1645. testExclude(int2, "[4,7],[12,15]", "[4,12]", "(12,15]");
  1646. testExclude(int2, "[4,7],[12,15]", "[4,14]", "(14,15]");
  1647. testExclude(int2, "[4,7],[12,15]", "[4,15]", "");
  1648. testExclude(int2, "[4,7],[12,15]", "[4,16]", "");
  1649. testExclude(int2, "[4,7],[12,15]", "(5,7)", "[4,5],[7],[12,15]");
  1650. testExclude(int2, "[4,7],[12,15]", "(5,7]", "[4,5],[12,15]");
  1651. testExclude(int2, "[4,7],[12,15]", "(5,8]", "[4,5],[12,15]");
  1652. testExclude(int2, "[4,7],[12,15]", "(5,12)", "[4,5],[12,15]");
  1653. testExclude(int2, "[4,7],[12,15]", "(5,12]", "[4,5],(12,15]");
  1654. testExclude(int2, "[4,7],[12,15]", "(5,14]", "[4,5],(14,15]");
  1655. testExclude(int2, "[4,7],[12,15]", "(5,15)", "[4,5],[15]");
  1656. testExclude(int2, "[4,7],[12,15]", "(5,15]", "[4,5]");
  1657. testExclude(int2, "[4,7],[12,15]", "(5,17]", "[4,5]");
  1658. testExclude(int2, "[4,7],[12,15]", "(7,8]", "[4,7],[12,15]");
  1659. testExclude(int2, "[4,7],[12,15]", "(7,8)", "[4,7],[12,15]");
  1660. testExclude(int2, "[4,7],[12,15]", "(7,12)", "[4,7],[12,15]");
  1661. testExclude(int2, "[4,7],[12,15]", "(7,12]", "[4,7],(12,15]");
  1662. testExclude(int2, "[4,7],[12,15]", "(7,14]", "[4,7],(14,15]");
  1663. testExclude(int2, "[4,7],[12,15]", "(7,15]", "[4,7]");
  1664. testExclude(int2, "[4,7],[12,15]", "(7,17]", "[4,7]");
  1665. testExclude(int2, "[4,7],[12,15]", "[7,7]", "[4,7),[12,15]");
  1666. testExclude(int2, "[4,7],[12,15]", "[7,8]", "[4,7),[12,15]");
  1667. testExclude(int2, "[4,7],[12,15]", "[7,12)", "[4,7),[12,15]");
  1668. testExclude(int2, "[4,7],[12,15]", "[7,17]", "[4,7)");
  1669. testExclude(int2, "[4,7],[12,15]", "[8,8]", "[4,7],[12,15]");
  1670. testExclude(int2, "[4,7],[12,15]", "[8,12)", "[4,7],[12,15]");
  1671. testExclude(int2, "[4,7],[12,15]", "[8,12]", "[4,7],(12,15]");
  1672. testExclude(int2, "[4,7],[12,15]", "[8,14]", "[4,7],(14,15]");
  1673. testExclude(int2, "[4,7],[12,15]", "[8,15]", "[4,7]");
  1674. testExclude(int2, "[4,7],[12,15]", "[8,16]", "[4,7]");
  1675. testExclude(int2, "[4,7],[12,15]", "[8,17]", "[4,7]");
  1676. testExclude(int2, "[4,7],[12,15]", "(8,11)", "[4,7],[12,15]");
  1677. testExclude(int2, "[4,7],[12,15]", "(8,12)", "[4,7],[12,15]");
  1678. testExclude(int2, "[4,7],[12,15]", "(8,12]", "[4,7],(12,15]");
  1679. testExclude(int2, "[4,7],[12,15]", "(12,14]", "[4,7],[12],(14,15]");
  1680. testExclude(int2, "[4,7],[12,15]", "(12,15]", "[4,7],[12]");
  1681. testExclude(int2, "[4,7],[12,15]", "(12,16]", "[4,7],[12]");
  1682. testExclude(int2, "[4,7],[12,15]", "[12,12]", "[4,7],(12,15]");
  1683. testExclude(int2, "[4,7],[12,15]", "[12,14]", "[4,7],(14,15]");
  1684. testExclude(int2, "[4,7],[12,15]", "[12,15]", "[4,7]");
  1685. testExclude(int2, "[4,7],[12,15]", "[12,16]", "[4,7]");
  1686. testExclude(int2, "[4,7],[12,15]", "[14,14]", "[4,7],[12,14),(14,15]");
  1687. testExclude(int2, "[4,7],[12,15]", "[14,15]", "[4,7],[12,14)");
  1688. testExclude(int2, "[4,7],[12,15]", "[14,16]", "[4,7],[12,14)");
  1689. testExclude(int2, "[4,7],[12,15]", "[14,17]", "[4,7],[12,14)");
  1690. testExclude(int2, "[4,7],[12,15]", "[15]", "[4,7],[12,15)");
  1691. testExclude(int2, "[4,7],[12,15]", "[15,16]", "[4,7],[12,15)");
  1692. testExclude(int2, "[4,7],[12,15]", "[15,17]", "[4,7],[12,15)");
  1693. testExclude(int2, "[4,7],[12,15]", "[15,17)", "[4,7],[12,15)");
  1694. testExclude(int2, "[4,7],[12,15]", "[16]", "[4,7],[12,15]");
  1695. testExclude(int2, "(4,7),(12,15)", "[1,1]", "(4,7),(12,15)");
  1696. testExclude(int2, "(4,7),(12,15)", "[1,4)", "(4,7),(12,15)");
  1697. testExclude(int2, "(4,7),(12,15)", "[1,4]", "(4,7),(12,15)");
  1698. testExclude(int2, "(4,7),(12,15)", "[1,5)", "[5,7),(12,15)");
  1699. testExclude(int2, "(4,7),(12,15)", "[1,7)", "(12,15)");
  1700. testExclude(int2, "(4,7),(12,15)", "[1,7]", "(12,15)");
  1701. testExclude(int2, "(4,7),(12,15)", "[1,8]", "(12,15)");
  1702. testExclude(int2, "(4,7),(12,15)", "[1,12)", "(12,15)");
  1703. testExclude(int2, "(4,7),(12,15)", "[1,12]", "(12,15)");
  1704. testExclude(int2, "(4,7),(12,15)", "[1,14]", "(14,15)");
  1705. testExclude(int2, "(4,7),(12,15)", "[1,15]", "");
  1706. testExclude(int2, "(4,7),(12,15)", "[1,16]", "");
  1707. testExclude(int2, "(4,7),(12,15)", "(4,5)", "[5,7),(12,15)");
  1708. testExclude(int2, "(4,7),(12,15)", "(4,7)", "(12,15)");
  1709. testExclude(int2, "(4,7),(12,15)", "(4,7]", "(12,15)");
  1710. testExclude(int2, "(4,7),(12,15)", "(4,8]", "(12,15)");
  1711. testExclude(int2, "(4,7),(12,15)", "(4,12)", "(12,15)");
  1712. testExclude(int2, "(4,7),(12,15)", "(4,12]", "(12,15)");
  1713. testExclude(int2, "(4,7),(12,15)", "[4,4]", "(4,7),(12,15)");
  1714. testExclude(int2, "(4,7),(12,15)", "[4,5)", "[5,7),(12,15)");
  1715. testExclude(int2, "(4,7),(12,15)", "[4,7)", "(12,15)");
  1716. testExclude(int2, "(4,7),(12,15)", "[4,7]", "(12,15)");
  1717. testExclude(int2, "(4,7),(12,15)", "[4,8]", "(12,15)");
  1718. testExclude(int2, "(4,7),(12,15)", "[4,12)", "(12,15)");
  1719. testExclude(int2, "(4,7),(12,15)", "[4,12]", "(12,15)");
  1720. testExclude(int2, "(4,7),(12,15)", "[4,14]", "(14,15)");
  1721. testExclude(int2, "(4,7),(12,15)", "[4,15]", "");
  1722. testExclude(int2, "(4,7),(12,15)", "(5,6)", "(4,5],[6,7),(12,15)");
  1723. testExclude(int2, "(4,7),(12,15)", "(5,7)", "(4,5],(12,15)");
  1724. testExclude(int2, "(4,7),(12,15)", "(5,7]", "(4,5],(12,15)");
  1725. testExclude(int2, "(4,7),(12,15)", "(5,8]", "(4,5],(12,15)");
  1726. testExclude(int2, "(4,7),(12,15)", "(5,12)", "(4,5],(12,15)");
  1727. testExclude(int2, "(4,7),(12,15)", "(5,12]", "(4,5],(12,15)");
  1728. testExclude(int2, "(4,7),(12,15)", "(5,14]", "(4,5],(14,15)");
  1729. testExclude(int2, "(4,7),(12,15)", "(5,15]", "(4,5]");
  1730. testExclude(int2, "(4,7),(12,15)", "(5,17]", "(4,5]");
  1731. //return;
  1732. testExclude(int2, "(4,7),(12,15)", "(7,8]", "(4,7),(12,15)");
  1733. testExclude(int2, "(4,7),(12,15)", "(7,8)", "(4,7),(12,15)");
  1734. testExclude(int2, "(4,7),(12,15)", "(7,12)", "(4,7),(12,15)");
  1735. testExclude(int2, "(4,7),(12,15)", "(7,12]", "(4,7),(12,15)");
  1736. testExclude(int2, "(4,7),(12,15)", "(7,14]", "(4,7),(14,15)");
  1737. testExclude(int2, "(4,7),(12,15)", "(7,15]", "(4,7)");
  1738. testExclude(int2, "(4,7),(12,15)", "(7,17]", "(4,7)");
  1739. testExclude(int2, "(4,7),(12,15)", "[7,7]", "(4,7),(12,15)");
  1740. testExclude(int2, "(4,7),(12,15)", "[7,8]", "(4,7),(12,15)");
  1741. testExclude(int2, "(4,7),(12,15)", "[7,12)", "(4,7),(12,15)");
  1742. testExclude(int2, "(4,7),(12,15)", "[7,17]", "(4,7)");
  1743. testExclude(int2, "(4,7),(12,15)", "[8,8]", "(4,7),(12,15)");
  1744. testExclude(int2, "(4,7),(12,15)", "[8,12)", "(4,7),(12,15)");
  1745. testExclude(int2, "(4,7),(12,15)", "[8,12]", "(4,7),(12,15)");
  1746. testExclude(int2, "(4,7),(12,15)", "[8,14]", "(4,7),(14,15)");
  1747. testExclude(int2, "(4,7),(12,15)", "[8,15]", "(4,7)");
  1748. testExclude(int2, "(4,7),(12,15)", "[8,16]", "(4,7)");
  1749. testExclude(int2, "(4,7),(12,15)", "[8,17]", "(4,7)");
  1750. testExclude(int2, "(4,7),(12,15)", "(8,11)", "(4,7),(12,15)");
  1751. testExclude(int2, "(4,7),(12,15)", "(8,12)", "(4,7),(12,15)");
  1752. testExclude(int2, "(4,7),(12,15)", "(8,12]", "(4,7),(12,15)");
  1753. testExclude(int2, "(4,7),(12,15)", "(8,14]", "(4,7),(14,15)");
  1754. testExclude(int2, "(4,7),(12,15)", "(8,15]", "(4,7)");
  1755. testExclude(int2, "(4,7),(12,15)", "(8,16]", "(4,7)");
  1756. testExclude(int2, "(4,7),(12,15)", "(8,17]", "(4,7)");
  1757. testExclude(int2, "(4,7),(12,15)", "(12,14]", "(4,7),(14,15)");
  1758. testExclude(int2, "(4,7),(12,15)", "(12,15]", "(4,7)");
  1759. testExclude(int2, "(4,7),(12,15)", "(12,16]", "(4,7)");
  1760. testExclude(int2, "(4,7),(12,15)", "[12,12]", "(4,7),(12,15)");
  1761. testExclude(int2, "(4,7),(12,15)", "[13]", "(4,7),(12,13),(13,15)");
  1762. testExclude(int2, "(4,7),(12,15)", "[12,14)", "(4,7),[14,15)");
  1763. testExclude(int2, "(4,7),(12,15)", "[12,15)", "(4,7)");
  1764. testExclude(int2, "(4,7),(12,15)", "[12,16)", "(4,7)");
  1765. testExclude(int2, "(4,7),(12,15)", "[14,14]", "(4,7),(12,14),(14,15)");
  1766. testExclude(int2, "(4,7),(12,15)", "[14,15]", "(4,7),(12,14)");
  1767. testExclude(int2, "(4,7),(12,15)", "[14,16]", "(4,7),(12,14)");
  1768. testExclude(int2, "(4,7),(12,15)", "[15]", "(4,7),(12,15)");
  1769. }
  1770. void testInverse(RtlTypeInfo & type, const char * filter, const char * expected)
  1771. {
  1772. Owned<IValueSet> set = createValueSet(type);
  1773. deserializeSet(*set, filter);
  1774. set->invertSet();
  1775. checkSet(set, expected);
  1776. }
  1777. //Tests killRange which is used by excludeSet()
  1778. void testInverse()
  1779. {
  1780. RtlIntTypeInfo int2(type_int, 2);
  1781. testInverse(int2, "[4]", "(,4),(4,)");
  1782. testInverse(int2, "[4,5]", "(,4),(5,)");
  1783. testInverse(int2, "(4,5)", "(,4],[5,)");
  1784. testInverse(int2, "(,5)", "[5,)");
  1785. testInverse(int2, "[6,)", "(,6)");
  1786. testInverse(int2, "", "(,)");
  1787. testInverse(int2, "(,)", "");
  1788. testInverse(int2, "[4,5],(8,9),[12,14)", "(,4),(5,8],[9,12),[14,)");
  1789. }
  1790. void testIntersect(RtlTypeInfo & type, const char * filter, const char * next, const char * expected)
  1791. {
  1792. Owned<IValueSet> set = createValueSet(type);
  1793. deserializeSet(*set, filter);
  1794. Owned<IValueSet> set2 = createValueSet(type);
  1795. deserializeSet(*set2, next);
  1796. set->intersectSet(set2);
  1797. checkSet(set, expected);
  1798. //Test the opposite way around
  1799. Owned<IValueSet> seta = createValueSet(type);
  1800. deserializeSet(*seta, filter);
  1801. Owned<IValueSet> setb = createValueSet(type);
  1802. deserializeSet(*setb, next);
  1803. setb->intersectSet(seta);
  1804. checkSet(set, expected);
  1805. }
  1806. void testIntersect()
  1807. {
  1808. RtlIntTypeInfo int2(type_int, 2);
  1809. testIntersect(int2, "", "[1,2],(3,6)", "");
  1810. testIntersect(int2, "(,)", "[1,2],(3,6)", "[1,2],(3,6)");
  1811. testIntersect(int2, "(,)", "", "");
  1812. testIntersect(int2, "", "", "");
  1813. testIntersect(int2, "(,)", "(,)", "(,)");
  1814. testIntersect(int2, "(3,7),[10,20]", "[2]", "");
  1815. testIntersect(int2, "(3,7),[10,20]", "[3]", "");
  1816. testIntersect(int2, "(3,7),[10,20]", "[4]", "[4]");
  1817. testIntersect(int2, "(3,7),[10,20]", "[6]", "[6]");
  1818. testIntersect(int2, "(3,7),[10,20]", "[7]", "");
  1819. testIntersect(int2, "(3,7),[10,20]", "[10]", "[10]");
  1820. testIntersect(int2, "(3,7),[10,20]", "[20]", "[20]");
  1821. testIntersect(int2, "(3,7),[10,20]", "[21]", "");
  1822. testIntersect(int2, "(3,7),[10,20]", "[2,3]", "");
  1823. testIntersect(int2, "(3,7),[10,20]", "[2,5]", "(3,5]");
  1824. testIntersect(int2, "(3,7),[10,20]", "[2,7]", "(3,7)");
  1825. testIntersect(int2, "(3,7),[10,20]", "[2,8]", "(3,7)");
  1826. testIntersect(int2, "(3,7),[10,20]", "[2,10]", "(3,7),[10]");
  1827. testIntersect(int2, "(3,7),[10,20]", "[2,15]", "(3,7),[10,15]");
  1828. testIntersect(int2, "(3,7),[10,20]", "[2,20]", "(3,7),[10,20]");
  1829. testIntersect(int2, "(3,7),[10,20]", "[2,25]", "(3,7),[10,20]");
  1830. testIntersect(int2, "(3,7),[10,20]", "[3,3]", "");
  1831. testIntersect(int2, "(3,7),[10,20]", "[3,5]", "(3,5]");
  1832. testIntersect(int2, "(3,7),[10,20]", "[3,7]", "(3,7)");
  1833. testIntersect(int2, "(3,7),[10,20]", "[3,8]", "(3,7)");
  1834. testIntersect(int2, "(3,7),[10,20]", "[3,10]", "(3,7),[10]");
  1835. testIntersect(int2, "(3,7),[10,20]", "[3,15]", "(3,7),[10,15]");
  1836. testIntersect(int2, "(3,7),[10,20]", "[3,20]", "(3,7),[10,20]");
  1837. testIntersect(int2, "(3,7),[10,20]", "[3,25]", "(3,7),[10,20]");
  1838. testIntersect(int2, "(3,7),[10,20]", "[5,7]", "[5,7)");
  1839. testIntersect(int2, "(3,7),[10,20]", "[5,8]", "[5,7)");
  1840. testIntersect(int2, "(3,7),[10,20]", "[5,10]", "[5,7),[10]");
  1841. testIntersect(int2, "(3,7),[10,20]", "[5,15]", "[5,7),[10,15]");
  1842. testIntersect(int2, "(3,7),[10,20]", "[5,20]", "[5,7),[10,20]");
  1843. testIntersect(int2, "(3,7),[10,20]", "[5,25]", "[5,7),[10,20]");
  1844. testIntersect(int2, "(3,7),[10,20]", "[7,8]", "");
  1845. testIntersect(int2, "(3,7),[10,20]", "[7,10]", "[10]");
  1846. testIntersect(int2, "(3,7),[10,20]", "[7,15]", "[10,15]");
  1847. testIntersect(int2, "(3,7),[10,20]", "[7,20]", "[10,20]");
  1848. testIntersect(int2, "(3,7),[10,20]", "[7,25]", "[10,20]");
  1849. testIntersect(int2, "(3,7),[10,20]", "[10,15]", "[10,15]");
  1850. testIntersect(int2, "(3,7),[10,20]", "[10,20]", "[10,20]");
  1851. testIntersect(int2, "(3,7),[10,20]", "[10,25]", "[10,20]");
  1852. testIntersect(int2, "(3,7),[10,20]", "[15,20]", "[15,20]");
  1853. testIntersect(int2, "(3,7),[10,20]", "[15,25]", "[15,20]");
  1854. testIntersect(int2, "(3,7),[10,20]", "[20,25]", "[20]");
  1855. testIntersect(int2, "(3,7),[10,20]", "(2,3)", "");
  1856. testIntersect(int2, "(3,7),[10,20]", "(2,5)", "(3,5)");
  1857. testIntersect(int2, "(3,7),[10,20]", "(2,7)", "(3,7)");
  1858. testIntersect(int2, "(3,7),[10,20]", "(2,8)", "(3,7)");
  1859. testIntersect(int2, "(3,7),[10,20]", "(2,10)", "(3,7)");
  1860. testIntersect(int2, "(3,7),[10,20]", "(2,15)", "(3,7),[10,15)");
  1861. testIntersect(int2, "(3,7),[10,20]", "(2,20)", "(3,7),[10,20)");
  1862. testIntersect(int2, "(3,7),[10,20]", "(2,25)", "(3,7),[10,20]");
  1863. testIntersect(int2, "(3,7),[10,20]", "(3,5)", "(3,5)");
  1864. testIntersect(int2, "(3,7),[10,20]", "(3,7)", "(3,7)");
  1865. testIntersect(int2, "(3,7),[10,20]", "(3,8)", "(3,7)");
  1866. testIntersect(int2, "(3,7),[10,20]", "(3,10)", "(3,7)");
  1867. testIntersect(int2, "(3,7),[10,20]", "(3,15)", "(3,7),[10,15)");
  1868. testIntersect(int2, "(3,7),[10,20]", "(3,20)", "(3,7),[10,20)");
  1869. testIntersect(int2, "(3,7),[10,20]", "(3,25)", "(3,7),[10,20]");
  1870. testIntersect(int2, "(3,7),[10,20]", "(5,7)", "(5,7)");
  1871. testIntersect(int2, "(3,7),[10,20]", "(5,8)", "(5,7)");
  1872. testIntersect(int2, "(3,7),[10,20]", "(5,10)", "(5,7)");
  1873. testIntersect(int2, "(3,7),[10,20]", "(5,15)", "(5,7),[10,15)");
  1874. testIntersect(int2, "(3,7),[10,20]", "(5,20)", "(5,7),[10,20)");
  1875. testIntersect(int2, "(3,7),[10,20]", "(5,25)", "(5,7),[10,20]");
  1876. testIntersect(int2, "(3,7),[10,20]", "(7,8)", "");
  1877. testIntersect(int2, "(3,7),[10,20]", "(7,10)", "");
  1878. testIntersect(int2, "(3,7),[10,20]", "(7,15)", "[10,15)");
  1879. testIntersect(int2, "(3,7),[10,20]", "(7,20)", "[10,20)");
  1880. testIntersect(int2, "(3,7),[10,20]", "(7,25)", "[10,20]");
  1881. testIntersect(int2, "(3,7),[10,20]", "(10,15)", "(10,15)");
  1882. testIntersect(int2, "(3,7),[10,20]", "(10,20)", "(10,20)");
  1883. testIntersect(int2, "(3,7),[10,20]", "(15,20)", "(15,20)");
  1884. testIntersect(int2, "(3,7),[10,20]", "(15,25)", "(15,20]");
  1885. testIntersect(int2, "(3,7),[10,20]", "(20,25)", "");
  1886. testIntersect(int2, "(3,5),[7,10),[15,20),(30,32),[37]", "(4,7],(9,12),[13,31],(36,)", "(4,5),[7],(9,10),[15,20),(30,31],[37]");
  1887. }
  1888. void testStr2()
  1889. {
  1890. RtlStringTypeInfo str1(type_string, 1);
  1891. Owned<IValueSet> az = createValueSet(str1);
  1892. addRange(az, "A", "Z");
  1893. checkSet(az, "['A','Z']");
  1894. Owned<IValueSet> dj = createValueSet(str1);
  1895. addRange(dj, "D", "J");
  1896. checkSet(dj, "['D','J']");
  1897. Owned<IValueSet> hz = createValueSet(str1);
  1898. addRange(hz, "H", "Z");
  1899. Owned<IValueSet> jk = createValueSet(str1);
  1900. addRange(jk, "J", "K");
  1901. Owned<IValueSet> kj = createValueSet(str1);
  1902. addRange(kj, "K", "J");
  1903. checkSet(kj, "");
  1904. }
  1905. // id:int2 extra:string padding:! name:string2
  1906. // Keep in sorted order so they can be reused for index testing
  1907. const char *testRows[6] = {
  1908. "\002\000\000\000\000\000!AB",
  1909. "\001\000\004\000\000\000MARK!GH",
  1910. "\000\001\003\000\000\000FRY!JH",
  1911. "\001\001\003\000\000\000MAR!AC",
  1912. "\002\001\003\000\000\000MAS!JH",
  1913. "\003\001\004\000\000\000MASK!JH",
  1914. };
  1915. //testFilter("id=[1,3];name=(,GH)", { false, true, false, false, false });
  1916. void testFilter(const char * originalFilter, const std::initializer_list<bool> & expected)
  1917. {
  1918. const byte * * rows = reinterpret_cast<const byte * *>(testRows);
  1919. RtlIntTypeInfo int2(type_int, 2);
  1920. RtlStringTypeInfo str1(type_string, 2);
  1921. RtlStringTypeInfo str2(type_string, 2);
  1922. RtlStringTypeInfo strx(type_string|RFTMunknownsize, 0);
  1923. RtlFieldInfo id("id", nullptr, &int2);
  1924. RtlFieldInfo extra("extra", nullptr, &strx);
  1925. RtlFieldInfo padding("padding", nullptr, &str1);
  1926. RtlFieldInfo name("name", nullptr, &str2);
  1927. const RtlFieldInfo * fields[] = { &id, &extra, &padding, &name, nullptr };
  1928. RtlRecordTypeInfo recordType(type_record, 4, fields);
  1929. RtlRecord record(recordType, true);
  1930. RowFilter cursor;
  1931. const char * filter = originalFilter;
  1932. while (filter && *filter)
  1933. {
  1934. StringBuffer next;
  1935. const char * semi = strchr(filter, ';');
  1936. if (semi)
  1937. {
  1938. next.append(semi-filter, filter);
  1939. filter = semi+1;
  1940. }
  1941. else
  1942. {
  1943. next.append(filter);
  1944. filter = nullptr;
  1945. }
  1946. const char * equal = strchr(next, '=');
  1947. assertex(equal);
  1948. StringBuffer fieldName(equal-next, next);
  1949. unsigned fieldNum = record.getFieldNum(fieldName);
  1950. assertex(fieldNum != (unsigned) -1);
  1951. const RtlTypeInfo *fieldType = record.queryType(fieldNum);
  1952. Owned<IValueSet> set = createValueSet(*fieldType);
  1953. deserializeSet(*set, equal+1);
  1954. cursor.addFilter(*new SetFieldFilter(fieldNum, set));
  1955. }
  1956. RtlDynRow row(record, nullptr);
  1957. assertex((expected.end() - expected.begin()) == (unsigned)_elements_in(testRows));
  1958. const bool * curExpected = expected.begin();
  1959. for (unsigned i= 0; i < _elements_in(testRows); i++)
  1960. {
  1961. row.setRow(rows[i]);
  1962. if (cursor.matches(row) != curExpected[i])
  1963. {
  1964. printf("Failure to match row %u filter '%s'\n", i, originalFilter);
  1965. CPPUNIT_ASSERT_EQUAL(curExpected[i], cursor.matches(row));
  1966. }
  1967. }
  1968. };
  1969. void testFilter()
  1970. {
  1971. testFilter("", { true, true, true, true, true, true });
  1972. testFilter("id=[1]", { false, true, false, false, false, false });
  1973. testFilter("id=[1,2]", { true, true, false, false, false, false });
  1974. testFilter("id=(1,2]", { true, false, false, false, false, false });
  1975. testFilter("id=[1,3];name=(,GH)", { true, false, false, false, false, false });
  1976. testFilter("id=[1,3];name=(,GH)", { true, false, false, false, false, false });
  1977. testFilter("extra=['MAR','MAS']", { false, true, false, true, true, false });
  1978. testFilter("extra=('MAR','MAS')", { false, true, false, false, false, false });
  1979. testFilter("id=(,257]", { true, true, true, true, false, false });
  1980. }
  1981. };
  1982. CPPUNIT_TEST_SUITE_REGISTRATION(ValueSetTest);
  1983. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ValueSetTest, "ValueSetTest");
  1984. #endif