|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991-1998.
//
// File: PRelXpr.cxx
//
// Contents: Property relation expression
//
// Classes: CXprPropertyRelation
//
// History: 11-Sep-91 KyleP Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <parse.hxx>
#include <objcur.hxx>
#include <compare.hxx>
#include <xpr.hxx>
#include <strategy.hxx>
//+---------------------------------------------------------------------------
//
// Member: CXprPropertyRelation::CXprPropertyRelation, public
//
// Synopsis: Create an expression used to test <prop> <relop> <const>
//
// Arguments: [pid] -- Property ID to be compared
// [relop] -- Relational operator
// [prval] -- Constant value to be compared against
// [prstContentHelper] -- Content index helper
//
// History: 30-Oct-91 KyleP Created.
//
//----------------------------------------------------------------------------
CXprPropertyRelation::CXprPropertyRelation( PROPID pid, ULONG relop, CStorageVariant const & prval, CRestriction * prstContentHelper ) : CXpr( CXpr::NTProperty ), _xpval( pid ), _rel( relop ), _cval( prval ), _xrstContentHelper( prstContentHelper ) { Win4Assert( getBaseRelop( _rel ) <= PRSomeBits );
if ( ! _cval.IsValid() ) { vqDebugOut(( DEB_ERROR, "ERROR: restriction with pointer value of 0\n" ));
THROW( CException( QUERY_E_INVALIDRESTRICTION ) ); }
_relop = VariantCompare.GetRelop( _cval.Type(), _rel );
if ( 0 == _relop ) { vqDebugOut(( DEB_ERROR, "ERROR: Unsupported relational operator %d " "on type 0x%x\n", _rel, _cval.Type() )); THROW( CException( QUERY_E_INVALIDRESTRICTION ) ); } }
//+---------------------------------------------------------------------------
//
// Member: CXprPropertyRelation::CXprPropertyRelation, public
//
// Synopsis: Copy contstructor
//
// Arguments: [propxpr] -- Expression to copy
//
// History: 11-Dec-91 KyleP Created.
//
//----------------------------------------------------------------------------
CXprPropertyRelation::CXprPropertyRelation( CXprPropertyRelation & propxpr ) : CXpr( propxpr.NType(), propxpr.GetWeight() ), _xpval( propxpr._xpval ), _relop( propxpr._relop ), _cval( propxpr._cval ), _rel( propxpr._rel ) { if ( !propxpr._xrstContentHelper.IsNull() ) _xrstContentHelper.Set( propxpr._xrstContentHelper->Clone() ); }
//+---------------------------------------------------------------------------
//
// Member: CXprPropertyRelation::~CXprPropertyRelation, public
//
// Synopsis: Destroys the expression
//
// History: 30-Oct-91 KyleP Created.
//
//----------------------------------------------------------------------------
CXprPropertyRelation::~CXprPropertyRelation() { }
//+---------------------------------------------------------------------------
//
// Member: CXprPropertyRelation::Clone, public
//
// Returns: A copy of this node.
//
// Derivation: From base class CXpr, Always override in subclasses.
//
// History: 11-Dec-91 KyleP Created.
//
//----------------------------------------------------------------------------
CXpr * CXprPropertyRelation::Clone() { return( new CXprPropertyRelation( *this ) ); }
void CXprPropertyRelation::SelectIndexing( CIndexStrategy & strategy ) { //
// Bounds checking is for index selection. Query properties are not
// in any index.
//
if ( IS_CIQUERYPROPID(_xpval.Pid()) && _xpval.Pid() != pidUnfiltered ) { strategy.SetUnknownBounds( _xpval.Pid() ); return; }
if ( ! _xrstContentHelper.IsNull() && _xpval.Pid() != pidPath && _xpval.Pid() != pidDirectory && _xpval.Pid() != pidVirtualPath ) { Win4Assert( _rel == PREQ || _rel == (PREQ|PRAny) || _rel == (PREQ|PRAll) );
strategy.SetContentHelper( _xrstContentHelper.Acquire() ); }
switch ( _rel ) { case PRLT: case PRLE: strategy.SetUpperBound( _xpval.Pid(), _cval ); break;
case PRGT: case PRGE: case PRAllBits: strategy.SetLowerBound( _xpval.Pid(), _cval ); break;
case PREQ: strategy.SetBounds( _xpval.Pid(), _cval, _cval ); break;
case PRSomeBits: //
// Value must be at least as large as lowest set bit.
//
if ( _cval.Type() == VT_I4 ) { long l = _cval;
for ( unsigned lowbit = 0; l != 0; lowbit++ ) l <<= 1; lowbit = 32 - lowbit;
if ( lowbit > 0 ) { CStorageVariant var( (long)(1 << lowbit) );
strategy.SetLowerBound( _xpval.Pid(), var ); } } break;
case PRNE: default: strategy.SetUnknownBounds( _xpval.Pid() ); break; } }
//+---------------------------------------------------------------------------
//
// Member: CXprPropertyRelation::IsMatch, public
//
// Arguments: [obj] -- The object retriever. [obj] is already positioned
// to the record to test.
//
// Returns: TRUE if the current record satisfies the relation.
//
// History: 30-Oct-91 KyleP Created.
//
//----------------------------------------------------------------------------
BOOL CXprPropertyRelation::IsMatch( CRetriever & obj ) { // this is an array of LONGLONGs to force 8-byte alignment
LONGLONG allBuffer[ 10 ]; ULONG cb = sizeof allBuffer; PROPVARIANT * ppv = (PROPVARIANT *) allBuffer;
GetValueResult rc = _xpval.GetValue( obj, ppv, &cb );
//
// If the object is too big for the stack then allocate heap (sigh).
//
XArray<BYTE> xTemp;
if ( rc == GVRNotEnoughSpace ) { xTemp.Init( cb ); ppv = (PROPVARIANT *) xTemp.GetPointer(); rc = _xpval.GetValue( obj, ppv, &cb ); }
if ( rc != GVRSuccess ) { vqDebugOut(( DEB_TRACE, "CXprPropertyRelation::IsMatch -- Can't get value.\n" )); return FALSE; }
//
// In general, the types must match for values to match.
// There are exceptions for the vector case, and for != comparisons.
//
if ( ppv->vt != _cval.Type() ) { // If != comparison and value is VT_EMPTY, it matches
if ( PRNE == _rel && VT_EMPTY == _cval.Type() ) return TRUE;
// Could be a vector compare iff ppv is a vector and the
// relop is any/all.
// Otherwise, return that there is no match.
if ( ! ( isVectorOrArray( *ppv ) && isVectorRelop( _rel ) ) ) return FALSE; }
Win4Assert( 0 != _relop );
return _relop( *ppv, (PROPVARIANT &)_cval ); }
|