NCBI C++ ToolKit
query_exec.cpp
Go to the documentation of this file.
00001 /*  $Id: query_exec.cpp 51033 2011-08-26 17:19:51Z falkrb $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors: Anatoliy Kuznetsov
00027  *
00028  * File Description:
00029  *      Query execution implementations
00030  *
00031  */
00032 
00033 
00034 #include <ncbi_pch.hpp>
00035 #include <corelib/ncbitime.hpp>
00036 #include <util/qparse/query_exec.hpp>
00037 
00038 BEGIN_NCBI_SCOPE
00039 
00040 CQueryFunctionBase::~CQueryFunctionBase()
00041 {
00042 }
00043 
00044 void CQueryFunctionBase::MakeArgVector(CQueryParseTree::TNode& qnode, 
00045                                        TArgVector&             args)
00046 {
00047     args.resize(0);
00048     CTreeNode<CQueryParseNode>::TNodeList_I it = qnode.SubNodeBegin();
00049     CTreeNode<CQueryParseNode>::TNodeList_I it_end = qnode.SubNodeEnd();
00050     int i = 0;       
00051     for (; it != it_end; ++it, ++i) {
00052         CTreeNode<CQueryParseNode>* arg_node = *it;
00053         args.push_back(arg_node);
00054     } // for
00055 }
00056 
00057 CQueryParseTree::TNode* 
00058 CQueryFunctionBase::GetArg0(CQueryParseTree::TNode& qnode)
00059 {
00060     CTreeNode<CQueryParseNode>::TNodeList_I it = qnode.SubNodeBegin();
00061     CTreeNode<CQueryParseNode>::TNodeList_I it_end = qnode.SubNodeEnd();
00062     if (it == it_end)
00063         return 0;
00064     return *it;
00065 }
00066 
00067 
00068 CQueryParseTree& CQueryFunctionBase::GetQueryTree() 
00069 { 
00070     return *(GetExec().GetQTree()); 
00071 }
00072 
00073 
00074 
00075 
00076 
00077 
00078 CQueryExec::CQueryExec()
00079 : m_FuncReg(CQueryParseNode::eMaxType),
00080   m_QTree(0),
00081   m_ExceptionCount(0),
00082   m_QueriedCount(0)
00083 {
00084     for (size_t i = 0; i < m_FuncReg.size(); ++i) {
00085         m_FuncReg[i] = 0;
00086     }
00087 }
00088 
00089 CQueryExec::~CQueryExec()
00090 {
00091     for (size_t i = 0; i < m_FuncReg.size(); ++i) {
00092         delete m_FuncReg[i];
00093     }
00094 }
00095 
00096 void CQueryExec::AddFunc(CQueryParseNode::EType func_type, 
00097                          CQueryFunctionBase*    func)
00098 {
00099     int i = func_type;
00100     delete m_FuncReg[i];
00101     m_FuncReg[i] = func;
00102     func->SetExec(*this);
00103 }
00104 
00105 void CQueryExec::AddImplicitSearchFunc(CQueryFunctionBase* func)
00106 {
00107     m_ImplicitSearchFunc.reset(func);
00108 }
00109 
00110 
00111 
00112 
00113 
00114 /// Expression evaluation visitor functor
00115 ///
00116 /// @internal
00117 ///
00118 class CQueryExecEvalFunc
00119 {
00120 public: 
00121     CQueryExecEvalFunc(CQueryExec& exec)
00122     : m_Exec(exec)
00123     {}
00124 
00125     
00126     ETreeTraverseCode 
00127     operator()(CTreeNode<CQueryParseNode>& tr, int delta) 
00128     {
00129         CQueryParseNode& qnode = tr.GetValue();
00130         if (delta == 0 || delta == 1) {
00131             // If node has children, we skip it and process on the way back
00132             if (!tr.IsLeaf()) {
00133                 return eTreeTraverse;
00134             }
00135         }
00136         CQueryParseNode::EType func_type = qnode.GetType();
00137         CQueryFunctionBase* func = 0;
00138         
00139         // check if execution env has implicit search configured 
00140         // and value node is derives from a logical node (AND, OR).
00141         // in this case we fire implicit search
00142         //
00143         if (m_Exec.GetImplicitSearchFunc()) {
00144             if (qnode.IsValue()) {
00145                 CTreeNode<CQueryParseNode>* parent = tr.GetParent();
00146                 if (parent && parent->GetValue().IsLogic()) {
00147                     func = m_Exec.GetImplicitSearchFunc();
00148                 }
00149             }
00150         }
00151         
00152         if (!func) {
00153             func = m_Exec.GetFunc(func_type);        
00154         }
00155         if (func == 0) { // function not registered
00156             // values (string, int, etc) do not require evaluation
00157             if (qnode.IsValue()) {
00158                 return eTreeTraverse;
00159             }
00160             NCBI_THROW(CQueryParseException, eUnknownFunction, 
00161                "Query execution failed. Unknown function:" + qnode.GetOrig());
00162         }
00163         
00164         CStopWatch sw(CStopWatch::eStart);
00165         {{
00166             func->Evaluate(tr);
00167         }}
00168         double e = sw.Elapsed();
00169         qnode.SetElapsed(e);
00170         
00171         return eTreeTraverse;        
00172     }
00173 private:
00174     CQueryExec& m_Exec;
00175 };
00176 
00177 
00178 void CQueryExec::Evaluate(CQueryParseTree& qtree)
00179 {
00180     m_QTree = &qtree;
00181     CQueryExecEvalFunc visitor(*this);
00182     TreeDepthFirstTraverse(*qtree.GetQueryTree(), visitor);
00183     m_QTree = 0;
00184 }
00185 
00186 
00187 void CQueryExec::Evaluate(CQueryParseTree& qtree, CQueryParseTree::TNode& node)
00188 {
00189     m_QTree = &qtree;
00190     CQueryExecEvalFunc visitor(*this);
00191     TreeDepthFirstTraverse(node, visitor);
00192     m_QTree = 0;
00193 }
00194 
00195 
00196 END_NCBI_SCOPE
Modified on Wed May 23 13:38:18 2012 by modify_doxy.py rev. 337098