windows-nt/Source/XPSP1/NT/inetsrv/query/icommand/dbcmdop.cxx
2020-09-26 16:20:57 +08:00

489 lines
14 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: dbcmdop.cxx
//
// Contents: Wrapper classes for DBCOMMANDTREE structure
//
// Classes: CDbSelectNode
// CDbProjectNode
// CDbProjectListAnchor
// CDbSortNode
// CDbSortListAnchor
// CDbNestingNode
//
// History: 6-15-95 srikants Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
//+---------------------------------------------------------------------------
//
// Method: CDbSelectNode::CDbSelectNode
//
// Synopsis: Construct a select node.
//
// Arguments: -NONE-
//
// History: 6-15-95 srikants Created
//
// Notes: Only the normal select can be created. For OFS,
// order-preserving functions identially with normal select.
//
//----------------------------------------------------------------------------
CDbSelectNode::CDbSelectNode( )
: CDbCmdTreeNode( DBOP_select )
{
CDbTableId * pTableId = new CDbTableId( DBTABLEID_NAME );
if ( 0 != pTableId )
{
if ( pTableId->IsValid() )
{
InsertChild( pTableId );
}
else
{
delete pTableId;
}
}
}
//+---------------------------------------------------------------------------
//
// Method: CDbSelectNode::SetRestriction
//
// Synopsis: Set the restriction expression
//
// Arguments: [pRestr] - restriction expression to be set.
//
// History: 6-15-95 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CDbSelectNode::SetRestriction( CDbCmdTreeNode * pRestr )
{
if ( IsValid() &&
GetFirstChild() &&
GetFirstChild()->GetNextSibling() != 0 )
{
//
// Restriction expression already set on node. Remove and
// replace it.
//
CDbCmdTreeNode * pTableNode = RemoveFirstChild();
CDbCmdTreeNode * pOldRst = RemoveFirstChild();
Win4Assert( 0 == GetFirstChild() ); // don't expect any more children
delete pOldRst;
InsertChild(pTableNode);
}
return AddRestriction(pRestr);
}
//+---------------------------------------------------------------------------
//
// Member: CDbListAnchor::_AppendListElement
//
// Synopsis: Helper function to add a list-element node and the given
// column node to the anchor.
//
// Arguments: [eleType] - The type of the element node.
// [pColumn] - The column specification node. This will be made
// the child of the newly created list element.
//
// Returns: TRUE if successful; FALSE otherwise.
//
// History: 11-16-95 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CDbListAnchor::_AppendListElement( DBCOMMANDOP eleType, CDbColumnNode * pColumn )
{
Win4Assert( _IsValidListElement( eleType ) );
Win4Assert( 0 != pColumn );
CDbCmdTreeNode * pLE = new CDbCmdTreeNode( eleType );
if ( 0 != pLE )
{
pLE->InsertChild( pColumn );
AppendChild( pLE );
}
return (0 != pLE);
}
//+---------------------------------------------------------------------------
//
// Method: CDbListAnchor::AppendList, protected
//
// Synopsis: Appends a list of elements to a list anchor
//
// Arguments: [pListElement] - pointer to head list element
//
// Returns: BOOL - TRUE if successful, FALSE otherwise
//
// History: 17 Aug 1995 AlanW Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CDbListAnchor::AppendList( CDbCmdTreeNode * pListElement )
{
Win4Assert( _IsValidListElement( pListElement->GetCommandType() ));
Win4Assert( pListElement->GetFirstChild() != 0 );
AppendChild( pListElement );
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Method: CDbListAnchor::AppendListElement, protected
//
// Synopsis: Appends a single element to a list anchor
//
// Arguments: [pListElement] - pointer to list element
//
// Returns: BOOL - TRUE if successful, FALSE otherwise
//
// History: 17 Aug 1995 AlanW Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CDbListAnchor::AppendListElement( CDbCmdTreeNode * pListElement )
{
Win4Assert( _IsValidListElement( pListElement->GetCommandType() ) &&
pListElement->GetNextSibling() == 0 );
Win4Assert( pListElement->GetFirstChild() != 0 );
AppendChild( pListElement );
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Method: CDbListAnchor::AppendListElement, protected
//
// Synopsis:
//
// Arguments: [eleType] - list element type
// [PropSpec] - Full property spec of column to add
//
// Returns: BOOL - TRUE if successful, FALSE otherwise
//
// History: 6-15-95 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CDbListAnchor::AppendListElement( DBCOMMANDOP eleType,
const DBID & PropSpec)
{
XPtr<CDbColumnNode> pColumn( new CDbColumnNode( PropSpec, TRUE ) );
if ( 0 == pColumn.GetPointer() || !pColumn->IsValid() )
return FALSE;
if ( _AppendListElement( eleType, pColumn.GetPointer() ) )
{
pColumn.Acquire();
return TRUE;
}
else
{
return FALSE;
}
}
//+---------------------------------------------------------------------------
//
// Method: CDbProjectListAnchor::AppendListElement, public
//
// Synopsis: Add a project_list_element node to the end of the list
//
// Arguments: [propSpec] - column to be added to the list
// [pwszName] - name of column
//
// Returns: BOOL - TRUE if successful, FALSE otherwise
//
// History: 6-15-95 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CDbProjectListAnchor::AppendListElement( const DBID & propSpec, LPWSTR pwszName )
{
BOOL fSuccess = FALSE;
XPtr<CDbProjectListElement> pListElem( new CDbProjectListElement( ) );
if ( 0 == pListElem.GetPointer() )
return FALSE;
if ( !pListElem->SetName(pwszName) )
return FALSE;
XPtr<CDbColumnNode> pColumn( new CDbColumnNode( propSpec, TRUE ) );
if ( 0 == pColumn.GetPointer() || !pColumn->IsValid() )
return FALSE;
if ( pListElem->SetColumn( pColumn.GetPointer() ) )
pColumn.Acquire();
else
return FALSE;
AppendChild( pListElem.GetPointer() );
pListElem.Acquire();
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Method: CDbProjectNode::_FindOrAddAnchor, private
//
// Synopsis: Return the project list anchor node. Add one if there
// isn't one.
//
// Returns: CDbProjectListAnchor* - pointer to the anchor node, or NULL
// if there was an allocation failure.
//
// History: 6-15-95 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
CDbProjectListAnchor * CDbProjectNode::_FindOrAddAnchor()
{
CDbCmdTreeNode * pChild = GetFirstChild();
while ( 0 != pChild )
{
if (pChild->IsListAnchor())
{
Win4Assert( DBOP_project_list_anchor == pChild->GetCommandType() );
return (CDbProjectListAnchor *)pChild;
}
pChild = pChild->GetNextSibling();
}
CDbProjectListAnchor * pAnchor = new CDbProjectListAnchor();
if ( 0 != pAnchor )
{
AppendChild( pAnchor );
}
return pAnchor;
}
//+---------------------------------------------------------------------------
//
// Method: CDbSortNode::_FindOrAddAnchor, private
//
// Synopsis: Return the sort list anchor node. Add one if there
// isn't one.
//
// Returns: CDbSortListAnchor* - pointer to the anchor node, or NULL
// if there was an allocation failure.
//
// History: 6-15-95 srikants Created
//
// Notes: We should probably implement this in a base class
// with the method taking the list anchor type.
//
//----------------------------------------------------------------------------
CDbSortListAnchor * CDbSortNode::_FindOrAddAnchor()
{
CDbCmdTreeNode * pChild = GetFirstChild();
while ( 0 != pChild )
{
if (pChild->IsListAnchor())
{
Win4Assert( DBOP_sort_list_anchor == pChild->GetCommandType() );
return (CDbSortListAnchor *)pChild;
}
pChild = pChild->GetNextSibling();
}
CDbSortListAnchor * pAnchor = new CDbSortListAnchor();
if ( 0 != pAnchor )
{
AppendChild( pAnchor );
}
return pAnchor;
}
//+---------------------------------------------------------------------------
//
// Method: CDbSortNode::AddSortColumn, public
//
// Synopsis: Add a sort column to the sort list.
//
// Returns: TRUE if successful, FALSE otherwise (allocation failure).
//
// History: 17 Aug 1995 AlanW Created
//
// Notes: Sort lists consist of a sort list anchor, with a chain
// of sort list elements as children. Each sort list element
// has information pertaining to the sort (direction and locale)
// and one child which is a column specification.
//
//----------------------------------------------------------------------------
BOOL CDbSortNode::AddSortColumn(DBID const & propSpec,
BOOL fDirection,
LCID locale)
{
CDbSortListAnchor * pAnchor = _FindOrAddAnchor();
XPtr<CDbColumnNode> pCol( new CDbColumnNode( propSpec, TRUE ) );
if ( 0 == pCol.GetPointer() || 0 == pAnchor || !pCol->IsValid() )
return FALSE;
CDbSortListElement * pSortInfo = new CDbSortListElement( fDirection,
locale );
if ( 0 != pSortInfo )
{
if ( pSortInfo->IsValid() )
{
pSortInfo->AddColumn( pCol.Acquire() );
if ( pAnchor->AppendListElement( pSortInfo ) )
return TRUE;
}
delete pSortInfo;
}
return FALSE;
} //AddSortColumn
//+---------------------------------------------------------------------------
//
// Method: CDbNestingNode::AddTable, public
//
// Synopsis: Add a table node to a nesting. Remove an existing
// table node if there is one there.
//
// Arguments: [pTable] - node to be added to tree. Ownership passes
// to the command tree.
//
// Returns: BOOL - TRUE if operation worked
//
// History: 08 Aug 1995 AlanW Created
//
// Notes: Nesting nodes are expected to have 0, 1, 4 or 5 child
// nodes depending upon whether AddTable and _FindGroupListAnchor
// have been called.
//
//----------------------------------------------------------------------------
BOOL CDbNestingNode::AddTable( CDbCmdTreeNode * pTable )
{
Win4Assert (! pTable->IsListAnchor());
CDbCmdTreeNode * pChild = GetFirstChild();
if ( 0 != pChild && ! pChild->IsListAnchor())
{
// Found a table??? Assert on this; we could be nice to the
// caller and replace it.
Win4Assert ( ! pChild->IsListAnchor() );
return FALSE;
}
InsertChild( pTable );
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Method: CDbNestingNode::_FindGroupListAnchor, private
//
// Synopsis: Return the group list anchor node. If there is none,
// add it and the parent list node, the child list node and
// the grouping column node.
//
// Returns: CDbProjectListAnchor* - pointer to the anchor node, or NULL
// if there was an allocation failure.
//
// History: 08 Aug 1995 AlanW Created
//
// Notes: Nesting nodes are expected to have 0, 1, 4 or 5 child
// nodes depending upon whether AddTable and _FindGroupListAnchor
// have been called.
//
//----------------------------------------------------------------------------
CDbProjectListAnchor * CDbNestingNode::_FindGroupListAnchor()
{
CDbCmdTreeNode * pChild = GetFirstChild();
if ( 0 != pChild )
{
if (! pChild->IsListAnchor())
{
pChild = pChild->GetNextSibling();
}
if ( 0 != pChild )
{
Win4Assert( DBOP_project_list_anchor == pChild->GetCommandType() );
return (CDbProjectListAnchor *)pChild;
}
}
XPtr<CDbProjectListAnchor> pGroupList = new CDbProjectListAnchor();
XPtr<CDbProjectListAnchor> pParentList = new CDbProjectListAnchor();
XPtr<CDbProjectListAnchor> pChildList = new CDbProjectListAnchor();
XPtr<CDbColumnNode> pGroupColumn = new CDbColumnNode(
//, PROPID_CHAPTER
);
if ( ! pGroupList.IsNull() &&
! pParentList.IsNull() &&
! pChildList.IsNull() &&
! pGroupColumn.IsNull() )
{
pGroupList->AppendSibling(pGroupColumn.Acquire());
pGroupList->InsertSibling(pChildList.Acquire());
pGroupList->InsertSibling(pParentList.Acquire());
AppendChild(pGroupList.GetPointer());
return pGroupList.Acquire();
}
return 0;
}