bdb_cursor.cpp
来自「ncbi源码」· C++ 代码 · 共 543 行
CPP
543 行
/* * =========================================================================== * PRODUCTION $Log: bdb_cursor.cpp,v $ * PRODUCTION Revision 1000.2 2004/06/01 18:37:17 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13 * PRODUCTION * =========================================================================== *//* $Id: bdb_cursor.cpp,v 1000.2 2004/06/01 18:37:17 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anatoliy Kuznetsov * * File Description: BDB library cursor implementations. * */#include <ncbi_pch.hpp>#include <bdb/bdb_cursor.hpp>#include <db.h>BEGIN_NCBI_SCOPE////////////////////////////////////////////////////////////////////// Internal class used by CBDB_FileCursor to represent search// condition criteries.//class CBDB_FC_Condition{public: // Get field buffer reference (non-const) CBDB_BufferManager& GetBuffer() { return m_Buf; } // Get field buffer reference (const) const CBDB_BufferManager& GetBuffer() const { return m_Buf; } // Get number of fields assigned to condition unsigned int GetFieldsAssigned() const { return m_FieldsAssigned; } // +1 increment of number of assigned fields. // Return new fields count unsigned int IncFieldsAssigned() { _ASSERT(m_Buf.FieldCount()-1 >= m_FieldsAssigned); m_Cursor.ResetFirstFetched(); return ++m_FieldsAssigned; } // Return TRUE if all search criteria fileds have been assigned bool IsComplete() const { return m_KeyBuf.FieldCount() == GetFieldsAssigned(); } // Return next unassigned field IBDB_FieldConvert& GetUnassignedField() { _ASSERT(m_FieldsAssigned < m_Buf.FieldCount()); return m_Cursor.GetFieldConvert(m_Buf, m_FieldsAssigned); } ~CBDB_FC_Condition() { DeleteFields(m_Buf); }protected: enum EIncompleteVal { eAssignMinVal, eAssignMaxVal }; // Constructor. key_buf - key buffer of the main table CBDB_FC_Condition(const CBDB_BufferManager& key_buf, CBDB_FileCursor& cursor) : m_KeyBuf(key_buf), m_Cursor(cursor), m_FieldsAssigned(0) { m_Buf.DuplicateStructureFrom(key_buf); m_Buf.Construct(); } // Set incomplete (non assigned) fields to min(max) possible values void InitUnassignedFields(EIncompleteVal incv) { if (incv == eAssignMinVal) { m_Buf.SetMinVal(m_FieldsAssigned, m_Buf.FieldCount()); } else { // eAssignMaxVal m_Buf.SetMaxVal(m_FieldsAssigned, m_Buf.FieldCount()); } } // Set number of assigned fields to zero void ResetUnassigned() { m_FieldsAssigned = 0; }private: CBDB_FC_Condition(const CBDB_FC_Condition&); const CBDB_FC_Condition& operator= (const CBDB_FC_Condition&);private: // Reference on "parent file" key buffer const CBDB_BufferManager& m_KeyBuf; // Reference on parent cursor CBDB_FileCursor& m_Cursor; // Field buffer. Correspond to CBDB_BufferManager m_Buf; // Number of fields assigned (for multi-segment) prefix searches unsigned int m_FieldsAssigned; friend class CBDB_FileCursor; friend class CBDB_ConditionHandle;};/////////////////////////////////////////////////////////////////////////////// CBDB_ConditionHandle:://CBDB_ConditionHandle::CBDB_ConditionHandle(CBDB_FC_Condition& cond) : m_Condition(cond){}CBDB_ConditionHandle::~CBDB_ConditionHandle(){ delete &m_Condition;}/////////////////////////////////////////////////////////////////////////////// CBDB_FileCursor:://CBDB_FileCursor::CBDB_FileCursor(CBDB_File& dbf): m_Dbf(dbf), From( *(new CBDB_FC_Condition(*dbf.m_KeyBuf, *this)) ), To( *(new CBDB_FC_Condition(*dbf.m_KeyBuf, *this)) ), m_DBC(0), m_CondFrom(eFirst), m_CondTo(eLast), m_FetchDirection(eForward), m_FirstFetched(false){ m_DBC = m_Dbf.CreateCursor();}CBDB_FileCursor::CBDB_FileCursor(CBDB_File& dbf, CBDB_Transaction& trans): m_Dbf(dbf), From( *(new CBDB_FC_Condition(*dbf.m_KeyBuf, *this)) ), To( *(new CBDB_FC_Condition(*dbf.m_KeyBuf, *this)) ), m_DBC(0), m_CondFrom(eFirst), m_CondTo(eLast), m_FetchDirection(eForward), m_FirstFetched(false){ m_DBC = m_Dbf.CreateCursor(&trans);}CBDB_FileCursor::~CBDB_FileCursor(){ if (m_DBC) { m_DBC->c_close(m_DBC); }}void CBDB_FileCursor::SetCondition(ECondition cond_from, ECondition cond_to){ m_FetchDirection = eForward; if (cond_from == eGT || cond_from == eGE) { if (cond_to == eGT || cond_to == eGE) { cond_to = eNotSet; } } else if (cond_from == eLT || cond_from == eLE) { if (cond_to == eLT || cond_to == eLE) { cond_to = eNotSet; } m_FetchDirection = eBackward; } else if (cond_from == eEQ) { if (cond_to != eNotSet) cond_to = eNotSet; } else if (cond_from == eLast) { m_FetchDirection = eBackward; } else if (cond_from == eNotSet) { BDB_THROW(eIdxSearch, "Cursor search 'FROM' parameter must be set"); } if (cond_to == eEQ) BDB_THROW(eIdxSearch, "Cursor search 'TO' parameter cannot be EQ"); m_CondFrom = cond_from; m_CondTo = cond_to; m_FirstFetched = false; From.m_Condition.ResetUnassigned(); To.m_Condition.ResetUnassigned();}EBDB_ErrCode CBDB_FileCursor::Update(CBDB_File::EAfterWrite write_flag){ if(m_DBC == 0) BDB_THROW(eInvalidValue, "Try to use invalid cursor"); return m_Dbf.WriteCursor(m_DBC, DB_CURRENT, write_flag);}EBDB_ErrCode CBDB_FileCursor::Delete(CBDB_File::EIgnoreError on_error){ return m_Dbf.DeleteCursor(m_DBC, on_error);}CBDB_FileCursor::TRecordCount CBDB_FileCursor::KeyDupCount() const{ if(m_DBC == 0) BDB_THROW(eInvalidValue, "Try to use invalid cursor"); db_recno_t ret; if( int err = m_DBC->c_count(m_DBC, &ret, 0) ) BDB_ERRNO_THROW(err, "Failed to count duplicate entries for cursor"); return TRecordCount(ret);}EBDB_ErrCode CBDB_FileCursor::FetchFirst(){ m_FirstFetched = true; ECondition cond_from = m_CondFrom; if (m_CondFrom != eFirst && m_CondFrom != eLast) { // If cursor from buffer contains not all key fields // (prefix search) we set all remaining fields to max. // possible value for GT condition From.m_Condition.InitUnassignedFields(m_CondFrom == eGT ? CBDB_FC_Condition::eAssignMaxVal : CBDB_FC_Condition::eAssignMinVal); m_Dbf.m_KeyBuf->CopyFieldsFrom(From.m_Condition.GetBuffer()); To.m_Condition.InitUnassignedFields(m_CondTo == eLE ? CBDB_FC_Condition::eAssignMaxVal : CBDB_FC_Condition::eAssignMinVal); // Incomplete == search transformed into >= search with incomplete // fields set to min if (m_CondFrom == eEQ && !From.m_Condition.IsComplete()) { cond_from = eGE; } } unsigned int flag; switch ( cond_from ) { case eFirst: flag = DB_FIRST; // first record retrieval break; case eLast: // last record flag = DB_LAST; break; case eEQ: flag = DB_SET; // precise shot break; case eGT: case eGE: case eLT: case eLE: flag = DB_SET_RANGE; // permits partial key and range searches break; default: BDB_THROW(eIdxSearch, "Invalid FROM condition type"); } EBDB_ErrCode ret = m_Dbf.ReadCursor(m_DBC, flag); if (ret != eBDB_Ok) return ret; // Berkeley DB does not support "<" ">" conditions, so we need to scroll // up or down to reach the interval criteria. if (m_CondFrom == eGT) { while (m_Dbf.m_KeyBuf->Compare(From.m_Condition.m_Buf) == 0) { ret = m_Dbf.ReadCursor(m_DBC, DB_NEXT); if (ret != eBDB_Ok) return ret; } } else if (m_CondFrom == eLT) { while (m_Dbf.m_KeyBuf->Compare(From.m_Condition.m_Buf) == 0) { ret = m_Dbf.ReadCursor(m_DBC, DB_PREV); if (ret != eBDB_Ok) return ret; } } else if (m_CondFrom == eEQ && !From.m_Condition.IsComplete()) { int cmp = m_Dbf.m_KeyBuf->Compare(From.m_Condition.GetBuffer(), From.m_Condition.GetFieldsAssigned()); if (cmp != 0) { return eBDB_NotFound; } } if ( !TestTo() ) { ret = eBDB_NotFound; } return ret;}EBDB_ErrCode CBDB_FileCursor::Fetch(EFetchDirection fdir){ if ( !m_FirstFetched ) return FetchFirst(); if (fdir == eDefault) fdir = m_FetchDirection; unsigned int flag = (fdir == eForward) ? DB_NEXT : DB_PREV; EBDB_ErrCode ret; while (1) { ret = m_Dbf.ReadCursor(m_DBC, flag); if (ret != eBDB_Ok) { ret = eBDB_NotFound; break; } if ( !TestTo() ) { ret = eBDB_NotFound; break; } // Check if we have fallen out of the FROM range if (m_CondFrom == eEQ) { int cmp = m_Dbf.m_KeyBuf->Compare(From.m_Condition.GetBuffer(), From.m_Condition.GetFieldsAssigned()); if (cmp != 0) { ret = eBDB_NotFound; } } break; } // while if (ret != eBDB_Ok) { From.m_Condition.ResetUnassigned(); To.m_Condition.ResetUnassigned(); } return ret;}bool CBDB_FileCursor::TestTo() const{ switch (m_CondTo) { case eEQ: return (m_Dbf.m_KeyBuf->Compare(To.m_Condition.GetBuffer()) == 0); case eGT: return (m_Dbf.m_KeyBuf->Compare(To.m_Condition.GetBuffer()) > 0); case eGE: return (m_Dbf.m_KeyBuf->Compare(To.m_Condition.GetBuffer()) >= 0); case eLT: return (m_Dbf.m_KeyBuf->Compare(To.m_Condition.GetBuffer()) < 0); case eLE: return (m_Dbf.m_KeyBuf->Compare(To.m_Condition.GetBuffer()) <= 0); default: break; } return true;}///////////////////////////////////////////////////////////////////////////////// Operators//CBDB_ConditionHandle& CBDB_ConditionHandle::operator<< (int val){ IBDB_FieldConvert& cnv = m_Condition.GetUnassignedField(); cnv.SetInt(val); m_Condition.IncFieldsAssigned(); return *this;}CBDB_ConditionHandle& CBDB_ConditionHandle::operator<< (unsigned int val){ IBDB_FieldConvert& cnv = m_Condition.GetUnassignedField(); cnv.SetUint(val); m_Condition.IncFieldsAssigned(); return *this;}CBDB_ConditionHandle& CBDB_ConditionHandle::operator<< (float val){ IBDB_FieldConvert& cnv = m_Condition.GetUnassignedField(); cnv.SetFloat(val); m_Condition.IncFieldsAssigned(); return *this;}CBDB_ConditionHandle& CBDB_ConditionHandle::operator<< (double val){ IBDB_FieldConvert& cnv = m_Condition.GetUnassignedField(); cnv.SetDouble(val); m_Condition.IncFieldsAssigned(); return *this;}CBDB_ConditionHandle& CBDB_ConditionHandle::operator<< (const char* val){ IBDB_FieldConvert& cnv = m_Condition.GetUnassignedField(); cnv.SetString(val); m_Condition.IncFieldsAssigned(); return *this;}CBDB_ConditionHandle& CBDB_ConditionHandle::operator<< (const string& val){ IBDB_FieldConvert& cnv = m_Condition.GetUnassignedField(); cnv.SetString(val.c_str()); m_Condition.IncFieldsAssigned(); return *this;}END_NCBI_SCOPE/* * =========================================================================== * $Log: bdb_cursor.cpp,v $ * Revision 1000.2 2004/06/01 18:37:17 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13 * * Revision 1.13 2004/05/17 20:55:11 gorelenk * Added include of PCH ncbi_pch.hpp * * Revision 1.12 2004/05/06 19:19:22 rotmistr * Cursor KeyDupCount added * * Revision 1.11 2004/05/06 18:18:14 rotmistr * Cursor Update/Delete implemented * * Revision 1.10 2004/02/17 19:05:21 kuznets * GCC warnings fix * * Revision 1.9 2003/12/29 13:23:53 kuznets * Added support for transaction protected cursors. * * Revision 1.8 2003/12/29 12:54:33 kuznets * Fixed cursor leak. * * Revision 1.7 2003/07/21 19:51:04 kuznets * Performance tweak: do not worry about incomplete key fields when * "give me all records" cursor was requested * * Revision 1.6 2003/07/02 17:55:35 kuznets * Implementation modifications to eliminated direct dependency from <db.h> * * Revision 1.5 2003/05/01 13:42:12 kuznets * Bug fix * * Revision 1.4 2003/04/30 20:25:42 kuznets * Bug fix * * Revision 1.3 2003/04/29 19:07:22 kuznets * Cosmetics.. * * Revision 1.2 2003/04/28 14:51:55 kuznets * #include directives changed to conform the NCBI policy * * Revision 1.1 2003/04/24 16:34:30 kuznets * Initial revision * * =========================================================================== */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?