You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
499 lines
17 KiB
499 lines
17 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1998.
|
|
//
|
|
// File: tablecol.hxx
|
|
//
|
|
// Contents: Column descriptions used by CLargeTable.
|
|
//
|
|
// Classes: CColumnMasterDesc
|
|
// CTableColumn
|
|
//
|
|
// CColumnMasterArray
|
|
// CTableColumnArray
|
|
//
|
|
// CColumnMasterSet
|
|
// CTableColumnSet
|
|
//
|
|
// History: 15 Sep 94 AlanW Split out from coldesc.hxx
|
|
// 12 Feb 95 AlanW Updated fields and accessors in
|
|
// CTableColumn for OLE-DB phase III
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
class CTableVariant;
|
|
class PVarAllocator;
|
|
class CCompressedCol;
|
|
class SSortKey;
|
|
|
|
#include <pidmap.hxx>
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CColumnMasterDesc
|
|
//
|
|
// Purpose: A description of a column which is known to a table
|
|
// because it is a bound output column, a computed column,
|
|
// or a column in a sort key.
|
|
//
|
|
// Interface:
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CColumnMasterDesc
|
|
{
|
|
friend class CColumnMasterSet;
|
|
|
|
public:
|
|
CColumnMasterDesc(PROPID PropIdent = 0,
|
|
VARTYPE DatType = VT_EMPTY);
|
|
CColumnMasterDesc(SSortKey& rSortKey);
|
|
~CColumnMasterDesc();
|
|
|
|
void SetCompression( CCompressedCol* pCompr,
|
|
PROPID SharedID = 0);
|
|
|
|
void SetComputed(BOOL fComputed)
|
|
{ _fComputedProperty = fComputed; }
|
|
|
|
void SetUniform(BOOL fUniform)
|
|
{ _fUniformType = fUniform; }
|
|
|
|
void SetNotVariant(BOOL fNotVariant)
|
|
{ _fNotVariantType = fNotVariant; }
|
|
|
|
BOOL IsCompressedCol() const { return 0 != _pCompression; }
|
|
|
|
CCompressedCol * GetCompressor() const {
|
|
return _pCompression;
|
|
}
|
|
|
|
PROPID GetCompressMasterId() const { return _CompressMasterID; }
|
|
|
|
PROPID PropId; // Property ID in table
|
|
VARTYPE DataType; // most restrictive variant type in which
|
|
// all known values can be expressed.
|
|
VARTYPE _PredominantType; // most frequently occuring variant type
|
|
USHORT _cbData; // required width in segment row data
|
|
int _fComputedProperty:1; // TRUE if generated column. In this
|
|
// case, PropId gives a special prop. ID
|
|
int _fUniformType:1; // TRUE if all data are of type
|
|
// _PredominantType
|
|
int _fNotVariantType:1; // TRUE if it is absolutely known that
|
|
// the type cannot vary (e.g., system
|
|
// properties, some computed properties)
|
|
private:
|
|
CCompressedCol* _pCompression; // global compressor
|
|
PROPID _CompressMasterID; // if !0, shared compression
|
|
};
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CTableColumn
|
|
//
|
|
// Purpose: A description of a column stored in a table segment.
|
|
// Also used for transfer of data between the table and
|
|
// rowset, and for describing the format of row buffers
|
|
// in the rowset.
|
|
//
|
|
// Interface:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CTableColumn
|
|
{
|
|
public:
|
|
|
|
enum StoreParts {
|
|
StorePartValue = 0x1,
|
|
StorePartStatus = 0x2,
|
|
StorePartLength = 0x4,
|
|
};
|
|
|
|
enum StoreStatus
|
|
{
|
|
StoreStatusOK = 0,
|
|
StoreStatusDeferred = 1,
|
|
StoreStatusNull = 2,
|
|
};
|
|
|
|
CTableColumn( PROPID propid = 0, VARTYPE type = VT_NULL ):
|
|
PropId( propid ),
|
|
_obValue( 0 ), _cbValue( 0 ),
|
|
_obStatus( 0 ), _obLength( 0 ),
|
|
_usStoreParts( 0 ),
|
|
_StoreAsType( type ), _PredominantType( type ),
|
|
_fUniformType( TRUE ),
|
|
_pCompression( 0 ),
|
|
_fGlobalCompr( FALSE ), _CompressMasterID( 0 ),
|
|
_fSpecial( FALSE ),
|
|
_fPartialDeferred( FALSE )
|
|
{ }
|
|
|
|
CTableColumn( CTableColumn & src ):
|
|
PropId( src.PropId ),
|
|
_obValue( 0 ), _cbValue( 0 ),
|
|
_obStatus( 0 ), _obLength( 0 ),
|
|
_usStoreParts( 0 ),
|
|
_StoreAsType( src._StoreAsType ),
|
|
_PredominantType( src._PredominantType ),
|
|
_fGlobalCompr( src._fGlobalCompr ),
|
|
_fUniformType( src._fUniformType ),
|
|
_pCompression( 0 ),
|
|
_CompressMasterID( src._CompressMasterID ),
|
|
_fSpecial( FALSE ),
|
|
_fPartialDeferred( src._fPartialDeferred )
|
|
{
|
|
if ( _fGlobalCompr )
|
|
{
|
|
_pCompression = src._pCompression;
|
|
_obValue = src._obValue;
|
|
_cbValue = src._cbValue;
|
|
_obLength = src._obLength;
|
|
_obStatus = src._obStatus;
|
|
Win4Assert( src.StorePartStatus & src._usStoreParts );
|
|
_usStoreParts = ( StorePartValue | StorePartStatus );
|
|
}
|
|
}
|
|
|
|
~CTableColumn( );
|
|
|
|
PROPID GetPropId() const { return PropId; }
|
|
|
|
void SetPropId( PROPID val ) { PropId = val; }
|
|
|
|
void SetGlobalCompressor( CCompressedCol* pCompr,
|
|
PROPID SharedID = 0) {
|
|
_pCompression = pCompr;
|
|
_CompressMasterID = SharedID;
|
|
_fGlobalCompr = TRUE;
|
|
}
|
|
|
|
|
|
void SetLocalCompressor( CCompressedCol * pCompr,
|
|
PROPID SharedId = 0 )
|
|
{
|
|
_pCompression = pCompr;
|
|
_CompressMasterID = SharedId;
|
|
_fGlobalCompr = FALSE;
|
|
}
|
|
|
|
USHORT GetValueOffset() const {
|
|
return _obValue;
|
|
}
|
|
|
|
USHORT GetValueSize() const {
|
|
return _cbValue;
|
|
}
|
|
|
|
USHORT GetStatusOffset() const {
|
|
return _obStatus;
|
|
}
|
|
|
|
size_t GetStatusSize() const {
|
|
return sizeof (BYTE);
|
|
}
|
|
|
|
USHORT GetLengthOffset() const {
|
|
return _obLength;
|
|
}
|
|
|
|
size_t GetLengthSize() const {
|
|
return sizeof (ULONG);
|
|
}
|
|
|
|
VARTYPE GetStoredType() const {
|
|
return _StoreAsType;
|
|
}
|
|
|
|
CCompressedCol * GetCompressor() const {
|
|
return _pCompression;
|
|
}
|
|
|
|
BOOL IsCompressedCol() const {
|
|
return 0 != _pCompression;
|
|
}
|
|
|
|
BOOL IsGlobalCompressedCol() const {
|
|
return _fGlobalCompr;
|
|
}
|
|
|
|
PROPID GetCompressMasterId() const {
|
|
return _CompressMasterID;
|
|
}
|
|
|
|
// Copy a column from table to table or to row buffer
|
|
DBSTATUS CopyColumnData(
|
|
BYTE * pbDstRow,
|
|
CTableColumn const & rDstColumn,
|
|
PVarAllocator & rDstPool,
|
|
BYTE * pbSrcRow,
|
|
PVarAllocator & rSrcPool);
|
|
|
|
// Create a CTableVariant from from buffered data
|
|
BOOL CreateVariant(
|
|
CTableVariant & rVarnt,
|
|
BYTE * pbSrc,
|
|
PVarAllocator & rSrcPool) const;
|
|
|
|
void SetValueField(VARTYPE vt, USHORT obValue, USHORT cbValue) {
|
|
_StoreAsType = vt;
|
|
_obValue = obValue;
|
|
_cbValue = cbValue;
|
|
_usStoreParts |= StorePartValue;
|
|
}
|
|
|
|
void SetStatusField(USHORT obStatus, USHORT cbStatus) {
|
|
Win4Assert(cbStatus == sizeof (BYTE));
|
|
_obStatus = obStatus;
|
|
_usStoreParts |= StorePartStatus;
|
|
}
|
|
|
|
void SetLengthField(USHORT obLength, USHORT cbLength) {
|
|
Win4Assert(cbLength == sizeof (ULONG));
|
|
_obLength = obLength;
|
|
_usStoreParts |= StorePartLength;
|
|
}
|
|
|
|
BOOL IsValueStored() const {
|
|
return _usStoreParts & StorePartValue;
|
|
}
|
|
BOOL IsStatusStored() const {
|
|
Win4Assert( _usStoreParts & StorePartStatus );
|
|
return TRUE;
|
|
}
|
|
BOOL IsLengthStored() const {
|
|
return _usStoreParts & StorePartLength;
|
|
}
|
|
StoreStatus GetStatus( const BYTE * pb ) const
|
|
{
|
|
Win4Assert( IsStatusStored() );
|
|
|
|
return (StoreStatus) ( * ( pb + GetStatusOffset() ) );
|
|
}
|
|
|
|
BOOL IsDeferred(BYTE *pb) const
|
|
{
|
|
Win4Assert( IsStatusStored() );
|
|
|
|
return ( StoreStatusDeferred == GetStatus( pb ) );
|
|
}
|
|
|
|
inline BOOL IsPartialDeferred() const
|
|
{
|
|
return _fPartialDeferred;
|
|
}
|
|
|
|
BOOL IsNull(BYTE *pb) const
|
|
{
|
|
Win4Assert( IsStatusStored() );
|
|
|
|
return ( StoreStatusNull == GetStatus( pb ) );
|
|
}
|
|
|
|
ULONG GetLength(BYTE *pb) const
|
|
{
|
|
Win4Assert( IsLengthStored() );
|
|
|
|
return * (ULONG *) ( pb + GetLengthOffset() );
|
|
}
|
|
|
|
void SetStatus(BYTE *pb, StoreStatus stat) const
|
|
{
|
|
Win4Assert( IsStatusStored() );
|
|
|
|
* (pb + GetStatusOffset() ) = stat;
|
|
}
|
|
|
|
void SetLength( BYTE *pb, ULONG cb ) const
|
|
{
|
|
Win4Assert( IsLengthStored() );
|
|
|
|
* (ULONG *) (pb + GetLengthOffset() ) = cb;
|
|
}
|
|
|
|
void Marshall( PSerStream & stm, CPidMapper & pids ) const;
|
|
|
|
void MarkAsSpecial() { _fSpecial = TRUE; }
|
|
|
|
BOOL IsSpecial() { return _fSpecial; }
|
|
|
|
inline void SetPartialDeferred( BOOL fPartialDeferred )
|
|
{
|
|
_fPartialDeferred = fPartialDeferred;
|
|
}
|
|
|
|
PROPID PropId; // Property ID
|
|
|
|
|
|
private:
|
|
|
|
USHORT _obValue; // offset in row data (for key if compressed)
|
|
USHORT _cbValue; // width in row data (0 if compressed and no
|
|
// key needed
|
|
USHORT _obStatus; // offset in row data for value status (from
|
|
// DBSTATUSENUM, but stored in 1 byte)
|
|
USHORT _obLength; // offset in row data for value length (4 bytes)
|
|
|
|
USHORT _usStoreParts; // from StoreParts enum
|
|
|
|
VARTYPE _StoreAsType; // type stored in table
|
|
VARTYPE _PredominantType;
|
|
BOOL _fUniformType; // TRUE if all data are of type
|
|
// _PredominantType
|
|
BOOL _fGlobalCompr; // TRUE if _pCompression is a global compression
|
|
BOOL _fSpecial; // TRUE if this property has special fetch/storage requirements
|
|
CCompressedCol * _pCompression; // pointer to compressed col. data
|
|
PROPID _CompressMasterID; // if !0, shared compression
|
|
BOOL _fPartialDeferred; // TRUE if the column is partial deferred
|
|
// (deferred till requested by client)
|
|
|
|
BOOL _IsSpecialPathProcessing( CTableColumn const & dstCol ) const;
|
|
BOOL _GetPathOrFile( CTableColumn const & dstCol, const BYTE * pbSrc,
|
|
PVarAllocator & rDstPool, BYTE * pbDstRow );
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Classes: CColumnMasterArray
|
|
// CTableColumnArray
|
|
//
|
|
// Purpose: Dynamic arrays of the classes above. These support
|
|
// Add, Get and Size methods. The CColumnMasterArray
|
|
// and CTableColumnArray are wrapped by set classes
|
|
// which add Find and other methods.
|
|
//
|
|
// Notes: In-place dynamic arrays can only be used with types
|
|
// which do not have destructors.
|
|
//
|
|
// Interface:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
DECL_DYNARRAY( CColumnMasterArray, CColumnMasterDesc )
|
|
DECL_DYNARRAY( CTableColumnArray, CTableColumn )
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CTableColumnSet
|
|
//
|
|
// Purpose: A set of table columns. A dynamic array of columns
|
|
// with the addition of a Find method to lookup by PropID.
|
|
//
|
|
// Interface:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CTableColumnSet: public CTableColumnArray
|
|
{
|
|
public:
|
|
CTableColumnSet(int size = 0) :
|
|
_cColumns(0),
|
|
CTableColumnArray( size) {}
|
|
|
|
CTableColumnSet( PDeSerStream & stm, CPidMapper & pids );
|
|
|
|
unsigned Count(void) const {
|
|
return _cColumns;
|
|
}
|
|
|
|
void SetCount(unsigned cCol) {
|
|
_cColumns = cCol;
|
|
}
|
|
|
|
void Add(CTableColumn* pCol, unsigned iCol);
|
|
|
|
void Add(XPtr<CTableColumn> & pCol, unsigned iCol);
|
|
|
|
CTableColumn* Find(PROPID const propid, BOOL& rfFound) const;
|
|
|
|
CTableColumn* Find(PROPID const propid) const;
|
|
|
|
void Marshall( PSerStream & stm, CPidMapper & pids ) const;
|
|
|
|
private:
|
|
unsigned _cColumns;
|
|
};
|
|
|
|
inline
|
|
CTableColumn *
|
|
CTableColumnSet::Find(
|
|
PROPID const PropId
|
|
) const
|
|
{
|
|
for (unsigned i=0; i<Count(); i++)
|
|
{
|
|
CTableColumn* pCol = GetItem( i );
|
|
Win4Assert( 0 != pCol );
|
|
if ( pCol->PropId == PropId )
|
|
return pCol;
|
|
}
|
|
Win4Assert( !"propid not found" );
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CColumnMasterSet
|
|
//
|
|
// Purpose: A set of master columns. Multiple instances of a
|
|
// column with the same property ID are collapsed in
|
|
// the set.
|
|
//
|
|
// Interface:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CColumnMasterSet
|
|
{
|
|
public:
|
|
CColumnMasterSet(const CColumnSet* const pOutCols);
|
|
CColumnMasterSet(unsigned Size);
|
|
|
|
//
|
|
// Add an instance of a column description
|
|
//
|
|
CColumnMasterDesc* Add(XPtr<CColumnMasterDesc> & xpNewItem);
|
|
|
|
CColumnMasterDesc* Add(CColumnMasterDesc const & rNewItem);
|
|
|
|
//
|
|
// Lookup a column by property ID. Returns NULL if not found.
|
|
//
|
|
CColumnMasterDesc* Find(const PROPID propid);
|
|
|
|
//
|
|
// Passthrough to CColumnMasterArray
|
|
//
|
|
inline unsigned Size(void) { return _iNextFree; }
|
|
inline CColumnMasterDesc& Get(unsigned i) { return *_aMasterCol.Get(i); }
|
|
|
|
inline BOOL HasUserProp() { return _fHasUserProp; }
|
|
|
|
private:
|
|
//
|
|
// Lookup a column by property ID. Returns NULL if not found.
|
|
//
|
|
|
|
CColumnMasterDesc* Find(const PROPID propid, unsigned& riCol);
|
|
|
|
unsigned _iNextFree; // index of next column to use
|
|
CColumnMasterArray _aMasterCol; // The column descriptors
|
|
BOOL _fHasUserProp; // TRUE if non-system (deferred) property in list
|
|
};
|
|
|