//+--------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation, 1991 - 2000. // // File: NodeXpr.cxx // // Contents: Internal expression classes // // Classes: CXpr // // History: 11-Sep-91 KyleP Created // 23-Jan-95 t-colinb Added Support for RTVector in // CNodeXpr::IsMatch // //---------------------------------------------------------------------------- #include #pragma hdrstop #include #include //+--------------------------------------------------------------------------- // // Member: CNodeXpr::CNodeXpr, public // // Synopsis: Initialze an empty node. // // Arguments: [type] -- Type of node (AND, OR, etc.) // [cInit] -- A hint about the number of expressions which // will be added to this node. // // Signals: ??? // // History: 05-Dec-91 KyleP Created. // //---------------------------------------------------------------------------- CNodeXpr::CNodeXpr ( CXpr::NodeType type, unsigned cInit ) : CXpr ( type ), _cXpr( 0 ), _size( cInit ) { _aXpr = new CXpr* [cInit]; } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::CNodeXpr, public // // Synopsis: Copy constructor // // Arguments: [nxpr] -- Node to copy from. // // Signals: ??? // // History: 11-Dec-91 KyleP Created. // //---------------------------------------------------------------------------- CNodeXpr::CNodeXpr( CNodeXpr & nxpr ) : CXpr ( nxpr.NType() ) { _cXpr = nxpr._cXpr; _size = nxpr._cXpr; _weight = nxpr._weight; _aXpr = new CXpr * [ _size ]; RtlZeroMemory( _aXpr, _size * sizeof( CXpr * ) ); TRY { for ( int i = _cXpr-1; i >= 0; i-- ) _aXpr[i] = nxpr._aXpr[i]->Clone(); } CATCH( CException, e ) { for ( unsigned i = 0; i < _cXpr; i++ ) delete _aXpr[i]; delete _aXpr; RETHROW(); } END_CATCH } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::~CNodeXpr, public // // Synopsis: Destroy subexpressions and cursor (if any) // // Signals: ??? // // History: 05-Dec-91 KyleP Created. // //---------------------------------------------------------------------------- CNodeXpr::~CNodeXpr () { for ( unsigned i = 0; i < _cXpr; i++ ) delete _aXpr[i]; delete _aXpr; } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::Clone, public // // Returns: A copy of this node. // // Signals: ??? // // Derivation: From base class CXpr, Always override in subclasses. // // History: 11-Dec-91 KyleP Created. // //---------------------------------------------------------------------------- CXpr * CNodeXpr::Clone() { return( new CNodeXpr( *this ) ); } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::SelectIndexing, public // // Effects: Selects indexing for children. // // History: 03-Nov-94 KyleP Created. // // Notes: Index selection is only applicable for AND nodes. // //---------------------------------------------------------------------------- void CNodeXpr::SelectIndexing( CIndexStrategy & strategy ) { BOOL fModeChange; if ( NType() == NTAnd ) fModeChange = strategy.SetAndMode(); else if ( NType() == NTOr ) fModeChange = strategy.SetOrMode(); else { strategy.SetUnknownBounds(); return; } for ( unsigned i = 0; i < _cXpr; i++ ) _aXpr[i]->SelectIndexing( strategy ); if ( fModeChange ) strategy.DoneWithBoolean(); } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::IsLeaf, public // // Returns: FALSE. Nodes are never leaf expressions. // // Derivation: From base class CXpr, Frequently override in subclasses. // // History: 12-Dec-91 KyleP Created. // //---------------------------------------------------------------------------- BOOL CNodeXpr::IsLeaf() const { return FALSE; } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::AddChild, public // // Synopsis: Add an expression to the node. // // Arguments: [child] -- Expression to add. // // Signals: ??? // // History: 12-Dec-91 KyleP Created. // // Notes: Once an expression has been added to a node it is owned // by that node. (e.g., no one else should delete it) // //---------------------------------------------------------------------------- void CNodeXpr::AddChild ( CXpr* child ) { Win4Assert( child ); if ( _cXpr < _size ) { _aXpr[_cXpr++] = child; } else { CXpr ** newArray = new CXpr * [ 2 * _size ]; memcpy( newArray, _aXpr, _cXpr * sizeof( CXpr * ) ); Win4Assert( _cXpr == _size ); newArray[_cXpr++] = child; delete _aXpr; _size *= 2; _aXpr = newArray; } } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::HitCount, public // // Returns: Sum for OR, Min for AND // // History: 01-May-91 KyleP Created. // // Notes: HitCount only makes sense for content clauses. If there // are any non-content clauses then HitCount will return 0. // //---------------------------------------------------------------------------- ULONG CNodeXpr::HitCount( CRetriever & obj ) { ULONG result; switch ( NType() ) { case NTAnd: { result = 0; for (int i = Count()-1; i >= 0; i--) { ULONG thisChild = GetChild( i )->HitCount( obj ); result = (thisChild) ? min( result, thisChild ) : result; } } break; case NTOr: { result = 0; for (int i = Count()-1; i >= 0; i--) { ULONG thisChild = GetChild( i )->HitCount( obj ); if ( 0 != thisChild ) { result += GetChild( i )->HitCount( obj ); } else { result = 0; break; } } } break; default: result = 0; break; } return( result ); } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::Rank, public // // Returns: Sum for OR, Min for AND // // History: 01-May-91 KyleP Created. // //---------------------------------------------------------------------------- LONG CNodeXpr::Rank( CRetriever & obj ) { LONG result; switch ( NType() ) { case NTAnd: { result = MAX_QUERY_RANK; for (int i = Count()-1; i >= 0; i--) { result = min( result, GetChild( i )->Rank( obj ) ); } } break; case NTOr: { result = 0; for (int i = Count()-1; i >= 0; i--) { result += GetChild( i )->Rank( obj ); } result /= Count(); } break; default: result = 0; break; } return( result ); } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::IsMatch, public // // Arguments: [obj] -- The objects table. [obj] is already positioned // to the record to test. // [wid] -- Workid of object to which [obj] is positioned. // // Returns: TRUE if the current record satisfies the relation. // // Signals: ??? // // History: 20-Nov-91 KyleP Created. // 23-Jan-95 t-colinb Added Support for RTVector in // // //---------------------------------------------------------------------------- BOOL CNodeXpr::IsMatch( CRetriever & obj ) { Win4Assert( NType() == NTAnd || NType() == NTOr || NType() == NTVector ); // // If some portion of the node has been indexed, adjust the cursor to // the wid we're looking for. // WORKID widCur = widInvalid; BOOL result; switch ( NType() ) { case NTAnd: result = TRUE; { for (int i = Count()-1; result && i >= 0; i--) { result = GetChild( i )->IsMatch( obj ); } } break; case NTOr: case NTVector: result = FALSE; { for (int i = Count()-1; !result && i >= 0; i--) { result = GetChild( i )->IsMatch( obj ); } } break; default: result = FALSE; break; } return result; } //+--------------------------------------------------------------------------- // // Member: CNodeXpr::RemoveChild, public // // Synopsis: Removes a node. // // Arguments: [iPos] -- Position of node to remove. // // Requires: [iPos] is a valid node. // // Returns: The child node which was removed. // // History: 19-Nov-91 KyleP Created. // // Notes: CNodeXpr does not guarantee the position of nodes across // calls to RemoveChild. // //---------------------------------------------------------------------------- CXpr* CNodeXpr::RemoveChild ( unsigned iPos ) { Win4Assert ( iPos <= _cXpr ); CXpr * pxp = _aXpr[iPos]; _aXpr[iPos] = _aXpr[ _cXpr - 1 ]; _cXpr--; #if (CIDBG == 1) _aXpr[ _cXpr ] = 0; #endif return( pxp ); } //+------------------------------------------------------------------------- // // Member: CVectorXpr::CVectorXpr, public // // Synopsis: Constructs a vector expression. // // Arguments: [type] -- Type of node (AND, OR, etc.) // [cInit] -- A hint about the number of expressions // which will be added. // [RankMethod] -- Method used to compute rank. // // History: 24-Jul-92 KyleP Created // //-------------------------------------------------------------------------- CVectorXpr::CVectorXpr( unsigned cInit, ULONG RankMethod ) : CNodeXpr( CXpr::NTVector, cInit ), _ulRankMethod( RankMethod ) { }