windows-nt/Source/XPSP1/NT/inetsrv/query/bigtable/rowcomp.hxx
2020-09-26 16:20:57 +08:00

353 lines
9.9 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1999.
//
// File: rowcomp.hxx
//
// Contents: Declaration of the row comparison classes
//
// Classes: CRowCompareVariant
//
// Templates: TRowCompare
//
// History: 31 Aug 1994 dlee Created
//
//--------------------------------------------------------------------------
#pragma once
#include <compare.hxx>
#include <xbuffer.hxx>
#include <shardbuf.hxx>
#include <tblvarnt.hxx>
#include "varntcmp.hxx"
#include "pathstor.hxx"
class CTableWindow;
//+-------------------------------------------------------------------------
//
// Class: CRowCompare
//
// Purpose: Abstract class for row comparisons
//
// Notes: The comparison function should return (for ascending order)
//
// 1..cSortItems if Row1 > Row2,
// 0 if same
// -1..-cSortItems if Row1 < Row2
//
// Return the opposite for descending order.
//
// History: 8/24/94 dlee created
//
//--------------------------------------------------------------------------
class CRowCompare
{
public:
CRowCompare() {}
virtual ~CRowCompare() {}
virtual int Compare(TBL_OFF oRow1, TBL_OFF oRow2) = 0;
};
class CPathStore;
//+-------------------------------------------------------------------------
//
// Class: CRowCompareVariant
//
// Purpose: Default case of row comparisons if a more optimal
// special case is not used. Converts values to variants
// and compares the variants. Also used if more than one
// (not including WORKID) sort spec specified.
//
// Notes: This must be declared unwindable because it has embedded
// unwindable objects.
//
//--------------------------------------------------------------------------
class CRowCompareVariant : public CRowCompare
{
public:
CRowCompareVariant(CTableWindow & TableWindow);
virtual ~CRowCompareVariant();
int Compare(TBL_OFF oRow1,
TBL_OFF oRow2);
int CompareObject(CRetriever & obj,
TBL_OFF oRow2);
enum EVariantSource { eNone, eCompressor, eBuffer, eNewx };
private:
void _FreeVariant(CTableColumn * pColumn,
CTableVariant * pVar,
EVariantSource eSource);
void _MakeVariant(CTableColumn * pColumn,
BYTE * pbRow,
CTableVariant * pVar,
EVariantSource & evSource);
void _MakeVariant(CTableColumn * pColumn,
CRetriever & obj,
unsigned iProp);
PROPVARIANT * _MakeVariant( unsigned iCol,
XUseSharedBuffer & sharedBuf,
CRetriever & obj );
void _Cleanup1();
void _Cleanup2();
int _DoCompare(TBL_OFF oRow2);
void _InitComparators( CSortSet const & sortSet );
PATHID _GetPathId( const CTableColumn & col, BYTE * pbRow );
BOOL _FastCompare( unsigned iCol, BYTE *pbRow1, BYTE * pbRow2,
int & iComp );
BOOL _FastCompare( unsigned iCol, CRetriever & obj,
XUseSharedBuffer & sharedBuf,
BYTE * pbRow2, int & iComp );
unsigned _cProps;
CTableWindow &_TableWindow;
// Comparators for the columns
XArray<CCompareVariants> _aComparator;
// State data for the comparison.
XArray<CTableVariant> _aVar1;
XArray<CTableVariant> _aVar2;
XArray<CTableVariant *> _apVar1;
XArray<CTableVariant *> _apVar2;
XArray<CTableColumn *> _apColumn;
XArray<EVariantSource> _aVarFlags1;
XArray<EVariantSource> _aVarFlags2;
//
// Used for quick path comparison.
//
CPathStore * _pPathStore;
//
// Temporary shared memory for the whole table.
//
CSharedBuffer & _sharedBuf;
// Buffer used for CRetriever temporary data
enum { maxcbBuffer = MAX_PATH * sizeof WCHAR };
XBuffer<BYTE> _xBuffer;
// Most recent row 1 identified by this member is cached
WORKID _widCached;
};
//+-------------------------------------------------------------------------
//
// Template: TRowCompare
//
// Purpose: Special row comparator for inline values: values that are
// stored in the row as opposed to variable-length or easily
// compressed data that is stored out-of-line.
//
// Use of this template is just an optimization over using
// CRowCompareVariant, in which data must be converted to a
// variant before the comparison (which is slow).
//
// You can use this template if:
// -- only one property is in the sort spec
// -- the property value is stored inline
// -- the property value datatype supports relational ops
// -- length of the value is fixed and is not an array
//
//--------------------------------------------------------------------------
template <class T> class TRowCompare : public CRowCompare
{
public:
TRowCompare( CFixedVarTableWindowAllocator &Alloc,
ULONG oData,
ULONG dwOrder) :
_Alloc( Alloc ),
_oData( oData )
{
if (0 == (dwOrder & QUERY_SORTDESCEND /*DBSORTORDER_DESCEND*/ ))
_iGT = 1; // ascending
else
_iGT = -1; // descending
}
~TRowCompare() {}
int Compare( TBL_OFF oRow1,
TBL_OFF oRow2 )
{
T t1 = * (T *) ((BYTE *) _Alloc.FixedPointer( oRow1 ) + _oData);
T t2 = * (T *) ((BYTE *) _Alloc.FixedPointer( oRow2 ) + _oData);
if (t1 > t2)
return _iGT;
if (t1 < t2)
return -_iGT;
return 0;
}
private:
int _iGT; // return value if 1 > 2
CFixedVarTableWindowAllocator &_Alloc; // allocator where rows are
ULONG _oData; // offset in row where value resides
};
//+-------------------------------------------------------------------------
//
// Template: TRowCompareTwo
//
// Purpose: Same as TRowCompare, except that it also does a second
// compare. A is compared first, then B.
//
// Rules for use of this template are the same as for
// TRowCompare
//
//--------------------------------------------------------------------------
template <class TA, class TB> class TRowCompareTwo : public CRowCompare
{
public:
TRowCompareTwo( CFixedVarTableWindowAllocator &Alloc,
ULONG oDataA,
ULONG dwOrderA,
ULONG oDataB,
ULONG dwOrderB ) :
_CompareA( Alloc, oDataA, dwOrderA ),
_CompareB( Alloc, oDataB, dwOrderB ) {}
~TRowCompareTwo() {}
int Compare( TBL_OFF oRow1,
TBL_OFF oRow2 )
{
int result = _CompareA.Compare( oRow1, oRow2 );
if (0 == result)
{
// same first key -- now check the second key.
// the * 2 means that it was the second column.
result = 2 * _CompareB.Compare( oRow1, oRow2 );
}
return result;
}
private:
TRowCompare<TA> _CompareA;
TRowCompare<TB> _CompareB;
};
//+-------------------------------------------------------------------------
//
// Template: TRowCompareStringPlus
//
// Purpose: Same as TRowCompareTwo, except that the first key compared
// is a wide string, then the parameterized type is compared.
//
//--------------------------------------------------------------------------
template <class TB> class TRowCompareStringPlus : public CRowCompare
{
public:
TRowCompareStringPlus( CFixedVarTableWindowAllocator &Alloc,
ULONG oDataString,
ULONG dwOrderString,
ULONG oDataB,
ULONG dwOrderB ) :
_Alloc( Alloc ),
_oDataString( oDataString ),
_CompareB( Alloc, oDataB, dwOrderB )
{
if (0 == (dwOrderString & QUERY_SORTDESCEND /*DBSORTORDER_DESCEND*/ ))
_iGTString = 1; // ascending
else
_iGTString = -1; // descending
}
~TRowCompareStringPlus() {}
int Compare( TBL_OFF oRow1,
TBL_OFF oRow2 )
{
WCHAR * p1 = * (WCHAR **) ((BYTE *) _Alloc.FixedPointer( oRow1 ) + _oDataString );
WCHAR * p2 = * (WCHAR **) ((BYTE *) _Alloc.FixedPointer( oRow2 ) + _oDataString );
// No string is every guaranteed to exist -- even path,
// since a summary catalog may have VT_EMPTY, and a VPATH
// is VT_EMPTY for non-web downlevel queries.
if ( 0 == p1 )
{
if ( 0 == p2 )
return 2 * _CompareB.Compare( oRow1, oRow2 );
else
return _iGTString;
}
else if ( 0 == p2 )
{
return -_iGTString;
}
int rc = CompareStringW( LOCALE_SYSTEM_DEFAULT,
NORM_IGNORECASE,
p1,
-1,
p2,
-1 );
// rc == 1, means less than
// rc == 2, means equal
// rc == 3, means greater than
int result = rc - 2;
if ( result > 0 )
return _iGTString;
if ( result < 0 )
return -_iGTString;
Win4Assert( 0 == result );
// same first key -- now check the second key.
// the * 2 means that it was the second column.
return 2 * _CompareB.Compare( oRow1, oRow2 );
}
private:
int _iGTString; // return value if 1 > 2
CFixedVarTableWindowAllocator &_Alloc; // allocator where rows are
ULONG _oDataString; // offset in row where value resides
TRowCompare<TB> _CompareB;
};