Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

609 lines
17 KiB

  1. //--------------------------------------------------------------------
  2. // Microsoft OLE DB Parser object
  3. // (C) Copyright Microsoft Corporation, 1997 - 1999.
  4. //
  5. // @doc
  6. //
  7. // @module IParserSession.CPP | IParserSession object implementation
  8. //
  9. //
  10. #pragma hdrstop
  11. #include "msidxtr.h"
  12. #include <ciexcpt.hxx>
  13. // CViewData::CViewData ------------------------------------
  14. //
  15. // @mfunc Constructor
  16. //
  17. CViewData::CViewData() :
  18. m_pwszViewName( 0 ),
  19. m_pwszCatalogName( 0 ),
  20. m_pctProjectList( 0 ),
  21. m_pCScopeData( 0 )
  22. {
  23. }
  24. // CViewData::CViewData ------------------------------------
  25. //
  26. // @mfunc Destructor
  27. //
  28. CViewData::~CViewData()
  29. {
  30. delete [] m_pwszViewName;
  31. delete [] m_pwszCatalogName;
  32. DeleteDBQT(m_pctProjectList);
  33. if ( 0 != m_pCScopeData )
  34. m_pCScopeData->Release();
  35. }
  36. // CViewList::CViewList ------------------------------------
  37. //
  38. // @mfunc Constructor
  39. //
  40. CViewList::CViewList() :
  41. m_pViewData( 0 )
  42. {
  43. }
  44. // CViewList::~CViewList -----------------------------------
  45. //
  46. // @mfunc Destructor
  47. //
  48. CViewList::~CViewList()
  49. {
  50. CViewData* pViewData = m_pViewData;
  51. CViewData* pNextViewData = NULL;
  52. while( NULL != pViewData )
  53. {
  54. pNextViewData = pViewData->m_pNextView;
  55. delete pViewData;
  56. pViewData = pNextViewData;
  57. }
  58. }
  59. // CImpIParserSession::CImpIParserSession ------------------------------------
  60. //
  61. // @mfunc Constructor
  62. //
  63. CImpIParserSession::CImpIParserSession(
  64. const GUID* pGuidDialect, // in | dialect for this session
  65. IParserVerify* pIPVerify, // in |
  66. IColumnMapperCreator* pIColMapCreator, // in |
  67. CViewList* pGlobalViewList ) : // in |
  68. m_pLocalViewList( 0 )
  69. {
  70. assert( pGuidDialect && pIPVerify && pIColMapCreator );
  71. m_cRef = 1;
  72. m_lcid = LOCALE_SYSTEM_DEFAULT;
  73. m_dwRankingMethod = VECTOR_RANK_JACCARD;
  74. m_pwszCatalog = NULL;
  75. m_pwszMachine = NULL;
  76. m_pGlobalViewList = pGlobalViewList;
  77. m_globalDefinitions = FALSE;
  78. m_pColumnMapper = NULL;
  79. m_pCPropertyList = NULL;
  80. InitializeCriticalSection( &m_csSession );
  81. m_pIPVerify = pIPVerify;
  82. m_pIPVerify->AddRef();
  83. m_pIColMapCreator = pIColMapCreator;
  84. m_pIColMapCreator->AddRef();
  85. m_GuidDialect = *pGuidDialect;
  86. if ( DBGUID_MSSQLTEXT == m_GuidDialect )
  87. m_dwSQLDialect = DBDIALECT_MSSQLTEXT;
  88. else if ( DBGUID_MSSQLJAWS == m_GuidDialect )
  89. m_dwSQLDialect = DBDIALECT_MSSQLJAWS;
  90. else
  91. assert( DBGUID_MSSQLTEXT == m_GuidDialect || DBGUID_MSSQLJAWS == m_GuidDialect );
  92. }
  93. // CImpIParserSession::~CImpIParserSession -----------------------------------
  94. //
  95. // @mfunc Destructor
  96. //
  97. CImpIParserSession::~CImpIParserSession()
  98. {
  99. if( 0 != m_pIPVerify )
  100. m_pIPVerify->Release();
  101. if( 0 != m_pIColMapCreator )
  102. m_pIColMapCreator->Release();
  103. delete [] m_pwszCatalog;
  104. delete [] m_pwszMachine;
  105. delete m_pCPropertyList;
  106. delete m_pLocalViewList;
  107. DeleteCriticalSection( &m_csSession );
  108. }
  109. //-----------------------------------------------------------------------------
  110. // @mfunc FInit
  111. //
  112. // Initialize member vars that could potentially fail.
  113. //
  114. //-----------------------------------------------------------------------------
  115. HRESULT CImpIParserSession::FInit(
  116. LPCWSTR pwszMachine, // in | provider's current machine
  117. CPropertyList** ppGlobalPropertyList ) // in | caller's property list
  118. {
  119. assert( 0 == m_pCPropertyList );
  120. assert( 0 != pwszMachine && 0 == m_pwszMachine );
  121. SCODE sc = S_OK;
  122. TRY
  123. {
  124. XPtrST<WCHAR> xMachine( CopyString(pwszMachine) );
  125. XPtr<CPropertyList> xpPropertyList( new CPropertyList(ppGlobalPropertyList) );
  126. XPtr<CViewList> xpLocalViewList( new CViewList() );
  127. Win4Assert( 0 == m_pCPropertyList );
  128. m_pCPropertyList = xpPropertyList.Acquire();
  129. Win4Assert( 0 == m_pLocalViewList );
  130. m_pLocalViewList = xpLocalViewList.Acquire();
  131. m_pwszMachine = xMachine.Acquire();
  132. }
  133. CATCH( CException, e )
  134. {
  135. sc = e.GetErrorCode();
  136. }
  137. END_CATCH
  138. return sc;
  139. }
  140. // CImpIParserSession::QueryInterface ----------------------------------
  141. //
  142. // @mfunc Returns a pointer to a specified interface. Callers use
  143. // QueryInterface to determine which interfaces the called object
  144. // supports.
  145. //
  146. // @rdesc HResult indicating the status of the method
  147. // @flag S_OK | Interface is supported and ppvObject is set.
  148. // @flag E_NOINTERFACE | Interface is not supported by the object
  149. // @flag E_INVALIDARG | One or more arguments are invalid.
  150. //
  151. STDMETHODIMP CImpIParserSession::QueryInterface(
  152. REFIID riid, //@parm IN | Interface ID of the interface being queried for.
  153. LPVOID * ppv ) //@parm OUT | Pointer to interface that was instantiated
  154. {
  155. if( 0 == ppv )
  156. return ResultFromScode(E_INVALIDARG);
  157. if( (riid == IID_IUnknown) ||
  158. (riid == IID_IParserSession) )
  159. *ppv = (LPVOID)this;
  160. else
  161. *ppv = 0;
  162. // If we're going to return an interface, AddRef it first
  163. if( 0 != *ppv )
  164. {
  165. ((LPUNKNOWN)*ppv)->AddRef();
  166. return NOERROR;
  167. }
  168. return ResultFromScode(E_NOINTERFACE);
  169. }
  170. // CImpIParserSession::AddRef ------------------------------------------
  171. //
  172. // @mfunc Increments a persistence count for the object
  173. //
  174. // @rdesc Current reference count
  175. //
  176. STDMETHODIMP_(ULONG) CImpIParserSession::AddRef (void)
  177. {
  178. return InterlockedIncrement( (long*) &m_cRef);
  179. }
  180. // CImpIParserSession::Release -----------------------------------------
  181. //
  182. // @mfunc Decrements a persistence count for the object and if
  183. // persistence count is 0, the object destroys itself.
  184. //
  185. // @rdesc Current reference count
  186. //
  187. STDMETHODIMP_(ULONG) CImpIParserSession::Release (void)
  188. {
  189. assert( m_cRef > 0 );
  190. ULONG cRef = InterlockedDecrement( (long *) &m_cRef );
  191. if( 0 == cRef )
  192. {
  193. delete this;
  194. return 0;
  195. }
  196. return cRef;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // @func CImpIParserSession::ToTree
  200. //
  201. // Transform a given text command to a valid command tree
  202. //
  203. // @rdesc HRESULT
  204. // S_OK - Text was translated into DBCOMMANDTREE
  205. // DB_S_NORESULTS - CREATE VIEW or SET PROPERTY or batched set of
  206. // these parsed successfully. NOTE: *ppTree and
  207. // *ppPTProperties will be null.
  208. // E_OUTOFMEMORY - low on resources
  209. // E_FAIL - unexpected error
  210. // E_INVALIDARG - pcwszText, ppCommandTree, or ppPTProperties
  211. // was a NULL pointer.
  212. //-----------------------------------------------------------------------------
  213. STDMETHODIMP CImpIParserSession::ToTree(
  214. LCID lcid,
  215. LPCWSTR pcwszText,
  216. DBCOMMANDTREE** ppCommandTree,
  217. IParserTreeProperties** ppPTProperties )
  218. {
  219. HRESULT hr = S_OK;
  220. IColumnMapper* pIColumnMapper = NULL;
  221. assert(pcwszText && ppCommandTree && ppPTProperties);
  222. if ( 0 == pcwszText || 0 == ppCommandTree || 0 == ppPTProperties )
  223. hr = ResultFromScode(E_INVALIDARG);
  224. else
  225. {
  226. *ppCommandTree = 0;
  227. *ppPTProperties = 0;
  228. CAutoBlock cab( &m_csSession );
  229. // Clear some member variables for this pass through the parser
  230. SetLCID( lcid );
  231. SetGlobalDefinition( FALSE );
  232. // Attempt to get the interface for accessing the built-in properties
  233. // This is done on each call to the parser in case different commands
  234. // use a different catalog, which is part of the
  235. // GetColumnMapper parameter list.
  236. if( SUCCEEDED(hr = m_pIColMapCreator->GetColumnMapper(LOCAL_MACHINE,
  237. GetDefaultCatalog(),
  238. &pIColumnMapper)) )
  239. {
  240. SetColumnMapperPtr(pIColumnMapper);
  241. }
  242. else
  243. {
  244. goto ParseErr;
  245. }
  246. try
  247. {
  248. XInterface<CImpIParserTreeProperties> xpPTProps;
  249. xpPTProps.Set( new CImpIParserTreeProperties() );
  250. hr = xpPTProps->FInit(GetDefaultCatalog(), GetDefaultMachine());
  251. if (FAILED(hr) )
  252. THROW( CException(hr) );
  253. MSSQLLexer Lexer;
  254. MSSQLParser Parser(this, xpPTProps.GetPointer(), Lexer);
  255. // callee needs this to post parser errors when Parse() fails
  256. *ppPTProperties = xpPTProps.Acquire();
  257. Parser.yyprimebuffer( (LPWSTR)pcwszText );
  258. Parser.ResetParser();
  259. #ifdef DEBUG
  260. Parser.yydebug = getenv("YYDEBUG") ? 1 : 0;
  261. #endif
  262. // Actually parse the text producing a tree
  263. hr = Parser.Parse();
  264. if ( FAILED(hr) )
  265. goto ParseErr;
  266. // return the DBCOMMANDTREE
  267. *ppCommandTree = Parser.GetParseTree();
  268. #ifdef DEBUG
  269. if (getenv("PRINTTREE"))
  270. {
  271. if ( *ppCommandTree )
  272. {
  273. cout << "OLE DB Command Tree" << endl;
  274. cout << pcwszText << endl << **ppCommandTree << endl << endl;
  275. // Retrieve CiRestriction
  276. VARIANT vVal;
  277. VariantInit(&vVal);
  278. if( SUCCEEDED((*ppPTProperties)->GetProperties(PTPROPS_CIRESTRICTION, &vVal)) )
  279. if( V_BSTR(&vVal) )
  280. cout << "CiRestriction: " << (LPWSTR)V_BSTR(&vVal) << endl;
  281. VariantClear(&vVal);
  282. }
  283. }
  284. #endif
  285. if ( 0 == *ppCommandTree )
  286. {
  287. hr = ResultFromScode(DB_S_NORESULT);
  288. // Spec states that this should be NULL when DB_S_NORESULTs is returned.
  289. (*ppPTProperties)->Release();
  290. *ppPTProperties = 0;
  291. goto ParseErr;
  292. }
  293. }
  294. catch( CException e )
  295. {
  296. #ifdef DEBUG
  297. if (getenv("PRINTTREE"))
  298. cout << "At catch(...)!!!!!!!!!!!!!" << endl;
  299. #endif
  300. hr = e.GetErrorCode();
  301. }
  302. catch(...)
  303. {
  304. hr = E_FAIL;
  305. }
  306. ParseErr:
  307. pIColumnMapper = GetColumnMapperPtr();
  308. if ( 0 != pIColumnMapper )
  309. {
  310. pIColumnMapper->Release();
  311. pIColumnMapper = NULL;
  312. SetColumnMapperPtr(NULL);
  313. }
  314. }
  315. return hr;
  316. }
  317. //-----------------------------------------------------------------------------
  318. // @func CImpIParserSession::FreeTree
  319. //
  320. // Free memory associated with a given command tree.
  321. //
  322. // @rdesc HRESULT
  323. // S_OK - command tree released
  324. // E_FAIL - tree could not be freed
  325. // E_INVALIDARG - ppTree was a NULL pointer
  326. //-----------------------------------------------------------------------------
  327. STDMETHODIMP CImpIParserSession::FreeTree(
  328. DBCOMMANDTREE** ppTree )
  329. {
  330. SCODE sc = S_OK;
  331. if ( 0 == ppTree )
  332. sc = E_INVALIDARG;
  333. else
  334. {
  335. if ( 0 != *ppTree )
  336. DeleteDBQT( *ppTree ); // todo: put error returns on DeleteDBQT
  337. *ppTree = 0;
  338. }
  339. return sc;
  340. }
  341. //-----------------------------------------------------------------------------
  342. // @func CImpIParserSession::SetCatalog
  343. //
  344. // Establish the current catalog for this parser session.
  345. //
  346. // @rdesc HRESULT
  347. // S_OK - method successful
  348. // E_OUTOFMEMORY - low on resources
  349. // E_FAIL - unexpected error
  350. // E_INVALIDARG - pcwszCatalog was a NULL pointer (DEBUG ONLY)
  351. //-----------------------------------------------------------------------------
  352. STDMETHODIMP CImpIParserSession::SetCatalog(
  353. LPCWSTR pcwszCatalog )
  354. {
  355. SCODE sc = S_OK;
  356. if ( 0 == pcwszCatalog )
  357. return E_INVALIDARG;
  358. TRY
  359. {
  360. XPtrST<WCHAR> xCatalog( CopyString(pcwszCatalog) );
  361. delete [] m_pwszCatalog;
  362. m_pwszCatalog = xCatalog.Acquire();
  363. }
  364. CATCH( CException, e )
  365. {
  366. sc = e.GetErrorCode();
  367. }
  368. END_CATCH
  369. return sc;
  370. }
  371. //--------------------------------------------------------------------
  372. // @func Locate a view, if defined, in the view list
  373. //
  374. // @rdesc HRESULT
  375. //
  376. CViewData* CViewList::FindViewDefinition(
  377. LPWSTR pwszViewName, // @parm IN | name of view being defined
  378. LPWSTR pwszCatalogName ) // @parm IN | name of catalog view is to be defined in
  379. {
  380. CViewData* pViewData = m_pViewData;
  381. while (NULL != pViewData)
  382. {
  383. if ( 0 == _wcsicmp(pViewData->m_pwszViewName, pwszViewName) )
  384. {
  385. // pwszCatalogName will be null for built-in views which match all catalogs
  386. if ( 0 == pViewData->m_pwszCatalogName )
  387. break;
  388. if ( 0 == _wcsicmp(pViewData->m_pwszCatalogName, pwszCatalogName) )
  389. break;
  390. }
  391. pViewData = pViewData->m_pNextView;
  392. }
  393. return pViewData;
  394. }
  395. //--------------------------------------------------------------------
  396. // @func Stores the information from a temporary view
  397. //
  398. // @rdesc S_OK | Valid
  399. // E_INVALIDARG | Attempt to redefine a view in the specified catalog
  400. // E_OUTOFMEMORY | Error result from HrQeTreeCopy or CopyScopeDataToView
  401. //
  402. HRESULT CViewList::SetViewDefinition(
  403. CImpIParserSession* pIParsSess, // @parm IN | IParserSession interface
  404. CImpIParserTreeProperties* pIPTProps, // @parm IN | IParserTreeProperties interface
  405. LPWSTR pwszViewName, // @parm IN | name of view being defined
  406. LPWSTR pwszCatalogName,// @parm IN | name of catalog view is to be defined in
  407. DBCOMMANDTREE* pctProjectList )// @parm IN | project list for the selected columns
  408. {
  409. SCODE sc = S_OK;
  410. {
  411. CViewData* pViewData = FindViewDefinition( pwszViewName, pwszCatalogName );
  412. if( 0 != pViewData ) // this view already defined
  413. return E_INVALIDARG;
  414. }
  415. TRY
  416. {
  417. XPtr<CViewData> xpViewData( new CViewData() );
  418. xpViewData->m_pwszViewName = CopyString( pwszViewName );
  419. if ( 0 != pwszCatalogName )
  420. xpViewData->m_pwszCatalogName = CopyString( pwszCatalogName );
  421. sc = HrQeTreeCopy( &(xpViewData->m_pctProjectList),
  422. pctProjectList );
  423. if ( SUCCEEDED(sc) )
  424. {
  425. //Save pointer to ScopeData object and up the refcount for our use.
  426. xpViewData->m_pCScopeData = pIPTProps->GetScopeDataPtr();
  427. xpViewData->m_pCScopeData->AddRef();
  428. sc = pIPTProps->CreateNewScopeDataObject( pIParsSess->GetDefaultMachine() );
  429. if( SUCCEEDED(sc) )
  430. {
  431. //@DEVNOTE: Anything added before the next two lines should
  432. // go through the error_exit routine. WHY? Because we haven't
  433. // added this node to our linked list until the next 2 lines.
  434. xpViewData->m_pNextView = m_pViewData;
  435. m_pViewData = xpViewData.Acquire();
  436. }
  437. }
  438. }
  439. CATCH( CException, e )
  440. {
  441. sc = e.GetErrorCode();
  442. }
  443. END_CATCH
  444. return sc;
  445. }
  446. //--------------------------------------------------------------------
  447. // @func Deletes the information for a temporary view.
  448. //
  449. // @rdesc HRESULT
  450. //
  451. HRESULT CViewList::DropViewDefinition(
  452. LPWSTR pwszViewName, // @parm IN | name of view being defined
  453. LPWSTR pwszCatalogName ) // @parm IN | name of catalog view is defined in
  454. {
  455. CViewData* pViewData = m_pViewData;
  456. CViewData* pPrevViewData = NULL;
  457. while (NULL != pViewData)
  458. {
  459. if ( 0 == _wcsicmp(pViewData->m_pwszViewName, pwszViewName) )
  460. {
  461. // pwszCatalogName will be null for built-in views which match all catalogs
  462. if ( 0 == pViewData->m_pwszCatalogName )
  463. break;
  464. if ( 0 == _wcsicmp(pViewData->m_pwszCatalogName, pwszCatalogName) )
  465. break;
  466. }
  467. pPrevViewData = pViewData;
  468. pViewData = pViewData->m_pNextView;
  469. }
  470. if ( 0 == pViewData )
  471. return E_FAIL;
  472. // unlink the view
  473. if ( 0 != pPrevViewData )
  474. pPrevViewData->m_pNextView = pViewData->m_pNextView;
  475. else
  476. m_pViewData = pViewData->m_pNextView;
  477. delete pViewData;
  478. return S_OK;
  479. }
  480. //--------------------------------------------------------------------
  481. // @func Retrieves the information from a temporary view.
  482. // This returns a DBCOMMANDTREE for use as a project list
  483. // in the query specification. The scope information is
  484. // stored in the compiler envirnment scope data.
  485. //
  486. // @rdesc DBCOMMANDTREE*
  487. // NULL | view not defined
  488. // DBOP_catalog_name | verify catalog failed
  489. // DBOP_project_list_anchor| success
  490. //
  491. DBCOMMANDTREE* CViewList::GetViewDefinition(
  492. CImpIParserTreeProperties* pIPTProps,
  493. LPWSTR pwszViewName, // @parm IN | name of view being defined
  494. LPWSTR pwszCatalogName ) // @parm IN | name of catalog view is defined in
  495. {
  496. DBCOMMANDTREE* pct = 0;
  497. CViewData* pViewData = FindViewDefinition( pwszViewName, pwszCatalogName );
  498. if( 0 != pViewData )
  499. {
  500. // Take the pointer to the scope data stored in the view definition and
  501. // AddRef the object so we have ownership rights in our current PTProps.
  502. pIPTProps->ReplaceScopeDataPtr( pViewData->m_pCScopeData );
  503. SCODE sc = HrQeTreeCopy( &pct, pViewData->m_pctProjectList );
  504. if ( FAILED(sc) )
  505. pct = 0;
  506. }
  507. return pct;
  508. }