2025-11-28 00:35:46 +09:00

595 lines
14 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Test
//
// Copyright 1995-2000 Microsoft Corporation.
//
// @doc
//
// @module CTree Header Module | This module contains header information for CTree
//
// @comm
// Special Notes...: (OPTIONAL NOTES FOR SPECIAL CIRCUMSTANCES)
//
// <nl><nl>
// Revision History:<nl>
//---------------------------------------------------------------------------
#ifndef _CTree_HPP_
#define _CTree_HPP_
/////////////////////////////////////////////////////////////////////
// Includes
//
/////////////////////////////////////////////////////////////////////
#include "List.h"
typedef enum
{
NC_NONE = 0x0,
NC_Collection = 0x1,
NC_Singleton = 0x2,
NC_LEAF = 0x4,
NC_SUBTREE = 0x8,
NC_LEAF_Collection = NC_LEAF | NC_Collection,
} NODE_CONSTRAINT;
typedef enum
{
PCO_NONE = 0x0,
PCO_DIFF = 0x1,
PCO_OVERLAP = 0x2,
} PAIR_CONSTRAINT;
typedef BOOL (*CColApplicator)(CCol*);
class CSchema
{
private:
// row URL (the row on whose children rowset is opened)
WCHAR * m_pwszRowURL;
// the last part of the URL (name relative to parent)
WCHAR * m_pwszRowName;
// parent row seed; equals to -1 if not used => seed values limited to
// half of MAX_PTR
// for an ini file this value should be the row number
LONG_PTR m_lSeed;
// Number of leaves this schema has
ULONG_PTR m_cLeaves;
// info about the row being collection or not
BOOL m_fIsCollection;
protected:
// Indicates if NULL values will be generated by MakeData.
ENULL m_eNull;
// Column which has index on it. <nl>
DBORDINAL m_ulIndex;
// Column which has primary key constraint on it. <nl>
DBORDINAL m_ulPrimaryKey;
// @cmember Indicates if Primary Key will be created on a table
ECREATE_PK m_eCreatePK;
// List of columns in this schema. <nl>
CList <CCol,CCol&> m_ColList;
// List of descendents of this row. <nl>
CList <CSchema*,CSchema*> m_ChildrenList;
// the parent CSchema
CSchema * m_pParentSchema;
// Count of supported variant subtypes
ULONG m_cVariantSubTypes;
// Array of variant subtypes
DBTYPE m_rgVariantSubTypes[MAX_VARIANT_SUBTYPES];
// Updates CCol List based on information found in rgData. rgData
// an entire row.
HRESULT UpdateCCol
(
DBCOUNTITEM cBindings,
DBBINDING * rgBindings,
void * pData,
CCol & NewCol, // [IN/OUT] Element from the CCol List
EDATATYPES eDataTypes, // [IN] Enum for column data type
ULONG * pulAutoIncPrec, // [IN/OUT] Precision of largest autoincrement column
LONG_PTR lSQLSupport // [IN] SQL Support Level
);
public:
// used to speed up node retrieval
// when moving to the next node in a tree, based on a CSchema ptr
// (the crt position), one will get the parent CSchema and
// try to move child (m_ulCacheSelection+1)
LONG_PTR m_lCacheSelection;
CSchema
(
CSchema * pParentSchema = NULL, // [in] the parent schema of the row
WCHAR * pwszParentRowURL = NULL,// [in] the URL of the parent row
LONG_PTR lSeed = -1, // [in] the seed value used for the row
ENULL eNull = USENULLS, // [in] tells if nulls are used
ECREATE_PK eCreatePK=CREATENEVER_PK // [in] tells if a primary key be created
);
CSchema::CSchema
(
CSchema * pSchema, // [in] the schema to be copied
CSchema * pParentSchema = NULL, // [in] the parent schema (if exists)
BOOL fNonRecursive = FALSE // [in] whether the copying is recursive or not
);
virtual ~CSchema(void);
void SetParentSchema(CSchema *pSchema)
{
m_pParentSchema = pSchema;
}
CSchema *GetParentSchema()
{
return m_pParentSchema;
}
// manipulate the list of children
void AddChild(CSchema *pSchema);
void RemoveChild(CSchema *pSchema);
virtual HRESULT InitSchema(IUnknown* pIUnknown);
virtual HRESULT SetFromColumnsInfo
(
IColumnsInfo * pIColumnsInfo,
DBORDINAL * pcColsColInfo
);
virtual HRESULT SetFromColumnsRowset
(
IColumnsRowset * pIColumnsRowset,
DBORDINAL * pcColsFound
);
// retrieve the column list (for the copy constructor)
CList <CCol,CCol&> *GetColList()
{
return &m_ColList;
}
// retrieve the children list (for the copy constructor)
CList <CSchema*,CSchema*> *GetChildrenList()
{
return &m_ChildrenList;
}
// @cmember Gets CCol object associated with criteria
virtual HRESULT GetColInfo
(
CColApplicator pfApp, // [IN] Accepting criteria
CCol & ColInfo // [OUT] CCol object
);
// @cmember Gets CCol object associated with column number.
virtual HRESULT GetColInfo
(
DBORDINAL ulColNum, // [IN] Column number
CCol & ColInfo // [OUT] CCol object
);
// @cmember Gets first CCol object associated with Provider type.
virtual HRESULT GetColInfo
(
CCol & col, // [OUT] CCol object
DBTYPE wType // [IN] Datatype
);
// @cmember Gets first CCol object associated with Provider type.
virtual HRESULT GetColInfo
(
CCol & col, // [OUT] CCol object
WCHAR *pwszTypeName // [IN] Provider typename
);
// @cmember Gets first CCol object associated with dbcid (ColumnID).
virtual HRESULT GetColInfo
(
DBID * dbcid, // [IN] Column ID to be retrieved
CCol & col // [OUT] CCol object
);
// @cmember Returns CCol object associated with column number
virtual CCol & GetColInfoForUpdate
(
DBORDINAL ulColNum // [IN] Column number searching for, 1 based
);
LONG_PTR GetSeed()
{
return m_lSeed;
}
// @cmember returns info about the row being collection or not
BOOL IsCollection()
{
return m_fIsCollection;
}
virtual HRESULT MakeData
(
WCHAR * wszData, // @parm [OUT] Return data
DBCOUNTITEM ulRowNum, // @parm [IN] Row number which is one based
DBORDINAL iOrdinal, // @parm [IN] Column number which is one based
EVALUE eValue, // @parm [IN] Primary or secondary data
DBTYPE wSubType=DBTYPE_EMPTY, // @parm [IN] Column SubType
BOOL bNoNullValues=FALSE, // [IN] if bNoNullValues is True then MakeData will return valid data.
DBTYPE * pwVariantType=NULL // [OUT] Optional, returns underlying type if backend is a Variant
);
// Returns client's request to use nulls or not use nulls.
inline ENULL GetNull(void)
{
return m_eNull;
}
// Returns client's request to use nulls or not use nulls.
inline void SetNull(ENULL eNull)
{
m_eNull = eNull;
}
// Return Column number which index is created on.
inline DBORDINAL GetIndexColumn(void)
{
return m_ulIndex;
}
// Set Column number which index is created on.
inline DBORDINAL SetIndexColumn(DBORDINAL ulIndex)
{
DBORDINAL ulOldIndex = m_ulIndex;
m_ulIndex=ulIndex;
return ulOldIndex;
}
// Returns Column number which primary key is created on.
inline DBORDINAL GetPrimaryKeyColumn(void) {return m_ulPrimaryKey;}
// Sets Column number which Primary key is created on.
// Note!!!: if m_eCreatePK==CREATENEVER_PK then m_ulPrimaryKey will be ignored
inline void SetPrimaryKeyColumn(DBORDINAL ulPrimaryKey) {m_ulPrimaryKey=ulPrimaryKey;}
// Returns m_eCreatePK
inline ECREATE_PK GetCreatePK(void) {return m_eCreatePK;}
// Sets m_eCreatePK
void SetCreatePK(ECREATE_PK eCreatePK)
{
m_eCreatePK=eCreatePK;
if (CREATENEVER_PK==eCreatePK)
m_ulPrimaryKey=0;
}
DBCOUNTITEM SetLeafNo(DBCOUNTITEM cLeaves)
{
return m_cLeaves = cLeaves;
}
LONG_PTR SetSeed(LONG_PTR lSeed)
{
return m_lSeed = lSeed;
}
DBCOUNTITEM GetLeafNo(void)
{
return m_cLeaves;
}
DBCOUNTITEM GetChildrenNo(void)
{
return m_ChildrenList.GetCount();
}
// returns the URL associated with this row
WCHAR * GetRowURL()
{
return m_pwszRowURL;
}
// returns the last part of the name (e.g. confprov://dso/session/t/1/2/3 => 3)
WCHAR * GetRowName()
{
return m_pwszRowName;
}
WCHAR * SetRowURL
(
WCHAR *pwszRowURL
);
// methods to retrieve one of the children
CSchema * GetChild
(
DBCOUNTITEM ulIndex
);
CSchema * GetChild
(
WCHAR * pwszName,
DBCOUNTITEM * pulIndex = NULL
);
// method to update the URL of the tree
void UpdateURL(WCHAR *pwszURL);
// returns the index of the child given in the children list
LONG_PTR GetChildIndex(CSchema *pSchema);
// Populates an col list with a Provider's type information
HRESULT CSchema::PopulateTypeInfo
(
IUnknown * pIUnknown,
LONG_PTR lSQLSupport
);
// Returns the number of columns in the schema list
inline DBORDINAL CountColumnsOnSchema(void)
{
return (DBORDINAL) m_ColList.GetCount();
};
inline void GetVariantSubTypes(ULONG * pcVariantSubTypes, DBTYPE ** pprgVariantSubTypes)
{
ASSERT(pcVariantSubTypes && pprgVariantSubTypes);
*pcVariantSubTypes = m_cVariantSubTypes;
*pprgVariantSubTypes = m_rgVariantSubTypes;
}
};
class CTree
{
protected:
// A Tree to CSchema objects
CSchema * m_pRootSchema;
CSchema * m_pCrtSchema;
// Iteration limit
// This is the level of the subtree root.
// SetPosition sets this value and ResetPosition resets it to 0.
// When the iteration returns to this level in the tree, nav will stop.
CSchema * m_pStartingSchema;
// The depth that the tree was created with
DBCOUNTITEM m_ulMaxDepth;
// Number of children per node when tree was created
DBCOUNTITEM m_cMaxChildrenPerNode;
// Root Node
WCHAR * m_pwszTreeRoot;
// RootBinder interfaces
IBindResource * m_pIBindResource;
ICreateRow * m_pICreateRow;
// store the value of DBPROP_GENERATEURL property
LONG_PTR m_lGenerateURL;
public:
CTree
(
IUnknown * pSessionIUnknown, // [IN] SessionInterface
WCHAR * pwszModuleName=NULL, // [IN] Tree name, optional (Default=NULL)
ENULL eNull=USENULLS // [IN] Should nulls be used (Default=USENULLS)
);
virtual ~CTree(void);
virtual HRESULT CreateTree
(
WCHAR * pwszRootURL,
DBCOUNTITEM ulDepth,
DBCOUNTITEM cMaxChildrenPerNode
);
virtual HRESULT CopyTree
(
CTree * pCTree, // [in] the tree to be copied
WCHAR * pwszBaseRootURL // [in] the base root URL where to copy the tree
);
virtual HRESULT CreateAndPopulateRow
(
CSchema * pParentSchema, // [in] parent node's schema
ULONG_PTR ulSeed, // [in] the seed of the row
WCHAR * pwszURL, // [in] row URL
DBBINDURLFLAG dwBindURLFlags, // [in] binding flags
CSchema ** ppSchema, // [out] new row's schema
IUnknown ** ppIRowChange, // [out] pointer to interface to be returned
WCHAR ** ppwszNewURL // [out] pointer to the name of the new row
);
// check the rowset opened on pwszParentURL
// making sure that all the rows expected are contained and their values are ok
BOOL CheckRowset
(
IRowset * pIRowset, // [in] interface on the checked rowset
WCHAR * pwszParentURL, // [in] the URL used to open the rowset
BOOL fCmpRowVal = TRUE // [in] whether or not to compare the row values
);
BOOL CheckRowset
(
IRowset * pIRowset, // [in] interface on the checked rowset
CSchema * pRowsetSchema, // [in] schema of the rowset to be checked
BOOL fCmpRowVal // [in] whether or not to compare the row values
);
// checks whether all the rows in the tree can be bound
BOOL CheckTreeStructure();
// checks the tree structure as well as the values
BOOL CheckTree();
virtual HRESULT CreateChildRowset
(
CSchema * pParentSchema,
WCHAR * pwszParentURL,
DBCOUNTITEM cChildren,
DBCOUNTITEM ulDepth,
ULONG_PTR ulParentSeed = 1
);
virtual HRESULT DestroyTree();
virtual CSchema * GetSchema(WCHAR *pwszURL);
DBCOUNTITEM GetMaxDepth()
{
return m_ulMaxDepth;
}
DBCOUNTITEM GetMaxChildrenPerNode()
{
return m_cMaxChildrenPerNode;
}
virtual CSchema * GetCurrentSchema();
virtual WCHAR * GetCurrentRowURL();
virtual CSchema* GetRootSchema();
virtual HRESULT GetRelativeRowURL
(
WCHAR * pwszAbsoluteRowURL, // [in]
WCHAR ** ppwszRelativeRowURL // [out]
);
virtual HRESULT GetAbsoluteRowURL
(
WCHAR * pwszRelativeRowURL, // [in]
WCHAR ** ppwszAbsoluteRowURL // [out]
);
HRESULT GetOuterCollection
(
WCHAR * pwszLeafURL, // [in] the URL of the leaf row
WCHAR ** ppwszOuterCollection // [out] the URL of the outest Collection in the given path
);
HRESULT GetCommonAncestor
(
WCHAR * pwszFirstURL, // [in] the first URL
WCHAR * pwszSecondURL, // [in] the second URL
WCHAR ** ppwszCommonURL // [out] the URL of closest common ancestor
);
virtual BOOL MakeSuffix
(
DBCOUNTITEM ulNode,
WCHAR * pwszBaseURL,
WCHAR ** ppwszNewURL
);
virtual BOOL MakeSuffix
(
WCHAR * pwszNode,
WCHAR * pwszBaseURL,
WCHAR ** ppwszNewURL
);
virtual CSchema* AddSchema
(
CSchema * pParentSchema, // [in] pointer to the parent schema
IRowset * pIParentRow, // [in] interface to the current row
WCHAR * pwszParentURL, // [in] row URL of the parent
LONG_PTR lSeed // [in] the seed value
);
WCHAR * GetRootURL()
{
return m_pwszTreeRoot;
}
HRESULT GetRowLevel
(
WCHAR * pwszURL, // [in] the URL of the chosen row
DBCOUNTITEM * pulLevel // [out] the level of the row in the hierarchy
);
LONG_PTR GetGenerateURL()
{
return m_lGenerateURL;
}
// setting exact position inside a tree
inline void ResetPosition()
{
m_pCrtSchema = m_pRootSchema;
m_pStartingSchema = m_pRootSchema;
}
HRESULT SetPosition(WCHAR *pwszURL);
void MoveDownToChildNode(DBCOUNTITEM ulChildOrdinal);
// move to the next sibling (if there is any)
HRESULT MoveToNextSibling();
// move to the next node
// this should set the position and return the URL of that node
HRESULT MoveToNextNode
(
WCHAR ** ppwszURL // [out] the URL of the node
);
void ReturnFromChildNode();
HRESULT GetRow
(
DBCOUNTITEM ulRow, // [in] the number of row (as a leaf)
WCHAR ** ppwszURL //[out] the URL of the chosen row
);
// get the number of the first leaf in the subtree
// starting at the current position
DBCOUNTITEM GetNoOfFirstLeafInSubtree(CSchema*);
// @cmember tests whether the row give by its URL is a collection
BOOL IsCollection(WCHAR*);
BOOL IsCollection(CSchema *pSchema);
// methods that check the column values of a row
HRESULT VerifyRowValues
(
WCHAR * pwszRowURL, // [in] the URL of the row to be checked
IUnknown * pIUnk, // [in] ptr to the row interface
BOOL fFromRowset = TRUE // [in] whether it was obtained from a rowset
);
HRESULT VerifyRowValues
(
WCHAR * pwszRowURL // [in] the URL of the row to be checked
);
CSchema * RemoveSchema(CSchema *pSchema);
CSchema * RemoveSchema(WCHAR *pwszURL); // [in] URL associated with the schema
};
#endif _CTree_HPP_