hqlfilter.cpp 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "jliball.hpp"
  14. #include "hql.hpp"
  15. #include "platform.h"
  16. #include "jlib.hpp"
  17. #include "jmisc.hpp"
  18. #include "jstream.ipp"
  19. #include "jdebug.hpp"
  20. #include "eclrtl_imp.hpp"
  21. #include "rtlkey.hpp"
  22. #include "hql.hpp"
  23. #include "hqlattr.hpp"
  24. #include "hqlmeta.hpp"
  25. #include "hqlthql.hpp"
  26. #include "hqlutil.hpp"
  27. #include "hqlthql.hpp"
  28. #include "hqlfold.hpp"
  29. #include "hqltrans.ipp"
  30. #include "hqlpmap.hpp"
  31. #include "hqlfilter.hpp"
  32. #include "hqlerrors.hpp"
  33. //-----------------------------------------------------------------------------------------------
  34. //-- Index processing
  35. //-----------------------------------------------------------------------------------------------
  36. /*
  37. Note on generating segment monitors for conditions (ty)x = Y
  38. 1) casting from Tx to Ty loses information. E.g., (int1)string2field = int1value.
  39. In this case it is almost impossible to generate a segment monitor because we would need to work out all
  40. the possibly values for x which could generate the value y.
  41. The only exception is an inequality (and no_notin), which we can use to remove some of the candidates. The test will always need
  42. duplicating since we cannot remove all the expected values.
  43. 2) Casting from Ty to Tx loses information. E.g., (string)string2field = stringvalue
  44. In this case we can process the filter without prefiltering by testing whether isExact: (Ty)(Tx)Y == Y, and following the following rules:
  45. a) no_eq. If isExact, add value else nothing.
  46. b) no_ne. If isExtact, remove value else nothing.
  47. c) no_gt. Always add > value
  48. d) no_ge. If isExact add >= value else add > value
  49. e) no_lt. If isExact add < value else add <= value
  50. f) no_le. Always add <= value
  51. 3) Note casts must be present on both sides to indicate exactly what type the comparison will be done as. This includes (string)which would
  52. normally be missing if the field was of type string<n>.
  53. */
  54. static node_operator getModifiedOp(node_operator op, bool duplicate)
  55. {
  56. if (!duplicate)
  57. return op;
  58. switch (op)
  59. {
  60. case no_eq:
  61. case no_le:
  62. case no_ge:
  63. case no_in:
  64. return op;
  65. //err on the side of caution for the segment monitors -
  66. //the test later which check it more accurately.
  67. case no_gt:
  68. return no_ge;
  69. case no_lt:
  70. return no_le;
  71. case no_ne:
  72. case no_notin:
  73. return no_none;
  74. default:
  75. UNIMPLEMENTED;
  76. }
  77. }
  78. static IHqlExpression * querySubStringRange(IHqlExpression * expr)
  79. {
  80. for(;;)
  81. {
  82. switch (expr->getOperator())
  83. {
  84. case no_substring:
  85. return expr->queryChild(1);
  86. case no_cast:
  87. case no_implicitcast:
  88. break;
  89. default:
  90. return nullptr;
  91. }
  92. expr = expr->queryChild(0);
  93. }
  94. }
  95. void KeyFailureInfo::merge(const KeyFailureInfo & other)
  96. {
  97. if (code < other.code)
  98. set(other.code, other.field);
  99. }
  100. void KeyFailureInfo::reportError(IErrorReceiver & errorReceiver, IHqlExpression * condition)
  101. {
  102. StringBuffer ecl;
  103. getExprECL(condition, ecl);
  104. switch (code)
  105. {
  106. case KFRunknown:
  107. errorReceiver.throwError1(HQLERR_KeyedJoinTooComplex, ecl.str());
  108. case KFRnokey:
  109. errorReceiver.throwError1(HQLERR_KeyAccessNoKeyField, ecl.str());
  110. case KFRtoocomplex:
  111. errorReceiver.throwError1(HQLERR_KeyedJoinTooComplex, ecl.str());
  112. case KFRcast:
  113. errorReceiver.throwError2(HQLERR_KeyAccessNeedCast, ecl.str(), str(field->queryName()));
  114. case KFRor:
  115. errorReceiver.throwError1(HQLERR_OrMultipleKeyfields, ecl.str());
  116. }
  117. }
  118. IHqlExpression * KeyConditionInfo::createConjunction()
  119. {
  120. LinkedHqlExpr result = preFilter;
  121. ForEachItemIn(i, conditions)
  122. extendAndCondition(result, conditions.item(i).expr);
  123. extendAndCondition(result, postFilter);
  124. return result.getClear();
  125. }
  126. bool KeyConditionInfo::isSingleMatchCondition() const
  127. {
  128. if (preFilter || postFilter)
  129. return false;
  130. IHqlExpression * prevSelector = nullptr;
  131. ForEachItemIn(i, conditions)
  132. {
  133. KeyCondition & condition = conditions.item(i);
  134. IHqlExpression * selector = condition.selector;
  135. if (!prevSelector)
  136. prevSelector = selector;
  137. else if (prevSelector != selector)
  138. return false;
  139. }
  140. return (prevSelector != nullptr);
  141. }
  142. //---------------------------------------------------------------------------------------------------------------------
  143. const char * KeySelectorInfo::getFFOptions()
  144. {
  145. switch (keyedKind)
  146. {
  147. case KeyedExtend:
  148. return "FFopt";
  149. default:
  150. return "FFkeyed";
  151. }
  152. }
  153. //---------------------------------------------------------------------------------------------------------------------
  154. IHqlExpression * getExplicitlyPromotedCompare(IHqlExpression * filter)
  155. {
  156. switch (filter->getOperator())
  157. {
  158. case no_in:
  159. case no_notin:
  160. return LINK(filter);
  161. }
  162. IHqlExpression * l = filter->queryChild(0);
  163. IHqlExpression * r = filter->queryChild(1);
  164. ITypeInfo * lType = queryUnqualifiedType(l->queryType());
  165. ITypeInfo * rType = queryUnqualifiedType(r->queryType());
  166. if (lType == rType)
  167. return LINK(filter);
  168. //Add explicit casts to the type. ensureExprType won't add a (string) to a string2 field.
  169. Owned<ITypeInfo> promotedType = getPromotedECLType(lType, rType);
  170. HqlExprArray args;
  171. if (lType == promotedType)
  172. args.append(*LINK(l));
  173. else
  174. args.append(*createValue(no_implicitcast, LINK(promotedType), LINK(l)));
  175. args.append(*ensureExprType(r, promotedType));
  176. return filter->clone(args);
  177. }
  178. //---------------------------------------------------------------------------------------------------------------------
  179. static IHqlExpression * createExpandedRecord(IHqlExpression * expr);
  180. static ITypeInfo * getExpandedFieldType(ITypeInfo * type, IHqlExpression * expr)
  181. {
  182. Linked<ITypeInfo> expandedType = type;
  183. if (type->getSize() == UNKNOWN_LENGTH)
  184. expandedType.clear();
  185. switch (type->getTypeCode())
  186. {
  187. case type_packedint:
  188. expandedType.setown(makeIntType(type->queryPromotedType()->getSize(), type->isSigned()));
  189. break;
  190. case type_bitfield:
  191. expandedType.set(type->queryPromotedType());
  192. break;
  193. case type_varstring:
  194. case type_varunicode:
  195. #if 0
  196. if (type->getSize() != UNKNOWN_LENGTH)
  197. {
  198. unsigned len = type->getStringLen();
  199. switch (type->getTypeCode())
  200. {
  201. case type_varstring:
  202. expandedType.setown(makeStringType(len, LINK(type->queryCharset()), LINK(type->queryCollation())));
  203. break;
  204. case type_varunicode:
  205. expandedType.setown(makeUnicodeType(len, type->queryLocale()));
  206. break;
  207. }
  208. break;
  209. }
  210. #endif //fall through
  211. case type_data:
  212. case type_qstring:
  213. case type_string:
  214. case type_unicode:
  215. case type_utf8:
  216. if (type->getSize() == UNKNOWN_LENGTH)
  217. {
  218. unsigned maxLength = UNKNOWN_LENGTH;
  219. IHqlExpression * maxSizeExpr = expr ? queryAttributeChild(expr, maxSizeAtom, 0) : NULL;
  220. if (maxSizeExpr)
  221. {
  222. unsigned maxSize = (unsigned)maxSizeExpr->queryValue()->getIntValue();
  223. switch (type->getTypeCode())
  224. {
  225. case type_data:
  226. case type_string:
  227. maxLength = maxSize - sizeof(size32_t);
  228. break;
  229. case type_qstring:
  230. maxLength = rtlQStrLength(maxSize - sizeof(size32_t));
  231. break;
  232. case type_unicode:
  233. maxLength = (maxSize-sizeof(size32_t))/sizeof(UChar);
  234. break;
  235. case type_utf8:
  236. maxLength = (maxSize-sizeof(size32_t))/4;
  237. break;
  238. case type_varstring:
  239. maxLength = maxSize - 1;
  240. break;
  241. case type_varunicode:
  242. maxLength = (maxSize/sizeof(UChar)) - 1;
  243. break;
  244. }
  245. }
  246. else
  247. {
  248. IHqlExpression * maxLengthExpr = expr ? queryAttributeChild(expr, maxLengthAtom, 0) : NULL;
  249. if (maxLengthExpr)
  250. maxLength = (unsigned)maxLengthExpr->queryValue()->getIntValue();
  251. }
  252. if (maxLength != UNKNOWN_LENGTH)
  253. {
  254. switch (type->getTypeCode())
  255. {
  256. case type_data:
  257. expandedType.setown(makeDataType(maxLength));
  258. break;
  259. case type_qstring:
  260. expandedType.setown(makeQStringType(maxLength));
  261. break;
  262. case type_string:
  263. expandedType.setown(makeStringType(maxLength, LINK(type->queryCharset()), LINK(type->queryCollation())));
  264. break;
  265. case type_unicode:
  266. expandedType.setown(makeUnicodeType(maxLength, type->queryLocale()));
  267. break;
  268. case type_utf8:
  269. expandedType.setown(makeUtf8Type(maxLength, type->queryLocale()));
  270. break;
  271. case type_varstring:
  272. expandedType.setown(makeVarStringType(maxLength, LINK(type->queryCharset()), LINK(type->queryCollation())));
  273. break;
  274. case type_varunicode:
  275. expandedType.setown(makeVarUnicodeType(maxLength, type->queryLocale()));
  276. break;
  277. }
  278. }
  279. }
  280. else
  281. {
  282. //This could ensure the strings are ascii, but the ebcdic strings are still comparable, and the order will be more logical
  283. //if they remain as ebcdic.
  284. }
  285. break;
  286. case type_table:
  287. case type_groupedtable:
  288. case type_set:
  289. expandedType.clear();
  290. break;
  291. case type_row:
  292. {
  293. OwnedHqlExpr newRecord = createExpandedRecord(queryRecord(type));
  294. if (isEmptyRecord(newRecord))
  295. expandedType.clear();
  296. else
  297. expandedType.setown(makeRowType(LINK(newRecord->queryRecordType())));
  298. break;
  299. }
  300. case type_alien:
  301. {
  302. IHqlAlienTypeInfo * alien = queryAlienType(type);
  303. expandedType.set(alien->queryLogicalType());
  304. break;
  305. }
  306. }
  307. return expandedType.getClear();
  308. }
  309. static void createExpanded(HqlExprArray & fields, IHqlExpression * expr)
  310. {
  311. switch (expr->getOperator())
  312. {
  313. case no_ifblock:
  314. //if blocks need to generate translated segment monitors to be keyed, so don't expand them
  315. break;
  316. case no_record:
  317. {
  318. ForEachChild(i, expr)
  319. createExpanded(fields, expr->queryChild(i));
  320. break;
  321. }
  322. case no_field:
  323. {
  324. ITypeInfo * type = expr->queryType();
  325. Owned<ITypeInfo> expandedType = getExpandedFieldType(type, expr);
  326. if (expandedType)
  327. {
  328. if (expandedType == type)
  329. fields.append(*LINK(expr));
  330. else
  331. {
  332. HqlExprArray attrs;
  333. unwindChildren(attrs, expr);
  334. //MORE: Any default will now have the wrong type => remove it for the moment (ideally it would be projected)
  335. removeAttribute(attrs, defaultAtom);
  336. fields.append(*createField(expr->queryId(), LINK(expandedType), attrs));
  337. }
  338. }
  339. break;
  340. }
  341. case no_attr:
  342. case no_attr_link:
  343. case no_attr_expr:
  344. fields.append(*LINK(expr));
  345. break;
  346. }
  347. }
  348. static IHqlExpression * createExpandedRecord(IHqlExpression * expr)
  349. {
  350. HqlExprArray fields;
  351. createExpanded(fields, expr);
  352. return cloneOrLink(expr, fields);
  353. }
  354. IHqlExpression * castToFieldAndBack(IHqlExpression * left, IHqlExpression * right)
  355. {
  356. node_operator op = left->getOperator();
  357. switch (op)
  358. {
  359. case no_cast:
  360. case no_implicitcast:
  361. {
  362. IHqlExpression * uncast = left->queryChild(0);
  363. ITypeInfo * castType = right->queryType();
  364. ITypeInfo * uncastType = uncast->queryType();
  365. OwnedHqlExpr castRight = ensureExprType(right, uncastType);
  366. OwnedHqlExpr base = castToFieldAndBack(uncast, castRight);
  367. //If this cast doesn't lose any information and child didn't change then don't bother
  368. //casting back and forwards.
  369. if ((base == castRight) && !castLosesInformation(uncastType, castType))
  370. return LINK(right);
  371. return ensureExprType(base, castType);
  372. }
  373. case no_select:
  374. {
  375. ITypeInfo * leftType = left->queryType();
  376. ITypeInfo * rightType = right->queryType();
  377. if (leftType == rightType || !castLosesInformation(leftType, rightType))
  378. return LINK(right);
  379. OwnedHqlExpr castToField = ensureExprType(right, leftType);
  380. return ensureExprType(castToField, rightType);
  381. }
  382. case no_substring:
  383. {
  384. OwnedHqlExpr cast = castToFieldAndBack(left->queryChild(0), right);
  385. //Theoretically needed for all types. In practice this only makes a difference for data since strings
  386. //ignore trailing spaces
  387. if (left->queryType()->getTypeCode() == type_data)
  388. return replaceChild(left, 0, cast.getClear());
  389. return cast.getClear();
  390. }
  391. case no_add:
  392. case no_sub:
  393. return castToFieldAndBack(left->queryChild(0), right);
  394. default:
  395. throwUnexpected();
  396. }
  397. }
  398. //---------------------------------------------------------------------------------------------------------------------
  399. FilterExtractor::FilterExtractor(IErrorReceiver & _errorReceiver, IHqlExpression * _tableExpr, int _numKeyableFields, bool _isDiskRead, bool forceValueSets)
  400. : errorReceiver(_errorReceiver), createValueSets(forceValueSets)
  401. {
  402. tableExpr = _tableExpr;
  403. if (_numKeyableFields <= 0)
  404. {
  405. //-ve number means remove a certain number of fields from the record
  406. IHqlExpression * record = tableExpr->queryRecord();
  407. numKeyableFields = 0;
  408. ForEachChild(i, record)
  409. if (!record->queryChild(i)->isAttribute())
  410. numKeyableFields++;
  411. numKeyableFields += _numKeyableFields; // remove payload fields.
  412. }
  413. else
  414. numKeyableFields = (unsigned)_numKeyableFields;
  415. onlyHozedCompares = !_isDiskRead;
  416. excludeVirtuals = _isDiskRead;
  417. expandKeyableFields();
  418. cleanlyKeyedExplicitly = false;
  419. keyedExplicitly = false;
  420. allowDynamicFormatChange = !tableExpr->hasAttribute(fixedAtom);
  421. }
  422. bool FilterExtractor::isSingleMatchCondition() const
  423. {
  424. return keyed.isSingleMatchCondition();
  425. }
  426. void FilterExtractor::expandKeyableFields()
  427. {
  428. HqlExprArray fields;
  429. IHqlExpression * tableRecord = tableExpr->queryRecord();
  430. unsigned cnt = 0;
  431. ForEachChild(i, tableRecord)
  432. {
  433. if (cnt == numKeyableFields)
  434. break;
  435. IHqlExpression * cur = tableRecord->queryChild(i);
  436. if (!cur->isAttribute())
  437. {
  438. if (!(excludeVirtuals && cur->hasAttribute(virtualAtom)))
  439. {
  440. fields.append(*LINK(cur));
  441. cnt++;
  442. }
  443. }
  444. }
  445. keyableRecord.setown(createRecord(fields));
  446. if (createValueSets)
  447. expandedRecord.set(keyableRecord);
  448. else
  449. expandedRecord.setown(createExpandedRecord(keyableRecord));
  450. IHqlExpression * selector = tableExpr->queryNormalizedSelector();
  451. OwnedHqlExpr expandedSelector = createDataset(no_anon, LINK(expandedRecord), createUniqueId());
  452. firstOffsetField = NotFound;
  453. expandSelects(keyableRecord, expandedRecord->querySimpleScope(), selector, expandedSelector);
  454. if (firstOffsetField == NotFound)
  455. firstOffsetField = keyableSelects.ordinality();
  456. }
  457. void FilterExtractor::expandSelects(IHqlExpression * expr, IHqlSimpleScope * expandedScope, IHqlExpression * keySelector, IHqlExpression * expandedSelector)
  458. {
  459. switch (expr->getOperator())
  460. {
  461. case no_record:
  462. {
  463. ForEachChild(i, expr)
  464. expandSelects(expr->queryChild(i), expandedScope, keySelector, expandedSelector);
  465. break;
  466. }
  467. case no_ifblock:
  468. expandSelects(expr->queryChild(1), expandedScope, keySelector, expandedSelector);
  469. break;
  470. case no_field:
  471. {
  472. OwnedHqlExpr match = expandedScope->lookupSymbol(expr->queryId());
  473. if (match)
  474. {
  475. OwnedHqlExpr keySelected = createSelectExpr(LINK(keySelector), LINK(expr));
  476. OwnedHqlExpr expandedSelected = createSelectExpr(LINK(expandedSelector), LINK(match));
  477. IHqlExpression * record = expr->queryRecord();
  478. if (expr->isDatarow())
  479. expandSelects(record, match->queryRecord()->querySimpleScope(), keySelected, expandedSelected);
  480. else
  481. {
  482. if ((expr != match) && (firstOffsetField == NotFound))
  483. {
  484. ITypeInfo * exprType = expr->queryType();
  485. ITypeInfo * matchType = match->queryType();
  486. if ((exprType->getSize() != matchType->getSize()) ||
  487. (exprType->getTypeCode() == type_bitfield || matchType->getTypeCode() == type_bitfield))
  488. firstOffsetField = keyableSelects.ordinality();
  489. }
  490. keyableSelects.append(*LINK(keySelected));
  491. expandedSelects.append(*LINK(expandedSelected));
  492. }
  493. }
  494. else
  495. {
  496. if (firstOffsetField == NotFound)
  497. firstOffsetField = keyableSelects.ordinality();
  498. }
  499. break;
  500. }
  501. }
  502. }
  503. IHqlExpression * FilterExtractor::unwindConjunction(HqlExprArray & matches, IHqlExpression * expr)
  504. {
  505. node_operator op = expr->getOperator();
  506. expr->unwindList(matches, op);
  507. OwnedHqlExpr invariant;
  508. ForEachItemInRev(i, matches)
  509. {
  510. IHqlExpression & cur = matches.item(i);
  511. if (isIndexInvariant(&cur, false))
  512. {
  513. invariant.setown(extendConditionOwn(op, LINK(&cur), invariant.getClear()));
  514. matches.remove(i);
  515. }
  516. }
  517. return invariant.getClear();
  518. }
  519. bool FilterExtractor::isKeySelect(IHqlExpression * select)
  520. {
  521. return (keyableSelects.find(*select) != NotFound);
  522. }
  523. bool FilterExtractor::isEqualityFilter(IHqlExpression * search)
  524. {
  525. bool matched = false;
  526. ForEachItemIn(cond, keyed.conditions)
  527. {
  528. KeyCondition & cur = keyed.conditions.item(cond);
  529. if (cur.selector == search)
  530. {
  531. if (!cur.isWild)
  532. {
  533. if (matched)
  534. return false;
  535. matched = true;
  536. IHqlExpression * matchExpr = cur.expr;
  537. if (matchExpr->getOperator() != no_eq)
  538. return false;
  539. }
  540. }
  541. }
  542. return matched;
  543. }
  544. bool FilterExtractor::isEqualityFilterBefore(IHqlExpression * select)
  545. {
  546. ForEachItemIn(i, keyableSelects)
  547. {
  548. IHqlExpression & cur = keyableSelects.item(i);
  549. if (select == &cur)
  550. return true;
  551. if (!isEqualityFilter(&cur))
  552. return false;
  553. }
  554. throwUnexpected();
  555. }
  556. bool FilterExtractor::isPrevSelectKeyed(IHqlExpression * select)
  557. {
  558. unsigned match = keyableSelects.find(*select);
  559. assertex(match != NotFound);
  560. if (match == 0)
  561. return true;
  562. IHqlExpression * prev = &keyableSelects.item(match-1);
  563. ForEachItemIn(i, keyed.conditions)
  564. {
  565. KeyCondition & cur = keyed.conditions.item(i);
  566. if (cur.selector == prev)
  567. {
  568. if (!cur.isWild && cur.isKeyed())
  569. return true;
  570. if (cur.wasKeyed)
  571. return true;
  572. }
  573. }
  574. return false;
  575. }
  576. bool FilterExtractor::okToKey(IHqlExpression * select, KeyedKind keyedKind)
  577. {
  578. if (keyedKind == KeyedYes)
  579. return true;
  580. ForEachItemIn(i, keyed.conditions)
  581. {
  582. KeyCondition & cur = keyed.conditions.item(i);
  583. if (cur.selector == select && cur.isWild)
  584. return false;
  585. }
  586. return true;
  587. }
  588. bool FilterExtractor::isIndexInvariant(IHqlExpression * expr, bool includeRoot)
  589. {
  590. if (containsAssertKeyed(expr))
  591. return false;
  592. HqlExprCopyArray scopeUsed;
  593. expr->gatherTablesUsed(scopeUsed);
  594. IHqlExpression * search = tableExpr->queryNormalizedSelector();
  595. ForEachItemIn(i, scopeUsed)
  596. {
  597. IHqlExpression * cur = &scopeUsed.item(i);
  598. for (;;)
  599. {
  600. if (cur == search)
  601. return false;
  602. if (includeRoot && (queryRoot(cur) == search))
  603. return false;
  604. IHqlExpression * parent = queryNextMultiLevelDataset(cur, true);
  605. if (!parent)
  606. break;
  607. cur = parent;
  608. }
  609. }
  610. return true;
  611. }
  612. IHqlExpression * FilterExtractor::invertTransforms(IHqlExpression * left, IHqlExpression * right)
  613. {
  614. node_operator op = left->getOperator();
  615. switch (op)
  616. {
  617. case no_cast:
  618. case no_implicitcast:
  619. {
  620. assertex(right->queryType()->getTypeCode() != type_set);
  621. IHqlExpression * uncast = left->queryChild(0);
  622. ITypeInfo * uncastType = uncast->queryType();
  623. OwnedHqlExpr castRight = ensureExprType(right, uncastType);
  624. return invertTransforms(uncast, castRight);
  625. }
  626. case no_select:
  627. {
  628. assertex(isKeySelect(left));
  629. ITypeInfo * leftType = left->queryType();
  630. ITypeInfo * rightType = right->queryType();
  631. if (!createValueSets)
  632. {
  633. if (leftType == rightType || !castLosesInformation(leftType, rightType))
  634. return LINK(right);
  635. }
  636. return ensureExprType(right, leftType);
  637. }
  638. case no_add:
  639. case no_sub:
  640. {
  641. assertex(right->getOperator() != no_list);
  642. OwnedHqlExpr adjusted = createValue(op == no_sub ? no_add : no_sub, right->getType(), LINK(right), LINK(left->queryChild(1)));
  643. return invertTransforms(left->queryChild(0), adjusted);
  644. }
  645. case no_substring:
  646. {
  647. assertex(right->getOperator() != no_list);
  648. return invertTransforms(left->queryChild(0), right);
  649. }
  650. default:
  651. UNIMPLEMENTED;
  652. }
  653. }
  654. IHqlExpression * FilterExtractor::queryKeyableSelector(IHqlExpression * expr)
  655. {
  656. switch (expr->getOperator())
  657. {
  658. case no_cast:
  659. case no_implicitcast:
  660. case no_add:
  661. case no_sub:
  662. return queryKeyableSelector(expr->queryChild(0));
  663. case no_select:
  664. if (isKeySelect(expr))
  665. return expr;
  666. return NULL;
  667. }
  668. return NULL;
  669. }
  670. IHqlExpression * FilterExtractor::isKeyableFilter(IHqlExpression * left, IHqlExpression * right, bool & duplicate, node_operator compareOp, KeyFailureInfo & reason, KeyedKind keyedKind)
  671. {
  672. node_operator op = left->getOperator();
  673. switch (op)
  674. {
  675. case no_cast:
  676. case no_implicitcast:
  677. {
  678. IHqlExpression * uncast = left->queryChild(0);
  679. ITypeInfo * castType = left->queryType();
  680. ITypeInfo * uncastType = uncast->queryType();
  681. //Keyed filters on alien datatypes do not work, and can trigger an internal error in ensureExprType()
  682. if (uncastType->getTypeCode() == type_alien)
  683. {
  684. reason.set(KFRtoocomplex, left);
  685. return nullptr;
  686. }
  687. //(ty)x = y. E.g., (int1)string2field = int1value
  688. //if more than one value of x[uncastType] corresponds to a single value in y[castType] then we can't sensibly create
  689. //the key segment monitor. Because we will get false negatives. If it is an inverse then duplicate (see below)
  690. bool canRemoveCast = true;
  691. if (castLosesInformation(castType, uncastType))
  692. {
  693. if ((compareOp != no_ne) && (compareOp != no_notin))
  694. canRemoveCast = false;
  695. duplicate = true;
  696. }
  697. //if more than one value of y corresponds to a single value of x then need to duplicate the test condition.
  698. //or pretest whether (ty)(tx)y == y.
  699. //if (castLosesInformation(uncastType, castType))
  700. //Now taken care of when the segment monitors are created
  701. //If the comparison is non equality and the cast changes the collation sequence then you can't remove it.
  702. switch (compareOp)
  703. {
  704. case no_eq:
  705. case no_ne:
  706. case no_in:
  707. case no_notin:
  708. break;
  709. default:
  710. if (!preservesOrder(castType, uncastType))
  711. canRemoveCast = false;
  712. break;
  713. }
  714. Linked<ITypeInfo> newType = uncastType;
  715. if (right->queryType()->getTypeCode() == type_set)
  716. newType.setown(makeSetType(newType.getLink()));
  717. OwnedHqlExpr castRight = ensureExprType(right, newType);
  718. IHqlExpression * ret = isKeyableFilter(uncast, castRight, duplicate, compareOp, reason, keyedKind);
  719. if (canRemoveCast || !ret)
  720. return ret;
  721. reason.set(KFRcast, ret->queryChild(1));
  722. return NULL;
  723. }
  724. case no_select:
  725. if (isKeySelect(left) && okToKey(left, keyedKind))
  726. {
  727. if (isIndexInvariant(right, false))
  728. return left;
  729. reason.set(KFRtoocomplex, left);
  730. }
  731. else
  732. reason.set(KFRnokey);
  733. return NULL;
  734. case no_substring:
  735. {
  736. IHqlExpression * range = left->queryChild(1);
  737. if (range->getOperator() == no_rangeto)
  738. {
  739. IValue *end = range->queryChild(0)->queryValue();
  740. if (!createValueSets && !end)
  741. break;
  742. return isKeyableFilter(left->queryChild(0), right, duplicate, compareOp, reason, keyedKind);
  743. }
  744. else if (range->getOperator() == no_range)
  745. {
  746. if (!matchesConstantValue(range->queryChild(0), 1))
  747. break;
  748. if (!createValueSets && !range->queryChild(1)->queryValue())
  749. break;
  750. return isKeyableFilter(left->queryChild(0), right, duplicate, compareOp, reason, keyedKind);
  751. }
  752. reason.set(KFRtoocomplex, right);
  753. return NULL;
  754. }
  755. case no_add:
  756. case no_sub:
  757. if (isIndexInvariant(left->queryChild(1), false))
  758. return isKeyableFilter(left->queryChild(0), right, duplicate, compareOp, reason, keyedKind);
  759. reason.set(KFRtoocomplex, left);
  760. return NULL;
  761. }
  762. reason.set(KFRnokey);
  763. return NULL;
  764. }
  765. static IHqlExpression * getCompareValue(ITypeInfo * fieldType, unsigned subStringLen, IValue * value, int whichBoundary)
  766. {
  767. type_t ftc = fieldType->getTypeCode();
  768. unsigned fieldLen = fieldType->getStringLen();
  769. unsigned lenValue = value->queryType()->getStringLen();
  770. const void * rawValue = value->queryValue();
  771. size32_t resultLen;
  772. rtlDataAttr result;
  773. if (whichBoundary < 0)
  774. {
  775. switch (ftc)
  776. {
  777. case type_qstring:
  778. rtlCreateQStrRangeLow(resultLen, result.refstr(), fieldLen, subStringLen, lenValue, static_cast<const char *>(rawValue));
  779. break;
  780. case type_string:
  781. rtlCreateStrRangeLow(resultLen, result.refstr(), fieldLen, subStringLen, lenValue, static_cast<const char *>(rawValue));
  782. break;
  783. case type_data:
  784. rtlCreateDataRangeLow(resultLen, result.refdata(), fieldLen, subStringLen, lenValue, rawValue);
  785. break;
  786. case type_unicode:
  787. rtlCreateUnicodeRangeLow(resultLen, result.refustr(), fieldLen, subStringLen, lenValue, static_cast<const UChar *>(rawValue));
  788. break;
  789. default:
  790. //should this generate a warning/error instead?
  791. rtlCreateRange(resultLen, result.refstr(), fieldLen, subStringLen, fieldType->getSize(), static_cast<const char *>(rawValue), 0, 0);
  792. break;
  793. }
  794. }
  795. else
  796. {
  797. switch (ftc)
  798. {
  799. case type_qstring:
  800. rtlCreateQStrRangeHigh(resultLen, result.refstr(), fieldLen, subStringLen, lenValue, static_cast<const char *>(rawValue));
  801. break;
  802. case type_string:
  803. rtlCreateStrRangeHigh(resultLen, result.refstr(), fieldLen, subStringLen, lenValue, static_cast<const char *>(rawValue));
  804. break;
  805. case type_data:
  806. rtlCreateDataRangeHigh(resultLen, result.refdata(), fieldLen, subStringLen, lenValue, rawValue);
  807. break;
  808. case type_unicode:
  809. rtlCreateUnicodeRangeHigh(resultLen, result.refustr(), fieldLen, subStringLen, lenValue, static_cast<const UChar *>(rawValue));
  810. break;
  811. default:
  812. rtlCreateRange(resultLen, result.refstr(), fieldLen, subStringLen, fieldType->getSize(), static_cast<const char *>(rawValue), 255, 0);
  813. break;
  814. }
  815. }
  816. assertex(resultLen == fieldLen);
  817. return createConstant(createValueFromMem(LINK(fieldType), result.getdata()));
  818. }
  819. static IHqlExpression * removeCastTrim(IHqlExpression * expr)
  820. {
  821. for (;;)
  822. {
  823. if ((expr->getOperator() == no_trim) && !expr->queryChild(1))
  824. expr = expr->queryChild(0);
  825. else if (isLengthPreservingCast(expr))
  826. expr = expr->queryChild(0);
  827. else
  828. return expr;
  829. expr = queryNonAliased(expr);
  830. }
  831. }
  832. static IHqlExpression * queryLengthFromRange(IHqlExpression * range)
  833. {
  834. switch (range->getOperator())
  835. {
  836. case no_rangefrom:
  837. case no_rangecommon:
  838. return NULL;
  839. case no_rangeto:
  840. return range->queryChild(0);
  841. case no_range:
  842. if (getIntValue(range->queryChild(0), 0) == 1)
  843. return range->queryChild(1);
  844. return NULL;
  845. default:
  846. if (getIntValue(range, 0) == 1)
  847. return range;
  848. return NULL;
  849. }
  850. }
  851. static void extendRangeCheck(SharedHqlExpr & globalGuard, SharedHqlExpr & localCond, IHqlExpression * selector, IHqlExpression * lengthExpr, bool compareEqual)
  852. {
  853. #if 0
  854. //This might be a good idea, but probably doesn't make a great deal of difference at runtime
  855. //Optimize the case where you check zero length to use a wild carded range instead
  856. //x[1..len=0] = y from x in range 0000000..FFFFFF to len==0 || x in range....
  857. if (compareEqual)
  858. {
  859. if (!lengthExpr->queryValue())
  860. {
  861. OwnedHqlExpr testLength = createBoolExpr(no_eq, LINK(lengthExpr), ensureExprType(queryZero(), lengthExpr->queryType()));
  862. localCond.setown(createBoolExpr(no_or, testLength.getClear(), LINK(localCond)));
  863. }
  864. }
  865. #endif
  866. //For a range check x[1..m] = y we generate
  867. //x in range(sizeof(x), m, y, 0) and range(maxlength(x), m, y, 255)
  868. //need to guard with condition len(trim(y)) <= m
  869. //If x[1..length(trim(y))] == y then don't add a condition
  870. IHqlExpression * cur = queryNonAliased(lengthExpr);
  871. IHqlExpression * compare = removeCastTrim(queryNonAliased(selector));
  872. if (cur->getOperator() == no_charlen)
  873. {
  874. cur = queryNonAliased(cur->queryChild(0));
  875. if (cur->getOperator() == no_trim)
  876. {
  877. cur = queryNonAliased(cur->queryChild(0));
  878. while (isLengthPreservingCast(cur))
  879. cur = queryNonAliased(cur->queryChild(0));
  880. IHqlExpression * compare = selector;
  881. for (;;)
  882. {
  883. compare = removeCastTrim(queryNonAliased(compare));
  884. if (cur->queryBody() == compare->queryBody())
  885. return;
  886. //Casts between strings that reduce/increase the number of characters don't matter as long as
  887. //they eventually match the search string
  888. if (!isCast(compare) || !isStringType(compare->queryType()))
  889. break;
  890. compare = compare->queryChild(0);
  891. if (!isStringType(compare->queryType()))
  892. break;
  893. }
  894. }
  895. }
  896. // if x[1..n] = z[1..n] then no need for a condition
  897. if (compare->getOperator() == no_substring)
  898. {
  899. IHqlExpression * range = queryLengthFromRange(compare->queryChild(1));
  900. if (range == lengthExpr)
  901. return;
  902. }
  903. // if x[1..n] = (string<m>y) where m<n then no need for condition
  904. unsigned selectorLength = selector->queryType()->getStringLen();
  905. if (selectorLength <= getIntValue(lengthExpr, 0))
  906. return;
  907. //otherwise, if x[1..y] == z then add check length(trim(z)) <= y
  908. OwnedHqlExpr trim = createTrimExpr(selector, NULL);
  909. OwnedITypeInfo unsignedType = makeIntType(sizeof(unsigned), false);
  910. OwnedHqlExpr len = createValue(no_charlen, LINK(unsignedType), LINK(trim));
  911. ITypeInfo * lengthType = lengthExpr->queryType();
  912. Owned<ITypeInfo> compareType = getPromotedECLCompareType(unsignedType, lengthType);
  913. OwnedHqlExpr positiveLen = createValue(no_maxlist, lengthExpr->getType(), createValue(no_list, makeSetType(LINK(lengthType)), LINK(lengthExpr), createConstant(lengthType->castFrom(false, I64C(0)))));
  914. OwnedHqlExpr test = createValue(no_le, makeBoolType(), ensureExprType(len, compareType), ensureExprType(positiveLen, compareType));
  915. test.setown(foldHqlExpression(test));
  916. if (compareEqual)
  917. extendConditionOwn(globalGuard, no_and, test.getClear());
  918. else
  919. extendConditionOwn(localCond, no_or, getInverse(test));
  920. }
  921. IHqlExpression * FilterExtractor::getRangeLimit(ITypeInfo * fieldType, IHqlExpression * lengthExpr, IHqlExpression * value, int whichBoundary)
  922. {
  923. unsigned fieldLength = fieldType->getStringLen();
  924. IValue * constValue = value->queryValue();
  925. if (constValue && lengthExpr->queryValue())
  926. {
  927. unsigned subStringLen = (unsigned)lengthExpr->queryValue()->getIntValue();
  928. if ((int)subStringLen < 0) subStringLen = 0;
  929. if (subStringLen > fieldLength)
  930. errorReceiver.throwError1(HQLERR_SubstringOutOfRange, subStringLen);
  931. return getCompareValue(fieldType, subStringLen, constValue, whichBoundary);
  932. }
  933. return nullptr;
  934. }
  935. IHqlExpression * FilterExtractor::createRangeCompare(IHqlExpression * selector, IHqlExpression * value, IHqlExpression * lengthExpr, bool compareEqual)
  936. {
  937. OwnedHqlExpr foldedValue = foldHqlExpression(value);
  938. if (createValueSets)
  939. {
  940. OwnedHqlExpr rangeExpr = createValue(no_rangeto, makeNullType(), LINK(lengthExpr));
  941. OwnedHqlExpr substr = createValue(no_substring, getStretchedType(UNKNOWN_LENGTH, selector->queryType()), LINK(selector), rangeExpr.getClear());
  942. return createValue(compareEqual ? no_eq : no_ne, makeBoolType(), LINK(substr), foldedValue.getClear());
  943. }
  944. ITypeInfo * fieldType = selector->queryType();
  945. OwnedHqlExpr lowExpr = getRangeLimit(fieldType, lengthExpr, foldedValue, -1);
  946. OwnedHqlExpr highExpr = getRangeLimit(fieldType, lengthExpr, foldedValue, +1);
  947. if (!lowExpr || !highExpr)
  948. errorReceiver.throwError(HQLERR_NonConstantRange);
  949. //Could convert to two separate tests, but code is worse, and boundary conditions aren't going to happen.
  950. return createValue(compareEqual ? no_between : no_notbetween, makeBoolType(), LINK(selector), lowExpr.getClear(), highExpr.getClear());
  951. }
  952. bool FilterExtractor::matchSubstringFilter(KeyConditionInfo & matches, node_operator op, IHqlExpression * left, IHqlExpression * right, KeyedKind keyedKind, bool & duplicate)
  953. {
  954. LinkedHqlExpr value = right;
  955. duplicate = false;
  956. OwnedHqlExpr guard;
  957. ITypeInfo * guardCastType = NULL;
  958. if ((left->getOperator() == no_cast) || (left->getOperator() == no_implicitcast))
  959. {
  960. //code is extracted and simplified from isKeyableFilter() above - should be commoned up.
  961. IHqlExpression * uncast = left->queryChild(0);
  962. ITypeInfo * castType = left->queryType();
  963. ITypeInfo * uncastType = uncast->queryType();
  964. //(ty)x = y.
  965. //if more than one value of x[uncastType] corresponds to a single value in y[castType] then we can't sensibly create
  966. //the key segment monitor. Because we will get false negatives. If it is an inverse then duplicate (see below)
  967. bool canRemoveCast = true;
  968. if (castLosesInformation(castType, uncastType))
  969. canRemoveCast = false;
  970. //if more than one value of y corresponds to a single value of x then need to duplicate the test condition.
  971. if (!preservesOrder(castType, uncastType))
  972. canRemoveCast = false;
  973. if (!canRemoveCast)
  974. {
  975. // reason.set(KFRcast, ret->queryChild(1));
  976. return false;
  977. }
  978. if ((op != no_in) && (op != no_notin))
  979. {
  980. value.setown(ensureExprType(right, uncastType));
  981. //If a simple equality test then create a global guard to check that we aren't matching a false positive
  982. if (castLosesInformation(uncastType, castType))
  983. guard.setown(createBoolExpr(no_eq, ensureExprType(value, castType), LINK(right)));
  984. }
  985. else
  986. {
  987. //if an IN then add guards to each comparison - generated later...
  988. if (castLosesInformation(uncastType, castType))
  989. guardCastType = uncastType;
  990. else
  991. {
  992. Owned<ITypeInfo> targetType = makeSetType(LINK(uncastType));
  993. value.setown(ensureExprType(right, targetType));
  994. }
  995. }
  996. left = uncast;
  997. }
  998. if (left->getOperator() != no_substring)
  999. return false;
  1000. if ((op == no_in) || (op == no_notin))
  1001. {
  1002. value.setown(normalizeListCasts(value));
  1003. if (value->getOperator() != no_list)
  1004. return false;
  1005. }
  1006. IHqlExpression * selector = left->queryChild(0);
  1007. if (!isKeySelect(selector) || !okToKey(selector, keyedKind))
  1008. return false;
  1009. if (!isIndexInvariant(right, false))
  1010. return false;
  1011. ITypeInfo * fieldType = selector->queryType();
  1012. unsigned fieldLength = fieldType->getStringLen();
  1013. if (!createValueSets && (fieldLength == UNKNOWN_LENGTH))
  1014. return false;
  1015. OwnedHqlExpr range = foldHqlExpression(left->queryChild(1));
  1016. IHqlExpression * lengthExpr = queryLengthFromRange(range);
  1017. if (!lengthExpr)
  1018. return false;
  1019. OwnedHqlExpr newTest;
  1020. if ((op == no_eq) || (op == no_ne))
  1021. {
  1022. newTest.setown(createRangeCompare(selector, value, lengthExpr, op == no_eq));
  1023. extendRangeCheck(guard, newTest, right, lengthExpr, op == no_eq);
  1024. }
  1025. else //no_in, no_notin
  1026. {
  1027. HqlExprArray compares;
  1028. ForEachChild(i, value)
  1029. {
  1030. IHqlExpression * cur = value->queryChild(i);
  1031. LinkedHqlExpr castValue = cur;
  1032. OwnedHqlExpr valueGuard;
  1033. if (guardCastType)
  1034. {
  1035. castValue.setown(ensureExprType(castValue, guardCastType));
  1036. valueGuard.setown(createBoolExpr(no_eq, ensureExprType(castValue, cur->queryType()), LINK(cur)));
  1037. extendRangeCheck(valueGuard, valueGuard, cur, lengthExpr, (op == no_in));
  1038. }
  1039. OwnedHqlExpr cond = createRangeCompare(selector, castValue, lengthExpr, (op == no_in));
  1040. if (valueGuard)
  1041. cond.setown(createValue(no_and, makeBoolType(), valueGuard.getClear(), cond.getClear()));
  1042. compares.append(*cond.getClear());
  1043. }
  1044. node_operator combineOp = (op == no_in) ? no_or : no_and;
  1045. OwnedITypeInfo boolType = makeBoolType();
  1046. newTest.setown(createBalanced(combineOp, boolType, compares));
  1047. }
  1048. KeyCondition * entry = new KeyCondition(selector, newTest, keyedKind, left->queryChild(1));
  1049. matches.appendCondition(*entry);
  1050. if (guard)
  1051. matches.appendPreFilter(guard);
  1052. return true;
  1053. }
  1054. bool FilterExtractor::extractSimpleCompareFilter(KeyConditionInfo & matches, IHqlExpression * expr, KeyedKind keyedKind)
  1055. {
  1056. OwnedHqlExpr promoted = getExplicitlyPromotedCompare(expr);
  1057. IHqlExpression * l = promoted->queryChild(0);
  1058. IHqlExpression * r = promoted->queryChild(1);
  1059. bool duplicate = false;
  1060. KeyFailureInfo reasonl, reasonr;
  1061. node_operator op = expr->getOperator();
  1062. IHqlExpression * matchedSelector = isKeyableFilter(l, r, duplicate, op, reasonl, keyedKind);
  1063. Owned<KeyCondition> result;
  1064. if (matchedSelector)
  1065. {
  1066. node_operator newOp = getModifiedOp(op, duplicate);
  1067. if (newOp != no_none)
  1068. {
  1069. OwnedHqlExpr newFilter = createValue(newOp, expr->getType(), LINK(l), LINK(r));
  1070. result.setown(new KeyCondition(matchedSelector, newFilter, keyedKind, querySubStringRange(l)));
  1071. }
  1072. }
  1073. else
  1074. {
  1075. duplicate = false;
  1076. matchedSelector = isKeyableFilter(r, l, duplicate, op, reasonr, keyedKind);
  1077. if (matchedSelector)
  1078. {
  1079. node_operator newOp = getModifiedOp(getReverseOp(op), duplicate);
  1080. if (newOp != no_none)
  1081. {
  1082. OwnedHqlExpr newFilter = createValue(newOp, expr->getType(), LINK(r), LINK(l));
  1083. result.setown(new KeyCondition(matchedSelector, newFilter, keyedKind, querySubStringRange(r)));
  1084. }
  1085. }
  1086. }
  1087. bool extracted = (result != NULL);
  1088. if (extracted)
  1089. {
  1090. matches.appendCondition(*result.getClear());
  1091. }
  1092. else
  1093. {
  1094. failReason.merge(reasonl);
  1095. failReason.merge(reasonr);
  1096. }
  1097. if (duplicate || !extracted)
  1098. matches.appendPostFilter(expr);
  1099. return extracted;
  1100. }
  1101. bool FilterExtractor::extractOrFilter(KeyConditionInfo & matches, IHqlExpression * expr, KeyedKind keyedKind)
  1102. {
  1103. HqlExprArray conds;
  1104. expr->unwindList(conds, no_or);
  1105. bool validOrFilter = true;
  1106. HqlExprAttr invariant;
  1107. CIArrayOf<KeyConditionInfo> branches;
  1108. ForEachItemIn(idx, conds)
  1109. {
  1110. IHqlExpression & cur = conds.item(idx);
  1111. if (isIndexInvariant(&cur, false))
  1112. extendOrCondition(invariant, &cur);
  1113. else
  1114. {
  1115. KeyConditionInfo & branch = * new KeyConditionInfo;
  1116. branches.append(branch);
  1117. //Can't generate an OR with a pure post-filter
  1118. if (!extractFilters(branch, &cur, keyedKind))
  1119. validOrFilter = false;
  1120. }
  1121. }
  1122. //check all the conditions that are ORd together don't contain references to multiple fields.
  1123. KeyCondition * firstBranch = NULL;
  1124. bool multipleBranches = branches.ordinality() > 1;
  1125. bool multipleSelectors = false;
  1126. bool multipleConditions = false;
  1127. bool hasPostFilter = false;
  1128. ForEachItemIn(i1, branches)
  1129. {
  1130. KeyConditionInfo & branch = branches.item(i1);
  1131. if (branch.postFilter)
  1132. hasPostFilter = true;
  1133. ForEachItemIn(i2, branch.conditions)
  1134. {
  1135. KeyCondition & cur = branch.conditions.item(i2);
  1136. if (!firstBranch)
  1137. firstBranch = &cur;
  1138. else
  1139. {
  1140. multipleConditions = true;
  1141. if (i1 == 0)
  1142. {
  1143. //Check for ((i.x = 3) AND (i.y = 4))
  1144. //Which can only create a keyed filter if it is ORd with an invariant expression
  1145. if (firstBranch->selector != cur.selector)
  1146. multipleSelectors = true;
  1147. }
  1148. else
  1149. {
  1150. if ((firstBranch->selector != cur.selector) || multipleSelectors)
  1151. validOrFilter = false;
  1152. }
  1153. }
  1154. }
  1155. }
  1156. if (multipleBranches && hasPostFilter)
  1157. validOrFilter = false;
  1158. if (validOrFilter && firstBranch)
  1159. {
  1160. bool optimizeSingleBranch = true;
  1161. if (multipleSelectors || hasPostFilter || (optimizeSingleBranch && !multipleConditions))
  1162. {
  1163. //Invariant ored with a conjunction
  1164. //X or (A and B) -> (X or A) AND (X or B)
  1165. assertex(branches.ordinality() == 1);
  1166. KeyConditionInfo & branch = branches.item(0);
  1167. OwnedHqlExpr preFilter = branch.preFilter ? extendCondition(no_or, invariant, branch.preFilter) : NULL;
  1168. OwnedHqlExpr postFilter = branch.postFilter ? extendCondition(no_or, invariant, branch.postFilter) : NULL;
  1169. matches.appendPreFilter(preFilter);
  1170. matches.appendPostFilter(postFilter);
  1171. ForEachItemIn(i2, branch.conditions)
  1172. {
  1173. KeyCondition & cur = branch.conditions.item(i2);
  1174. OwnedHqlExpr filter = extendCondition(no_or, invariant, cur.expr);
  1175. matches.conditions.append(*new KeyCondition(cur.selector, filter, keyedKind, cur.subrange));
  1176. }
  1177. }
  1178. else
  1179. {
  1180. LinkedHqlExpr combinedCondition = invariant;
  1181. ForEachItemIn(i1, branches)
  1182. {
  1183. KeyConditionInfo & branch = branches.item(i1);
  1184. OwnedHqlExpr conjunction = branch.createConjunction();
  1185. extendOrCondition(combinedCondition, conjunction);
  1186. }
  1187. matches.conditions.append(*new KeyCondition(firstBranch->selector, combinedCondition, keyedKind, nullptr));
  1188. }
  1189. return true;
  1190. }
  1191. else
  1192. {
  1193. matches.appendPostFilter(expr);
  1194. KeyFailureInfo reason;
  1195. reason.set(KFRor);
  1196. failReason.merge(reason);
  1197. return false;
  1198. }
  1199. }
  1200. bool FilterExtractor::extractIfFilter(KeyConditionInfo & matches, IHqlExpression * expr, KeyedKind keyedKind)
  1201. {
  1202. //MORE: This could generate better code, but I don't think it is worth the effort at the moment.
  1203. //Really, I should analyse left and right. Iterate each selector referenced. If there are no post conditions then
  1204. //generate IF(a, X, Y) compound expression, otherwise generate the default below.
  1205. IHqlExpression * cond = expr->queryChild(0);
  1206. if ((keyedKind != KeyedNo) && isIndexInvariant(cond, false))
  1207. {
  1208. //Convert IF(a, X, Y) to... IF (a, X, true) AND IF (a, true, Y) to... (NOT a OR X) AND (a OR Y)
  1209. OwnedHqlExpr inverseCond = getInverse(cond);
  1210. OwnedHqlExpr trueValue = createBoolExpr(no_or, LINK(inverseCond), LINK(expr->queryChild(1)));
  1211. OwnedHqlExpr falseValue = createBoolExpr(no_or, LINK(cond), LINK(expr->queryChild(2)));
  1212. OwnedHqlExpr combined = createBoolExpr(no_and, LINK(trueValue), LINK(falseValue));
  1213. return extractFilters(matches, combined, keyedKind);
  1214. }
  1215. matches.appendPostFilter(expr);
  1216. return false;
  1217. }
  1218. bool FilterExtractor::containsTableSelects(IHqlExpression * expr)
  1219. {
  1220. HqlExprCopyArray inScope;
  1221. expr->gatherTablesUsed(inScope);
  1222. //Check that cursors for all inScope tables are already bound in the start context
  1223. return inScope.find(*tableExpr->queryNormalizedSelector()) != NotFound;
  1224. }
  1225. void FilterExtractor::extractFilters(IHqlExpression * expr, SharedHqlExpr & extraFilter)
  1226. {
  1227. HqlExprArray conds;
  1228. expr->unwindList(conds, no_and);
  1229. extractFilters(conds, extraFilter);
  1230. }
  1231. void FilterExtractor::extractFilters(HqlExprArray & exprs, SharedHqlExpr & extraFilter)
  1232. {
  1233. OwnedHqlExpr savedFilter = keyed.postFilter.getClear();
  1234. ForEachItemIn(i1, exprs)
  1235. {
  1236. IHqlExpression & cur = exprs.item(i1);
  1237. switch (cur.getOperator())
  1238. {
  1239. case no_assertkeyed:
  1240. case no_assertwild:
  1241. extractFilters(keyed, &cur, KeyedNo);
  1242. break;
  1243. }
  1244. }
  1245. keyedExplicitly = (keyed.conditions.ordinality() != 0);
  1246. cleanlyKeyedExplicitly = keyedExplicitly && !keyed.postFilter;
  1247. ForEachItemIn(i2, exprs)
  1248. {
  1249. IHqlExpression & cur = exprs.item(i2);
  1250. switch (cur.getOperator())
  1251. {
  1252. case no_assertkeyed:
  1253. case no_assertwild:
  1254. break;
  1255. default:
  1256. if (!keyedExplicitly)
  1257. extractFilters(keyed, &cur, KeyedNo);
  1258. else if (!cur.isAttribute() && isIndexInvariant(&cur, true))
  1259. keyed.appendPreFilter(&cur);
  1260. else
  1261. keyed.appendPostFilter(&cur);
  1262. break;
  1263. }
  1264. }
  1265. extraFilter.set(keyed.postFilter);
  1266. keyed.postFilter.setown(extendConditionOwn(no_and, savedFilter.getClear(), LINK(extraFilter)));
  1267. }
  1268. void FilterExtractor::extractFiltersFromFilterDs(IHqlExpression * expr)
  1269. {
  1270. HqlExprArray conds;
  1271. HqlExprAttr dummy;
  1272. unwindFilterConditions(conds, expr);
  1273. extractFilters(conds, dummy);
  1274. }
  1275. void FilterExtractor::extractFoldedWildFields(IHqlExpression * expr)
  1276. {
  1277. node_operator op = expr->getOperator();
  1278. switch (op)
  1279. {
  1280. case no_cast:
  1281. case no_implicitcast:
  1282. case no_add:
  1283. case no_sub:
  1284. //fields may have been transformed since folding...
  1285. extractFoldedWildFields(expr->queryChild(0));
  1286. break;
  1287. case no_select:
  1288. if (isKeySelect(expr))
  1289. {
  1290. KeyCondition * condition = new KeyCondition;
  1291. condition->selector.set(expr);
  1292. condition->isWild = true;
  1293. condition->wasKeyed = true;
  1294. keyed.conditions.append(*condition);
  1295. }
  1296. break;
  1297. }
  1298. }
  1299. bool FilterExtractor::extractBoolFieldFilter(KeyConditionInfo & matches, IHqlExpression * selector, KeyedKind keyedKind, bool compareValue)
  1300. {
  1301. if (selector->isBoolean())
  1302. {
  1303. if (isKeySelect(selector) && okToKey(selector, keyedKind))
  1304. {
  1305. OwnedHqlExpr newFilter = createValue(no_eq, makeBoolType(), LINK(selector), createConstant(compareValue));
  1306. matches.appendCondition(*new KeyCondition(selector, newFilter, keyedKind, nullptr));
  1307. return true;
  1308. }
  1309. }
  1310. return false;
  1311. }
  1312. bool FilterExtractor::extractFilters(KeyConditionInfo & matches, IHqlExpression * expr, KeyedKind keyedKind)
  1313. {
  1314. if (!expr->isAttribute() && isIndexInvariant(expr, true))
  1315. {
  1316. extendAndCondition(matches.preFilter, expr);
  1317. return true;
  1318. }
  1319. IHqlExpression *l = expr->queryChild(0);
  1320. IHqlExpression *r = expr->queryChild(1);
  1321. node_operator op = expr->getOperator();
  1322. switch (op)
  1323. {
  1324. case no_and:
  1325. {
  1326. bool extracted = extractFilters(matches, l, keyedKind);
  1327. if (!extractFilters(matches, r, keyedKind)) extracted = false;
  1328. return extracted;
  1329. }
  1330. case no_or:
  1331. return extractOrFilter(matches, expr, keyedKind);
  1332. case no_attr:
  1333. case no_attr_expr:
  1334. case no_attr_link:
  1335. return true;
  1336. case no_not:
  1337. {
  1338. IHqlExpression * arg = expr->queryChild(0);
  1339. OwnedHqlExpr inverse = getInverse(arg);
  1340. if (inverse->queryBody() != expr->queryBody())
  1341. return extractFilters(matches, inverse, keyedKind);
  1342. if ((arg->getOperator() == no_select) && arg->isBoolean() &&
  1343. extractBoolFieldFilter(matches, arg, keyedKind, false))
  1344. return true;
  1345. matches.appendPostFilter(expr);
  1346. return false;
  1347. }
  1348. case no_between:
  1349. case no_notbetween:
  1350. {
  1351. //Convert this into two comparisons because that will handle weird boundary conditions much better.
  1352. OwnedHqlExpr normalized = expandBetween(expr);
  1353. return extractFilters(matches, normalized, keyedKind);
  1354. }
  1355. case no_eq:
  1356. case no_ne:
  1357. {
  1358. bool duplicate = false;
  1359. if (matchSubstringFilter(matches, op, l, r, keyedKind, duplicate) || matchSubstringFilter(matches, op, r, l, keyedKind, duplicate))
  1360. {
  1361. if (duplicate)
  1362. matches.appendPostFilter(expr);
  1363. return true;
  1364. }
  1365. return extractSimpleCompareFilter(matches, expr, keyedKind);
  1366. }
  1367. case no_in:
  1368. case no_notin:
  1369. {
  1370. bool duplicate = false;
  1371. if (matchSubstringFilter(matches, op, l, r, keyedKind, duplicate))
  1372. {
  1373. if (duplicate)
  1374. matches.appendPostFilter(expr);
  1375. return true;
  1376. }
  1377. return extractSimpleCompareFilter(matches, expr, keyedKind);
  1378. }
  1379. case no_gt:
  1380. case no_lt:
  1381. case no_ge:
  1382. case no_le:
  1383. return extractSimpleCompareFilter(matches, expr, keyedKind);
  1384. case no_assertkeyed:
  1385. {
  1386. KeyFailureInfo reason;
  1387. reason.merge(failReason);
  1388. failReason.clear();
  1389. bool extend = expr->hasAttribute(extendAtom);
  1390. if (!extractFilters(matches, l, extend ? KeyedExtend : KeyedYes))
  1391. {
  1392. if (!extend)
  1393. failReason.reportError(errorReceiver, expr);
  1394. }
  1395. IHqlExpression * original = expr->queryAttribute(_selectors_Atom);
  1396. if (original)
  1397. {
  1398. ForEachChild(i, original)
  1399. extractFoldedWildFields(original->queryChild(i));
  1400. }
  1401. failReason.merge(reason);
  1402. return true;
  1403. }
  1404. case no_assertwild:
  1405. {
  1406. if (l->getOperator() == no_all)
  1407. {
  1408. IHqlExpression * original = expr->queryAttribute(_selectors_Atom);
  1409. assertex(original);
  1410. ForEachChild(i, original)
  1411. extractFoldedWildFields(original->queryChild(i));
  1412. }
  1413. else
  1414. {
  1415. IHqlExpression * selector = queryKeyableSelector(l);
  1416. if (!selector)
  1417. {
  1418. StringBuffer keyname;
  1419. errorReceiver.throwError1(HQLERR_WildNotReferenceIndex, queryKeyName(keyname));
  1420. }
  1421. KeyCondition * condition = new KeyCondition;
  1422. condition->selector.set(selector);
  1423. condition->isWild = true;
  1424. matches.appendCondition(*condition);
  1425. }
  1426. return true;
  1427. }
  1428. case no_if:
  1429. return extractIfFilter(matches, expr, keyedKind);
  1430. case no_select:
  1431. {
  1432. if (expr->isBoolean() && extractBoolFieldFilter(matches, expr, keyedKind, true))
  1433. return true;
  1434. matches.appendPostFilter(expr);
  1435. return false;
  1436. }
  1437. default:
  1438. // Add this condition to the catchall expr
  1439. matches.appendPostFilter(expr);
  1440. return false;
  1441. }
  1442. }
  1443. void FilterExtractor::extractAllFilters(IHqlExpression * dataset)
  1444. {
  1445. for (;;)
  1446. {
  1447. switch (dataset->getOperator())
  1448. {
  1449. case no_newkeyindex:
  1450. return;
  1451. case no_filter:
  1452. extractAllFilters(dataset->queryChild(0));
  1453. extractFiltersFromFilterDs(dataset);
  1454. return;
  1455. case no_compound_indexread:
  1456. case no_newusertable:
  1457. case no_hqlproject:
  1458. case no_distributed:
  1459. case no_preservemeta:
  1460. case no_unordered:
  1461. case no_sorted:
  1462. case no_stepped:
  1463. case no_grouped:
  1464. case no_alias_scope:
  1465. case no_dataset_alias:
  1466. break;
  1467. default:
  1468. UNIMPLEMENTED;
  1469. }
  1470. dataset = dataset->queryChild(0);
  1471. }
  1472. }
  1473. bool FilterExtractor::isKeyed()
  1474. {
  1475. ForEachItemIn(i, keyed.conditions)
  1476. {
  1477. if (!keyed.conditions.item(i).isWild)
  1478. return true;
  1479. }
  1480. return false;
  1481. }
  1482. bool expandFilename(StringBuffer & s, IHqlExpression * expr)
  1483. {
  1484. switch (expr->getOperator())
  1485. {
  1486. case no_constant:
  1487. expr->toString(s);
  1488. return true;
  1489. case no_getresult:
  1490. //more
  1491. break;
  1492. case no_concat:
  1493. {
  1494. bool hadString = expandFilename(s, expr->queryChild(0));
  1495. unsigned oldLength = s.length();
  1496. s.append("+");
  1497. if (expandFilename(s, expr->queryChild(1)) || hadString)
  1498. return true;
  1499. s.setLength(oldLength);
  1500. return false;
  1501. }
  1502. case no_alias:
  1503. case no_cast:
  1504. case no_implicitcast:
  1505. return expandFilename(s, expr->queryChild(0));
  1506. }
  1507. if (hasNamedSymbol(expr))
  1508. {
  1509. s.append(expr->queryName());
  1510. return true;
  1511. }
  1512. s.append("...");
  1513. return false;
  1514. }
  1515. void FilterExtractor::reportFailureReason(IHqlExpression * cond)
  1516. {
  1517. failReason.reportError(errorReceiver, cond);
  1518. }
  1519. const char * FilterExtractor::queryKeyName(StringBuffer & s)
  1520. {
  1521. IAtom * name = tableExpr->queryName();
  1522. if (name)
  1523. s.append(" \'").append(name).append("'");
  1524. else
  1525. {
  1526. IHqlExpression * filename = queryTableFilename(tableExpr);
  1527. if (filename)
  1528. {
  1529. if (!expandFilename(s.append(' '), filename))
  1530. s.clear();
  1531. }
  1532. }
  1533. return s.str();
  1534. }
  1535. IHqlExpression * FilterExtractor::querySimpleJoinValue(IHqlExpression * selector)
  1536. {
  1537. IHqlExpression * matched = NULL;
  1538. ForEachItemIn(cond, keyed.conditions)
  1539. {
  1540. KeyCondition & cur = keyed.conditions.item(cond);
  1541. if (cur.selector == selector)
  1542. {
  1543. if (!cur.isWild)
  1544. {
  1545. if (matched)
  1546. return NULL;
  1547. IHqlExpression * matchExpr = cur.expr;
  1548. if (matchExpr->getOperator() != no_eq)
  1549. return NULL;
  1550. if (matchExpr->queryChild(0) != selector)
  1551. return NULL;
  1552. matched = matchExpr->queryChild(1);
  1553. }
  1554. }
  1555. }
  1556. return matched;
  1557. }
  1558. //-- Runtime filter generation
  1559. static __declspec(noreturn) void throwTooComplex(IHqlExpression * expr) __attribute__((noreturn));
  1560. static void throwTooComplex(IHqlExpression * expr)
  1561. {
  1562. StringBuffer ecl;
  1563. getExprECL(expr, ecl);
  1564. throwError1(HQLERR_ExprTooComplexForValueSet, ecl.str());
  1565. }
  1566. static IHqlExpression * getNormalizedCompareValue(IHqlExpression * expr)
  1567. {
  1568. switch (expr->getOperator())
  1569. {
  1570. case no_cast:
  1571. case no_implicitcast:
  1572. {
  1573. OwnedHqlExpr arg = getNormalizedCompareValue(expr->queryChild(0));
  1574. return ensureExprType(arg, expr->queryType());
  1575. }
  1576. case no_nofold:
  1577. return getNormalizedCompareValue(expr->queryChild(0));
  1578. default:
  1579. return LINK(expr);
  1580. }
  1581. }
  1582. static bool normalizeValueCompare(OwnedHqlExpr & normalized, bool & truncated, IHqlExpression * lhs, IHqlExpression * value)
  1583. {
  1584. //Primarily to aid creating test cases....
  1585. OwnedHqlExpr rhs = getNormalizedCompareValue(value);
  1586. if (!rhs->queryValue())
  1587. return false;
  1588. truncated = false;
  1589. LinkedHqlExpr compareValue = rhs->queryBody();
  1590. OwnedHqlExpr recastValue;
  1591. if ((lhs->getOperator() != no_select) || (lhs->queryType() != compareValue->queryType()))
  1592. {
  1593. OwnedHqlExpr temp = castToFieldAndBack(lhs, compareValue);
  1594. if (temp != compareValue)
  1595. {
  1596. truncated = true;
  1597. }
  1598. }
  1599. normalized.set(rhs);
  1600. return true;
  1601. }
  1602. IValueSet * FilterExtractor::createValueSetInExpr(IHqlExpression * selector, const RtlTypeInfo & type, IHqlExpression * expr) const
  1603. {
  1604. if (!exprReferencesDataset(expr, tableExpr))
  1605. throwTooComplex(expr); //MORE: Possibly report another error
  1606. IHqlExpression * rhs = expr->queryChild(1);
  1607. Owned<IValueSet> values = createValueSet(type);
  1608. switch (rhs->getOperator())
  1609. {
  1610. case no_null:
  1611. return values.getClear();
  1612. case no_all:
  1613. values->addAll();
  1614. return values.getClear();
  1615. case no_list:
  1616. break;
  1617. default:
  1618. throwTooComplex(expr);
  1619. }
  1620. ForEachChild(i, rhs)
  1621. {
  1622. OwnedHqlExpr normalized;
  1623. bool truncated = false;
  1624. if (!normalizeValueCompare(normalized, truncated, selector, rhs->queryChild(i)))
  1625. throwTooComplex(expr); //MORE: Possibly report another error
  1626. if (!normalized->queryValue())
  1627. throwTooComplex(expr);
  1628. if (!truncated)
  1629. {
  1630. MemoryBuffer compareValue;
  1631. if (!createConstantField(compareValue, selector, normalized))
  1632. throwTooComplex(expr);
  1633. const char * compareRaw = compareValue.toByteArray();
  1634. values->addRawRange(compareRaw, compareRaw);
  1635. }
  1636. }
  1637. if (expr->getOperator() == no_notin)
  1638. values->invertSet();
  1639. return values.getClear();
  1640. }
  1641. IValueSet * FilterExtractor::createValueSetCompareExpr(IHqlExpression * selector, const RtlTypeInfo & type, IHqlExpression * expr) const
  1642. {
  1643. if (!exprReferencesDataset(expr, tableExpr))
  1644. throwTooComplex(expr); //MORE: Possibly report another error
  1645. OwnedHqlExpr normalized;
  1646. bool truncated = false;
  1647. if (!normalizeValueCompare(normalized, truncated, selector, expr->queryChild(1)))
  1648. throwTooComplex(expr); //MORE: Possibly report another error
  1649. Owned<IValueSet> values = createValueSet(type);
  1650. MemoryBuffer compareValue;
  1651. if (!normalized->queryValue())
  1652. throwTooComplex(expr);
  1653. if (!createConstantField(compareValue, selector, normalized))
  1654. throwTooComplex(expr);
  1655. //TBD: Support substring matches
  1656. size32_t subLength = MatchFullString;
  1657. node_operator op = expr->getOperator();
  1658. const char * compareRaw = compareValue.toByteArray();
  1659. switch (op)
  1660. {
  1661. case no_eq:
  1662. if (!truncated)
  1663. values->addRawRangeEx(compareRaw, compareRaw, subLength);
  1664. break;
  1665. case no_ne:
  1666. values->addAll();
  1667. if (!truncated)
  1668. values->killRawRangeEx(compareRaw, compareRaw, subLength);
  1669. break;
  1670. case no_le:
  1671. {
  1672. Owned<IValueTransition> upper = values->createRawTransitionEx(CMPle, compareRaw, subLength);
  1673. values->addRange(nullptr, upper);
  1674. break;
  1675. }
  1676. case no_lt:
  1677. {
  1678. Owned<IValueTransition> upper = values->createRawTransitionEx(truncated ? CMPle: CMPlt, compareRaw, subLength);
  1679. values->addRange(nullptr, upper);
  1680. break;
  1681. }
  1682. case no_ge:
  1683. {
  1684. Owned<IValueTransition> lower = values->createRawTransitionEx(truncated ? CMPgt : CMPge, compareRaw, subLength);
  1685. values->addRange(lower, nullptr);
  1686. break;
  1687. }
  1688. case no_gt:
  1689. {
  1690. Owned<IValueTransition> lower = values->createRawTransitionEx(CMPgt, compareRaw, subLength);
  1691. values->addRange(lower, nullptr);
  1692. break;
  1693. }
  1694. case no_between:
  1695. case no_notbetween:
  1696. {
  1697. //NB: This should only be generated for substring queries. User betweens are converted
  1698. //to two separate comparisons to cope with range issues.
  1699. throwUnexpectedOp(op);
  1700. }
  1701. default:
  1702. throwUnexpectedOp(op);
  1703. }
  1704. return values.getClear();
  1705. }
  1706. IValueSet * FilterExtractor::createValueSetExpr(IHqlExpression * selector, const RtlTypeInfo & type, IHqlExpression * expr) const
  1707. {
  1708. node_operator op = expr->getOperator();
  1709. switch (op)
  1710. {
  1711. case no_in:
  1712. case no_notin:
  1713. return createValueSetInExpr(selector, type, expr);
  1714. case no_if:
  1715. break; // Report an error
  1716. case no_and:
  1717. {
  1718. Owned<IValueSet> left = createValueSetExpr(selector, type, expr->queryChild(0));
  1719. Owned<IValueSet> right = createValueSetExpr(selector, type, expr->queryChild(1));
  1720. left->intersectSet(right);
  1721. return left.getClear();
  1722. }
  1723. case no_or:
  1724. {
  1725. Owned<IValueSet> left = createValueSetExpr(selector, type, expr->queryChild(0));
  1726. Owned<IValueSet> right = createValueSetExpr(selector, type, expr->queryChild(1));
  1727. left->unionSet(right);
  1728. return left.getClear();
  1729. }
  1730. case no_eq:
  1731. case no_ne:
  1732. case no_gt:
  1733. case no_ge:
  1734. case no_lt:
  1735. case no_le:
  1736. return createValueSetCompareExpr(selector, type, expr);
  1737. }
  1738. throwTooComplex(expr);
  1739. }
  1740. IFieldFilter * FilterExtractor::createSingleFieldFilter(IRtlFieldTypeDeserializer &deserializer) const
  1741. {
  1742. IHqlExpression * selector = keyed.conditions.item(0).selector;
  1743. return createFieldFilter(deserializer, selector);
  1744. }
  1745. IFieldFilter * FilterExtractor::createFieldFilter(IRtlFieldTypeDeserializer &deserializer, IHqlExpression * selector) const
  1746. {
  1747. const RtlTypeInfo * fieldType = buildRtlType(deserializer, selector->queryType());
  1748. Owned<IValueSet> values;
  1749. HqlExprArray conditions;
  1750. ForEachItemIn(i, keyed.conditions)
  1751. {
  1752. KeyCondition & cur = keyed.conditions.item(i);
  1753. if (cur.selector == selector)
  1754. conditions.append(*LINK(cur.expr));
  1755. }
  1756. if (conditions.ordinality())
  1757. {
  1758. OwnedITypeInfo boolType = makeBoolType();
  1759. OwnedHqlExpr fullExpr = createBalanced(no_and, boolType, conditions);
  1760. values.setown(createValueSetExpr(selector, *fieldType, fullExpr));
  1761. }
  1762. unsigned fieldIndex = keyableSelects.find(*selector);
  1763. if (values)
  1764. return ::createFieldFilter(fieldIndex, values);
  1765. return createWildFieldFilter(fieldIndex, *fieldType);
  1766. }