|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995-2000.
//
// File: DisQuery.cxx
//
// Contents: PIInternalQuery for distributed implementation.
//
// Classes: CDistributedQuery
//
// History: 05-Jun-95 KyleP Created
// 14-JAN-97 KrishnaN Undefined CI_INETSRV, related changes
//
// Notes:
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <coldesc.hxx>
#include <rstprop.hxx>
#include <pidmap.hxx>
#include <cmdprutl.hxx>
#include <proputl.hxx>
#include "disquery.hxx"
#include "seqser.hxx"
#include "seqsort.hxx"
#include "scrlsort.hxx"
//+-------------------------------------------------------------------------
//
// Function: EvalDistributedQuery, public
//
// Synopsis: Simulates bind to IInternalQuery for a ci object store
//
// Arguments: [ppQuery] -- Returns a PIInternalQuery
// [cScope] -- Count of [awcsScope]
// [pdwDepths] -- Array of scope depths
// [awcsScope] -- Array of scopes to query
// [awcsCat] -- Array of overrides for catalog location
// [fVirtualPaths] -- TRUE if [wcsScope] is a virtual scope
// instead of a physical scope.
//
// Returns: SCODE result
//
// History: 08-Feb-96 KyleP Added header
// 08-Feb-96 KyleP Add virtual path support
// 14-May-97 MohamedN hidden core and fs properties
//
// Notes: Scaffolding
//
//--------------------------------------------------------------------------
SCODE EvalDistributedQuery( PIInternalQuery ** ppQuery, CGetCmdProps & getCmdProps )
{ *ppQuery = 0; CDistributedQuery * pQuery = 0; SCODE sc = S_OK;
TRY { ULONG cChildren = getCmdProps.GetCardinality();
pQuery = new CDistributedQuery( cChildren );
for ( unsigned i = 0; i < cChildren ; i++ ) {
PIInternalQuery * pChild = 0; CDbProperties idbProps;
getCmdProps.PopulateDbProps( &idbProps, i );
SCODE s = EvalQuery(&pChild, idbProps );
if ( FAILED( s ) ) { vqDebugOut(( DEB_ERROR, "Error 0x%x getting PIInternalQuery for %ws\n", s, getCmdProps.GetCatalog(i) ));
THROW( CException( s ) ); }
pQuery->Add( pChild, i ); }
} CATCH( CException, e ) { if ( 0 != pQuery ) { pQuery->Release(); pQuery = 0; } sc = GetOleError( e ); } END_CATCH
*ppQuery = pQuery; return sc; }
//+-------------------------------------------------------------------------
//
// Member: CDistributedQuery::CDistributedQuery, public
//
// Synopsis: Constructor.
//
// Arguments: [cChild] -- Number of child scopes.
//
// History: 07-Jun-95 KyleP Created
//
//--------------------------------------------------------------------------
CDistributedQuery::CDistributedQuery( unsigned cChild ) : _aChild( cChild ), PIInternalQuery( 1 ) { RtlZeroMemory( _aChild.GetPointer(), cChild * sizeof(PIInternalQuery *) ); }
//+-------------------------------------------------------------------------
//
// Member: CDistributedQuery::~CDistributedQuery, public
//
// Synopsis: Destructor.
//
// History: 07-Jun-95 KyleP Created
//
//--------------------------------------------------------------------------
CDistributedQuery::~CDistributedQuery() { for ( unsigned i = 0; i < _aChild.Count(); i++ ) { if ( _aChild[i] ) { _aChild[i]->Release(); } } }
//+-------------------------------------------------------------------------
//
// Member: CDistributedQuery::QueryInterface, public
//
// Arguments: [ifid] -- Interface id
// [ppiuk] -- Interface return pointer
//
// Returns: Error. No rebind from this class is supported.
//
// History: 01-Oct-92 KyleP Created
//
//--------------------------------------------------------------------------
STDMETHODIMP CDistributedQuery::QueryInterface( REFIID ifid, void ** ppiuk ) { if ( ifid == IID_IUnknown ) { AddRef(); *ppiuk = (void *)((IUnknown *)this); return S_OK; } else { *ppiuk = 0; return E_NOINTERFACE; } }
//+-------------------------------------------------------------------------
//
// Member: CDistributedQuery::AddRef, public
//
// Synopsis: Reference the virtual table.
//
// History: 01-Oct-92 KyleP Created
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDistributedQuery::AddRef(void) { return InterlockedIncrement( (long *)&_ref ); }
//+-------------------------------------------------------------------------
//
// Member: CDistributedQuery::Release, public
//
// Synopsis: De-Reference the virtual table.
//
// Effects: If the ref count goes to 0 then the table is deleted.
//
// History: 01-Oct-92 KyleP Created
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDistributedQuery::Release(void) { long l = InterlockedDecrement( (long *)&_ref );
if ( l <= 0 ) { delete this; return 0; }
return l; }
//+-------------------------------------------------------------------------
//
// Member: CDistributedQuery::Execute, public
//
// Synopsis: Executes a query. Helper method for ICommand::Execute.
//
// Arguments: [pUnkOuter] -- Outer unknown
// [pRestriction] -- Query restriction
// [pidmap] -- pid mapper for output, sort, category columns
// [rColumns] -- Output columns in IRowset
// [rSort] -- Initial sort
// [Props] -- Rowset properties
// [rCateg] -- Categorization specification
// [cRowsets] -- # of rowsets
// [ppUnknowns] -- IUnknown pointers returned here
// [aAccessors] -- Bag of accessors which rowsets need to inherit
//
// Returns: Error code
//
// History: 07-Jun-95 KyleP Created
//
// Notes:
//
//--------------------------------------------------------------------------
void CDistributedQuery::Execute( IUnknown * pUnkOuter, RESTRICTION * pRestriction, CPidMapperWithNames & pidmap, CColumnSet & rColumns, CSortSet & rSort, XPtr<CMRowsetProps> & xProps, CCategorizationSet & rCateg, ULONG cRowsets, IUnknown ** ppUnknowns, CAccessorBag & aAccessors, IUnknown * pCreatorUnk ) { SCODE sc = S_OK;
unsigned iChild = 0; IRowset ** aRowset = 0;
TRY { if ( (xProps->GetPropertyFlags() & eLocatable) != 0 ) { //
// If no sort was specified for scrollable query, then add one
// based on workid.
//
if ( 0 == rSort.Count() ) { // This whole process could be streamlined if it was
// possible to query bindings *before* ExecQuery was
// called. Then we could potentially find an existing
// column suitable for sorting.
//
// Setup sort.
//
GUID guidQuery = DBQUERYGUID; CFullPropSpec propWorkId( guidQuery, DISPID_QUERY_WORKID ); SSortKey SortKey( pidmap.NameToPid(propWorkId), QUERY_SORTASCEND );
rSort.Add( SortKey, 0 ); } }
//
// Since we need to bind to sort columns in order to compare rows, all
// sort columns must be in the binding set.
// At the same time, create a CSort from the CSortSet for use by the
// rowset implementation class.
//
unsigned cOriginalColumns = rColumns.Count(); CSort SortDup;
if ( 0 != rSort.Count() ) { for ( unsigned i = 0; i < rSort.Count(); i++ ) { PROPID prop = rSort.Get( i ).pidColumn;
CSortKey sk( *pidmap.PidToName(prop), rSort.Get(i).dwOrder, rSort.Get(i).locale ); SortDup.Add(sk, i);
for ( unsigned j = 0; j < rColumns.Count(); j++ ) { if ( rColumns.Get(j) == prop ) break; }
if ( j == rColumns.Count() ) { rColumns.Add( prop, j ); } } }
//
// This array is passed to distributed rowset.
//
Win4Assert(1 == cRowsets ); // allocs below only account for 1 cRowset
XArray<IUnknown *> xUnknowns( _aChild.Count() ); aRowset = new IRowset * [_aChild.Count()]; //
// Create the children.
//
CAccessorBag aEmpty(this);
for ( iChild = 0; iChild < _aChild.Count(); iChild++ ) { //
// If we're going non-sequential, go all the way.
//
XPtr<CMRowsetProps> xPropsTemp( new CMRowsetProps( xProps.GetReference() ) ); if ( (xPropsTemp->GetPropertyFlags() & eLocatable) != 0 ) xPropsTemp->SetImpliedProperties( IID_IRowsetScroll, cRowsets );
// For distributed rowsets, always set holdrows to true
xPropsTemp->SetPropertyFlags( eHoldRows );
_aChild[iChild]->Execute( 0, // children are private and aren't aggregated
pRestriction, pidmap, rColumns, rSort, xPropsTemp, rCateg, cRowsets, &xUnknowns[iChild], aEmpty, // these guys don't really need aAccessors
pCreatorUnk );
if ( FAILED(sc) ) { vqDebugOut(( DEB_ERROR, "CDistributedQuery: Error 0x%x calling Execute for child %u\n", sc, iChild )); THROW( CException(sc) ); }
// get IRowset pointer
xUnknowns[iChild]->QueryInterface(IID_IRowset, (void **) &aRowset[iChild]); xUnknowns[iChild]->Release(); // release extra ref
}
//
// First case: sequential cursors
//
IUnknown * pIUnkInner = 0; XInterface<IUnknown> xIUnkInner(pIUnkInner); IRowset * pTemp; if ( 0 == (xProps->GetPropertyFlags() & eLocatable) ) { if ( 0 != rSort.Count() ) { pTemp = (IRowset *) new CSequentialSorted( pUnkOuter, (IUnknown **)xIUnkInner.GetQIPointer(), aRowset, _aChild.Count(), xProps.GetReference(), cOriginalColumns, SortDup, aAccessors ); } else { pTemp = (IRowset *) new CSequentialSerial( pUnkOuter, (IUnknown **)xIUnkInner.GetQIPointer(), aRowset, _aChild.Count(), xProps.GetReference(), cOriginalColumns, aAccessors ); } }
//
// Other case: Scrollable
//
else { Win4Assert( 0 != rSort.Count() );
pTemp = (IRowset *) new CScrollableSorted( pUnkOuter, (IUnknown **)xIUnkInner.GetQIPointer(), (IRowsetScroll **)aRowset, _aChild.Count(), xProps.GetReference(), cOriginalColumns, SortDup, aAccessors ); } *ppUnknowns = xIUnkInner.Acquire(); Win4Assert(*ppUnknowns);
} CATCH( CException, e ) { sc = e.GetErrorCode(); for ( ; iChild > 0; iChild-- ) aRowset[iChild-1]->Release(); delete [] aRowset;
RETHROW( ); } END_CATCH }
|