325 lines
9.8 KiB
C++
325 lines
9.8 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 2000.
|
|
//
|
|
// File: SvcQuery.cxx
|
|
//
|
|
// Contents: IInternalQuery interface for cisvc
|
|
//
|
|
// History: 13-Sep-96 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <restrict.hxx>
|
|
#include <rowset.hxx>
|
|
#include <query.hxx>
|
|
#include <pidmap.hxx>
|
|
#include <coldesc.hxx>
|
|
#include <lang.hxx>
|
|
#include <rstprop.hxx>
|
|
#include <proprst.hxx>
|
|
|
|
#include "svcquery.hxx"
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CSvcQuery::QueryInterface, public
|
|
//
|
|
// Arguments: [ifid] -- Interface id
|
|
// [ppiuk] -- Interface return pointer
|
|
//
|
|
// Returns: Error. No rebind from this class is supported.
|
|
//
|
|
// History: 13-Sep-96 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSvcQuery::QueryInterface(
|
|
REFIID ifid,
|
|
void ** ppiuk )
|
|
{
|
|
if ( IID_IUnknown == ifid )
|
|
{
|
|
AddRef();
|
|
*ppiuk = (void *)((IUnknown *)this);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
*ppiuk = 0;
|
|
return E_NOINTERFACE;
|
|
}
|
|
} //QueryInterface
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CSvcQuery::AddRef, public
|
|
//
|
|
// Synopsis: Reference the virtual table.
|
|
//
|
|
// History: 13-Sep-96 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSvcQuery::AddRef()
|
|
{
|
|
return InterlockedIncrement( (long *) &_ref );
|
|
} //AddRef
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CSvcQuery::Release, public
|
|
//
|
|
// Synopsis: De-Reference the virtual table.
|
|
//
|
|
// Effects: If the ref count goes to 0 then the table is deleted.
|
|
//
|
|
// History: 13-Sep-96 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSvcQuery::Release()
|
|
{
|
|
long l = InterlockedDecrement( (long *) &_ref );
|
|
|
|
if ( l <= 0 )
|
|
{
|
|
// delete self
|
|
|
|
vqDebugOut(( DEB_ITRACE,
|
|
"Svc IInternalQuery unreferenced. Deleting.\n" ));
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return l;
|
|
} //Release
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CCursorArray
|
|
//
|
|
// Synopsis: Smart container of query cursors
|
|
//
|
|
// History: 16-Feb-97 dlee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CCursorArray
|
|
{
|
|
public:
|
|
CCursorArray( ULONG * pCursors,
|
|
ULONG cCursors,
|
|
CSvcQueryProxy & Query ) :
|
|
_pCursors( pCursors ),
|
|
_cCursors( cCursors ),
|
|
_Query( Query )
|
|
{
|
|
}
|
|
|
|
void Acquire( ULONG iElement )
|
|
{
|
|
_pCursors[ iElement ] = 0;
|
|
}
|
|
|
|
~CCursorArray()
|
|
{
|
|
// FreeCursor can fail if the pipe is stale, in which
|
|
// case don't bother with freeing the rest of the cursors.
|
|
|
|
TRY
|
|
{
|
|
for ( ULONG x = 0; x < _cCursors; x++ )
|
|
{
|
|
if ( 0 != _pCursors[ x ] )
|
|
_Query.FreeCursor( _pCursors[ x ] );
|
|
}
|
|
}
|
|
CATCH( CException, e )
|
|
{
|
|
}
|
|
END_CATCH
|
|
}
|
|
|
|
private:
|
|
ULONG * _pCursors;
|
|
ULONG _cCursors;
|
|
CSvcQueryProxy & _Query;
|
|
};
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CSvcQuery::Execute, public
|
|
//
|
|
// Synopsis: Executes a query. Helper 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
|
|
// [xProps] -- Rowset properties (query flags)
|
|
// [rCateg] -- Categorization specification
|
|
// [cRowsets] -- # of rowsets
|
|
// [ppUnknowns] -- IUnknowns returned here
|
|
// [aAccessors] -- Bag of accessors which rowsets need to inherit
|
|
//
|
|
// Returns: Throws on error
|
|
//
|
|
// History: 26 Nov 1995 AlanW Created
|
|
// 13-Sep-96 dlee Make it support cisvc
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CSvcQuery::Execute( IUnknown * pUnkOuter,
|
|
RESTRICTION * pRestriction,
|
|
CPidMapperWithNames & pidmap,
|
|
CColumnSet & rColumns,
|
|
CSortSet & rSort,
|
|
XPtr<CMRowsetProps> & xProps,
|
|
CCategorizationSet & rCateg,
|
|
ULONG cRowsets,
|
|
IUnknown ** ppUnknowns,
|
|
CAccessorBag & aAccessors,
|
|
IUnknown * pUnkCreator )
|
|
{
|
|
if (0 == ppUnknowns)
|
|
THROW(CException( E_INVALIDARG));
|
|
|
|
if ( cRowsets != 1 + (rCateg.Count() ? rCateg.Count() : 0) )
|
|
THROW( CException( E_INVALIDARG ));
|
|
|
|
if (_QueryUnknown.IsQueryActive())
|
|
{
|
|
vqDebugOut(( DEB_ERROR,
|
|
"CSvcQuery: Query already active.\n" ));
|
|
|
|
// NTRAID#DB-NTBUG9-84330-2000/07/31-dlee OLE-DB spec variance in Indexing Service when reexecuting queries
|
|
|
|
// spec variance: only if query changed
|
|
|
|
THROW( CException( DB_E_OBJECTOPEN ));
|
|
}
|
|
|
|
// Construct table
|
|
*ppUnknowns = 0; // in case of error or exception
|
|
|
|
XArray<ULONG> aCursors( cRowsets );
|
|
|
|
// Construct a CRowsetProperties
|
|
CRowsetProperties Prop;
|
|
Prop.SetDefaults( xProps->GetPropertyFlags(),
|
|
xProps->GetMaxOpenRows(),
|
|
xProps->GetMemoryUsage(),
|
|
xProps->GetMaxResults(),
|
|
xProps->GetCommandTimeout(),
|
|
xProps->GetFirstRows() );
|
|
|
|
XInterface<CSvcQueryProxy> xQuery(new
|
|
CSvcQueryProxy( _client,
|
|
rColumns,
|
|
(CRestriction&) (*pRestriction),
|
|
rSort.Count() ? &rSort : 0,
|
|
rCateg.Count() ? &rCateg : 0,
|
|
Prop,
|
|
pidmap,
|
|
cRowsets,
|
|
aCursors.GetPointer()
|
|
));
|
|
|
|
// Make rowsets for each level in the hierarchy (usually 1).
|
|
// Rowset 0 is the top of the hierarchy.
|
|
|
|
CCursorArray cursorArray( aCursors.GetPointer(),
|
|
cRowsets,
|
|
xQuery.GetReference() );
|
|
|
|
_QueryUnknown.ReInit();
|
|
CRowsetArray apRowsets( cRowsets );
|
|
XArray<IUnknown *> xapUnknown( cRowsets );
|
|
|
|
CMRowsetProps & OrigProps = xProps.GetReference();
|
|
|
|
for ( unsigned r = 0; r < cRowsets; r++ )
|
|
{
|
|
// First rowset is not chaptered, even if others are.
|
|
|
|
XPtr<CMRowsetProps> xTmp;
|
|
|
|
if ( 0 != r )
|
|
{
|
|
xTmp.Set( new CMRowsetProps( OrigProps ) );
|
|
xTmp->SetChaptered( TRUE );
|
|
}
|
|
|
|
if ( 1 != cRowsets && 0 == r )
|
|
xProps->SetChaptered( FALSE );
|
|
|
|
apRowsets[r] = new CRowset( pUnkOuter,
|
|
&xapUnknown[r],
|
|
(r == (cRowsets - 1)) ?
|
|
rColumns :
|
|
rCateg.Get(r)->GetColumnSet(),
|
|
pidmap,
|
|
xQuery.GetReference(),
|
|
(IUnknown &) _QueryUnknown,
|
|
0 != r,
|
|
( 0 == r ) ? xProps : xTmp,
|
|
aCursors[r],
|
|
aAccessors,
|
|
pUnkCreator );
|
|
|
|
// the cursor is acquired
|
|
|
|
cursorArray.Acquire( r );
|
|
}
|
|
|
|
for (r = 0; r < cRowsets; r++)
|
|
{
|
|
if (r < cRowsets-1)
|
|
apRowsets[r]->SetRelatedRowset( apRowsets[r+1] );
|
|
|
|
ppUnknowns[r] = xapUnknown[r];
|
|
}
|
|
|
|
// xQuery goes out of scope, which does a Release() on it.
|
|
// Each rowset above has done an AddRef() on it and they own it.
|
|
|
|
// ReInit can't fail
|
|
|
|
_QueryUnknown.ReInit( cRowsets, apRowsets.Acquire() );
|
|
} //Execute
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CSvcQuery::CSvcQuery, public
|
|
//
|
|
// Synopsis: saves the query scope, machine, and catalog
|
|
//
|
|
// Arguments: [cScopes] - # of entries in the scope arrays
|
|
// [aDepths] - array of scope depths
|
|
// [aScopes] - array of paths to roots of scopes
|
|
// [pwcCatalog] - catalog override name or path
|
|
// [pwcMachine] - Machine name for catalog
|
|
//
|
|
// History: 13-Sep-96 dlee Updated from FAT for svc
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CSvcQuery::CSvcQuery(
|
|
WCHAR const * pwcMachine,
|
|
IDBProperties * pDbProperties ) :
|
|
#pragma warning(disable : 4355) // 'this' in a constructor
|
|
_QueryUnknown( * ((IUnknown *) this) ),
|
|
#pragma warning(default : 4355) // 'this' in a constructor
|
|
PIInternalQuery( 0 ),
|
|
_client( pwcMachine, pDbProperties )
|
|
{
|
|
AddRef();
|
|
} //CSvcQuery
|
|
|