bdb_query.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:30k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: bdb_query.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 18:37:29  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: bdb_query.cpp,v 1000.1 2004/06/01 18:37:29 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Anatoliy Kuznetsov
  35.  *
  36.  * File Description:  BDB libarary query implementation
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <bdb/bdb_query.hpp>
  41. #include <bdb/bdb_cursor.hpp>
  42. #include <bdb/bdb_util.hpp>
  43. #include <util/resource_pool.hpp>
  44. #include <util/strsearch.hpp>
  45. BEGIN_NCBI_SCOPE
  46. /////////////////////////////////////////////////////////////////////////////
  47. //  CBDB_QueryNode
  48. //
  49. CBDB_QueryNode::CBDB_QueryNode(string value)
  50.  : m_NodeType(eValue),
  51.    m_Value(value)
  52. {
  53. }
  54. CBDB_QueryNode::CBDB_QueryNode(ELogicalType  ltype)
  55.  : m_NodeType(eLogical)
  56. {
  57.     m_SubType.LogicalType = ltype;
  58. }
  59. CBDB_QueryNode::CBDB_QueryNode(EOperatorType otype,
  60.                                bool          not_flag)
  61.  : m_NodeType(eOperator),
  62.    m_NotFlag(not_flag)
  63. {
  64.     m_SubType.OperatorType = otype;
  65. }
  66. CBDB_QueryNode::CBDB_QueryNode(const CBDB_QueryNode& qnode)
  67. {
  68.     m_NodeType = qnode.m_NodeType;
  69.     m_Value = qnode.m_Value;
  70.     m_SubType.LogicalType = qnode.m_SubType.LogicalType;
  71.     m_NotFlag = qnode.m_NotFlag;
  72. }
  73. CBDB_QueryNode& CBDB_QueryNode::operator=(const CBDB_QueryNode& qnode)
  74. {
  75.     m_NodeType = qnode.m_NodeType;
  76.     m_Value = qnode.m_Value;
  77.     m_SubType.LogicalType = qnode.m_SubType.LogicalType;
  78.     m_NotFlag = qnode.m_NotFlag;
  79.     return *this;
  80. }
  81. CBDB_QueryNode::~CBDB_QueryNode()
  82. {
  83. }
  84. CBDB_QueryNode::ELogicalType CBDB_QueryNode::GetLogicType() const
  85. {
  86.     if (m_NodeType == eLogical) {
  87.         return m_SubType.LogicalType;
  88.     }
  89.     // Caller asking to get sub-type as logical when the node type is not
  90.     BDB_THROW(eQueryError, "Incorrect query node type");
  91. }
  92. CBDB_QueryNode::EOperatorType CBDB_QueryNode::GetOperatorType() const
  93. {
  94.     if (m_NodeType == eOperator) {
  95.         return m_SubType.OperatorType;
  96.     }
  97.     // Caller asking to get sub-type as operator when the node type is not
  98.     BDB_THROW(eQueryError, "Incorrect query node type");
  99. }
  100. void CBDB_QueryNode::SetField(int field_idx)
  101. {
  102.     m_NodeType = eDBField;
  103.     m_SubType.FieldIdx = field_idx;
  104. }
  105. /////////////////////////////////////////////////////////////////////////////
  106. //  CBDB_Query
  107. //
  108. CBDB_Query::CBDB_Query(TQueryClause* qc)
  109. {
  110.     if (qc) {
  111.         m_QueryClause = qc;
  112.     } else {
  113.         m_QueryClause = new TQueryClause;
  114.     }
  115. }
  116. CBDB_Query::~CBDB_Query()
  117. {
  118.     delete m_QueryClause;
  119. }
  120. /// Reset all intermidiate results of tree evaluation (values)
  121. /// value constants will not be destroyed
  122. static 
  123. ETreeTraverseCode s_ResetQueryNode(CTreeNode<CBDB_QueryNode>& tr, int delta)
  124. {
  125.     if (delta < 0)
  126.         return eTreeTraverse;
  127.     CBDB_QueryNode& qnode = tr.GetValue();
  128.     if (qnode.GetType() != CBDB_QueryNode::eValue) {
  129.         qnode.SetValue(kEmptyStr);
  130.     }
  131.     qnode.SetAltValue(kEmptyStr);
  132.     return eTreeTraverse;
  133. }
  134. void CBDB_Query::ResetQueryClause()
  135. {
  136.     TreeDepthFirstTraverse(*m_QueryClause, s_ResetQueryNode);
  137. }
  138. void CBDB_Query::SetQueryClause(TQueryClause* query_clause)
  139. {
  140.     delete m_QueryClause;
  141.     m_QueryClause = query_clause;
  142. }
  143. CBDB_Query::TQueryClause* 
  144. CBDB_Query::NewOperatorNode(CBDB_QueryNode::EOperatorType otype,
  145.                             const string&                 arg1, 
  146.                             const string&                 arg2)
  147. {
  148.     auto_ptr<TQueryClause> tr(new TQueryClause(CBDB_QueryNode(otype)));
  149.     tr->AddNode(new TQueryClause(CBDB_QueryNode(arg1)));
  150.     tr->AddNode(new TQueryClause(CBDB_QueryNode(arg2)));
  151.     return tr.release();
  152. }
  153. CBDB_Query::TQueryClause* 
  154. CBDB_Query::NewOperatorNode(CBDB_QueryNode::EOperatorType otype,
  155.                             TQueryClause*  arg1, 
  156.                             TQueryClause*  arg2)
  157. {
  158.     auto_ptr<TQueryClause> tr(new TQueryClause(CBDB_QueryNode(otype)));
  159.     if (arg1)
  160.         tr->AddNode(arg1);
  161.     if (arg2)
  162.         tr->AddNode(arg2);
  163.     return tr.release();
  164. }
  165. CBDB_Query::TQueryClause* 
  166. CBDB_Query::NewLogicalNode(CBDB_QueryNode::ELogicalType ltype,  
  167.                            TQueryClause*  arg1, 
  168.                            TQueryClause*  arg2)
  169. {
  170.     auto_ptr<TQueryClause> tr(new TQueryClause(CBDB_QueryNode(ltype)));
  171.     if (arg1)
  172.         tr->AddNode(arg1);
  173.     if (arg2)
  174.         tr->AddNode(arg2);
  175.     return tr.release();
  176. }
  177. /////////////////////////////////////////////////////////////////////////////
  178. //  Internal evaluation functors
  179. //
  180. /// Field resolution functor
  181. ///
  182. /// Every node is inspected if it contains a field value and
  183. /// marks it using CBDB_File::TUnifiedFieldIndex
  184. ///
  185. class CQueryTreeFieldResolveFunc
  186. {
  187. public: 
  188.     CQueryTreeFieldResolveFunc(CBDB_File& db_file)
  189.     : m_File(db_file)
  190.     {}
  191.   
  192.     ETreeTraverseCode 
  193.     operator()(CTreeNode<CBDB_QueryNode>& tr, int delta)
  194.     {
  195.         CBDB_QueryNode& qnode = tr.GetValue();
  196.         if (delta == 0 || delta == 1) {
  197.             // If node has children, we skip it and process on the way back
  198.             if (!tr.IsLeaf())
  199.                 return eTreeTraverse;
  200.         }
  201.         if (qnode.GetType() == CBDB_QueryNode::eDBField)
  202.                 return eTreeTraverse;
  203.         if (qnode.HasValue()) {
  204.             string& fvalue = qnode.GetValue();
  205.             int len = fvalue.length(); 
  206.             // if string value is in apostrophe marks: remove it
  207.             if (fvalue[0] == ''' && fvalue[len-1] == ''') {
  208.                 len -= 2;
  209.                 if (len) {
  210.                     qnode.SetValue(fvalue.substr(1, len));
  211.                 } else {
  212.                     qnode.SetValue(kEmptyStr);
  213.                 }
  214.             } else {
  215.                 CBDB_File::TUnifiedFieldIndex fidx = m_File.GetFieldIdx(fvalue);
  216.                 if (fidx) {
  217.                     qnode.SetField(fidx);
  218.                 }
  219.             }
  220.         }
  221.         return eTreeTraverse;
  222.     }
  223. private:
  224.     CBDB_File&  m_File;
  225. };
  226. /// Query execition environment
  227. class CQueryExecEnv
  228. {
  229. public:
  230.     CQueryExecEnv(CBDB_File& db_file)
  231.     : m_File(db_file)
  232.     {}
  233.     CBDB_File& GetFile(void) { return m_File; }
  234.     CResourcePool<string>&  GetStrPool() { return m_StrPool; }
  235. private:
  236.     CQueryExecEnv(const CQueryExecEnv& qenv);
  237.     CQueryExecEnv& operator=(const CQueryExecEnv& qenv);
  238. private:
  239.     CBDB_File&            m_File;      /// Query database file
  240.     CResourcePool<string> m_StrPool;   /// Pool of string variables   
  241. };
  242. /// Create new matcher
  243. ///
  244. /// @internal
  245. static
  246. CBoyerMooreMatcher* s_MakeNewMatcher(const string& search_value)
  247. {
  248.     CBoyerMooreMatcher* matcher =
  249.         new CBoyerMooreMatcher(search_value,
  250.                                NStr::eNocase,
  251.                                CBoyerMooreMatcher::ePrefixMatch);
  252.     matcher->InitCommonDelimiters();
  253.     return matcher;
  254. }
  255. /// Base class for functions of the evaluation engine
  256. ///
  257. /// @internal
  258. class CScannerFunctor
  259. {
  260. public:
  261.     CScannerFunctor(CQueryExecEnv& env)
  262.      : m_QueryEnv(env)
  263.     {}
  264. private:
  265.     CScannerFunctor(const CScannerFunctor&);
  266.     CScannerFunctor& operator=(const CScannerFunctor&);
  267. protected:
  268.     CQueryExecEnv&               m_QueryEnv;
  269. };
  270. /// Base class for N argument functions
  271. ///
  272. /// @internal
  273. class CScannerFunctorArgN : public CScannerFunctor
  274. {
  275. public:
  276.     /// Enum indicates how to interpret the plain value
  277.     /// tree elements. It can be takes as is (eNoCheck) or
  278.     /// converted to a "in any field" variant of check
  279.     /// (similar to what PubMed does)
  280.     enum EAllFieldsCheck 
  281.     {
  282.         eNoCheck,
  283.         eCheckAll
  284.     };
  285.     /// Vector of strings borrowed from the query environment
  286.     /// pool to keep temporary values during the query execution
  287.     typedef vector<string*>       TArgValueVector;
  288.     
  289.     /// Vector of arguments, elements can point on values from 
  290.     /// TArgValueVector or variables located in the query tree itself
  291.     typedef vector<const string*> TArgVector;
  292.     /// String matchers used for substring search
  293.     typedef vector<CBoyerMooreMatcher*> TStringMatcherVector;
  294.     /// If argument is a db field corresponding vector element 
  295.     /// contains the field pointer
  296.     typedef vector<const CBDB_Field*>  TFieldVector;
  297. public:
  298.     CScannerFunctorArgN(CQueryExecEnv& env)
  299.      : CScannerFunctor(env)
  300.     {}
  301.     ~CScannerFunctorArgN();
  302.     /// Checks if value is equal to any field in the database
  303.     bool IsAnyField(CBDB_File& dbf, 
  304.                     const string& search_value,
  305.                     unsigned int arg_idx)
  306.     {
  307.         CBoyerMooreMatcher* matcher = GetMatcher(search_value, arg_idx);
  308.         CBDB_File::TUnifiedFieldIndex fidx = BDB_find_field(dbf, *matcher);
  309.         
  310.         return (fidx != 0);
  311.     }
  312.     CBoyerMooreMatcher* GetMatcher(const string& search_value, 
  313.                                    unsigned int  arg_idx)
  314.     {
  315.         CBoyerMooreMatcher* matcher = m_MatcherVector[arg_idx];
  316.         if (!matcher) {
  317.             m_MatcherVector[arg_idx] = matcher = 
  318.                 s_MakeNewMatcher(search_value);
  319.         }
  320.         return matcher;
  321.     }
  322.     /// Extract function arguments from the parsing tree
  323.     void GetArguments(CTreeNode<CBDB_QueryNode>& tr, 
  324.                       EAllFieldsCheck            check_mode = eNoCheck)
  325.     {
  326.         CBDB_File& db_file = m_QueryEnv.GetFile();
  327.         CResourcePool<string>& str_pool = m_QueryEnv.GetStrPool();
  328.         typedef CTreeNode<CBDB_QueryNode>  TTree;
  329.         TTree::TNodeList_CI it = tr.SubNodeBegin();
  330.         TTree::TNodeList_CI it_end = tr.SubNodeEnd();
  331.         for (unsigned i = 0; it != it_end; ++it, ++i) {
  332.             const TTree* t = *it;
  333.             const CBDB_QueryNode& qnode = t->GetValue();
  334.             ResizeVectors(i + 1);
  335.             // Check if the argument should be taken from the
  336.             // db field
  337.             if (qnode.GetType() == CBDB_QueryNode::eDBField) {
  338.                 int fidx = qnode.GetFiledIdx();
  339.                 const CBDB_Field& fld = db_file.GetField(fidx);
  340.                 
  341.                 SyncArgValue(i, str_pool);
  342.                 fld.ToString(*m_ArgValueVector[i]);
  343.                 m_FieldVector[i] = &fld;
  344.                 continue;
  345.             }
  346.             // field value check mode
  347.             // eCheckAll is coming from logical functions if they
  348.             // support "value AND anothervalue" notation
  349.             // (search services work like that)
  350.             if ((check_mode == eCheckAll) && 
  351.                 (qnode.GetType() == CBDB_QueryNode::eValue)) {
  352.                 const string& v = qnode.GetValue();
  353.                 const char* sz = "0";
  354.                 if (IsAnyField(db_file, v, i)) {
  355.                     sz = "1";
  356.                 }
  357.                 SyncArgValue(i, str_pool);
  358.                 *m_ArgValueVector[i] = sz;
  359.                 continue;
  360.             }
  361.             // Get constant value or return type of the subnodes
  362.             const string& str = qnode.GetValue();
  363.             m_ArgVector[i] = &str;
  364.         } // for 
  365.     }
  366.     const string* GetArg(unsigned int idx) const
  367.     {
  368.         _ASSERT(idx < m_ArgVector.size());
  369.         return m_ArgVector[idx];
  370.     }
  371.     const CBDB_Field* GetArgField(unsigned int idx) const
  372.     {
  373.         _ASSERT(idx < m_FieldVector.size());
  374.         return m_FieldVector[idx];
  375.     }
  376.     void SetResult(CBDB_QueryNode& qnode, bool res)
  377.     {
  378.         if (res) {
  379.             qnode.SetValue("1");
  380.         } else {
  381.             qnode.SetValue("0");
  382.         }
  383.     }
  384. private:
  385.     /// Syncronously resize all arguments vectors
  386.     void ResizeVectors(unsigned int new_size)
  387.     {
  388.         TArgVector::size_type old_size = m_ArgVector.size();
  389.         _ASSERT(new_size <= old_size + 1);  // 1 increments only
  390.         if (new_size > old_size) {
  391.             m_ArgVector.push_back(0);
  392.             m_ArgValueVector.push_back(0);
  393.             m_MatcherVector.push_back(0);
  394.             m_FieldVector.push_back(0);
  395.         }
  396.     }
  397.     /// m_ArgVector[idx] = m_ArgValueVector[idx] 
  398.     void SyncArgValue(unsigned int idx, CResourcePool<string>& str_pool)
  399.     {
  400.         if (m_ArgValueVector[idx] == 0) {
  401.             m_ArgValueVector[idx] = str_pool.Get();
  402.         }
  403.         m_ArgVector[idx] = m_ArgValueVector[idx];
  404.     }
  405. protected:
  406.     TArgVector            m_ArgVector;
  407.     TArgValueVector       m_ArgValueVector;
  408.     TStringMatcherVector  m_MatcherVector;
  409.     TFieldVector          m_FieldVector;
  410. };
  411. CScannerFunctorArgN::~CScannerFunctorArgN()
  412. {
  413.     CResourcePool<string>& str_pool = m_QueryEnv.GetStrPool();
  414.     unsigned int size = m_ArgValueVector.size();
  415.     for (unsigned int i = 0; i < size; ++i) {
  416.         string* str = m_ArgValueVector[i];
  417.         if (str) {
  418.             str_pool.Return(str);
  419.         }
  420.         CBoyerMooreMatcher* matcher = m_MatcherVector[i];
  421.         delete matcher;
  422.     }
  423. }
  424. /// EQ function 
  425. ///
  426. /// @internal
  427. class CScannerFunctorEQ : public CScannerFunctorArgN
  428. {
  429. public:
  430.     CScannerFunctorEQ(CQueryExecEnv& env, bool not_flag)
  431.      : CScannerFunctorArgN(env),
  432.        m_NotFlag(not_flag)
  433.     {}
  434.     bool IsNot() const { return m_NotFlag; }
  435.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  436.     {
  437.         GetArguments(tr);
  438.         CBDB_QueryNode& qnode = tr.GetValue();
  439.         const string* arg0 = GetArg(0);
  440.         const string* arg1 = GetArg(1);
  441.         const CBDB_Field* fld0 = GetArgField(0);
  442.         const CBDB_Field* fld1 = GetArgField(1);
  443.         // here we check two cases: 
  444.         //   field = "value"
  445.         //   "value" == field
  446.         if (fld0 != 0 && fld1 == 0) {
  447.             CBoyerMooreMatcher* matcher = GetMatcher(*arg1, 0);
  448.             int pos = matcher->Search(*arg0);
  449.             if (pos == -1) { // not found
  450.                 qnode.SetValue("0");
  451.             } else {
  452.                 qnode.SetValue("1");
  453.             }
  454.             return;
  455.         }
  456.         if (fld0 == 0 && fld1 != 0) {
  457.             CBoyerMooreMatcher* matcher = GetMatcher(*arg0, 0);
  458.             int pos = matcher->Search(*arg1);
  459.             if (pos == -1) { // not found
  460.                 qnode.SetValue("0");
  461.             } else {
  462.                 qnode.SetValue("1");
  463.             }
  464.             return;
  465.         }
  466.         // Plain equal
  467.         bool res = (*arg0 == *arg1);
  468.         if (IsNot())
  469.             res = !res;
  470.         SetResult(qnode, res);
  471.     }
  472. protected:
  473.     bool   m_NotFlag;
  474. };
  475. /// Basic class for all comparison (GT, LT, etc) functors
  476. ///
  477. /// @internal
  478. class CScannerFunctorComp : public CScannerFunctorArgN
  479. {
  480. public:
  481.     CScannerFunctorComp(CQueryExecEnv& env)
  482.      : CScannerFunctorArgN(env)
  483.     {}
  484.     int CmpEval(CTreeNode<CBDB_QueryNode>& tr)
  485.     {
  486.         GetArguments(tr);
  487.         const string* arg0 = GetArg(0);
  488.         const string* arg1 = GetArg(1);
  489.         int cmpres = arg0->compare(*arg1);
  490.         return cmpres;
  491.     }
  492. };
  493. /// GT function 
  494. ///
  495. /// @internal
  496. class CScannerFunctorGT : public CScannerFunctorComp
  497. {
  498. public:
  499.     CScannerFunctorGT(CQueryExecEnv& env)
  500.      : CScannerFunctorComp(env)
  501.     {}
  502.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  503.     {
  504.         int cmpres = CmpEval(tr);
  505.         bool res = cmpres > 0;
  506.         SetResult(tr.GetValue(), res);
  507.     }
  508. };
  509. /// GE function 
  510. ///
  511. /// @internal
  512. class CScannerFunctorGE : public CScannerFunctorComp
  513. {
  514. public:
  515.     CScannerFunctorGE(CQueryExecEnv& env)
  516.      : CScannerFunctorComp(env)
  517.     {}
  518.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  519.     {
  520.         int cmpres = CmpEval(tr);
  521.         bool res = cmpres >= 0;
  522.         SetResult(tr.GetValue(), res);
  523.     }
  524. };
  525. /// LT function 
  526. ///
  527. /// @internal
  528. class CScannerFunctorLT : public CScannerFunctorComp
  529. {
  530. public:
  531.     CScannerFunctorLT(CQueryExecEnv& env)
  532.      : CScannerFunctorComp(env)
  533.     {}
  534.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  535.     {
  536.         int cmpres = CmpEval(tr);
  537.         bool res = cmpres < 0;
  538.         SetResult(tr.GetValue(), res);
  539.     }
  540. };
  541. /// LE function 
  542. ///
  543. /// @internal
  544. class CScannerFunctorLE : public CScannerFunctorComp
  545. {
  546. public:
  547.     CScannerFunctorLE(CQueryExecEnv& env)
  548.      : CScannerFunctorComp(env)
  549.     {}
  550.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  551.     {
  552.         int cmpres = CmpEval(tr);
  553.         bool res = cmpres <= 0;
  554.         SetResult(tr.GetValue(), res);
  555.     }
  556. };
  557. /// AND function 
  558. ///
  559. /// @internal
  560. class CScannerFunctorAND : public CScannerFunctorArgN
  561. {
  562. public:
  563.     CScannerFunctorAND(CQueryExecEnv& env)
  564.      : CScannerFunctorArgN(env)
  565.     {}
  566.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  567.     {
  568.         GetArguments(tr, eCheckAll);
  569.         CBDB_QueryNode& qnode = tr.GetValue();
  570.         unsigned int size = m_ArgVector.size();
  571.         _ASSERT(size);
  572.         for (unsigned int i = 0; i < size; ++i) {
  573.             const string* arg = GetArg(i);
  574.             if (*arg == "0") {
  575.                 qnode.SetValue("0");
  576.                 return;
  577.             }
  578.         }
  579.         qnode.SetValue("1");
  580.     }
  581. };
  582. /// OR function 
  583. ///
  584. /// @internal
  585. class CScannerFunctorOR : public CScannerFunctorArgN
  586. {
  587. public:
  588.     CScannerFunctorOR(CQueryExecEnv& env)
  589.      : CScannerFunctorArgN(env)
  590.     {}
  591.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  592.     {
  593.         GetArguments(tr, eCheckAll);
  594.         CBDB_QueryNode& qnode = tr.GetValue();
  595.         unsigned int size = m_ArgVector.size();
  596.         _ASSERT(size);
  597.         for (unsigned int i = 0; i < size; ++i) {
  598.             const string* arg = GetArg(i);
  599.             if (*arg == "1") {
  600.                 qnode.SetValue("1");
  601.                 return;
  602.             }
  603.         }
  604.         qnode.SetValue("0");
  605.     }
  606. };
  607. /// NOT function 
  608. ///
  609. /// @internal
  610. class CScannerFunctorNOT : public CScannerFunctorArgN
  611. {
  612. public:
  613.     CScannerFunctorNOT(CQueryExecEnv& env)
  614.      : CScannerFunctorArgN(env)
  615.     {}
  616.     void Eval(CTreeNode<CBDB_QueryNode>& tr)
  617.     {
  618.         GetArguments(tr, eCheckAll);
  619.         CBDB_QueryNode& qnode = tr.GetValue();
  620.         unsigned int size = m_ArgVector.size();
  621.         _ASSERT(size);
  622.         const string* arg = GetArg(0);
  623.         if (*arg == "0") {
  624.             qnode.SetValue("1");
  625.         } else {
  626.             qnode.SetValue("0");
  627.         }
  628.     }
  629. };
  630. /////////////////////////////////////////////////////////////////////////////
  631. //  CBDB_FileScanner
  632. //
  633. CBDB_FileScanner::CBDB_FileScanner(CBDB_File& db_file)
  634.  : m_File(db_file)
  635. {
  636. }
  637. CBDB_FileScanner::~CBDB_FileScanner()
  638. {
  639. }
  640. CBDB_FileScanner::EScanAction CBDB_FileScanner::OnRecordFound()
  641. {
  642.     return eContinue;
  643. }
  644. void CBDB_FileScanner::Scan(CBDB_Query& query)
  645. {
  646.     ResolveFields(query);
  647.     CBDB_FileCursor cur(m_File);
  648.     cur.SetCondition(CBDB_FileCursor::eFirst);
  649.     while (cur.Fetch() == eBDB_Ok) {
  650.         bool res = Evaluate(query);
  651.         if (res) {
  652.             EScanAction act = OnRecordFound();
  653.             if (act == eStop) {
  654.                 break;
  655.             }
  656.         }
  657.         query.ResetQueryClause();
  658.     } // while
  659. }
  660. void CBDB_FileScanner::Scan(CBDB_FileCursor& cur, 
  661.                             CBDB_Query&      query)
  662. {
  663.     ResolveFields(query);
  664.     while (cur.Fetch() == eBDB_Ok) {
  665.         bool res = Evaluate(query);
  666.         if (res) {
  667.             EScanAction act = OnRecordFound();
  668.             if (act == eStop) {
  669.                 break;
  670.             }
  671.         }
  672.         query.ResetQueryClause();
  673.     } // while
  674. }
  675. /// The main tree evaluation functor
  676. ///
  677. /// @internal
  678. class CScannerEvaluateFunc
  679. {
  680. public: 
  681.     CScannerEvaluateFunc(CQueryExecEnv& env)
  682.     : m_QueryEnv(env),
  683.       m_Matcher(0)
  684.     {
  685.     }
  686.     ~CScannerEvaluateFunc()
  687.     {
  688.         delete m_Matcher;
  689.     }
  690.     CScannerEvaluateFunc(const CScannerEvaluateFunc& func)
  691.     : m_QueryEnv(func.m_QueryEnv),
  692.       m_Matcher(0)
  693.     {
  694.     }
  695.   
  696.     ETreeTraverseCode 
  697.     operator()(CTreeNode<CBDB_QueryNode>& tr, int delta);
  698. protected:
  699.     CQueryExecEnv&       m_QueryEnv;
  700.     CBoyerMooreMatcher*  m_Matcher;
  701. };
  702. ETreeTraverseCode 
  703. CScannerEvaluateFunc::operator()(CTreeNode<CBDB_QueryNode>& tr, int delta)
  704. {
  705.     CBDB_QueryNode& qnode = tr.GetValue();
  706.     // cout << delta << " " << tr.GetValue().GetValue() << endl;
  707.     if (delta == 0 || delta == 1) {
  708.         // If node has children, we skip it and process on the way back
  709.         if (!tr.IsLeaf())
  710.             return eTreeTraverse;
  711.     }
  712.     if (qnode.GetType() == CBDB_QueryNode::eValue) {
  713.         if (tr.GetParent() == 0) { // single top node
  714.             CBDB_File& dbf = m_QueryEnv.GetFile();
  715.                 
  716.             if (!m_Matcher) {
  717.                 const string& search_value = qnode.GetValue();
  718.                 m_Matcher = s_MakeNewMatcher(search_value);
  719.             }
  720.             CBDB_File::TUnifiedFieldIndex fidx;
  721.             fidx = BDB_find_field(dbf, *m_Matcher);
  722.             qnode.SetAltValue(fidx ? "1" : "0");
  723.         }
  724.     }
  725.     if (!qnode.HasValue()) {
  726.         switch (qnode.GetType()) {
  727.         case CBDB_QueryNode::eValue:
  728.             break;
  729.         case CBDB_QueryNode::eOperator:
  730.         {
  731.             CBDB_QueryNode::EOperatorType eop = qnode.GetOperatorType();
  732.             switch (eop) {
  733.             case CBDB_QueryNode::eEQ:
  734.             {
  735.                 CScannerFunctorEQ func(m_QueryEnv, qnode.IsNot());
  736.                 func.Eval(tr);
  737.             }
  738.             break;
  739.             case CBDB_QueryNode::eGT:
  740.             {
  741.                 CScannerFunctorGT func(m_QueryEnv);
  742.                 func.Eval(tr);
  743.             }
  744.             break;
  745.             case CBDB_QueryNode::eGE:
  746.             {
  747.                 CScannerFunctorGE func(m_QueryEnv);
  748.                 func.Eval(tr);
  749.             }
  750.             break;
  751.             case CBDB_QueryNode::eLT:
  752.             {
  753.                 CScannerFunctorLT func(m_QueryEnv);
  754.                 func.Eval(tr);
  755.             }
  756.             break;
  757.             case CBDB_QueryNode::eLE:
  758.             {
  759.                 CScannerFunctorLE func(m_QueryEnv);
  760.                 func.Eval(tr);
  761.             }
  762.             break;
  763.             default:
  764.                 _ASSERT(0);
  765.             } // switch eop
  766.         }
  767.         break;
  768.         case CBDB_QueryNode::eLogical:
  769.         {
  770.             CBDB_QueryNode::ELogicalType elogic = qnode.GetLogicType();
  771.             switch (elogic) {
  772.             case CBDB_QueryNode::eAnd:
  773.             {
  774.                 CScannerFunctorAND func(m_QueryEnv);
  775.                 func.Eval(tr);
  776.             }
  777.             break;
  778.             case CBDB_QueryNode::eOr:
  779.             {
  780.                 CScannerFunctorOR func(m_QueryEnv);
  781.                 func.Eval(tr);
  782.             }
  783.             break;
  784.             case CBDB_QueryNode::eNot:
  785.             {
  786.                 CScannerFunctorNOT func(m_QueryEnv);
  787.                 func.Eval(tr);
  788.             }
  789.             break;
  790.             default:
  791.                 _ASSERT(0);
  792.             } // switch elogic
  793.         }
  794.         break;
  795.         default:
  796.             break;
  797.         } // switch node type
  798.     } // if
  799.     return eTreeTraverse;
  800. }
  801. bool CBDB_FileScanner::Evaluate(CBDB_Query& query)
  802. {
  803.     ResolveFields(query);
  804.     CBDB_Query::TQueryClause& qtree = query.GetQueryClause();
  805.     CQueryExecEnv query_env(m_File);
  806.     CScannerEvaluateFunc scanner_eval(query_env);
  807.     TreeDepthFirstTraverse(qtree, scanner_eval);
  808.     const CBDB_QueryNode& qnode = qtree.GetValue();
  809.     const string& v_alt = qnode.GetAltValue();
  810.     if (v_alt.empty()) {
  811.         const string& v = qnode.GetValue();
  812.         if (v == "0")
  813.             return false;
  814.         return true;
  815.     } else {
  816.         if (v_alt == "0")
  817.             return false;
  818.     }
  819.     return true;
  820. }
  821. void CBDB_FileScanner::ResolveFields(CBDB_Query& query)
  822. {
  823.     CBDB_Query::TQueryClause& qtree = query.GetQueryClause();
  824.     CQueryTreeFieldResolveFunc resolve_func(m_File);
  825.     TreeDepthFirstTraverse(qtree, resolve_func);
  826. }
  827. /// The main tree printing functor class.
  828. /// Used for internal debugging purposes.
  829. ///
  830. /// @internal
  831. ///
  832. class CQueryTreePrintFunc
  833. {
  834. public: 
  835.     CQueryTreePrintFunc(CNcbiOstream& os)
  836.     : m_OStream(os),
  837.       m_Level(0)
  838.     {}
  839.     void PrintLevelMargin()
  840.     {
  841.         for (int i = 0; i < m_Level; ++i) {
  842.             m_OStream << "  ";
  843.         }
  844.     }
  845.   
  846.     ETreeTraverseCode 
  847.     operator()(const CTreeNode<CBDB_QueryNode>& tr, int delta) 
  848.     {
  849.         const CBDB_QueryNode& qnode = tr.GetValue();
  850.         m_Level += delta;
  851.         if (delta < 0)
  852.             return eTreeTraverse;
  853.         PrintLevelMargin();
  854.         switch (qnode.GetType()) {
  855.         case CBDB_QueryNode::eValue:
  856.             m_OStream << qnode.GetValue();
  857.             break;
  858.         case CBDB_QueryNode::eOperator:
  859.             {
  860.                 CBDB_QueryNode::EOperatorType eop = qnode.GetOperatorType();
  861.                 switch (eop) {
  862.                 case CBDB_QueryNode::eEQ:
  863.                     if (qnode.IsNot()) {
  864.                         m_OStream << "NOT EQ";
  865.                     } else {
  866.                         m_OStream << "EQ";
  867.                     }
  868.                     break;
  869.                 case CBDB_QueryNode::eGT:
  870.                     m_OStream << "GT";
  871.                     break;
  872.                 case CBDB_QueryNode::eGE:
  873.                     m_OStream << "GE";
  874.                     break;
  875.                 case CBDB_QueryNode::eLT:
  876.                     m_OStream << "LT";
  877.                     break;
  878.                 case CBDB_QueryNode::eLE:
  879.                     m_OStream << "LE";
  880.                     break;
  881.                 default:
  882.                     _ASSERT(0);
  883.                 } // switch eop
  884.             }
  885.             if (qnode.HasValue()) {
  886.                 m_OStream << " => " << qnode.GetValue();
  887.             }
  888.             break;
  889.         case CBDB_QueryNode::eLogical:
  890.             {
  891.                 CBDB_QueryNode::ELogicalType elogic = qnode.GetLogicType();
  892.                 switch (elogic) {
  893.                 case CBDB_QueryNode::eAnd:
  894.                     m_OStream << "AND";
  895.                     break;
  896.                 case CBDB_QueryNode::eOr:
  897.                     m_OStream << "OR";
  898.                     break;
  899.                 case CBDB_QueryNode::eNot:
  900.                     m_OStream << "NOT";
  901.                     break;
  902.                 default:
  903.                     _ASSERT(0);
  904.                 } // switch elogic
  905.             }
  906.             if (qnode.HasValue()) {
  907.                 m_OStream << " => " << qnode.GetValue();
  908.             }
  909.             break;
  910.         case CBDB_QueryNode::eDBField:
  911.             m_OStream << "@" << qnode.GetValue();
  912.             break;
  913.         default:
  914.             if (qnode.HasValue()) {
  915.                 m_OStream << qnode.GetValue();
  916.             }
  917.             break;
  918.         } // switch node type
  919.         m_OStream << "n";
  920.         return eTreeTraverse;
  921.     }
  922. private:
  923.     CNcbiOstream&  m_OStream;
  924.     int            m_Level;
  925. };
  926. void BDB_PrintQueryTree(CNcbiOstream& os, const CBDB_Query& query)
  927. {
  928.     // Here I use a const cast hack because TreeDepthFirstTraverse
  929.     // uses a non-cost iterators and semantics in the algorithm.
  930.     // When a const version of TreeDepthFirstTraverse is ready
  931.     // we can get rid of this...
  932.     const CBDB_Query::TQueryClause& qtree = query.GetQueryClause();
  933.     CBDB_Query::TQueryClause& qtree_nc = 
  934.            const_cast<CBDB_Query::TQueryClause&>(qtree);
  935.     CQueryTreePrintFunc func(os);
  936.     TreeDepthFirstTraverse(qtree_nc, func);
  937. }
  938. END_NCBI_SCOPE
  939. /*
  940.  * ===========================================================================
  941.  * $Log: bdb_query.cpp,v $
  942.  * Revision 1000.1  2004/06/01 18:37:29  gouriano
  943.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  944.  *
  945.  * Revision 1.13  2004/05/17 20:55:11  gorelenk
  946.  * Added include of PCH ncbi_pch.hpp
  947.  *
  948.  * Revision 1.12  2004/03/23 16:58:18  kuznets
  949.  * Fixed compilation warning (GCC)
  950.  *
  951.  * Revision 1.11  2004/03/23 16:37:54  kuznets
  952.  * Implemented NOT predicate
  953.  *
  954.  * Revision 1.10  2004/03/23 14:51:19  kuznets
  955.  * Implemented logical NOT, <, <=, >, >=
  956.  *
  957.  * Revision 1.9  2004/03/17 16:35:42  kuznets
  958.  * EQ functor improved to enable substring searches
  959.  *
  960.  * Revision 1.8  2004/03/11 22:27:49  ucko
  961.  * Pull the bodies of CScannerFunctorArgN::~CScannerFunctorArgN and
  962.  * CScannerEvaluateFunc::operator() out of line so that they can call
  963.  * s_MakeNewMatcher.  (WorkShop prohibits inline or template functions
  964.  * from calling [file-]static functions.)
  965.  *
  966.  * Revision 1.7  2004/03/11 18:42:01  kuznets
  967.  * code cleaned up, minor bug fix
  968.  *
  969.  * Revision 1.6  2004/03/11 13:16:10  kuznets
  970.  * Bug fixed corner case when query is one word only
  971.  *
  972.  * Revision 1.5  2004/03/08 13:35:07  kuznets
  973.  * Modified queries to do full text searches
  974.  *
  975.  * Revision 1.4  2004/03/01 14:03:57  kuznets
  976.  * CQueryTreeFieldResolveFunc improved to remove string marks
  977.  *
  978.  * Revision 1.3  2004/02/24 14:12:45  kuznets
  979.  * CBDB_Query add new constructor parameter and several helper functions
  980.  *
  981.  * Revision 1.2  2004/02/19 17:35:57  kuznets
  982.  * + BDB_PrintQueryTree (tree printing utility function for debugging)
  983.  *
  984.  * Revision 1.1  2004/02/17 17:26:45  kuznets
  985.  * Initial revision
  986.  *
  987.  *
  988.  * ===========================================================================
  989.  */