rtlnewkey.cpp 72 KB

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