NCBI C++ ToolKit
macro_exec.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: macro_exec.cpp 44959 2020-04-28 18:49:47Z asztalos $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Anatoly Osipov
27  *
28  * File Description: Macro execution
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbiobj.hpp>
34 #include <corelib/ncbistd.hpp>
37 
38 #undef _TRACE
39 #define _TRACE(arg) ((void)0)
40 
41 /** @addtogroup GUI_MACRO_SCRIPTS_UTIL
42  *
43  * @{
44  */
45 
47 BEGIN_SCOPE(macro)
48 
49 template <typename T>
50 static bool BinOpsFunc(CQueryParseNode::EType op, const T& a1, const T& a2)
51 {
52  _TRACE("====");
53  switch(op) {
55  return a1 && a2;
57  return a1 || a2;
59  return (!a1 && a2) || (a1 && !a2);
61  return a1 && !a2;
63  return a1 == a2;
65  return a1 > a2;
67  return a1 >= a2;
69  return a1 < a2;
71  return a1 <= a2;
72  default: {
73  // Should be unreachable
74  string err_msg = "Invalid operation: " + CQueryParseNode::GetNodeTypeAsString(op);
75  NCBI_THROW(CMacroExecException, eInternalError, err_msg);
76  }
77  }
78  return false;
79 }
80 
82  const string& s1,
83  const string& s2,
84  bool case_sensitive)
85 {
86  _TRACE("====");
87  Int4 res = (case_sensitive) ? NStr::CompareCase(s1, s2) : NStr::CompareNocase(s1, s2);
88  return BinOpsFunc(op, res, 0);
89 }
90 
91 ///////////////////////////////////////////////////////////////////////////////
92 /// class CMQueryNodeValue
93 ///
95 {
96  while (GetDataType() == eRef) {
97  CRef<CMQueryNodeValue> tmp_obj = m_Ref;
98  *this = *tmp_obj;
99  }
100 }
101 
103 {
104  if ( m_DataType != eRef || !m_Ref)
105  return false;
106 
107  *m_Ref = source;
108  return true;
109 }
110 
112 {
114 
115  if (objinfo.GetTypeFamily() != eTypeFamilyPrimitive)
116  return;
117 
118  switch (objinfo.GetPrimitiveValueType()) {
119  case ePrimitiveValueString:
120  m_String = objinfo.GetPrimitiveValueString();
122  break;
123  case ePrimitiveValueEnum:
124  // getting a string from an enum can cause an exception if
125  // the number does not correspond to any defined string,
126  // use the number converted into a string in this case
127  try {
128  m_String = objinfo.GetPrimitiveValueString();
129  } catch(const CException&) {
131  }
133  break;
134  case ePrimitiveValueBool:
135  m_Bool = objinfo.GetPrimitiveValueBool();
137  break;
138  case ePrimitiveValueReal:
139  m_Double = objinfo.GetPrimitiveValueDouble();
141  break;
143  case ePrimitiveValueChar:
144  m_Int = objinfo.GetPrimitiveValueInt();
145  SetDataType(eInt);
146  break;
147  default:
148  ; // This type is not supported
149  }
150 }
151 
152 ///////////////////////////////////////////////////////////////////////////////
153 /// class CMQueryFunctionOps
154 ///
156 {
157  m_Result = x_GetUserObject(node);
158  _ASSERT(m_Result);
159 
160  TArgVector m_argNodes;
161  // Consider to rewrite taking subnodes from the tree without MakeArgVector
162  // However, qparse update is needed to get subnodes number to reserve
163  // space in vector without result relocation.
164  MakeArgVector(node, m_argNodes);
165  m_Arguments.clear();
166  m_Arguments.reserve(m_argNodes.size());
167  TArgVector::const_iterator iter = m_argNodes.begin();
168  while(iter != m_argNodes.end()) {
169  CRef<CMQueryNodeValue> user_obj = x_GetUserObject(**iter);
170  _ASSERT(user_obj.GetPointerOrNull());
171  if (user_obj) {
172  m_Arguments.push_back(user_obj);
173  ++iter;
174  }
175  }
176 }
177 
179 {
180  if (m_Arguments.size() != number)
181  return false;
182 
183  for (auto& it : m_Arguments) {
184  if (it->GetDataType() != type)
185  return false;
186  }
187  return true;
188 }
189 
191 {
192  if (m_Arguments.size() != number)
193  return false;
194 
195  for (auto& it : m_Arguments) {
196  if (it->GetDataType() != type1 && it->GetDataType() != type2) {
197  return false;
198  }
199  }
200  return true;
201 }
202 
204 {
205  for(auto& iter : m_Arguments) {
206  if (iter->GetDataType() == CMQueryNodeValue::eNotSet) {
207  return true;
208  }
209  }
210  return false;
211 }
212 
214 {
215  CMacroExec* macro_exec = GetContext();
216  _ASSERT(macro_exec);
217  if (macro_exec) {
218  return macro_exec->IsCaseSensitive();
219  }
220  return false;
221 }
222 
224 {
225  if (x_FindNotSet()) {
226  //if variable was unresolved
228  }
229  else {
231  "Wrong number or type of argument", &node);
232  }
233 }
234 
235 /// functor classes.
236 /// See CMacroExec::x_Init to get a match between tree node types and
237 /// its corresponding functor class. Note that these are only for processing
238 /// predefined node types (CQueryParseNode::EType) and not for processing
239 /// specific user functions.
240 ///////////////////////////////////////////////////////////////////////////////
241 /// class CMQueryFunctionOps_BooleanBinary
242 ///
244 {
245  virtual void Evaluate(CQueryParseTree::TNode& node)
246  {
247  _TRACE("<<<< node: " << &node.GetValue() << " type: " << node.GetValue().GetType() << " orig text: " << node.GetValue().GetOrig());
248  x_InitReferences(node);
250  m_Result->SetBool(BinOpsFunc(node.GetValue().GetType(), m_Arguments[0]->GetBool(), m_Arguments[1]->GetBool()) );
251  else
253  _TRACE(">>>>");
254  }
255 };
256 
257 ///////////////////////////////////////////////////////////////////////////////
258 /// class CMQueryFunctionOps_BooleanNot
259 ///
261 {
262  virtual void Evaluate(CQueryParseTree::TNode& node)
263  {
264  x_InitReferences(node);
266  m_Result->SetBool( !m_Arguments[0]->GetBool() );
267  else
269  }
270 };
271 
272 ///////////////////////////////////////////////////////////////////////////////
273 /// class CMQueryFunctionOps_Comparison
274 ///
276 {
277  virtual void Evaluate(CQueryParseTree::TNode& node)
278  {
279  _TRACE("<<<< node: " << &node.GetValue() << " type: " << node.GetValue().GetType() << " orig text: " << node.GetValue().GetOrig());
280  x_InitReferences(node);
281 
282  // either of the parameters can be a not just a value, but also a reference,
283  // so dereference both before use
284  m_Arguments[0]->Dereference();
285  m_Arguments[1]->Dereference();
286 
287  bool valid = false; // below is an assignment and not a comparison of 'valid'
288  if (!valid && x_ValidateAll(2, CMQueryNodeValue::eInt) && (valid = true)) {
289  m_Result->SetBool(BinOpsFunc(node.GetValue().GetType(),
290  m_Arguments[0]->GetInt(),
291  m_Arguments[1]->GetInt()));
292  }
293  if (!valid && x_ValidateAll(2, CMQueryNodeValue::eFloat) && (valid = true)) {
294  m_Result->SetBool(BinOpsFunc(node.GetValue().GetType(),
295  m_Arguments[0]->GetDouble(),
296  m_Arguments[1]->GetDouble()));
297  }
300  && (valid = true)) {
301  m_Result->SetBool(BinOpsFunc(node.GetValue().GetType(),
302  m_Arguments[0]->GetDouble(),
303  m_Arguments[1]->GetDouble()));
304  }
305  if (!valid && x_ValidateAll(2, CMQueryNodeValue::eString) && (valid = true)) {
306  m_Result->SetBool(BinOpsFuncString(node.GetValue().GetType(),
307  m_Arguments[0]->GetString(),
308  m_Arguments[1]->GetString(),
309  x_IsCaseSensitive()));
310  }
311  if (!valid && x_ValidateAll(2, CMQueryNodeValue::eBool) && (valid = true)) {
312  m_Result->SetBool(BinOpsFunc(node.GetValue().GetType(),
313  m_Arguments[0]->GetBool(),
314  m_Arguments[1]->GetBool()));
315  }
316  if (!valid)
318  _TRACE(">>>>");
319  }
320 
321  /// Converts the integer arguments to double in order to perform comparisons
323  {
324  for (auto& it : m_Arguments) {
325  if (it->GetDataType() == CMQueryNodeValue::eInt) {
326  it->SetDouble(double(it->GetInt()));
327  }
328  }
330  }
331 };
332 
333 ///////////////////////////////////////////////////////////////////////////////
334 /// class CMQueryFunctionOps_Like
335 ///
337 {
338  virtual void Evaluate(CQueryParseTree::TNode& node)
339  {
340  x_InitReferences(node);
341 
342  bool valid = false; // below is an assignment and not a comparison of 'valid'
343  if(!valid && x_ValidateAll(2, CMQueryNodeValue::eString) && (valid = true))
344  m_Result->SetBool ( NStr::MatchesMask(m_Arguments[0]->GetString(),
345  m_Arguments[1]->GetString(),
347 
348  if(!valid)
350  }
351 };
352 
353 ///////////////////////////////////////////////////////////////////////////////
354 /// class CMQueryFunctionOps_In
355 ///
357 {
358  virtual void Evaluate(CQueryParseTree::TNode& node)
359  {
360  bool valid = false;
361  x_InitReferences(node);
362 
363  auto arg_num = m_Arguments.size();
364  size_t index = 0;
365  if (arg_num >= 2) {
366  // below is an assignment and not a comparison of 'valid'
367  if (!valid && x_ValidateAll(Uint4(arg_num), CMQueryNodeValue::eInt) && (valid = true)) {
368  for (index = 1; index < arg_num; ++index) {
369  if (m_Arguments[0]->GetInt() == m_Arguments[index]->GetInt()) {
370  break;
371  }
372  }
373  }
374  if (!valid && x_ValidateAll(Uint4(arg_num), CMQueryNodeValue::eString) && (valid = true)) {
375  for (index = 1; index < arg_num; ++index) {
377  m_Arguments[0]->GetString(),
378  m_Arguments[index]->GetString(),
379  x_IsCaseSensitive())) {
380  break;
381  }
382  }
383  }
384  }
385 
386  if (!valid) {
388  } else {
389  m_Result->SetBool(index < arg_num);
390  }
391  }
392 };
393 
394 ///////////////////////////////////////////////////////////////////////////////
395 /// class CMQueryFunctionOps_Between
396 ///
398 {
399  virtual void Evaluate(CQueryParseTree::TNode& node)
400  {
401  x_InitReferences(node);
402 
403  bool valid = false;
404  if (!valid && x_ValidateAll(3, CMQueryNodeValue::eInt)) {
405  valid = true;
407  m_Arguments[0]->GetInt(),
408  m_Arguments[1]->GetInt()) );
409  m_Result->SetBool ( m_Result->GetBool() &&
411  m_Arguments[0]->GetInt(),
412  m_Arguments[2]->GetInt()) );
413  }
414 
415  if (!valid && x_ValidateAll(3, CMQueryNodeValue::eString)) {
416  valid = true;
418  m_Arguments[0]->GetString(),
419  m_Arguments[1]->GetString(),
420  x_IsCaseSensitive()) );
421  m_Result->SetBool ( m_Result->GetBool() &&
423  m_Arguments[0]->GetString(),
424  m_Arguments[2]->GetString(),
425  x_IsCaseSensitive()) );
426  }
427 
428  if (!valid)
430  }
431 };
432 
433 ///////////////////////////////////////////////////////////////////////////////
434 /// class CMQueryFunctionFunction implementation
435 ///
437 {
438  _TRACE("<<<< node: " << &node.GetValue() << " type: " << node.GetValue().GetType() << " orig text: " << node.GetValue().GetOrig());
439 
440  CMacroExec* macro_exec = GetContext();
441  _ASSERT(macro_exec);
442  IResolver* resolver = macro_exec->GetResolver();
443  _ASSERT(resolver);
444 
445  // return information also about the parent of the current node
446  // if the parent is a function, the current function should return a CObjectInfo instead of a standard data type
447  // This is useful mostly for functions used in the WHERE clause of the macro script
448  resolver->CallFunction(node->GetOriginalText(), node);
449  _TRACE(">>>>");
450 }
451 
452 ///////////////////////////////////////////////////////////////////////////////
453 /// class CMQueryFunctionDummy implementation
454 ///
456 {
458  "Node type is not supported: " + node.GetValue().GetNodeTypeAsString(), &node);
459 }
460 
461 ///////////////////////////////////////////////////////////////////////////////
462 /// class CMacroExec implementation
463 ///
465 {
466  m_Boolean = false;
467 
468  int lo = CQueryParseNode::eNotSet;
469  int hi = CQueryParseNode::eMaxType; // array does not include this
470  for (int i = lo; i < hi; i++)
472 
473  // create or reset user objects (node values)
474  CMQueryNodePreprocessor pre_exec;
476 
477  // Logical operators:
482 
484 
485  // Constants:
490 
491  // Comparison operators:
497 
501 
502  /* TBD: needs to be implemented
503  AddFunc(CQueryParseNode::eLike, new CMQueryFunctionCompare());
504  */
505 
506  // For functions implementation:
509 
510  // Assignment operator implementaion.
511  // Unusual mapping was chosen:
512  // Run time variable -> CQueryParseNode::eSelect
513  // Assignment -> CQueryParseNode::eFrom
514  // This is done to preserve CQueryParseNode from modification.
516  AddFunc(CQueryParseNode::eFrom, new CMQueryFunctionAssignment); // Assignment operator
517 }
518 
519 void CMacroExec::EvaluateTree(CQueryParseTree& Qtree, IResolver& resolver, bool query_tree, bool cs)
520 {
521  m_QTree = &Qtree;
522  m_Resolver = &resolver;
523  m_CaseSensitive = cs;
524  x_Init();
525 
526  if (query_tree) {
528  }
529  else {
530  TBase::Evaluate(*m_QTree);
531  }
532 
533  m_QTree = &Qtree; // call to Evaluate resets m_QTree pointer
534 
535  m_Result = false;
536  m_Boolean = false;
537  m_NotSet = false;
538 
540  if (pNodeValue) {
541  m_NotSet = (pNodeValue->GetDataType() == CMQueryNodeValue::eNotSet);
542  m_Boolean = (pNodeValue->GetDataType() == CMQueryNodeValue::eBool);
543  }
544  m_Result = (m_Boolean) ? pNodeValue->GetBool() : false;
545 }
546 
548 {
549  return GetResolver()->GetOrCreateRTVar(name);
550 }
551 
552 // Variables resolver (consider to make it virtual)
553 bool CMacroExec::PassIdentifierToResolver(const string& identifier,
554  CMQueryNodeValue& v, const CQueryParseTree::TNode* parent)
555 {
556  return m_Resolver->ResolveIdentifier(identifier, v, parent);
557 }
558 
560 {
561  switch (node.GetValue().GetType()) {
563  {{
564  bool res = false;
566  if (iter != node.SubNodeEnd()) {
567  res = x_EvaluateQueryTree(**iter);
568  ++iter;
569  }
570 
571  for (; iter != node.SubNodeEnd() && res; ++iter) {
572  res &= x_EvaluateQueryTree(**iter);
573  }
574 
575  CMQueryNodeValue* user_obj = dynamic_cast<CMQueryNodeValue*>(node->GetUserObject());
576  _ASSERT(user_obj);
577  if (user_obj) {
578  user_obj->SetBool(res);
579  }
580  return res;
581  }}
583  {{
584  bool res = false;
586  if (iter != node.SubNodeEnd()) {
587  res = x_EvaluateQueryTree(**iter);
588  ++iter;
589  }
590 
591  for (; iter != node.SubNodeEnd() && !res; ++iter) {
592  res |= x_EvaluateQueryTree(**iter);
593  }
594 
595  CMQueryNodeValue* user_obj = dynamic_cast<CMQueryNodeValue*>(node->GetUserObject());
596  _ASSERT(user_obj);
597  if (user_obj) {
598  user_obj->SetBool(res);
599  }
600  return res;
601  }}
603  {{
604  bool res = false;
606  if (iter != node.SubNodeEnd()) {
607  res = !x_EvaluateQueryTree(**iter);
608  }
609 
610  CMQueryNodeValue* user_obj = dynamic_cast<CMQueryNodeValue*>(node->GetUserObject());
611  _ASSERT(user_obj);
612  if (user_obj) {
613  user_obj->SetBool(res);
614  }
615  return res;
616  }}
617  default:
618  {{
619  CQueryParseTree* orig_qtree = m_QTree;
620  TBase::Evaluate(*m_QTree, node); // call to Evaluate resets m_QTree pointer
621  m_QTree = orig_qtree;
622 
623  bool res = false;
624  IQueryParseUserObject* user_object = node.GetValue().GetUserObject();
625  if (user_object) {
626  CMQueryNodeValue* pTopUserNodeValue = dynamic_cast<CMQueryNodeValue*>(user_object);
627  if (pTopUserNodeValue) {
628  bool boolean = (pTopUserNodeValue->GetDataType() == CMQueryNodeValue::eBool);
629  res = (boolean) ? pTopUserNodeValue->GetBool() : false;
630  }
631  }
632 
633  return res;
634  }}
635 
636  }
637  return false;
638 }
639 
641 {
642  CQueryParseTree::TNode* query_parsenode = m_QTree->GetQueryTree();
643  if (query_parsenode) {
644  IQueryParseUserObject* query_userobject = query_parsenode->GetValue().GetUserObject();
645  if (query_userobject) {
646  CMQueryNodeValue* top_user_nodevalue = dynamic_cast<CMQueryNodeValue*>(query_userobject);
647  return CRef<CMQueryNodeValue>(top_user_nodevalue);
648  }
649  }
650  return CRef<CMQueryNodeValue>();
651 }
652 
653 ///////////////////////////////////////////////////////////////////////////////
654 /// class CMQueryNodePreprocessor implementation
655 ///
658 {
659  if (delta == 0 || delta == 1) {
660  // If node has children, we skip it and process on the way back
661  if (!tr.IsLeaf()) {
662  return eTreeTraverse;
663  }
664  }
665 
666  CMQueryNodeValue* v = dynamic_cast<CMQueryNodeValue*>(tr->GetUserObject());
667  if(v)
668  tr->ResetUserObject();
669  else
670  tr->SetUserObject(new CMQueryNodeValue(&tr));
671 
672  return eTreeTraverse;
673 }
674 
675 
676 ///////////////////////////////////////////////////////////////////////////////
677 /// class CMQueryFunctionValue
678 ///
680 {
681  _TRACE("<<<< node: " << &node.GetValue() << " type: " << node.GetValue().GetType() << " orig text: " << node.GetValue().GetOrig());
682  CMQueryNodeValue* v = dynamic_cast<CMQueryNodeValue*>(node->GetUserObject());
683  _ASSERT(v);
684 
685  switch(node->GetType()) {
687  v->SetInt ( node.GetValue().GetInt() );
688  break;
690  v->SetDouble( node.GetValue().GetDouble() );
691  break;
693  // TODO: the parser does not parse 'true' and 'false' values as boolean constants
694  v->SetBool ( node.GetValue().GetBool() );
695  break;
697  {{
698  const string& str = node.GetValue().GetStrValue();
699  const string& strOrig = node.GetValue().GetOriginalText();
700 
701  if (str == strOrig) {
702  // Check for number
703  // Negative numbers are parsed as strings
704 
705  if (NStr::EqualNocase(str, "true") || NStr::EqualNocase(str, "false")) {
706  // the variable is boolean
708  }
709  else {
710  bool is_int = false, is_float = false;
711 
713  if (errno != 0 && !data_int) {
714  double data_dbl = NStr::StringToDouble(str, NStr::fConvErr_NoThrow);
715  if (errno == 0) {
716  v->SetDouble(data_dbl);
717  is_float = true;
718  }
719  }
720  else {
721  v->SetInt(data_int);
722  is_int = true;
723  }
724 
725  if (!is_int && !is_float) {
726  // It is an identifier
727  // return simple data when the parent is not eFunction
728  // return eobject when the parent is eFunction
729  if (!GetContext()->PassIdentifierToResolver(str, *v, node.GetParent())) {
731  "Unknown identifier: '" + str + "'", &node);
732  }
733  }
734  }
735  } else if ((strOrig.length() - str.length() > 1) &&
736  (strOrig[0] == '"') && // first char
737  (strOrig[strOrig.length()-1] == '"')) { // last char
738 
739  string root, subfield;
740  NStr::SplitInTwo(str, ".", root, subfield);
741  if (NStr::FindNoCase(str, ".") != NPOS && GetContext()->GetResolver()->ExistRTVar(root)) {
742  if (!GetContext()->PassIdentifierToResolver(str, *v, node.GetParent()))
744  "Unknown identifier: '" + str + "'", &node);
745  } else {
746  // It is a string
747  v->SetString ( str );
748  }
749  } else {
750  // It is something unknown
752  "Invalid string: '" + node->GetOriginalText() + "'", &node);
753  }
754  }}
755  break;
757  {{
758  const string& strOrig = node.GetValue().GetOriginalText();
759  if (!GetContext()->PassIdentifierToResolver(strOrig, *v, node.GetParent()))
761  "Unknown identifier: '" + strOrig + "'", &node);
762  }}
763  break;
764  default:
765  // It is something unknown
767  "Incorrect node type: " + node.GetValue().GetNodeTypeAsString(), &node);
768  }
769  _TRACE(">>>>");
770 }
771 
772 ///////////////////////////////////////////////////////////////////////////////
773 /// class CMQueryFunctionRTVar
774 ///
776 {
777  _TRACE("<<<< node: " << &node.GetValue() << " type: " << node.GetValue().GetType() << " orig text: " << node.GetValue().GetOrig());
778  _ASSERT(node.GetValue().GetType() == CQueryParseNode::eSelect);
779 
781  CMQueryNodeValue* node_value = dynamic_cast<CMQueryNodeValue*>(node->GetUserObject());
782  _ASSERT(context && node_value);
783  _TRACE("User data type: " << node_value->GetDataType());
784 
785  node_value->SetRef( context->GetOrCreateRTVar(node.GetValue().GetOriginalText()) );
786  _TRACE(">>>>");
787 }
788 
789 ///////////////////////////////////////////////////////////////////////////////
790 /// class CMQueryFunctionAssignment
791 ///
793 {
794  _TRACE("<<<< node: " << &node.GetValue() << " type: " << node.GetValue().GetType() << " orig text: " << node.GetValue().GetOrig());
795  x_InitReferences(node);
796  size_t arg_size = m_Arguments.size();
797  if ((arg_size < 2)
798  || (m_Arguments[0]->GetDataType() != CMQueryNodeValue::eRef)
799  || (arg_size > 2 && m_Arguments[2]->GetDataType() != CMQueryNodeValue::eInt) ) {
800 
802  return;
803  }
804 
805  CRef<CMQueryNodeValue> node_value = m_Arguments[1];
806  _TRACE("number of arguments: " << arg_size);
807  _TRACE("For filtering to work, it must be 3");
808  _TRACE("Arg 1 user data type: " << node_value->GetDataType());
809  _TRACE("For filtering to work, it must be eObjects: " << CMQueryNodeValue::eObjects);
810 
811  // --------------------------------------
812  // Next, filter the found objects
813  if (arg_size == 3 && node_value->GetDataType() == CMQueryNodeValue::eObjects) {
814  _TRACE("Proceeding to filtering");
815  CMQueryNodeValue::TObs objs = node_value->GetObjects();
816 
817  _TRACE("Going through # objects: " << objs.size());
818  CMQueryNodeValue::TObs updated_objs;
819  for (auto objs_iter = objs.begin(); objs_iter != objs.end(); ++objs_iter) {
820  // --------------------------------------
821  // Copy context for execution
822  CMacroExec* exec_context = GetContext();
823  CMacroExec me;
824 
825  IResolver* resolver = exec_context->GetResolver();
826  CQueryParseTree* where_tree = resolver->GetAssignmentWhereClause(int(m_Arguments[2]->GetInt()));
827 
828  // To properly evaluate the do-where clause, we may need to evaluate the RT-var to the left of assignment
829  // since it is not yet assigned to anything, we create a temp RT-var that can be used
830  CObjectInfo tmp_obj = objs_iter->field;
831  CQueryParseTree::TNode* arg_node = m_Arguments[0]->GetNode();
832  if (arg_node) {
833  const string tmp_obj_name = arg_node->GetValue().GetOrig();
834  resolver->AddTmpRTVarObject(tmp_obj_name, tmp_obj);
835  }
836 
837 /*
838 #ifdef _DEBUG
839  p_where_tree->Print(NcbiCout);
840 #endif
841 */
842  _TRACE("Evaluating where tree id: " << m_Arguments[2]->GetInt());
843  me.EvaluateTree ( *where_tree, *resolver, true, me.IsCaseSensitive() );
844  resolver->ResetTmpRTVarObjects();
845 
846  if (!me.IsBoolType() && !me.IsNotSetType()) {
847  NCBI_THROW(CMacroExecException, eInternalError, "Wrong type of computed WHERE clause");
848  }
849  _TRACE("Evaluated to " << (me.IsBoolType() && me.GetBoolValue()));
850 
851  if (me.IsBoolType() && me.GetBoolValue()) {
852  updated_objs.push_back(CMQueryNodeValue::SResolvedField(objs_iter->parent, tmp_obj));
853  }
854  }
855  node_value->SetObjects(updated_objs);
856  }
857  // End of filtering
858  m_Arguments[0]->AssignToRef(*node_value);
859  _TRACE(">>>>");
860 }
861 
862 ///////////////////////////////////////////////////////////////////////////////
863 /// class CMQueryFunctionBase
864 ///
866 {
867  _ASSERT(m_QExec);
868  CMacroExec* macro_exec = dynamic_cast<CMacroExec*>(m_QExec);
869  _ASSERT(macro_exec);
870  return macro_exec;
871 }
872 
873 END_SCOPE(macro)
875 
876 /* @} */
Query execution function for assignment operator.
Definition: macro_exec.hpp:261
Default node processor.
Definition: macro_exec.hpp:281
Class implements functions calls in the do section of macro.
Definition: macro_exec.hpp:271
class CMQueryFunctionOps_Between
Definition: macro_exec.cpp:398
class CMQueryFunctionOps_BooleanNot
Definition: macro_exec.cpp:261
class CMQueryFunctionOps_Comparison
Definition: macro_exec.cpp:276
class CMQueryFunctionOps_In
Definition: macro_exec.cpp:357
class CMQueryFunctionOps_Like
Definition: macro_exec.cpp:337
Query execution function for run-time variables.
Definition: macro_exec.hpp:217
Query execution function for simple atomic values.
Definition: macro_exec.hpp:204
This class applies an operation to each node of the query tree to do necessary initialization (constr...
Definition: macro_exec.hpp:55
Subclass of the IQueryParseUserObject which is held as the user-defined object in each CQueryParseNod...
Definition: macro_exec.hpp:71
class CMacroExecException
Definition: macro_ex.hpp:196
Subclass of CQueryExec that adds: 1) Macro identifiers resolution 2) Where clause evaluation.
Definition: macro_exec.hpp:319
CObjectInfo –.
Definition: objectinfo.hpp:597
Query tree and associated utility methods.
definition of a Culling tree
Definition: ncbi_tree.hpp:100
Base class for query node user defined object.
Definition: query_parse.hpp:60
Interface class for resolving entities during function execution.
Definition: macro_exec.hpp:291
Include a standard set of the NCBI C++ Toolkit most basic headers.
#define T(s)
Definition: common.h:230
char boolean
static const char * str(char *buf, int n)
Definition: stats.c:84
#define DIAG_COMPILE_INFO
Make compile time diagnostic information object to use in CNcbiDiag and CException.
Definition: ncbidiag.hpp:170
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
bool x_Validate(Uint4 number, CMQueryNodeValue::EType type1, CMQueryNodeValue::EType type2)
Checks the number of arguments, also their type should be one of the given types.
Definition: macro_exec.cpp:190
void SetString(const string &data)
Set/get underlying data type.
Definition: macro_exec.hpp:125
ETreeTraverseCode operator()(CTreeNode< CQueryParseNode > &tr, int delta)
Operator builds node values for each CQueryParseNode.
Definition: macro_exec.cpp:657
void ThrowCMacroExecException(const CDiagCompileInfo &info, CMacroExecException::EErrCode code, const string &message, const CQueryParseTree::TNode *treeNode, const CException *previous=nullptr)
Throws CMacroExecException with the specified message and error location from the TNode.
Definition: macro_ex.hpp:279
virtual void Evaluate(CQueryParseTree::TNode &node)
Function throws an exception about not implmented operation for the node.
Definition: macro_exec.cpp:455
bool m_Boolean
Type of result is boolean.
Definition: macro_exec.hpp:372
IResolver * m_Resolver
Variables resolver.
Definition: macro_exec.hpp:365
void EvaluateTree(CQueryParseTree &Qtree, IResolver &resolver, bool query_tree, bool case_sensitive=false)
Evaluates tree.
Definition: macro_exec.cpp:519
virtual CQueryParseTree * GetAssignmentWhereClause(int index) const =0
virtual void AddTmpRTVarObject(const string &name, CObjectInfo &oi)=0
bool IsBoolType() const
Definition: macro_exec.hpp:339
list< SResolvedField > TObs
Definition: macro_exec.hpp:92
string m_String
Data String data, if data came from a string or data field in the tree.
Definition: macro_exec.hpp:168
void SetDouble(double data)
Definition: macro_exec.hpp:129
void AssignFromObjectInfo(const CObjectInfo &objinfo)
Assigns data from objinfo. It is used when storing evaluation result.
Definition: macro_exec.cpp:111
virtual CRef< CMQueryNodeValue > GetOrCreateRTVar(const string &name)=0
void SetBool(bool data)
Definition: macro_exec.hpp:127
void Dereference()
If it is a reference it is resolved to the first non reference type in the hierarchy.
Definition: macro_exec.cpp:94
const TObs & GetObjects() const
Definition: macro_exec.hpp:144
bool m_CaseSensitive
Case sensitive flag for string comparisons.
Definition: macro_exec.hpp:368
virtual void Evaluate(CQueryParseTree::TNode &node)
Calculates node values for constants and resolved identifiers.
Definition: macro_exec.cpp:679
void SetDataType(EType dt)
Definition: macro_exec.hpp:121
bool m_Result
Boolean result of calculation.
Definition: macro_exec.hpp:373
bool IsCaseSensitive() const
Get function to access case sensitivity flag.
Definition: macro_exec.hpp:343
void x_InitReferences(CQueryParseTree::TNode &node)
Ininializes protected members to be used in derived classes.
Definition: macro_exec.cpp:155
CRef< CMQueryNodeValue > x_GetTopUserNodeValue()
Definition: macro_exec.cpp:640
EType GetDataType() const
Definition: macro_exec.hpp:122
virtual void Evaluate(CQueryParseTree::TNode &node)
Function implements functions calls in the do section of macro.
Definition: macro_exec.cpp:436
bool PassIdentifierToResolver(const string &identifier, CMQueryNodeValue &NodeValue, const CQueryParseTree::TNode *parent)
Identifier resolver function.
Definition: macro_exec.cpp:553
CRef< CMQueryNodeValue > x_GetUserObject(CQueryParseTree::TNode &node)
Gets user node value from CQueryParseTree node.
Definition: macro_exec.hpp:251
IResolver * GetResolver() const
Definition: macro_exec.hpp:347
bool GetBool() const
Definition: macro_exec.hpp:141
virtual void Evaluate(CQueryParseTree::TNode &node)
Abstract node evaluation function.
Definition: macro_exec.cpp:245
EType m_DataType
Node value data type.
Definition: macro_exec.hpp:164
CRef< CMQueryNodeValue > m_Ref
Reference to similar object.
Definition: macro_exec.hpp:183
virtual void Evaluate(CQueryParseTree::TNode &node)
Abstract node evaluation function.
Definition: macro_exec.cpp:262
bool AssignToRef(const CMQueryNodeValue &source)
Definition: macro_exec.cpp:102
bool x_FindNotSet()
Find not set value.
Definition: macro_exec.cpp:203
void SetRef(CRef< CMQueryNodeValue > node)
Definition: macro_exec.hpp:130
bool IsNotSetType() const
Check/get functions result from the top node after calculation.
Definition: macro_exec.hpp:338
static bool BinOpsFunc(CQueryParseNode::EType op, const T &a1, const T &a2)
Definition: macro_exec.cpp:50
void x_ProcessInvalidParams(CQueryParseTree::TNode &node)
Throws exception for invalid number of types of arguments.
Definition: macro_exec.cpp:223
Int8 m_Int
For data that is an integer or converted into one.
Definition: macro_exec.hpp:177
bool m_Bool
For data that is a boolean or converted into one.
Definition: macro_exec.hpp:174
bool x_EvaluateQueryTree(CQueryParseTree::TNode &node)
Definition: macro_exec.cpp:559
virtual void ResetTmpRTVarObjects()=0
void x_Init()
class CMacroExec implementation
Definition: macro_exec.cpp:464
virtual void Evaluate(CQueryParseTree::TNode &node)
Function is a placeholder for run-time variable processing.
Definition: macro_exec.cpp:775
CRef< CMQueryNodeValue > m_Result
Node for result storage.
Definition: macro_exec.hpp:247
CMacroExec * GetContext()
class CMQueryFunctionBase
Definition: macro_exec.cpp:865
TUserArgs m_Arguments
Vector of argument node values.
Definition: macro_exec.hpp:246
bool x_ValidateAll(Uint4 number, CMQueryNodeValue::EType type)
Checks the number and type of arguments.
Definition: macro_exec.cpp:178
virtual void Evaluate(CQueryParseTree::TNode &node)
Abstract node evaluation function.
Definition: macro_exec.cpp:358
virtual void Evaluate(CQueryParseTree::TNode &node)
Abstract node evaluation function.
Definition: macro_exec.cpp:338
void SetInt(Int8 data)
Definition: macro_exec.hpp:128
bool x_ConvertIntArgsToDouble()
Converts the integer arguments to double in order to perform comparisons.
Definition: macro_exec.cpp:322
void SetObjects(const TObs &obs)
Definition: macro_exec.hpp:131
bool GetBoolValue() const
Definition: macro_exec.hpp:340
double m_Double
For data that is a double or converted into one.
Definition: macro_exec.hpp:180
virtual void Evaluate(CQueryParseTree::TNode &node)
Abstract node evaluation function.
Definition: macro_exec.cpp:399
bool x_IsCaseSensitive()
Gets case sensitiveness flag from environment.
Definition: macro_exec.cpp:213
CRef< CMQueryNodeValue > GetOrCreateRTVar(const string &name)
Definition: macro_exec.cpp:547
bool m_NotSet
Type of result is not set.
Definition: macro_exec.hpp:371
virtual void Evaluate(CQueryParseTree::TNode &node)
Function implements the assignment operator.
Definition: macro_exec.cpp:792
virtual bool ResolveIdentifier(const string &identifier, CMQueryNodeValue &vi, const CQueryParseTree::TNode *parent)=0
virtual void CallFunction(const string &name, CQueryParseTree::TNode &qnode)=0
virtual void Evaluate(CQueryParseTree::TNode &node)
Abstract node evaluation function.
Definition: macro_exec.cpp:277
static bool BinOpsFuncString(CQueryParseNode::EType op, const string &s1, const string &s2, bool case_sensitive)
Definition: macro_exec.cpp:81
@ ePrimitiveValueString
string|char*|const char*
Definition: serialdef.hpp:153
@ ePrimitiveValueInteger
(signed|unsigned) (char|short|int|long)
Definition: serialdef.hpp:151
@ ePrimitiveValueChar
char
Definition: serialdef.hpp:150
@ ePrimitiveValueBool
bool
Definition: serialdef.hpp:149
@ ePrimitiveValueEnum
enum
Definition: serialdef.hpp:154
@ ePrimitiveValueReal
float|double
Definition: serialdef.hpp:152
@ eTypeFamilyPrimitive
Definition: serialdef.hpp:139
bool GetPrimitiveValueBool(void) const
Get boolean data.
Definition: objectinfo.cpp:144
int GetPrimitiveValueInt(void) const
Get data as int.
Definition: objectinfo.cpp:154
ETypeFamily GetTypeFamily(void) const
Get data type family.
void GetPrimitiveValueString(string &value) const
Get string data.
Definition: objectinfo.cpp:199
double GetPrimitiveValueDouble(void) const
Get data as double.
Definition: objectinfo.cpp:194
Int4 GetPrimitiveValueInt4(void) const
Get data as Int4.
Definition: objectinfo.cpp:174
EPrimitiveValueType GetPrimitiveValueType(void) const
Get type of primitive value.
Definition: objectinfo.cpp:109
TObjectType * GetPointerOrNull(void) THROWS_NONE
Get pointer value.
Definition: ncbiobj.hpp:986
int32_t Int4
4-byte (32-bit) signed integer
Definition: ncbitype.h:102
uint32_t Uint4
4-byte (32-bit) unsigned integer
Definition: ncbitype.h:103
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
CQueryParseTree * m_QTree
Definition: query_exec.hpp:240
CQueryExec * m_QExec
Definition: query_exec.hpp:119
string GetNodeTypeAsString() const
Return query node type as a string (for debugging output)
vector< CQueryParseTree::TNode * > TArgVector
Vector for easy argument access.
Definition: query_exec.hpp:72
const TNode * GetQueryTree() const
EType
Query node type.
Definition: query_parse.hpp:84
void AddFunc(CQueryParseNode::EType func_type, CQueryFunctionBase *func)
Register function implementation.
Definition: query_exec.cpp:96
void MakeArgVector(CQueryParseTree::TNode &qnode, TArgVector &args)
Created vector of arguments (translate sub-nodes to vector)
Definition: query_exec.cpp:44
@ eFunction
Function.
Definition: query_parse.hpp:91
@ eNotSet
Produced by the (private) default constructor.
Definition: query_parse.hpp:85
@ eIdentifier
Identifier like db.field (Org, Fld12, etc.)
Definition: query_parse.hpp:86
@ eFloatConst
Floating point const.
Definition: query_parse.hpp:88
@ eIntConst
Integer const.
Definition: query_parse.hpp:87
@ eBoolConst
Boolean (TRUE or FALSE)
Definition: query_parse.hpp:89
@ eString
String ("free text")
Definition: query_parse.hpp:90
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define END_SCOPE(ns)
End the previously defined scope.
Definition: ncbistl.hpp:75
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define BEGIN_SCOPE(ns)
Define a new scope.
Definition: ncbistl.hpp:72
static bool StringToBool(const CTempString str)
Convert string to bool.
Definition: ncbistr.cpp:2821
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
Definition: ncbistr.cpp:219
static Int8 StringToInt8(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to Int8.
Definition: ncbistr.cpp:793
static SIZE_TYPE FindNoCase(const CTempString str, const CTempString pattern, SIZE_TYPE start, SIZE_TYPE end, EOccurrence which=eFirst)
Find the pattern in the specified range of a string using a case insensitive search.
Definition: ncbistr.cpp:2993
static bool MatchesMask(CTempString str, CTempString mask, ECase use_case=eCase)
Match "str" against the "mask".
Definition: ncbistr.cpp:389
static double StringToDouble(const CTempStringEx str, TStringToNumFlags flags=0)
Convert string to double.
Definition: ncbistr.cpp:1387
#define NPOS
Definition: ncbistr.hpp:133
static bool SplitInTwo(const CTempString str, const CTempString delim, string &str1, string &str2, TSplitFlags flags=0)
Split a string into two pieces using the specified delimiters.
Definition: ncbistr.cpp:3554
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5353
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
static int CompareCase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-sensitive compare of a substring with another string.
Definition: ncbistr.cpp:135
@ fConvErr_NoThrow
Do not throw an exception on error.
Definition: ncbistr.hpp:285
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
@ eCase
Case sensitive compare.
Definition: ncbistr.hpp:1205
TNodeList::iterator TNodeList_I
Definition: ncbi_tree.hpp:109
Fun TreeDepthFirstTraverse(TTreeNode &tree_node, Fun func)
Depth-first tree traversal algorithm.
Definition: ncbi_tree.hpp:504
ETreeTraverseCode
Tree traverse code returned by the traverse predicate function.
Definition: ncbi_tree.hpp:51
TNodeList_CI SubNodeBegin(void) const
Return first const iterator on subnode list.
Definition: ncbi_tree.hpp:160
bool IsLeaf() const
Report whether this is a leaf node.
Definition: ncbi_tree.hpp:296
TNodeList_CI SubNodeEnd(void) const
Return last const iterator on subnode list.
Definition: ncbi_tree.hpp:166
const TValue & GetValue(void) const
Return node's value.
Definition: ncbi_tree.hpp:184
const TTreeType * GetParent(void) const
Get node's parent.
Definition: ncbi_tree.hpp:139
@ eTreeTraverse
Keep traversal.
Definition: ncbi_tree.hpp:52
int i
Macro exceptions.
#define _TRACE(arg)
Definition: macro_exec.cpp:39
const CharType(& source)[N]
Definition: pointer.h:1149
Portable reference counted smart and weak pointers using CWeakRef, CRef, CObject and CObjectEx.
Int4 delta(size_t dimension_, const Int4 *score_)
static BOOL number
Definition: pcregrep.c:193
Definition: type.c:6
#define _ASSERT
static CS_CONTEXT * context
Definition: will_convert.c:21
Modified on Sun Apr 21 03:43:01 2024 by modify_doxy.py rev. 669887