query_engine.hpp 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476
  1. /*************************************************************************
  2. *
  3. * Copyright 2016 Realm Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. **************************************************************************/
  18. /*
  19. A query consists of node objects, one for each query condition. Each node contains pointers to all other nodes:
  20. node1 node2 node3
  21. ------ ----- -----
  22. node2* node1* node1*
  23. node3* node3* node2*
  24. The construction of all this takes part in query.cpp. Each node has two important functions:
  25. aggregate(start, end)
  26. aggregate_local(start, end)
  27. The aggregate() function executes the aggregate of a query. You can call the method on any of the nodes
  28. (except children nodes of OrNode and SubtableNode) - it has the same behaviour. The function contains
  29. scheduling that calls aggregate_local(start, end) on different nodes with different start/end ranges,
  30. depending on what it finds is most optimal.
  31. The aggregate_local() function contains a tight loop that tests the condition of its own node, and upon match
  32. it tests all other conditions at that index to report a full match or not. It will remain in the tight loop
  33. after a full match.
  34. So a call stack with 2 and 9 being local matches of a node could look like this:
  35. aggregate(0, 10)
  36. node1->aggregate_local(0, 3)
  37. node2->find_first_local(2, 3)
  38. node3->find_first_local(2, 3)
  39. node3->aggregate_local(3, 10)
  40. node1->find_first_local(4, 5)
  41. node2->find_first_local(4, 5)
  42. node1->find_first_local(7, 8)
  43. node2->find_first_local(7, 8)
  44. find_first_local(n, n + 1) is a function that can be used to test a single row of another condition. Note that
  45. this is very simplified. There are other statistical arguments to the methods, and also, find_first_local() can be
  46. called from a callback function called by an integer Array.
  47. Template arguments in methods:
  48. ----------------------------------------------------------------------------------------------------
  49. TConditionFunction: Each node has a condition from query_conditions.c such as Equal, GreaterEqual, etc
  50. TConditionValue: Type of values in condition column. That is, int64_t, float, int, bool, etc
  51. TAction: What to do with each search result, from the enums act_ReturnFirst, act_Count, act_Sum, etc
  52. TResult: Type of result of actions - float, double, int64_t, etc. Special notes: For act_Count it's
  53. int64_t, for RLM_FIND_ALL it's int64_t which points at destination array.
  54. TSourceColumn: Type of source column used in actions, or *ignored* if no source column is used (like for
  55. act_Count, act_ReturnFirst)
  56. There are two important classes used in queries:
  57. ----------------------------------------------------------------------------------------------------
  58. SequentialGetter Column iterator used to get successive values with leaf caching. Used both for condition columns
  59. and aggregate source column
  60. AggregateState State of the aggregate - contains a state variable that stores intermediate sum, max, min,
  61. etc, etc.
  62. */
  63. #ifndef REALM_QUERY_ENGINE_HPP
  64. #define REALM_QUERY_ENGINE_HPP
  65. #include <algorithm>
  66. #include <functional>
  67. #include <sstream>
  68. #include <string>
  69. #include <array>
  70. #include <realm/array_basic.hpp>
  71. #include <realm/array_key.hpp>
  72. #include <realm/array_string.hpp>
  73. #include <realm/array_binary.hpp>
  74. #include <realm/array_timestamp.hpp>
  75. #include <realm/array_decimal128.hpp>
  76. #include <realm/array_fixed_bytes.hpp>
  77. #include <realm/array_mixed.hpp>
  78. #include <realm/array_list.hpp>
  79. #include <realm/array_bool.hpp>
  80. #include <realm/array_backlink.hpp>
  81. #include <realm/column_type_traits.hpp>
  82. #include <realm/metrics/query_info.hpp>
  83. #include <realm/query_conditions.hpp>
  84. #include <realm/table.hpp>
  85. #include <realm/column_integer.hpp>
  86. #include <realm/unicode.hpp>
  87. #include <realm/util/miscellaneous.hpp>
  88. #include <realm/util/serializer.hpp>
  89. #include <realm/util/shared_ptr.hpp>
  90. #include <realm/util/string_buffer.hpp>
  91. #include <realm/utilities.hpp>
  92. #include <realm/index_string.hpp>
  93. #include <map>
  94. #include <unordered_set>
  95. #if REALM_X86_OR_X64_TRUE && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219
  96. #include <immintrin.h>
  97. #endif
  98. namespace realm {
  99. // Number of matches to find in best condition loop before breaking out to probe other conditions. Too low value gives
  100. // too many constant time overheads everywhere in the query engine. Too high value makes it adapt less rapidly to
  101. // changes in match frequencies.
  102. const size_t findlocals = 64;
  103. // Average match distance in linear searches where further increase in distance no longer increases query speed
  104. // (because time spent on handling each match becomes insignificant compared to time spent on the search).
  105. const size_t bestdist = 512;
  106. // Minimum number of matches required in a certain condition before it can be used to compute statistics. Too high
  107. // value can spent too much time in a bad node (with high match frequency). Too low value gives inaccurate statistics.
  108. const size_t probe_matches = 4;
  109. const size_t bitwidth_time_unit = 64;
  110. typedef bool (*CallbackDummy)(int64_t);
  111. using Evaluator = util::FunctionRef<bool(const Obj& obj)>;
  112. class ParentNode {
  113. typedef ParentNode ThisType;
  114. public:
  115. ParentNode() = default;
  116. virtual ~ParentNode() = default;
  117. virtual bool has_search_index() const
  118. {
  119. return false;
  120. }
  121. virtual void index_based_aggregate(size_t, Evaluator) {}
  122. void gather_children(std::vector<ParentNode*>& v)
  123. {
  124. m_children.clear();
  125. size_t i = v.size();
  126. v.push_back(this);
  127. if (m_child)
  128. m_child->gather_children(v);
  129. m_children = v;
  130. m_children.erase(m_children.begin() + i);
  131. m_children.insert(m_children.begin(), this);
  132. }
  133. double cost() const
  134. {
  135. // dt = 1/64 to 1. Match dist is 8 times more important than bitwidth
  136. return 8 * bitwidth_time_unit / m_dD + m_dT;
  137. }
  138. size_t find_first(size_t start, size_t end);
  139. bool match(const Obj& obj);
  140. virtual void init(bool will_query_ranges)
  141. {
  142. m_dD = 100.0;
  143. if (m_child)
  144. m_child->init(will_query_ranges);
  145. }
  146. void get_link_dependencies(std::vector<TableKey>& tables) const
  147. {
  148. collect_dependencies(tables);
  149. if (m_child)
  150. m_child->get_link_dependencies(tables);
  151. }
  152. void set_table(ConstTableRef table)
  153. {
  154. if (table == m_table)
  155. return;
  156. m_table = table;
  157. if (m_child)
  158. m_child->set_table(table);
  159. table_changed();
  160. }
  161. void set_cluster(const Cluster* cluster)
  162. {
  163. m_cluster = cluster;
  164. if (m_child)
  165. m_child->set_cluster(cluster);
  166. cluster_changed();
  167. }
  168. virtual void collect_dependencies(std::vector<TableKey>&) const
  169. {
  170. }
  171. virtual size_t find_first_local(size_t start, size_t end) = 0;
  172. virtual size_t find_all_local(size_t start, size_t end);
  173. virtual size_t aggregate_local(QueryStateBase* st, size_t start, size_t end, size_t local_limit,
  174. ArrayPayload* source_column);
  175. virtual std::string validate()
  176. {
  177. if (error_code != "")
  178. return error_code;
  179. if (m_child == nullptr)
  180. return "";
  181. else
  182. return m_child->validate();
  183. }
  184. ParentNode(const ParentNode& from);
  185. void add_child(std::unique_ptr<ParentNode> child)
  186. {
  187. if (m_child)
  188. m_child->add_child(std::move(child));
  189. else
  190. m_child = std::move(child);
  191. }
  192. virtual std::unique_ptr<ParentNode> clone() const = 0;
  193. ColKey get_column_key(StringData column_name) const
  194. {
  195. ColKey column_key;
  196. if (column_name.size() > 0) {
  197. column_key = m_table.unchecked_ptr()->get_column_key(column_name);
  198. if (column_key == ColKey()) {
  199. throw LogicError(LogicError::column_does_not_exist);
  200. }
  201. }
  202. return column_key;
  203. }
  204. virtual std::string describe(util::serializer::SerialisationState&) const
  205. {
  206. return "";
  207. }
  208. virtual std::string describe_condition() const
  209. {
  210. return "matches";
  211. }
  212. virtual std::string describe_expression(util::serializer::SerialisationState& state) const
  213. {
  214. std::string s;
  215. s = describe(state);
  216. if (m_child) {
  217. s = s + " and " + m_child->describe_expression(state);
  218. }
  219. return s;
  220. }
  221. bool consume_condition(ParentNode& other, bool ignore_indexes)
  222. {
  223. // We can only combine conditions if they're the same operator on the
  224. // same column and there's no additional conditions ANDed on
  225. if (m_condition_column_key != other.m_condition_column_key)
  226. return false;
  227. if (m_child || other.m_child)
  228. return false;
  229. if (typeid(*this) != typeid(other))
  230. return false;
  231. // If a search index is present, don't try to combine conditions since index search is most likely faster.
  232. // Assuming N elements to search and M conditions to check:
  233. // 1) search index present: O(log(N)*M)
  234. // 2) no search index, combine conditions: O(N)
  235. // 3) no search index, conditions not combined: O(N*M)
  236. // In practice N is much larger than M, so if we have a search index, choose 1, otherwise if possible
  237. // choose 2. The exception is if we're inside a Not group or if the query is restricted to a view, as in those
  238. // cases end will always be start+1 and we'll have O(N*M) runtime even with a search index, so we want to
  239. // combine even with an index.
  240. if (has_search_index() && !ignore_indexes)
  241. return false;
  242. return do_consume_condition(other);
  243. }
  244. std::unique_ptr<ParentNode> m_child;
  245. std::vector<ParentNode*> m_children;
  246. mutable ColKey m_condition_column_key = ColKey(); // Column of search criteria
  247. ArrayPayload* m_source_column = nullptr;
  248. double m_dD; // Average row distance between each local match at current position
  249. double m_dT = 1.0; // Time overhead of testing index i + 1 if we have just tested index i. > 1 for linear scans, 0
  250. // for index/tableview
  251. size_t m_probes = 0;
  252. size_t m_matches = 0;
  253. protected:
  254. ConstTableRef m_table = ConstTableRef();
  255. const Cluster* m_cluster = nullptr;
  256. QueryStateBase* m_state = nullptr;
  257. std::string error_code;
  258. ColumnType get_real_column_type(ColKey key)
  259. {
  260. return m_table.unchecked_ptr()->get_real_column_type(key);
  261. }
  262. private:
  263. virtual void table_changed()
  264. {
  265. }
  266. virtual void cluster_changed()
  267. {
  268. // TODO: Should eventually be pure
  269. }
  270. virtual bool do_consume_condition(ParentNode&)
  271. {
  272. return false;
  273. }
  274. };
  275. class ColumnNodeBase : public ParentNode {
  276. protected:
  277. ColumnNodeBase(ColKey column_key)
  278. {
  279. m_condition_column_key = column_key;
  280. }
  281. ColumnNodeBase(const ColumnNodeBase& from)
  282. : ParentNode(from)
  283. {
  284. }
  285. };
  286. template <class LeafType>
  287. class IntegerNodeBase : public ColumnNodeBase {
  288. public:
  289. using TConditionValue = typename LeafType::value_type;
  290. // static const bool nullable = ColType::nullable;
  291. protected:
  292. IntegerNodeBase(TConditionValue value, ColKey column_key)
  293. : ColumnNodeBase(column_key)
  294. , m_value(std::move(value))
  295. {
  296. }
  297. IntegerNodeBase(const IntegerNodeBase& from)
  298. : ColumnNodeBase(from)
  299. , m_value(from.m_value)
  300. {
  301. }
  302. void cluster_changed() override
  303. {
  304. // Assigning nullptr will cause the Leaf destructor to be called. Must
  305. // be done before assigning a new one. Otherwise the destructor will be
  306. // called after the constructor is called and that is unfortunate if
  307. // the object has the same address. (As in this case)
  308. m_array_ptr = nullptr;
  309. // Create new Leaf
  310. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) LeafType(m_table.unchecked_ptr()->get_alloc()));
  311. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  312. m_leaf_ptr = m_array_ptr.get();
  313. }
  314. void init(bool will_query_ranges) override
  315. {
  316. ColumnNodeBase::init(will_query_ranges);
  317. m_dT = .25;
  318. }
  319. bool run_single() const
  320. {
  321. if (m_source_column == nullptr)
  322. return true;
  323. // Compare leafs to see if they are the same
  324. auto leaf = dynamic_cast<LeafType*>(m_source_column);
  325. return leaf ? leaf->get_ref() == m_leaf_ptr->get_ref() : false;
  326. }
  327. template <class TConditionFunction>
  328. size_t find_all_local(size_t start, size_t end)
  329. {
  330. if (run_single()) {
  331. m_leaf_ptr->template find<TConditionFunction>(m_value, start, end, 0, m_state, nullptr);
  332. }
  333. else {
  334. auto callback = [this](size_t index) {
  335. auto val = m_source_column->get_any(index);
  336. return m_state->match(index, val);
  337. };
  338. m_leaf_ptr->template find<TConditionFunction>(m_value, start, end, 0, m_state, callback);
  339. }
  340. return end;
  341. }
  342. std::string describe(util::serializer::SerialisationState& state) const override
  343. {
  344. return state.describe_column(ParentNode::m_table, ColumnNodeBase::m_condition_column_key) + " " +
  345. describe_condition() + " " + util::serializer::print_value(this->m_value);
  346. }
  347. // Search value:
  348. TConditionValue m_value;
  349. // Leaf cache
  350. using LeafCacheStorage = typename std::aligned_storage<sizeof(LeafType), alignof(LeafType)>::type;
  351. using LeafPtr = std::unique_ptr<LeafType, PlacementDelete>;
  352. LeafCacheStorage m_leaf_cache_storage;
  353. LeafPtr m_array_ptr;
  354. const LeafType* m_leaf_ptr = nullptr;
  355. };
  356. template <class LeafType, class TConditionFunction>
  357. class IntegerNode : public IntegerNodeBase<LeafType> {
  358. using BaseType = IntegerNodeBase<LeafType>;
  359. using ThisType = IntegerNode<LeafType, TConditionFunction>;
  360. public:
  361. using TConditionValue = typename BaseType::TConditionValue;
  362. IntegerNode(TConditionValue value, ColKey column_key)
  363. : BaseType(value, column_key)
  364. {
  365. }
  366. IntegerNode(const IntegerNode& from)
  367. : BaseType(from)
  368. {
  369. }
  370. size_t find_first_local(size_t start, size_t end) override
  371. {
  372. return this->m_leaf_ptr->template find_first<TConditionFunction>(this->m_value, start, end);
  373. }
  374. size_t find_all_local(size_t start, size_t end) override
  375. {
  376. return BaseType::template find_all_local<TConditionFunction>(start, end);
  377. }
  378. std::string describe_condition() const override
  379. {
  380. return TConditionFunction::description();
  381. }
  382. std::unique_ptr<ParentNode> clone() const override
  383. {
  384. return std::unique_ptr<ParentNode>(new ThisType(*this));
  385. }
  386. };
  387. template <size_t linear_search_threshold, class LeafType, class NeedleContainer>
  388. static size_t find_first_haystack(LeafType& leaf, NeedleContainer& needles, size_t start, size_t end)
  389. {
  390. // for a small number of conditions, it is faster to do a linear search than to compute the hash
  391. // the exact thresholds were found experimentally
  392. if (needles.size() < linear_search_threshold) {
  393. for (size_t i = start; i < end; ++i) {
  394. auto element = leaf.get(i);
  395. if (std::find(needles.begin(), needles.end(), element) != needles.end())
  396. return i;
  397. }
  398. }
  399. else {
  400. for (size_t i = start; i < end; ++i) {
  401. auto element = leaf.get(i);
  402. if (needles.count(element))
  403. return i;
  404. }
  405. }
  406. return realm::npos;
  407. }
  408. template <class LeafType>
  409. class IntegerNode<LeafType, Equal> : public IntegerNodeBase<LeafType> {
  410. public:
  411. using BaseType = IntegerNodeBase<LeafType>;
  412. using TConditionValue = typename BaseType::TConditionValue;
  413. using ThisType = IntegerNode<LeafType, Equal>;
  414. IntegerNode(TConditionValue value, ColKey column_key)
  415. : BaseType(value, column_key)
  416. {
  417. }
  418. ~IntegerNode()
  419. {
  420. }
  421. void init(bool will_query_ranges) override
  422. {
  423. BaseType::init(will_query_ranges);
  424. m_nb_needles = m_needles.size();
  425. if (has_search_index()) {
  426. // _search_index_init();
  427. m_result.clear();
  428. auto index = ParentNode::m_table->get_search_index(ParentNode::m_condition_column_key);
  429. index->find_all(m_result, BaseType::m_value);
  430. m_result_get = 0;
  431. m_last_start_key = ObjKey();
  432. IntegerNodeBase<LeafType>::m_dT = 0;
  433. }
  434. }
  435. bool do_consume_condition(ParentNode& node) override
  436. {
  437. auto& other = static_cast<ThisType&>(node);
  438. REALM_ASSERT(this->m_condition_column_key == other.m_condition_column_key);
  439. REALM_ASSERT(other.m_needles.empty());
  440. if (m_needles.empty()) {
  441. m_needles.insert(this->m_value);
  442. }
  443. m_needles.insert(other.m_value);
  444. return true;
  445. }
  446. bool has_search_index() const override
  447. {
  448. return this->m_table->has_search_index(IntegerNodeBase<LeafType>::m_condition_column_key);
  449. }
  450. void index_based_aggregate(size_t limit, Evaluator evaluator) override
  451. {
  452. for (size_t t = 0; t < m_result.size() && limit > 0; ++t) {
  453. auto obj = this->m_table->get_object(m_result[t]);
  454. if (evaluator(obj)) {
  455. --limit;
  456. }
  457. }
  458. }
  459. size_t find_first_local(size_t start, size_t end) override
  460. {
  461. REALM_ASSERT(this->m_table);
  462. size_t s = realm::npos;
  463. if (start < end) {
  464. if (m_nb_needles) {
  465. s = find_first_haystack<22>(*this->m_leaf_ptr, m_needles, start, end);
  466. }
  467. else if (has_search_index()) {
  468. return do_search_index(m_last_start_key, m_result_get, m_result, BaseType::m_cluster, start, end);
  469. }
  470. else if (end - start == 1) {
  471. if (this->m_leaf_ptr->get(start) == this->m_value) {
  472. s = start;
  473. }
  474. }
  475. else {
  476. s = this->m_leaf_ptr->template find_first<Equal>(this->m_value, start, end);
  477. }
  478. }
  479. return s;
  480. }
  481. size_t find_all_local(size_t start, size_t end) override
  482. {
  483. return BaseType::template find_all_local<Equal>(start, end);
  484. }
  485. std::string describe(util::serializer::SerialisationState& state) const override
  486. {
  487. REALM_ASSERT(this->m_condition_column_key);
  488. std::string col_descr = state.describe_column(this->m_table, this->m_condition_column_key);
  489. if (m_needles.empty()) {
  490. return col_descr + " " + Equal::description() + " " +
  491. util::serializer::print_value(IntegerNodeBase<LeafType>::m_value);
  492. }
  493. // FIXME: once the parser supports it, print something like "column IN {n1, n2, n3}"
  494. std::string desc = "(";
  495. bool is_first = true;
  496. for (auto it : m_needles) {
  497. if (!is_first)
  498. desc += " or ";
  499. desc +=
  500. col_descr + " " + Equal::description() + " " + util::serializer::print_value(it); // "it" may be null
  501. is_first = false;
  502. }
  503. desc += ")";
  504. return desc;
  505. }
  506. std::unique_ptr<ParentNode> clone() const override
  507. {
  508. return std::unique_ptr<ParentNode>(new ThisType(*this));
  509. }
  510. private:
  511. std::unordered_set<TConditionValue> m_needles;
  512. std::vector<ObjKey> m_result;
  513. size_t m_nb_needles = 0;
  514. size_t m_result_get = 0;
  515. ObjKey m_last_start_key;
  516. IntegerNode(const IntegerNode<LeafType, Equal>& from)
  517. : BaseType(from)
  518. , m_needles(from.m_needles)
  519. {
  520. }
  521. };
  522. // This node is currently used for floats and doubles only
  523. template <class LeafType, class TConditionFunction>
  524. class FloatDoubleNode : public ParentNode {
  525. public:
  526. using TConditionValue = typename LeafType::value_type;
  527. static const bool special_null_node = false;
  528. FloatDoubleNode(TConditionValue v, ColKey column_key)
  529. : m_value(v)
  530. {
  531. m_condition_column_key = column_key;
  532. m_dT = 1.0;
  533. }
  534. FloatDoubleNode(null, ColKey column_key)
  535. : m_value(null::get_null_float<TConditionValue>())
  536. {
  537. m_condition_column_key = column_key;
  538. m_dT = 1.0;
  539. }
  540. void cluster_changed() override
  541. {
  542. // Assigning nullptr will cause the Leaf destructor to be called. Must
  543. // be done before assigning a new one. Otherwise the destructor will be
  544. // called after the constructor is called and that is unfortunate if
  545. // the object has the same address. (As in this case)
  546. m_array_ptr = nullptr;
  547. // Create new Leaf
  548. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) LeafType(m_table.unchecked_ptr()->get_alloc()));
  549. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  550. m_leaf_ptr = m_array_ptr.get();
  551. }
  552. size_t find_first_local(size_t start, size_t end) override
  553. {
  554. TConditionFunction cond;
  555. auto find = [&](bool nullability) {
  556. bool m_value_nan = nullability ? null::is_null_float(m_value) : false;
  557. for (size_t s = start; s < end; ++s) {
  558. TConditionValue v = m_leaf_ptr->get(s);
  559. REALM_ASSERT(!(null::is_null_float(v) && !nullability));
  560. if (cond(v, m_value, nullability ? null::is_null_float<TConditionValue>(v) : false, m_value_nan))
  561. return s;
  562. }
  563. return not_found;
  564. };
  565. // This will inline the second case but no the first. Todo, use templated lambda when switching to c++14
  566. if (m_table->is_nullable(m_condition_column_key))
  567. return find(true);
  568. else
  569. return find(false);
  570. }
  571. std::string describe(util::serializer::SerialisationState& state) const override
  572. {
  573. REALM_ASSERT(m_condition_column_key);
  574. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " + describe_condition() + " " +
  575. util::serializer::print_value(FloatDoubleNode::m_value);
  576. }
  577. std::string describe_condition() const override
  578. {
  579. return TConditionFunction::description();
  580. }
  581. std::unique_ptr<ParentNode> clone() const override
  582. {
  583. return std::unique_ptr<ParentNode>(new FloatDoubleNode(*this));
  584. }
  585. FloatDoubleNode(const FloatDoubleNode& from)
  586. : ParentNode(from)
  587. , m_value(from.m_value)
  588. {
  589. }
  590. protected:
  591. TConditionValue m_value;
  592. // Leaf cache
  593. using LeafCacheStorage = typename std::aligned_storage<sizeof(LeafType), alignof(LeafType)>::type;
  594. using LeafPtr = std::unique_ptr<LeafType, PlacementDelete>;
  595. LeafCacheStorage m_leaf_cache_storage;
  596. LeafPtr m_array_ptr;
  597. const LeafType* m_leaf_ptr = nullptr;
  598. };
  599. template <class T, class TConditionFunction>
  600. class SizeNode : public ParentNode {
  601. public:
  602. SizeNode(int64_t v, ColKey column)
  603. : m_value(v)
  604. {
  605. m_condition_column_key = column;
  606. m_dT = 20.0;
  607. }
  608. void cluster_changed() override
  609. {
  610. // Assigning nullptr will cause the Leaf destructor to be called. Must
  611. // be done before assigning a new one. Otherwise the destructor will be
  612. // called after the constructor is called and that is unfortunate if
  613. // the object has the same address. (As in this case)
  614. m_array_ptr = nullptr;
  615. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) LeafType(m_table.unchecked_ptr()->get_alloc()));
  616. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  617. m_leaf_ptr = m_array_ptr.get();
  618. }
  619. size_t find_first_local(size_t start, size_t end) override
  620. {
  621. for (size_t s = start; s < end; ++s) {
  622. T v = m_leaf_ptr->get(s);
  623. if (v) {
  624. int64_t sz = v.size();
  625. if (TConditionFunction()(sz, m_value))
  626. return s;
  627. }
  628. }
  629. return not_found;
  630. }
  631. std::unique_ptr<ParentNode> clone() const override
  632. {
  633. return std::unique_ptr<ParentNode>(new SizeNode(*this));
  634. }
  635. SizeNode(const SizeNode& from)
  636. : ParentNode(from)
  637. , m_value(from.m_value)
  638. {
  639. }
  640. private:
  641. // Leaf cache
  642. using LeafType = typename ColumnTypeTraits<T>::cluster_leaf_type;
  643. using LeafCacheStorage = typename std::aligned_storage<sizeof(LeafType), alignof(LeafType)>::type;
  644. using LeafPtr = std::unique_ptr<LeafType, PlacementDelete>;
  645. LeafCacheStorage m_leaf_cache_storage;
  646. LeafPtr m_array_ptr;
  647. const LeafType* m_leaf_ptr = nullptr;
  648. int64_t m_value;
  649. };
  650. extern size_t size_of_list_from_ref(ref_type ref, Allocator& alloc, ColumnType col_type, bool nullable);
  651. template <class TConditionFunction>
  652. class SizeListNode : public ParentNode {
  653. public:
  654. SizeListNode(int64_t v, ColKey column)
  655. : m_value(v)
  656. {
  657. m_condition_column_key = column;
  658. m_dT = 30.0;
  659. }
  660. void reset_cache()
  661. {
  662. m_cached_col_type = m_condition_column_key.get_type();
  663. m_cached_nullable = m_condition_column_key.is_nullable();
  664. REALM_ASSERT_DEBUG(m_condition_column_key.is_list());
  665. }
  666. void cluster_changed() override
  667. {
  668. // Assigning nullptr will cause the Leaf destructor to be called. Must
  669. // be done before assigning a new one. Otherwise the destructor will be
  670. // called after the constructor is called and that is unfortunate if
  671. // the object has the same address. (As in this case)
  672. m_array_ptr = nullptr;
  673. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayList(m_table.unchecked_ptr()->get_alloc()));
  674. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  675. m_leaf_ptr = m_array_ptr.get();
  676. reset_cache();
  677. }
  678. void init(bool will_query_ranges) override
  679. {
  680. ParentNode::init(will_query_ranges);
  681. reset_cache();
  682. }
  683. size_t find_first_local(size_t start, size_t end) override
  684. {
  685. Allocator& alloc = m_table.unchecked_ptr()->get_alloc();
  686. for (size_t s = start; s < end; ++s) {
  687. ref_type ref = m_leaf_ptr->get(s);
  688. if (ref) {
  689. int64_t sz = size_of_list_from_ref(ref, alloc, m_cached_col_type, m_cached_nullable);
  690. if (TConditionFunction()(sz, m_value))
  691. return s;
  692. }
  693. }
  694. return not_found;
  695. }
  696. std::unique_ptr<ParentNode> clone() const override
  697. {
  698. return std::unique_ptr<ParentNode>(new SizeListNode(*this));
  699. }
  700. SizeListNode(const SizeListNode& from)
  701. : ParentNode(from)
  702. , m_value(from.m_value)
  703. {
  704. }
  705. private:
  706. // Leaf cache
  707. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayList), alignof(ArrayList)>::type;
  708. using LeafPtr = std::unique_ptr<ArrayList, PlacementDelete>;
  709. LeafCacheStorage m_leaf_cache_storage;
  710. LeafPtr m_array_ptr;
  711. const ArrayList* m_leaf_ptr = nullptr;
  712. int64_t m_value;
  713. ColumnType m_cached_col_type;
  714. bool m_cached_nullable;
  715. };
  716. template <class TConditionFunction>
  717. class BinaryNode : public ParentNode {
  718. public:
  719. using TConditionValue = BinaryData;
  720. static const bool special_null_node = false;
  721. BinaryNode(BinaryData v, ColKey column)
  722. : m_value(v)
  723. {
  724. m_condition_column_key = column;
  725. m_dT = 100.0;
  726. }
  727. BinaryNode(null, ColKey column)
  728. : BinaryNode(BinaryData{}, column)
  729. {
  730. }
  731. void cluster_changed() override
  732. {
  733. m_array_ptr = nullptr;
  734. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayBinary(m_table.unchecked_ptr()->get_alloc()));
  735. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  736. m_leaf_ptr = m_array_ptr.get();
  737. }
  738. size_t find_first_local(size_t start, size_t end) override
  739. {
  740. TConditionFunction condition;
  741. for (size_t s = start; s < end; ++s) {
  742. BinaryData value = m_leaf_ptr->get(s);
  743. if (condition(m_value.get(), value))
  744. return s;
  745. }
  746. return not_found;
  747. }
  748. virtual std::string describe(util::serializer::SerialisationState& state) const override
  749. {
  750. REALM_ASSERT(m_condition_column_key);
  751. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " +
  752. TConditionFunction::description() + " " + util::serializer::print_value(BinaryNode::m_value.get());
  753. }
  754. std::unique_ptr<ParentNode> clone() const override
  755. {
  756. return std::unique_ptr<ParentNode>(new BinaryNode(*this));
  757. }
  758. BinaryNode(const BinaryNode& from)
  759. : ParentNode(from)
  760. , m_value(from.m_value)
  761. {
  762. }
  763. private:
  764. OwnedBinaryData m_value;
  765. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayBinary), alignof(ArrayBinary)>::type;
  766. using LeafPtr = std::unique_ptr<ArrayBinary, PlacementDelete>;
  767. LeafCacheStorage m_leaf_cache_storage;
  768. LeafPtr m_array_ptr;
  769. const ArrayBinary* m_leaf_ptr = nullptr;
  770. };
  771. template <class TConditionFunction>
  772. class BoolNode : public ParentNode {
  773. public:
  774. using TConditionValue = bool;
  775. BoolNode(util::Optional<bool> v, ColKey column)
  776. : m_value(v)
  777. {
  778. m_condition_column_key = column;
  779. }
  780. BoolNode(const BoolNode& from)
  781. : ParentNode(from)
  782. , m_value(from.m_value)
  783. {
  784. }
  785. void cluster_changed() override
  786. {
  787. m_array_ptr = nullptr;
  788. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayBoolNull(m_table.unchecked_ptr()->get_alloc()));
  789. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  790. m_leaf_ptr = m_array_ptr.get();
  791. }
  792. size_t find_first_local(size_t start, size_t end) override
  793. {
  794. TConditionFunction condition;
  795. bool m_value_is_null = !m_value;
  796. for (size_t s = start; s < end; ++s) {
  797. util::Optional<bool> value = m_leaf_ptr->get(s);
  798. if (condition(value, m_value, !value, m_value_is_null))
  799. return s;
  800. }
  801. return not_found;
  802. }
  803. virtual std::string describe(util::serializer::SerialisationState& state) const override
  804. {
  805. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " +
  806. TConditionFunction::description() + " " + util::serializer::print_value(m_value);
  807. }
  808. std::unique_ptr<ParentNode> clone() const override
  809. {
  810. return std::unique_ptr<ParentNode>(new BoolNode(*this));
  811. }
  812. private:
  813. util::Optional<bool> m_value;
  814. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayBoolNull), alignof(ArrayBoolNull)>::type;
  815. using LeafPtr = std::unique_ptr<ArrayBoolNull, PlacementDelete>;
  816. LeafCacheStorage m_leaf_cache_storage;
  817. LeafPtr m_array_ptr;
  818. const ArrayBoolNull* m_leaf_ptr = nullptr;
  819. };
  820. class TimestampNodeBase : public ParentNode {
  821. public:
  822. using TConditionValue = Timestamp;
  823. static const bool special_null_node = false;
  824. TimestampNodeBase(Timestamp v, ColKey column)
  825. : m_value(v)
  826. {
  827. m_condition_column_key = column;
  828. m_dT = 2.0;
  829. }
  830. TimestampNodeBase(null, ColKey column)
  831. : TimestampNodeBase(Timestamp{}, column)
  832. {
  833. }
  834. void cluster_changed() override
  835. {
  836. m_array_ptr = nullptr;
  837. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayTimestamp(m_table.unchecked_ptr()->get_alloc()));
  838. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  839. m_leaf_ptr = m_array_ptr.get();
  840. }
  841. protected:
  842. TimestampNodeBase(const TimestampNodeBase& from)
  843. : ParentNode(from)
  844. , m_value(from.m_value)
  845. {
  846. }
  847. Timestamp m_value;
  848. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayTimestamp), alignof(ArrayTimestamp)>::type;
  849. using LeafPtr = std::unique_ptr<ArrayTimestamp, PlacementDelete>;
  850. LeafCacheStorage m_leaf_cache_storage;
  851. LeafPtr m_array_ptr;
  852. const ArrayTimestamp* m_leaf_ptr = nullptr;
  853. };
  854. template <class TConditionFunction>
  855. class TimestampNode : public TimestampNodeBase {
  856. public:
  857. using TimestampNodeBase::TimestampNodeBase;
  858. size_t find_first_local(size_t start, size_t end) override
  859. {
  860. return m_leaf_ptr->find_first<TConditionFunction>(m_value, start, end);
  861. }
  862. std::string describe(util::serializer::SerialisationState& state) const override
  863. {
  864. REALM_ASSERT(m_condition_column_key);
  865. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " +
  866. TConditionFunction::description() + " " + util::serializer::print_value(TimestampNode::m_value);
  867. }
  868. std::unique_ptr<ParentNode> clone() const override
  869. {
  870. return std::unique_ptr<ParentNode>(new TimestampNode(*this));
  871. }
  872. protected:
  873. TimestampNode(const TimestampNode& from, Transaction* tr)
  874. : TimestampNodeBase(from, tr)
  875. {
  876. }
  877. };
  878. class DecimalNodeBase : public ParentNode {
  879. public:
  880. using TConditionValue = Decimal128;
  881. static const bool special_null_node = false;
  882. DecimalNodeBase(Decimal128 v, ColKey column)
  883. : m_value(v)
  884. {
  885. m_condition_column_key = column;
  886. }
  887. DecimalNodeBase(null, ColKey column)
  888. : DecimalNodeBase(Decimal128{null()}, column)
  889. {
  890. }
  891. void cluster_changed() override
  892. {
  893. m_array_ptr = nullptr;
  894. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayDecimal128(m_table.unchecked_ptr()->get_alloc()));
  895. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  896. m_leaf_ptr = m_array_ptr.get();
  897. }
  898. void init(bool will_query_ranges) override
  899. {
  900. ParentNode::init(will_query_ranges);
  901. m_dD = 100.0;
  902. }
  903. protected:
  904. DecimalNodeBase(const DecimalNodeBase& from)
  905. : ParentNode(from)
  906. , m_value(from.m_value)
  907. {
  908. }
  909. Decimal128 m_value;
  910. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayDecimal128), alignof(ArrayDecimal128)>::type;
  911. using LeafPtr = std::unique_ptr<ArrayDecimal128, PlacementDelete>;
  912. LeafCacheStorage m_leaf_cache_storage;
  913. LeafPtr m_array_ptr;
  914. const ArrayDecimal128* m_leaf_ptr = nullptr;
  915. };
  916. template <class TConditionFunction>
  917. class DecimalNode : public DecimalNodeBase {
  918. public:
  919. using DecimalNodeBase::DecimalNodeBase;
  920. size_t find_first_local(size_t start, size_t end) override
  921. {
  922. TConditionFunction cond;
  923. bool value_is_null = m_value.is_null();
  924. for (size_t i = start; i < end; i++) {
  925. Decimal128 val = m_leaf_ptr->get(i);
  926. if (cond(val, m_value, val.is_null(), value_is_null))
  927. return i;
  928. }
  929. return realm::npos;
  930. }
  931. std::string describe(util::serializer::SerialisationState& state) const override
  932. {
  933. REALM_ASSERT(m_condition_column_key);
  934. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " +
  935. TConditionFunction::description() + " " + util::serializer::print_value(DecimalNode::m_value);
  936. }
  937. std::unique_ptr<ParentNode> clone() const override
  938. {
  939. return std::unique_ptr<ParentNode>(new DecimalNode(*this));
  940. }
  941. protected:
  942. DecimalNode(const DecimalNode& from, Transaction* tr)
  943. : DecimalNodeBase(from, tr)
  944. {
  945. }
  946. };
  947. size_t do_search_index(ObjKey& last_start_key, size_t& result_get, std::vector<ObjKey>& results,
  948. const Cluster* cluster, size_t start, size_t end);
  949. template <class ObjectType, class ArrayType>
  950. class FixedBytesNodeBase : public ParentNode {
  951. public:
  952. using TConditionValue = ObjectType;
  953. static const bool special_null_node = false;
  954. FixedBytesNodeBase(ObjectType v, ColKey column)
  955. : m_value(v)
  956. {
  957. m_condition_column_key = column;
  958. }
  959. FixedBytesNodeBase(null, ColKey column)
  960. : FixedBytesNodeBase(ObjectType{}, column)
  961. {
  962. m_value_is_null = true;
  963. }
  964. void cluster_changed() override
  965. {
  966. m_array_ptr = nullptr;
  967. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayType(m_table.unchecked_ptr()->get_alloc()));
  968. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  969. m_leaf_ptr = m_array_ptr.get();
  970. }
  971. void init(bool will_query_ranges) override
  972. {
  973. ParentNode::init(will_query_ranges);
  974. m_dD = 100.0;
  975. }
  976. protected:
  977. FixedBytesNodeBase(const FixedBytesNodeBase& from)
  978. : ParentNode(from)
  979. , m_value(from.m_value)
  980. , m_value_is_null(from.m_value_is_null)
  981. {
  982. }
  983. ObjectType m_value;
  984. bool m_value_is_null = false;
  985. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayType), alignof(ArrayType)>::type;
  986. using LeafPtr = std::unique_ptr<ArrayType, PlacementDelete>;
  987. LeafCacheStorage m_leaf_cache_storage;
  988. LeafPtr m_array_ptr;
  989. const ArrayType* m_leaf_ptr = nullptr;
  990. };
  991. template <class TConditionFunction, class ObjectType, class ArrayType>
  992. class FixedBytesNode : public FixedBytesNodeBase<ObjectType, ArrayType> {
  993. public:
  994. using FixedBytesNodeBase<ObjectType, ArrayType>::FixedBytesNodeBase;
  995. size_t find_first_local(size_t start, size_t end) override
  996. {
  997. TConditionFunction cond;
  998. for (size_t i = start; i < end; i++) {
  999. util::Optional<ObjectType> val = this->m_leaf_ptr->get(i);
  1000. if (val) {
  1001. if (cond(*val, this->m_value, false, this->m_value_is_null))
  1002. return i;
  1003. }
  1004. else {
  1005. if (cond(ObjectType{}, this->m_value, true, this->m_value_is_null))
  1006. return i;
  1007. }
  1008. }
  1009. return realm::npos;
  1010. }
  1011. std::string describe(util::serializer::SerialisationState& state) const override
  1012. {
  1013. REALM_ASSERT(this->m_condition_column_key);
  1014. return state.describe_column(ParentNode::m_table, this->m_condition_column_key) + " " +
  1015. TConditionFunction::description() + " " +
  1016. (this->m_value_is_null ? util::serializer::print_value(realm::null())
  1017. : util::serializer::print_value(this->m_value));
  1018. }
  1019. std::unique_ptr<ParentNode> clone() const override
  1020. {
  1021. return std::unique_ptr<ParentNode>(new FixedBytesNode(*this));
  1022. }
  1023. protected:
  1024. FixedBytesNode(const FixedBytesNode& from, Transaction* tr)
  1025. : FixedBytesNode(from, tr)
  1026. {
  1027. }
  1028. };
  1029. template <class ObjectType, class ArrayType>
  1030. class FixedBytesNode<Equal, ObjectType, ArrayType> : public FixedBytesNodeBase<ObjectType, ArrayType> {
  1031. public:
  1032. using FixedBytesNodeBase<ObjectType, ArrayType>::FixedBytesNodeBase;
  1033. using BaseType = FixedBytesNodeBase<ObjectType, ArrayType>;
  1034. void init(bool will_query_ranges) override
  1035. {
  1036. BaseType::init(will_query_ranges);
  1037. if (!this->m_value_is_null) {
  1038. m_optional_value = this->m_value;
  1039. }
  1040. if (has_search_index()) {
  1041. // _search_index_init();
  1042. m_result.clear();
  1043. auto index = BaseType::m_table->get_search_index(BaseType::m_condition_column_key);
  1044. index->find_all(m_result, m_optional_value);
  1045. m_result_get = 0;
  1046. m_last_start_key = ObjKey();
  1047. this->m_dT = 0;
  1048. }
  1049. }
  1050. void index_based_aggregate(size_t limit, Evaluator evaluator) override
  1051. {
  1052. for (size_t t = 0; t < m_result.size() && limit > 0; ++t) {
  1053. auto obj = this->m_table->get_object(m_result[t]);
  1054. if (evaluator(obj)) {
  1055. --limit;
  1056. }
  1057. }
  1058. }
  1059. bool has_search_index() const override
  1060. {
  1061. return this->m_table->has_search_index(BaseType::m_condition_column_key);
  1062. }
  1063. size_t find_first_local(size_t start, size_t end) override
  1064. {
  1065. REALM_ASSERT(this->m_table);
  1066. size_t s = realm::npos;
  1067. if (start < end) {
  1068. if (has_search_index()) {
  1069. return do_search_index(m_last_start_key, m_result_get, m_result, this->m_cluster, start, end);
  1070. }
  1071. if (end - start == 1) {
  1072. if (this->m_leaf_ptr->get(start) == m_optional_value) {
  1073. s = start;
  1074. }
  1075. }
  1076. else {
  1077. s = this->m_leaf_ptr->find_first(m_optional_value, start, end);
  1078. }
  1079. }
  1080. return s;
  1081. }
  1082. std::string describe(util::serializer::SerialisationState& state) const override
  1083. {
  1084. REALM_ASSERT(this->m_condition_column_key);
  1085. return state.describe_column(ParentNode::m_table, this->m_condition_column_key) + " " + Equal::description() +
  1086. " " +
  1087. (this->m_value_is_null ? util::serializer::print_value(realm::null())
  1088. : util::serializer::print_value(this->m_value));
  1089. }
  1090. std::unique_ptr<ParentNode> clone() const override
  1091. {
  1092. return std::unique_ptr<ParentNode>(new FixedBytesNode(*this));
  1093. }
  1094. protected:
  1095. FixedBytesNode(const FixedBytesNode& from, Transaction* tr)
  1096. : FixedBytesNode(from, tr)
  1097. {
  1098. }
  1099. util::Optional<ObjectType> m_optional_value;
  1100. std::vector<ObjKey> m_result;
  1101. size_t m_result_get = 0;
  1102. ObjKey m_last_start_key;
  1103. };
  1104. template <typename T>
  1105. using ObjectIdNode = FixedBytesNode<T, ObjectId, ArrayObjectIdNull>;
  1106. template <typename T>
  1107. using UUIDNode = FixedBytesNode<T, UUID, ArrayUUIDNull>;
  1108. class MixedNodeBase : public ParentNode {
  1109. public:
  1110. using TConditionValue = Mixed;
  1111. static const bool special_null_node = false;
  1112. MixedNodeBase(Mixed v, ColKey column)
  1113. : m_value(v)
  1114. , m_value_is_null(v.is_null())
  1115. {
  1116. REALM_ASSERT(column.get_type() == col_type_Mixed);
  1117. get_ownership();
  1118. m_condition_column_key = column;
  1119. }
  1120. MixedNodeBase(null, ColKey column)
  1121. : MixedNodeBase(Mixed{}, column)
  1122. {
  1123. m_value_is_null = true;
  1124. }
  1125. void cluster_changed() override
  1126. {
  1127. m_array_ptr = nullptr;
  1128. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayMixed(m_table.unchecked_ptr()->get_alloc()));
  1129. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  1130. m_leaf_ptr = m_array_ptr.get();
  1131. }
  1132. void init(bool will_query_ranges) override
  1133. {
  1134. ParentNode::init(will_query_ranges);
  1135. m_dD = 100.0;
  1136. }
  1137. std::string describe(util::serializer::SerialisationState& state) const override
  1138. {
  1139. REALM_ASSERT(m_condition_column_key);
  1140. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " + this->describe_condition() +
  1141. " " +
  1142. (m_value_is_null ? util::serializer::print_value(realm::null())
  1143. : util::serializer::print_value(m_value));
  1144. }
  1145. protected:
  1146. MixedNodeBase(const MixedNodeBase& from)
  1147. : ParentNode(from)
  1148. , m_value(from.m_value)
  1149. , m_value_is_null(from.m_value_is_null)
  1150. {
  1151. get_ownership();
  1152. }
  1153. void get_ownership()
  1154. {
  1155. if (m_value.is_type(type_String, type_Binary)) {
  1156. auto bin = m_value.get_binary();
  1157. m_buffer = OwnedBinaryData(bin.data(), bin.size());
  1158. auto tmp = m_buffer.get();
  1159. if (m_value.is_type(type_String)) {
  1160. m_value = Mixed(StringData(tmp.data(), tmp.size()));
  1161. }
  1162. else {
  1163. m_value = Mixed(tmp);
  1164. }
  1165. }
  1166. }
  1167. QueryValue m_value;
  1168. OwnedBinaryData m_buffer;
  1169. bool m_value_is_null = false;
  1170. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayMixed), alignof(ArrayMixed)>::type;
  1171. using LeafPtr = std::unique_ptr<ArrayMixed, PlacementDelete>;
  1172. LeafCacheStorage m_leaf_cache_storage;
  1173. LeafPtr m_array_ptr;
  1174. const ArrayMixed* m_leaf_ptr = nullptr;
  1175. };
  1176. template <class TConditionFunction>
  1177. class MixedNode : public MixedNodeBase {
  1178. public:
  1179. using MixedNodeBase::MixedNodeBase;
  1180. size_t find_first_local(size_t start, size_t end) override
  1181. {
  1182. TConditionFunction cond;
  1183. for (size_t i = start; i < end; i++) {
  1184. QueryValue val(m_leaf_ptr->get(i));
  1185. if constexpr (realm::is_any_v<TConditionFunction, BeginsWith, BeginsWithIns, EndsWith, EndsWithIns, Like,
  1186. LikeIns, NotEqualIns, Contains, ContainsIns>) {
  1187. // For some strange reason the parameters are swapped for string conditions
  1188. if (cond(m_value, val))
  1189. return i;
  1190. }
  1191. else {
  1192. if (cond(val, m_value))
  1193. return i;
  1194. }
  1195. }
  1196. return realm::npos;
  1197. }
  1198. virtual std::string describe_condition() const override
  1199. {
  1200. return TConditionFunction::description();
  1201. }
  1202. std::unique_ptr<ParentNode> clone() const override
  1203. {
  1204. return std::unique_ptr<ParentNode>(new MixedNode(*this));
  1205. }
  1206. protected:
  1207. MixedNode(const MixedNode& from, Transaction* tr)
  1208. : MixedNode(from, tr)
  1209. {
  1210. }
  1211. };
  1212. template <>
  1213. class MixedNode<Equal> : public MixedNodeBase {
  1214. public:
  1215. MixedNode<Equal>(Mixed v, ColKey column)
  1216. : MixedNodeBase(v, column)
  1217. {
  1218. }
  1219. MixedNode<Equal>(const MixedNode<Equal>& other)
  1220. : MixedNodeBase(other)
  1221. , m_has_search_index(other.m_has_search_index)
  1222. {
  1223. }
  1224. void init(bool will_query_ranges) override;
  1225. void cluster_changed() override
  1226. {
  1227. // If we use searchindex, we do not need further access to clusters
  1228. if (!m_has_search_index) {
  1229. MixedNodeBase::cluster_changed();
  1230. }
  1231. }
  1232. void table_changed() override
  1233. {
  1234. m_has_search_index = m_table.unchecked_ptr()->has_search_index(m_condition_column_key);
  1235. }
  1236. bool has_search_index() const override
  1237. {
  1238. return m_has_search_index;
  1239. }
  1240. size_t find_first_local(size_t start, size_t end) override;
  1241. virtual std::string describe_condition() const override
  1242. {
  1243. return Equal::description();
  1244. }
  1245. std::unique_ptr<ParentNode> clone() const override
  1246. {
  1247. return std::unique_ptr<ParentNode>(new MixedNode<Equal>(*this));
  1248. }
  1249. protected:
  1250. std::vector<ObjKey> m_index_matches;
  1251. ObjKey m_actual_key;
  1252. ObjKey m_last_start_key;
  1253. size_t m_results_start;
  1254. size_t m_results_ndx;
  1255. size_t m_results_end;
  1256. bool m_has_search_index = false;
  1257. void index_based_aggregate(size_t limit, Evaluator evaluator) override;
  1258. };
  1259. class StringNodeBase : public ParentNode {
  1260. public:
  1261. using TConditionValue = StringData;
  1262. static const bool special_null_node = true;
  1263. StringNodeBase(StringData v, ColKey column)
  1264. : m_value(v.is_null() ? util::none : util::make_optional(std::string(v)))
  1265. {
  1266. m_condition_column_key = column;
  1267. m_dT = 10.0;
  1268. }
  1269. void table_changed() override
  1270. {
  1271. m_is_string_enum = m_table.unchecked_ptr()->is_enumerated(m_condition_column_key);
  1272. }
  1273. void cluster_changed() override
  1274. {
  1275. // Assigning nullptr will cause the Leaf destructor to be called. Must
  1276. // be done before assigning a new one. Otherwise the destructor will be
  1277. // called after the constructor is called and that is unfortunate if
  1278. // the object has the same address. (As in this case)
  1279. m_array_ptr = nullptr;
  1280. // Create new Leaf
  1281. m_array_ptr = LeafPtr(new (&m_leaf_cache_storage) ArrayString(m_table.unchecked_ptr()->get_alloc()));
  1282. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  1283. m_leaf_ptr = m_array_ptr.get();
  1284. }
  1285. void init(bool will_query_ranges) override
  1286. {
  1287. ParentNode::init(will_query_ranges);
  1288. m_probes = 0;
  1289. m_matches = 0;
  1290. m_end_s = 0;
  1291. m_leaf_start = 0;
  1292. m_leaf_end = 0;
  1293. }
  1294. virtual void clear_leaf_state()
  1295. {
  1296. m_array_ptr = nullptr;
  1297. }
  1298. StringNodeBase(const StringNodeBase& from)
  1299. : ParentNode(from)
  1300. , m_value(from.m_value)
  1301. , m_is_string_enum(from.m_is_string_enum)
  1302. {
  1303. }
  1304. virtual std::string describe(util::serializer::SerialisationState& state) const override
  1305. {
  1306. REALM_ASSERT(m_condition_column_key);
  1307. StringData sd;
  1308. if (bool(StringNodeBase::m_value)) {
  1309. sd = StringData(StringNodeBase::m_value.value());
  1310. }
  1311. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " + describe_condition() + " " +
  1312. util::serializer::print_value(sd);
  1313. }
  1314. protected:
  1315. util::Optional<std::string> m_value;
  1316. using LeafCacheStorage = typename std::aligned_storage<sizeof(ArrayString), alignof(ArrayString)>::type;
  1317. using LeafPtr = std::unique_ptr<ArrayString, PlacementDelete>;
  1318. LeafCacheStorage m_leaf_cache_storage;
  1319. LeafPtr m_array_ptr;
  1320. const ArrayString* m_leaf_ptr = nullptr;
  1321. bool m_is_string_enum = false;
  1322. size_t m_end_s = 0;
  1323. size_t m_leaf_start = 0;
  1324. size_t m_leaf_end = 0;
  1325. inline StringData get_string(size_t s)
  1326. {
  1327. return m_leaf_ptr->get(s);
  1328. }
  1329. };
  1330. // Conditions for strings. Note that Equal is specialized later in this file!
  1331. template <class TConditionFunction>
  1332. class StringNode : public StringNodeBase {
  1333. public:
  1334. StringNode(StringData v, ColKey column)
  1335. : StringNodeBase(v, column)
  1336. {
  1337. auto upper = case_map(v, true);
  1338. auto lower = case_map(v, false);
  1339. if (!upper || !lower) {
  1340. error_code = "Malformed UTF-8: " + std::string(v);
  1341. }
  1342. else {
  1343. m_ucase = std::move(*upper);
  1344. m_lcase = std::move(*lower);
  1345. }
  1346. }
  1347. void init(bool will_query_ranges) override
  1348. {
  1349. StringNodeBase::init(will_query_ranges);
  1350. clear_leaf_state();
  1351. }
  1352. size_t find_first_local(size_t start, size_t end) override
  1353. {
  1354. TConditionFunction cond;
  1355. for (size_t s = start; s < end; ++s) {
  1356. StringData t = get_string(s);
  1357. if (cond(StringData(m_value), m_ucase.c_str(), m_lcase.c_str(), t))
  1358. return s;
  1359. }
  1360. return not_found;
  1361. }
  1362. virtual std::string describe_condition() const override
  1363. {
  1364. return TConditionFunction::description();
  1365. }
  1366. std::unique_ptr<ParentNode> clone() const override
  1367. {
  1368. return std::unique_ptr<ParentNode>(new StringNode<TConditionFunction>(*this));
  1369. }
  1370. StringNode(const StringNode& from)
  1371. : StringNodeBase(from)
  1372. , m_ucase(from.m_ucase)
  1373. , m_lcase(from.m_lcase)
  1374. {
  1375. }
  1376. protected:
  1377. std::string m_ucase;
  1378. std::string m_lcase;
  1379. };
  1380. // Specialization for Contains condition on Strings - we specialize because we can utilize Boyer-Moore
  1381. template <>
  1382. class StringNode<Contains> : public StringNodeBase {
  1383. public:
  1384. StringNode(StringData v, ColKey column)
  1385. : StringNodeBase(v, column)
  1386. , m_charmap()
  1387. {
  1388. if (v.size() == 0)
  1389. return;
  1390. // Build a dictionary of char-to-last distances in the search string
  1391. // (zero indicates that the char is not in needle)
  1392. size_t last_char_pos = v.size() - 1;
  1393. for (size_t i = 0; i < last_char_pos; ++i) {
  1394. // we never jump longer increments than 255 chars, even if needle is longer (to fit in one byte)
  1395. uint8_t jump = last_char_pos - i < 255 ? static_cast<uint8_t>(last_char_pos - i) : 255;
  1396. unsigned char c = v[i];
  1397. m_charmap[c] = jump;
  1398. }
  1399. m_dT = 50.0;
  1400. }
  1401. void init(bool will_query_ranges) override
  1402. {
  1403. StringNodeBase::init(will_query_ranges);
  1404. clear_leaf_state();
  1405. }
  1406. size_t find_first_local(size_t start, size_t end) override
  1407. {
  1408. Contains cond;
  1409. for (size_t s = start; s < end; ++s) {
  1410. StringData t = get_string(s);
  1411. if (cond(StringData(m_value), m_charmap, t))
  1412. return s;
  1413. }
  1414. return not_found;
  1415. }
  1416. virtual std::string describe_condition() const override
  1417. {
  1418. return Contains::description();
  1419. }
  1420. std::unique_ptr<ParentNode> clone() const override
  1421. {
  1422. return std::unique_ptr<ParentNode>(new StringNode<Contains>(*this));
  1423. }
  1424. StringNode(const StringNode& from)
  1425. : StringNodeBase(from)
  1426. , m_charmap(from.m_charmap)
  1427. {
  1428. }
  1429. protected:
  1430. std::array<uint8_t, 256> m_charmap;
  1431. };
  1432. // Specialization for ContainsIns condition on Strings - we specialize because we can utilize Boyer-Moore
  1433. template <>
  1434. class StringNode<ContainsIns> : public StringNodeBase {
  1435. public:
  1436. StringNode(StringData v, ColKey column)
  1437. : StringNodeBase(v, column)
  1438. , m_charmap()
  1439. {
  1440. auto upper = case_map(v, true);
  1441. auto lower = case_map(v, false);
  1442. if (!upper || !lower) {
  1443. error_code = "Malformed UTF-8: " + std::string(v);
  1444. }
  1445. else {
  1446. m_ucase = std::move(*upper);
  1447. m_lcase = std::move(*lower);
  1448. }
  1449. if (v.size() == 0)
  1450. return;
  1451. // Build a dictionary of char-to-last distances in the search string
  1452. // (zero indicates that the char is not in needle)
  1453. size_t last_char_pos = m_ucase.size() - 1;
  1454. for (size_t i = 0; i < last_char_pos; ++i) {
  1455. // we never jump longer increments than 255 chars, even if needle is longer (to fit in one byte)
  1456. uint8_t jump = last_char_pos - i < 255 ? static_cast<uint8_t>(last_char_pos - i) : 255;
  1457. unsigned char uc = m_ucase[i];
  1458. unsigned char lc = m_lcase[i];
  1459. m_charmap[uc] = jump;
  1460. m_charmap[lc] = jump;
  1461. }
  1462. m_dT = 75.0;
  1463. }
  1464. void init(bool will_query_ranges) override
  1465. {
  1466. StringNodeBase::init(will_query_ranges);
  1467. clear_leaf_state();
  1468. }
  1469. size_t find_first_local(size_t start, size_t end) override
  1470. {
  1471. ContainsIns cond;
  1472. for (size_t s = start; s < end; ++s) {
  1473. StringData t = get_string(s);
  1474. // The current behaviour is to return all results when querying for a null string.
  1475. // See comment above Query_NextGen_StringConditions on why every string including "" contains null.
  1476. if (!bool(m_value)) {
  1477. return s;
  1478. }
  1479. if (cond(StringData(m_value), m_ucase.c_str(), m_lcase.c_str(), m_charmap, t))
  1480. return s;
  1481. }
  1482. return not_found;
  1483. }
  1484. virtual std::string describe_condition() const override
  1485. {
  1486. return ContainsIns::description();
  1487. }
  1488. std::unique_ptr<ParentNode> clone() const override
  1489. {
  1490. return std::unique_ptr<ParentNode>(new StringNode<ContainsIns>(*this));
  1491. }
  1492. StringNode(const StringNode& from)
  1493. : StringNodeBase(from)
  1494. , m_charmap(from.m_charmap)
  1495. , m_ucase(from.m_ucase)
  1496. , m_lcase(from.m_lcase)
  1497. {
  1498. }
  1499. protected:
  1500. std::array<uint8_t, 256> m_charmap;
  1501. std::string m_ucase;
  1502. std::string m_lcase;
  1503. };
  1504. class StringNodeEqualBase : public StringNodeBase {
  1505. public:
  1506. StringNodeEqualBase(StringData v, ColKey column)
  1507. : StringNodeBase(v, column)
  1508. {
  1509. }
  1510. StringNodeEqualBase(const StringNodeEqualBase& from)
  1511. : StringNodeBase(from)
  1512. , m_has_search_index(from.m_has_search_index)
  1513. {
  1514. }
  1515. void init(bool) override;
  1516. bool has_search_index() const override
  1517. {
  1518. return m_has_search_index;
  1519. }
  1520. void cluster_changed() override
  1521. {
  1522. // If we use searchindex, we do not need further access to clusters
  1523. if (!m_has_search_index) {
  1524. StringNodeBase::cluster_changed();
  1525. }
  1526. }
  1527. size_t find_first_local(size_t start, size_t end) override;
  1528. virtual std::string describe_condition() const override
  1529. {
  1530. return Equal::description();
  1531. }
  1532. protected:
  1533. ObjKey m_actual_key;
  1534. ObjKey m_last_start_key;
  1535. size_t m_results_start;
  1536. size_t m_results_ndx;
  1537. size_t m_results_end;
  1538. bool m_has_search_index = false;
  1539. inline BinaryData str_to_bin(const StringData& s) noexcept
  1540. {
  1541. return BinaryData(s.data(), s.size());
  1542. }
  1543. virtual ObjKey get_key(size_t ndx) = 0;
  1544. virtual void _search_index_init() = 0;
  1545. virtual size_t _find_first_local(size_t start, size_t end) = 0;
  1546. };
  1547. // Specialization for Equal condition on Strings - we specialize because we can utilize indexes (if they exist) for
  1548. // Equal. This specialisation also supports combining other StringNode<Equal> conditions into itself in order to
  1549. // optimise the non-indexed linear search that can be happen when many conditions are OR'd together in an "IN" query.
  1550. // Future optimization: make specialization for greater, notequal, etc
  1551. template <>
  1552. class StringNode<Equal> : public StringNodeEqualBase {
  1553. public:
  1554. using StringNodeEqualBase::StringNodeEqualBase;
  1555. void table_changed() override
  1556. {
  1557. StringNodeBase::table_changed();
  1558. m_has_search_index = m_table.unchecked_ptr()->has_search_index(m_condition_column_key) ||
  1559. m_table.unchecked_ptr()->get_primary_key_column() == m_condition_column_key;
  1560. }
  1561. void _search_index_init() override;
  1562. bool do_consume_condition(ParentNode& other) override;
  1563. std::unique_ptr<ParentNode> clone() const override
  1564. {
  1565. return std::unique_ptr<ParentNode>(new StringNode<Equal>(*this));
  1566. }
  1567. std::string describe(util::serializer::SerialisationState& state) const override;
  1568. StringNode<Equal>(const StringNode& from)
  1569. : StringNodeEqualBase(from)
  1570. {
  1571. for (auto& needle : from.m_needles) {
  1572. if (needle.is_null()) {
  1573. m_needles.emplace();
  1574. }
  1575. else {
  1576. m_needle_storage.push_back(std::make_unique<char[]>(needle.size()));
  1577. std::copy(needle.data(), needle.data() + needle.size(), m_needle_storage.back().get());
  1578. m_needles.insert(StringData(m_needle_storage.back().get(), needle.size()));
  1579. }
  1580. }
  1581. }
  1582. void index_based_aggregate(size_t limit, Evaluator evaluator) override
  1583. {
  1584. if (limit == 0)
  1585. return;
  1586. if (m_index_matches == nullptr) {
  1587. if (m_results_end) { // 1 result
  1588. auto obj = m_table->get_object(m_actual_key);
  1589. evaluator(obj);
  1590. }
  1591. }
  1592. else { // multiple results
  1593. for (size_t t = m_results_start; t < m_results_end && limit > 0; ++t) {
  1594. auto obj = m_table->get_object(ObjKey(m_index_matches->get(t)));
  1595. if (evaluator(obj)) {
  1596. --limit;
  1597. }
  1598. }
  1599. }
  1600. }
  1601. private:
  1602. std::unique_ptr<IntegerColumn> m_index_matches;
  1603. ObjKey get_key(size_t ndx) override
  1604. {
  1605. if (IntegerColumn* vec = m_index_matches.get()) {
  1606. return ObjKey(vec->get(ndx));
  1607. }
  1608. else if (m_results_end == 1) {
  1609. return m_actual_key;
  1610. }
  1611. return ObjKey();
  1612. }
  1613. size_t _find_first_local(size_t start, size_t end) override;
  1614. std::unordered_set<StringData> m_needles;
  1615. std::vector<std::unique_ptr<char[]>> m_needle_storage;
  1616. };
  1617. // Specialization for EqualIns condition on Strings - we specialize because we can utilize indexes (if they exist) for
  1618. // EqualIns.
  1619. template <>
  1620. class StringNode<EqualIns> : public StringNodeEqualBase {
  1621. public:
  1622. StringNode(StringData v, ColKey column)
  1623. : StringNodeEqualBase(v, column)
  1624. {
  1625. auto upper = case_map(v, true);
  1626. auto lower = case_map(v, false);
  1627. if (!upper || !lower) {
  1628. error_code = "Malformed UTF-8: " + std::string(v);
  1629. }
  1630. else {
  1631. m_ucase = std::move(*upper);
  1632. m_lcase = std::move(*lower);
  1633. }
  1634. }
  1635. void clear_leaf_state() override
  1636. {
  1637. StringNodeEqualBase::clear_leaf_state();
  1638. m_index_matches.clear();
  1639. }
  1640. void table_changed() override
  1641. {
  1642. StringNodeBase::table_changed();
  1643. m_has_search_index = m_table.unchecked_ptr()->has_search_index(m_condition_column_key);
  1644. }
  1645. void _search_index_init() override;
  1646. virtual std::string describe_condition() const override
  1647. {
  1648. return EqualIns::description();
  1649. }
  1650. std::unique_ptr<ParentNode> clone() const override
  1651. {
  1652. return std::unique_ptr<ParentNode>(new StringNode(*this));
  1653. }
  1654. StringNode(const StringNode& from)
  1655. : StringNodeEqualBase(from)
  1656. , m_ucase(from.m_ucase)
  1657. , m_lcase(from.m_lcase)
  1658. {
  1659. }
  1660. void index_based_aggregate(size_t limit, Evaluator evaluator) override
  1661. {
  1662. for (size_t t = 0; t < m_index_matches.size() && limit > 0; ++t) {
  1663. auto obj = m_table->get_object(m_index_matches[t]);
  1664. if (evaluator(obj)) {
  1665. --limit;
  1666. }
  1667. }
  1668. }
  1669. private:
  1670. // Used for index lookup
  1671. std::vector<ObjKey> m_index_matches;
  1672. std::string m_ucase;
  1673. std::string m_lcase;
  1674. ObjKey get_key(size_t ndx) override
  1675. {
  1676. return m_index_matches[ndx];
  1677. }
  1678. size_t _find_first_local(size_t start, size_t end) override;
  1679. };
  1680. // OR node contains at least two node pointers: Two or more conditions to OR
  1681. // together in m_conditions, and the next AND condition (if any) in m_child.
  1682. //
  1683. // For 'second.equal(23).begin_group().first.equal(111).Or().first.equal(222).end_group().third().equal(555)', this
  1684. // will first set m_conditions[0] = left-hand-side through constructor, and then later, when .first.equal(222) is
  1685. // invoked, invocation will set m_conditions[1] = right-hand-side through Query& Query::Or() (see query.cpp).
  1686. // In there, m_child is also set to next AND condition (if any exists) following the OR.
  1687. class OrNode : public ParentNode {
  1688. public:
  1689. OrNode(std::unique_ptr<ParentNode> condition)
  1690. {
  1691. m_dT = 50.0;
  1692. if (condition)
  1693. m_conditions.emplace_back(std::move(condition));
  1694. }
  1695. OrNode(const OrNode& other)
  1696. : ParentNode(other)
  1697. {
  1698. for (const auto& condition : other.m_conditions) {
  1699. m_conditions.emplace_back(condition->clone());
  1700. }
  1701. }
  1702. void table_changed() override
  1703. {
  1704. for (auto& condition : m_conditions) {
  1705. condition->set_table(m_table);
  1706. }
  1707. }
  1708. void cluster_changed() override
  1709. {
  1710. for (auto& condition : m_conditions) {
  1711. condition->set_cluster(m_cluster);
  1712. }
  1713. m_start.clear();
  1714. m_start.resize(m_conditions.size(), 0);
  1715. m_last.clear();
  1716. m_last.resize(m_conditions.size(), 0);
  1717. m_was_match.clear();
  1718. m_was_match.resize(m_conditions.size(), false);
  1719. }
  1720. std::string describe(util::serializer::SerialisationState& state) const override
  1721. {
  1722. std::string s;
  1723. for (size_t i = 0; i < m_conditions.size(); ++i) {
  1724. if (m_conditions[i]) {
  1725. s += m_conditions[i]->describe_expression(state);
  1726. if (i != m_conditions.size() - 1) {
  1727. s += " or ";
  1728. }
  1729. }
  1730. }
  1731. if (m_conditions.size() > 1) {
  1732. s = "(" + s + ")";
  1733. }
  1734. return s;
  1735. }
  1736. void collect_dependencies(std::vector<TableKey>& versions) const override
  1737. {
  1738. for (const auto& cond : m_conditions) {
  1739. cond->collect_dependencies(versions);
  1740. }
  1741. }
  1742. void init(bool will_query_ranges) override
  1743. {
  1744. ParentNode::init(will_query_ranges);
  1745. combine_conditions(!will_query_ranges);
  1746. m_start.clear();
  1747. m_start.resize(m_conditions.size(), 0);
  1748. m_last.clear();
  1749. m_last.resize(m_conditions.size(), 0);
  1750. m_was_match.clear();
  1751. m_was_match.resize(m_conditions.size(), false);
  1752. std::vector<ParentNode*> v;
  1753. for (auto& condition : m_conditions) {
  1754. condition->init(will_query_ranges);
  1755. v.clear();
  1756. condition->gather_children(v);
  1757. }
  1758. }
  1759. size_t find_first_local(size_t start, size_t end) override
  1760. {
  1761. if (start >= end)
  1762. return not_found;
  1763. size_t index = not_found;
  1764. for (size_t c = 0; c < m_conditions.size(); ++c) {
  1765. // out of order search; have to discard cached results
  1766. if (start < m_start[c]) {
  1767. m_last[c] = 0;
  1768. m_was_match[c] = false;
  1769. }
  1770. // already searched this range and didn't match
  1771. else if (m_last[c] >= end)
  1772. continue;
  1773. // already search this range and *did* match
  1774. else if (m_was_match[c] && m_last[c] >= start) {
  1775. if (index > m_last[c])
  1776. index = m_last[c];
  1777. continue;
  1778. }
  1779. m_start[c] = start;
  1780. size_t fmax = std::max(m_last[c], start);
  1781. size_t f = m_conditions[c]->find_first(fmax, end);
  1782. m_was_match[c] = f != not_found;
  1783. m_last[c] = f == not_found ? end : f;
  1784. if (f != not_found && index > m_last[c])
  1785. index = m_last[c];
  1786. }
  1787. return index;
  1788. }
  1789. std::string validate() override
  1790. {
  1791. if (error_code != "")
  1792. return error_code;
  1793. if (m_conditions.size() == 0)
  1794. return "Missing left-hand side of OR";
  1795. if (m_conditions.size() == 1)
  1796. return "Missing right-hand side of OR";
  1797. std::string s;
  1798. if (m_child != 0)
  1799. s = m_child->validate();
  1800. if (s != "")
  1801. return s;
  1802. for (size_t i = 0; i < m_conditions.size(); ++i) {
  1803. s = m_conditions[i]->validate();
  1804. if (s != "")
  1805. return s;
  1806. }
  1807. return "";
  1808. }
  1809. std::unique_ptr<ParentNode> clone() const override
  1810. {
  1811. return std::unique_ptr<ParentNode>(new OrNode(*this));
  1812. }
  1813. std::vector<std::unique_ptr<ParentNode>> m_conditions;
  1814. private:
  1815. void combine_conditions(bool ignore_indexes)
  1816. {
  1817. std::sort(m_conditions.begin(), m_conditions.end(), [](auto& a, auto& b) {
  1818. return a->m_condition_column_key < b->m_condition_column_key;
  1819. });
  1820. auto prev = m_conditions.begin()->get();
  1821. auto cond = [&](auto& node) {
  1822. if (prev->consume_condition(*node, ignore_indexes))
  1823. return true;
  1824. prev = &*node;
  1825. return false;
  1826. };
  1827. m_conditions.erase(std::remove_if(m_conditions.begin() + 1, m_conditions.end(), cond), m_conditions.end());
  1828. }
  1829. // start index of the last find for each cond
  1830. std::vector<size_t> m_start;
  1831. // last looked at index of the lasft find for each cond
  1832. // is a matching index if m_was_match is true
  1833. std::vector<size_t> m_last;
  1834. std::vector<bool> m_was_match;
  1835. };
  1836. class NotNode : public ParentNode {
  1837. public:
  1838. NotNode(std::unique_ptr<ParentNode> condition)
  1839. : m_condition(std::move(condition))
  1840. {
  1841. m_dT = 50.0;
  1842. }
  1843. void table_changed() override
  1844. {
  1845. m_condition->set_table(m_table);
  1846. }
  1847. void cluster_changed() override
  1848. {
  1849. m_condition->set_cluster(m_cluster);
  1850. // Heuristics bookkeeping:
  1851. m_known_range_start = 0;
  1852. m_known_range_end = 0;
  1853. m_first_in_known_range = not_found;
  1854. }
  1855. void init(bool will_query_ranges) override
  1856. {
  1857. ParentNode::init(will_query_ranges);
  1858. std::vector<ParentNode*> v;
  1859. m_condition->init(false);
  1860. v.clear();
  1861. m_condition->gather_children(v);
  1862. }
  1863. size_t find_first_local(size_t start, size_t end) override;
  1864. std::string validate() override
  1865. {
  1866. if (error_code != "")
  1867. return error_code;
  1868. if (m_condition == 0)
  1869. return "Missing argument to Not";
  1870. std::string s;
  1871. if (m_child != 0)
  1872. s = m_child->validate();
  1873. if (s != "")
  1874. return s;
  1875. s = m_condition->validate();
  1876. if (s != "")
  1877. return s;
  1878. return "";
  1879. }
  1880. std::string describe(util::serializer::SerialisationState& state) const override
  1881. {
  1882. if (m_condition) {
  1883. return "!(" + m_condition->describe_expression(state) + ")";
  1884. }
  1885. return "!()";
  1886. }
  1887. void collect_dependencies(std::vector<TableKey>& versions) const override
  1888. {
  1889. if (m_condition) {
  1890. m_condition->collect_dependencies(versions);
  1891. }
  1892. }
  1893. std::unique_ptr<ParentNode> clone() const override
  1894. {
  1895. return std::unique_ptr<ParentNode>(new NotNode(*this));
  1896. }
  1897. NotNode(const NotNode& from)
  1898. : ParentNode(from)
  1899. , m_condition(from.m_condition ? from.m_condition->clone() : nullptr)
  1900. , m_known_range_start(from.m_known_range_start)
  1901. , m_known_range_end(from.m_known_range_end)
  1902. , m_first_in_known_range(from.m_first_in_known_range)
  1903. {
  1904. }
  1905. std::unique_ptr<ParentNode> m_condition;
  1906. private:
  1907. // FIXME This heuristic might as well be reused for all condition nodes.
  1908. size_t m_known_range_start;
  1909. size_t m_known_range_end;
  1910. size_t m_first_in_known_range;
  1911. bool evaluate_at(size_t rowndx);
  1912. void update_known(size_t start, size_t end, size_t first);
  1913. size_t find_first_loop(size_t start, size_t end);
  1914. size_t find_first_covers_known(size_t start, size_t end);
  1915. size_t find_first_covered_by_known(size_t start, size_t end);
  1916. size_t find_first_overlap_lower(size_t start, size_t end);
  1917. size_t find_first_overlap_upper(size_t start, size_t end);
  1918. size_t find_first_no_overlap(size_t start, size_t end);
  1919. };
  1920. // Compare two columns with eachother row-by-row
  1921. class TwoColumnsNodeBase : public ParentNode {
  1922. public:
  1923. TwoColumnsNodeBase(ColKey column1, ColKey column2)
  1924. {
  1925. m_dT = 100.0;
  1926. m_condition_column_key1 = column1;
  1927. m_condition_column_key2 = column2;
  1928. }
  1929. ~TwoColumnsNodeBase() noexcept override {}
  1930. void table_changed() override
  1931. {
  1932. if (this->m_table) {
  1933. if (m_condition_column_key1.is_collection() || m_condition_column_key2.is_collection()) {
  1934. throw std::runtime_error(util::format("queries comparing two properties are not yet supported for "
  1935. "collections (list/set/dictionary) (%1 and %2)",
  1936. ParentNode::m_table->get_column_name(m_condition_column_key1),
  1937. ParentNode::m_table->get_column_name(m_condition_column_key2)));
  1938. }
  1939. ParentNode::m_table->check_column(m_condition_column_key1);
  1940. ParentNode::m_table->check_column(m_condition_column_key2);
  1941. }
  1942. }
  1943. static std::unique_ptr<ArrayPayload> update_cached_leaf_pointers_for_column(Allocator& alloc,
  1944. const ColKey& col_key);
  1945. void cluster_changed() override
  1946. {
  1947. if (!m_leaf_ptr1) {
  1948. m_leaf_ptr1 =
  1949. update_cached_leaf_pointers_for_column(m_table.unchecked_ptr()->get_alloc(), m_condition_column_key1);
  1950. }
  1951. if (!m_leaf_ptr2) {
  1952. m_leaf_ptr2 =
  1953. update_cached_leaf_pointers_for_column(m_table.unchecked_ptr()->get_alloc(), m_condition_column_key2);
  1954. }
  1955. this->m_cluster->init_leaf(m_condition_column_key1, m_leaf_ptr1.get());
  1956. this->m_cluster->init_leaf(m_condition_column_key2, m_leaf_ptr2.get());
  1957. }
  1958. virtual std::string describe(util::serializer::SerialisationState& state) const override
  1959. {
  1960. REALM_ASSERT(m_condition_column_key1 && m_condition_column_key2);
  1961. return state.describe_column(ParentNode::m_table, m_condition_column_key1) + " " + describe_condition() +
  1962. " " + state.describe_column(ParentNode::m_table, m_condition_column_key2);
  1963. }
  1964. TwoColumnsNodeBase(const TwoColumnsNodeBase& from)
  1965. : ParentNode(from)
  1966. , m_condition_column_key1(from.m_condition_column_key1)
  1967. , m_condition_column_key2(from.m_condition_column_key2)
  1968. {
  1969. }
  1970. protected:
  1971. mutable ColKey m_condition_column_key1;
  1972. mutable ColKey m_condition_column_key2;
  1973. std::unique_ptr<ArrayPayload> m_leaf_ptr1 = nullptr;
  1974. std::unique_ptr<ArrayPayload> m_leaf_ptr2 = nullptr;
  1975. };
  1976. template <class TConditionFunction>
  1977. class TwoColumnsNode : public TwoColumnsNodeBase {
  1978. public:
  1979. using TwoColumnsNodeBase::TwoColumnsNodeBase;
  1980. ~TwoColumnsNode() noexcept override {}
  1981. size_t find_first_local(size_t start, size_t end) override
  1982. {
  1983. size_t s = start;
  1984. while (s < end) {
  1985. QueryValue v1(m_leaf_ptr1->get_any(s));
  1986. QueryValue v2(m_leaf_ptr2->get_any(s));
  1987. if (TConditionFunction()(v1, v2))
  1988. return s;
  1989. else
  1990. s++;
  1991. }
  1992. return not_found;
  1993. }
  1994. virtual std::string describe_condition() const override
  1995. {
  1996. return TConditionFunction::description();
  1997. }
  1998. std::unique_ptr<ParentNode> clone() const override
  1999. {
  2000. return std::unique_ptr<ParentNode>(new TwoColumnsNode<TConditionFunction>(*this));
  2001. }
  2002. protected:
  2003. TwoColumnsNode(const TwoColumnsNode& from, Transaction* tr)
  2004. : TwoColumnsNode(from, tr)
  2005. {
  2006. }
  2007. };
  2008. // For Next-Generation expressions like col1 / col2 + 123 > col4 * 100.
  2009. class ExpressionNode : public ParentNode {
  2010. public:
  2011. ExpressionNode(std::unique_ptr<Expression>);
  2012. void init(bool) override;
  2013. size_t find_first_local(size_t start, size_t end) override;
  2014. void table_changed() override;
  2015. void cluster_changed() override;
  2016. void collect_dependencies(std::vector<TableKey>&) const override;
  2017. virtual std::string describe(util::serializer::SerialisationState& state) const override;
  2018. std::unique_ptr<ParentNode> clone() const override;
  2019. private:
  2020. ExpressionNode(const ExpressionNode& from);
  2021. std::unique_ptr<Expression> m_expression;
  2022. };
  2023. class LinksToNodeBase : public ParentNode {
  2024. public:
  2025. LinksToNodeBase(ColKey origin_column_key, ObjKey target_key)
  2026. : LinksToNodeBase(origin_column_key, std::vector<ObjKey>{target_key})
  2027. {
  2028. }
  2029. LinksToNodeBase(ColKey origin_column_key, const std::vector<ObjKey>& target_keys)
  2030. : m_target_keys(target_keys)
  2031. {
  2032. m_dT = 50.0;
  2033. m_condition_column_key = origin_column_key;
  2034. m_column_type = origin_column_key.get_type();
  2035. REALM_ASSERT(m_column_type == col_type_Link || m_column_type == col_type_LinkList);
  2036. REALM_ASSERT(!m_target_keys.empty());
  2037. }
  2038. void cluster_changed() override
  2039. {
  2040. m_array_ptr = nullptr;
  2041. if (m_column_type == col_type_Link) {
  2042. m_array_ptr = LeafPtr(new (&m_storage.m_list) ArrayKey(m_table.unchecked_ptr()->get_alloc()));
  2043. }
  2044. else if (m_column_type == col_type_LinkList) {
  2045. m_array_ptr = LeafPtr(new (&m_storage.m_linklist) ArrayList(m_table.unchecked_ptr()->get_alloc()));
  2046. }
  2047. m_cluster->init_leaf(this->m_condition_column_key, m_array_ptr.get());
  2048. m_leaf_ptr = m_array_ptr.get();
  2049. }
  2050. virtual std::string describe(util::serializer::SerialisationState& state) const override
  2051. {
  2052. REALM_ASSERT(m_condition_column_key);
  2053. if (m_target_keys.size() > 1)
  2054. throw SerialisationError("Serializing a query which links to multiple objects is currently unsupported.");
  2055. return state.describe_column(ParentNode::m_table, m_condition_column_key) + " " + describe_condition() + " " +
  2056. util::serializer::print_value(m_target_keys[0]);
  2057. }
  2058. protected:
  2059. std::vector<ObjKey> m_target_keys;
  2060. ColumnType m_column_type;
  2061. using LeafPtr = std::unique_ptr<ArrayPayload, PlacementDelete>;
  2062. union Storage {
  2063. typename std::aligned_storage<sizeof(ArrayKey), alignof(ArrayKey)>::type m_list;
  2064. typename std::aligned_storage<sizeof(ArrayList), alignof(ArrayList)>::type m_linklist;
  2065. };
  2066. Storage m_storage;
  2067. LeafPtr m_array_ptr;
  2068. const ArrayPayload* m_leaf_ptr = nullptr;
  2069. LinksToNodeBase(const LinksToNodeBase& source)
  2070. : ParentNode(source)
  2071. , m_target_keys(source.m_target_keys)
  2072. , m_column_type(source.m_column_type)
  2073. {
  2074. }
  2075. };
  2076. template <class TConditionFunction>
  2077. class LinksToNode : public LinksToNodeBase {
  2078. public:
  2079. using LinksToNodeBase::LinksToNodeBase;
  2080. virtual std::string describe_condition() const override
  2081. {
  2082. return TConditionFunction::description();
  2083. }
  2084. std::unique_ptr<ParentNode> clone() const override
  2085. {
  2086. return std::unique_ptr<ParentNode>(new LinksToNode<TConditionFunction>(*this));
  2087. }
  2088. size_t find_first_local(size_t start, size_t end) override;
  2089. };
  2090. } // namespace realm
  2091. #endif // REALM_QUERY_ENGINE_HPP