NCBI C++ ToolKit
query_exec.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef UTIL__QUERY_EXEC_HPP__
2 #define UTIL__QUERY_EXEC_HPP__
3 
4 /* $Id: query_exec.hpp 78813 2017-07-20 13:25:24Z falkrb $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Anatoliy Kuznetsov
30  *
31  * File Description: Query execution components
32  *
33  */
34 
35 /// @file query_exec.hpp
36 /// Query parser execution implementations
37 
38 
40 #include <corelib/ncbitime.hpp>
41 
42 #include <vector>
43 
45 
46 
47 /** @addtogroup QParser
48  *
49  * @{
50  */
51 
52 class CQueryExec;
53 
54 /// Base class for evaluation functions
55 ///
56 /// <pre>
57 /// Implementation guidelines for derived classes:
58 /// 1. Make it stateless.
59 /// All evaluation results should go to query node user object.
60 /// 2. Make it reentrant
61 /// 3. Make it thread safe and thread sync. (some functions may run in parallel)
62 /// (stateless class satisfies both thread safety and reenterability)
63 /// </pre>
64 ///
65 /// @sa IQueryParseUserObject
66 ///
68 {
69 public:
70  /// Vector for easy argument access
71  ///
72  typedef vector<CQueryParseTree::TNode*> TArgVector;
73 
74 public:
75  virtual ~CQueryFunctionBase();
76 
77  /// Do we evaluate before visiting the nodes children or after. Visiting
78  /// after can allow us to avoid evaluating some sub-expressions
79  /// @return true if children should all be evaluated before parent for
80  /// this type of node, otherwise false
81  virtual bool EvaluateChildrenFirst() const { return true; }
82 
83  /// Query node evaluation function
84  /// (performs actual programmed by the node action)
85  ///
86  virtual void Evaluate(CQueryParseTree::TNode& qnode) = 0;
87 
88 protected:
89  /// @name Utility functions
90  /// @{
91 
92  /// Created vector of arguments (translate sub-nodes to vector)
93  ///
94  /// @param qnode
95  /// Query node (all sub-nodes are treated as parameters
96  /// @param args
97  /// Output vector
98  void MakeArgVector(CQueryParseTree::TNode& qnode,
99  TArgVector& args);
100 
101  /// Get first sub-node
102  ///
104 
105  /// @}
106 
107  /// Get reference on parent execution environment
108  CQueryExec& GetExec() { return *m_QExec; }
109 
110  /// Get query tree (execution context)
111  CQueryParseTree& GetQueryTree();
112 
113 private:
114  friend class CQueryExec;
115  /// Set reference on parent query execution class
116  void SetExec(CQueryExec& qexec) { m_QExec = &qexec; }
117 
118 protected:
120 };
121 
122 
123 /// Query execution environment holds the function registry and the execution
124 /// context. Execution context is vaguely defined term, it can be anything
125 /// query functions need:
126 /// open files, databases, network connections, pools of threads, etc.
127 ///
128 /// <pre>
129 ///
130 /// Query execution consists of distinct several phases:
131 /// 1.Construction of execution environment
132 /// All function implementations are registered in CQueryExec
133 /// 2.Query parsing (see CQueryParseTree). This step transforms query (string)
134 /// into query tree, the tree reflects operations precedence
135 /// 3.Parsing tree validation and transformation (optional)
136 /// 4.Query execution-evaluation. Execution engine traverses the query tree calling
137 /// appropriate functions to do expression(query tree node) evaluation.
138 /// Execution results for every tree node are stored in the tree as user
139 /// objects (classes derived from IQueryParseUserObject).
140 ///
141 /// </pre>
142 ///
144 {
145 public:
146  // Subclasses can optionally pass in a field identifier
147  // to resolve values (faster for trees, tables..)
148  typedef unsigned int TFieldID;
149 
150 public:
151  CQueryExec();
152  virtual ~CQueryExec();
153 
154  /// Register function implementation.
155  /// (with ownership transfer)
156  ///
157  void AddFunc(CQueryParseNode::EType func_type, CQueryFunctionBase* func);
158 
159  /// This is a callback for implicit search nodes
160  /// Our syntax allows queries like (a=1) AND "search_term"
161  /// Execution recognises "search_term" connected with logical operation
162  /// represents a special case.
163  /// This method defines a reactor (function implementation).
164  ///
165  void AddImplicitSearchFunc(CQueryFunctionBase* func);
167  { return m_ImplicitSearchFunc.get(); }
168 
169  /// Return query function pointer (if registered).
170  ///
172  { return m_FuncReg[(size_t)func_type]; }
173 
174  /// Extend this function to look up and invoke functions that appear
175  /// in the query
176  ///
177  virtual void CallFunction(const string& name,
178  CQueryParseTree::TNode &node) {}
179 
180  /// Run query tree evaluation
181  ///
182  virtual void Evaluate(CQueryParseTree& qtree);
183 
184  // Evaluate subtree of 'qtree' beginning from 'node'
185  virtual void Evaluate(CQueryParseTree& qtree, CQueryParseTree::TNode& node);
186 
187  /// If query has an identifier, this will resolve it in an
188  /// application-specific way. Returns true if resolved, with the
189  /// data item's value in 'value'. Using field identifiers, if available,
190  /// such as column numbers or biotree feature IDs will be faster.
191  ///
192  virtual bool ResolveIdentifier(const std::string& /* identifier */,
193  bool& /* value */) { return false; }
194  virtual bool ResolveIdentifier(const std::string& /* identifier */,
195  Int8& /* value */) { return false; }
196  virtual bool ResolveIdentifier(const std::string& /* identifier */,
197  double& /* value */) { return false; }
198  virtual bool ResolveIdentifier(const std::string& /* identifier */,
199  std::string& /* value */) { return false; }
200 
201  virtual bool ResolveIdentifier(const TFieldID& /* id */,
202  bool& /* value */) { return false; }
203  virtual bool ResolveIdentifier(const TFieldID& /* id */,
204  Int8& /* value */) { return false; }
205  virtual bool ResolveIdentifier(const TFieldID& /* id */,
206  double& /* value */) { return false; }
207  virtual bool ResolveIdentifier(const TFieldID& /* id */,
208  std::string& /* value */) { return false; }
209 
210  virtual bool HasIdentifier(const std::string& /* identifier */) { return false; }
211  virtual TFieldID GetIdentifier(const std::string& /* identifier */) { return TFieldID(-1); }
212 
213  /// Some applications may know the type of an identifier. This hook
214  /// should be overriden to return an identifier's type, when available.
215  /// Return one of eIntConst, eBoolConst, eFloatConst, eString, or eNotSet.
216  virtual CQueryParseNode::EType IdentifierType(const std::string& /* identifier */)
217  { return CQueryParseNode::eNotSet; }
218 
219  virtual void EvalStart() {}
220  /// Move to (iterate) to next entry
221  virtual bool EvalNext(CQueryParseTree& /* qtree */) {return false;}
222  virtual bool EvalComplete() {return true;}
223 
224  int GetQueriedCount() const { return m_QueriedCount; }
225  int GetExceptionCount() const { return m_ExceptionCount; }
226 
227 protected:
228  friend class CQueryFunctionBase;
229  CQueryParseTree* GetQTree() { return m_QTree; }
230 
231 private:
234 
235 protected:
236  typedef vector<CQueryFunctionBase*> TFuncReg;
237 protected:
239  unique_ptr<CQueryFunctionBase> m_ImplicitSearchFunc;
241 
244 };
245 
246 /// Expression evaluation visitor functor
247 ///
249 {
250 public:
252  : m_Exec(exec)
253  {}
254 
257  {
258  CQueryParseNode& qnode = tr.GetValue();
259  CQueryParseNode::EType func_type = qnode.GetType();
260 
261  if ((delta == 0 || delta == 1) && !tr.IsLeaf()) {
262  CQueryFunctionBase* func = m_Exec.GetFunc(func_type);
263 
264  // if current query node requires child query nodes to be
265  // evaluated first, continue depth-first traversal
266  if (func == NULL || func->EvaluateChildrenFirst()) {
267  return eTreeTraverse;
268  }
269  // process query node before processing its children. Allows
270  // node processing to stop early for effciency whenever possible
271  // (specifically for AND and OR nodes)
272  else {
274  {{
275  func->Evaluate(tr);
276  }}
277  qnode.SetElapsed(sw.Elapsed());
278 
279  return eTreeTraverseStepOver;
280  }
281  }
282 
283  CQueryFunctionBase* func = 0;
284 
285  // check if execution env has implicit search configured
286  // and value node is child of a logical node (AND, OR).
287  // in this case we fire implicit search
288  //
290  if (qnode.IsValue()) {
291  CTreeNode<CQueryParseNode>* parent = tr.GetParent();
292  if (parent && parent->GetValue().IsLogic()) {
293  func = m_Exec.GetImplicitSearchFunc();
294  }
295  }
296  }
297 
298  if (!func) {
299  func = m_Exec.GetFunc(func_type);
300  }
301  if (func == 0) { // function not registered
302  // values (string, int, etc) do not require evaluation
303  if (qnode.IsValue()) {
304  return eTreeTraverse;
305  }
306  NCBI_THROW(CQueryParseException, eUnknownFunction,
307  "Query execution failed. Unknown function:" + qnode.GetOrig());
308  }
309 
311  {{
312  func->Evaluate(tr);
313  }}
314  qnode.SetElapsed(sw.Elapsed());
315 
316  return eTreeTraverse;
317  }
318 private:
320 };
321 
322 
323 /* @} */
324 
326 
327 
328 #endif // UTIL__QUERY_EXEC_HPP__
CObject –.
Definition: ncbiobj.hpp:180
Expression evaluation visitor functor.
Definition: query_exec.hpp:249
Query execution environment holds the function registry and the execution context.
Definition: query_exec.hpp:144
Base class for evaluation functions.
Definition: query_exec.hpp:68
Query parser exceptions.
Query node class.
Definition: query_parse.hpp:79
Query tree and associated utility methods.
CStopWatch –.
Definition: ncbitime.hpp:1938
definition of a Culling tree
Definition: ncbi_tree.hpp:100
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
#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
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
void SetExec(CQueryExec &qexec)
Set reference on parent query execution class.
Definition: query_exec.hpp:116
void SetElapsed(double e)
Set node timing.
const string & GetOrig() const
int m_ExceptionCount
Definition: query_exec.hpp:242
int GetQueriedCount() const
Definition: query_exec.hpp:224
CQueryFunctionBase * GetFunc(CQueryParseNode::EType func_type)
Return query function pointer (if registered).
Definition: query_exec.hpp:171
virtual void EvalStart()
Definition: query_exec.hpp:219
virtual bool ResolveIdentifier(const TFieldID &, double &)
Definition: query_exec.hpp:205
CQueryExec & m_Exec
Definition: query_exec.hpp:319
unsigned int TFieldID
Definition: query_exec.hpp:148
virtual bool EvalComplete()
Definition: query_exec.hpp:222
virtual bool ResolveIdentifier(const TFieldID &, Int8 &)
Definition: query_exec.hpp:203
vector< CQueryParseTree::TNode * > TArgVector
Vector for easy argument access.
Definition: query_exec.hpp:72
ETreeTraverseCode operator()(CTreeNode< CQueryParseNode > &tr, int delta)
Definition: query_exec.hpp:256
CQueryExecEvalFunc(CQueryExec &exec)
Definition: query_exec.hpp:251
virtual TFieldID GetIdentifier(const std::string &)
Definition: query_exec.hpp:211
EType
Query node type.
Definition: query_parse.hpp:84
TFuncReg m_FuncReg
Definition: query_exec.hpp:238
bool IsValue() const
Returns TRUE if node is value (INT, String, etc.)
unique_ptr< CQueryFunctionBase > m_ImplicitSearchFunc
Definition: query_exec.hpp:239
virtual bool ResolveIdentifier(const std::string &, bool &)
If query has an identifier, this will resolve it in an application-specific way.
Definition: query_exec.hpp:192
CQueryFunctionBase * GetImplicitSearchFunc()
Definition: query_exec.hpp:166
CQueryExec & GetExec()
Get reference on parent execution environment.
Definition: query_exec.hpp:108
virtual void CallFunction(const string &name, CQueryParseTree::TNode &node)
Extend this function to look up and invoke functions that appear in the query.
Definition: query_exec.hpp:177
virtual CQueryParseNode::EType IdentifierType(const std::string &)
Some applications may know the type of an identifier.
Definition: query_exec.hpp:216
CQueryParseTree * GetQTree()
Definition: query_exec.hpp:229
int GetExceptionCount() const
Definition: query_exec.hpp:225
virtual bool ResolveIdentifier(const std::string &, Int8 &)
Definition: query_exec.hpp:194
int m_QueriedCount
Definition: query_exec.hpp:243
virtual void Evaluate(CQueryParseTree::TNode &qnode)=0
Query node evaluation function (performs actual programmed by the node action)
virtual bool ResolveIdentifier(const TFieldID &, std::string &)
Definition: query_exec.hpp:207
virtual bool EvalNext(CQueryParseTree &)
Move to (iterate) to next entry.
Definition: query_exec.hpp:221
vector< CQueryFunctionBase * > TFuncReg
Definition: query_exec.hpp:236
virtual bool ResolveIdentifier(const std::string &, double &)
Definition: query_exec.hpp:196
virtual bool HasIdentifier(const std::string &)
Definition: query_exec.hpp:210
virtual bool EvaluateChildrenFirst() const
Do we evaluate before visiting the nodes children or after.
Definition: query_exec.hpp:81
virtual bool ResolveIdentifier(const std::string &, std::string &)
Definition: query_exec.hpp:198
EType GetType() const
CQueryExec(const CQueryExec &)
virtual bool ResolveIdentifier(const TFieldID &, bool &)
Definition: query_exec.hpp:201
CQueryExec & operator=(const CQueryExec &)
@ eNotSet
Produced by the (private) default constructor.
Definition: query_parse.hpp:85
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
double Elapsed(void) const
Return time elapsed since first Start() or last Restart() call (in seconds).
Definition: ncbitime.hpp:2776
@ eStart
Start timer immediately after creating.
Definition: ncbitime.hpp:1942
ETreeTraverseCode
Tree traverse code returned by the traverse predicate function.
Definition: ncbi_tree.hpp:51
bool IsLeaf() const
Report whether this is a leaf node.
Definition: ncbi_tree.hpp:296
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
@ eTreeTraverseStepOver
Do not traverse current node (pick the next one)
Definition: ncbi_tree.hpp:54
static CStopWatch sw
Defines: CTimeFormat - storage class for time format.
Int4 delta(size_t dimension_, const Int4 *score_)
Query string parsing components.
NCBI_XUTIL_EXPORT
Parameter to control printing diagnostic message about conversion of static array data from a differe...
Definition: static_set.hpp:72
Modified on Fri Jan 05 07:24:00 2024 by modify_doxy.py rev. 669887