//-------------------------------------------------------------------- // 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) // // // Revision History: //--------------------------------------------------------------------------- #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. DBORDINAL m_ulIndex; // Column which has primary key constraint on it. DBORDINAL m_ulPrimaryKey; // @cmember Indicates if Primary Key will be created on a table ECREATE_PK m_eCreatePK; // List of columns in this schema. CList m_ColList; // List of descendents of this row. CList 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 *GetColList() { return &m_ColList; } // retrieve the children list (for the copy constructor) CList *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_