CalendarDataProviderSQL.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:16k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // CalendarDataProviderSQL.cpp: implementation of the CCalendarDataProviderSQL class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "SQLServerDataProvider.h"
  6. #include "CalendarDataProviderSQL.h"
  7. #include "SQLDataHelper.h"
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. //////////////////////////////////////////////////////////////////////
  14. extern void TRACE_ComError(_com_error &e);
  15. extern void TRACE_ProviderError(XTPADODB::_Connection* pConnDB);
  16. #define DBGDATA_ASSERT ASSERT
  17. #ifndef DBGDATA_ASSERT
  18. #define DBGDATA_ASSERT
  19. #endif
  20. //////////////////////////////////////////////////////////////////////
  21. // Construction/Destruction
  22. //////////////////////////////////////////////////////////////////////
  23. CCalendarDataProviderSQL::CCalendarDataProviderSQL()
  24. {
  25. }
  26. CCalendarDataProviderSQL::~CCalendarDataProviderSQL()
  27. {
  28. }
  29. BOOL CCalendarDataProviderSQL::Open()
  30. {
  31. if (GetConnectionString().IsEmpty())
  32. return FALSE;
  33. if (IsOpen())
  34. {
  35. TRACE(_T("Provider is alredy opened. CCalendarDataProviderSQL::Open(ConnectionString='%s') n"), (LPCTSTR)GetConnectionString());
  36. return TRUE;
  37. }
  38. try
  39. {
  40. HRESULT hr = m_ptrDBconn.CreateInstance(__uuidof(XTPADODB::Connection));
  41. ASSERT(SUCCEEDED(hr));
  42. if (FAILED(hr) || m_ptrDBconn == NULL)
  43. {
  44. TRACE(_T("ERROR: Cannot create XTPADODB::Connection. (HRESULT = %08lx) n"), hr);
  45. return FALSE;
  46. }
  47. hr = m_ptrDBconn->Open(_bstr_t(GetConnectionString()), _T(""), _T(""), XTPADODB::adOptionUnspecified);
  48. ASSERT(SUCCEEDED(hr));
  49. if (FAILED(hr))
  50. {
  51. TRACE(_T("ERROR: Cannot open DB Connection. (HRESULT = %08lx, ConnectionString='%s') n"), hr, (LPCTSTR)m_strConnectionString);
  52. return FALSE;
  53. }
  54. CXTPCalendarData::Open();
  55. return IsOpen();
  56. }
  57. catch (_com_error &e)
  58. {
  59. TRACE_ProviderError(m_ptrDBconn);
  60. TRACE_ComError(e);
  61. }
  62. catch (...)
  63. {}
  64. TRACE(_T("ERROR: Exeption in CXTPCalendarDatabaseDataProvider::Open(ConnectionString='%s') n"), (LPCTSTR)m_strConnectionString);
  65. return FALSE;
  66. }
  67. void CCalendarDataProviderSQL::Close()
  68. {
  69. if (IsOpen())
  70. {
  71. try
  72. {
  73. if (m_ptrDBconn != NULL)
  74. m_ptrDBconn->Close();
  75. }
  76. catch (_com_error &e)
  77. {
  78. TRACE_ProviderError(m_ptrDBconn);
  79. TRACE_ComError(e);
  80. }
  81. catch (...)
  82. {}
  83. CXTPCalendarData::Close();
  84. }
  85. }
  86. CXTPCalendarEventsPtr CCalendarDataProviderSQL::DoRetrieveDayEvents(COleDateTime dtDay)
  87. {
  88. if (!IsOpen() || m_ptrDBconn == NULL)
  89. {
  90. ASSERT(FALSE);
  91. return NULL;
  92. }
  93. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  94. _bstr_t bstrSQL = CSQLDataHelper::MakeRetrieveDayEventsSQL(dtDay);
  95. try
  96. {
  97. XTPADODB::_RecordsetPtr ptrRSevents = m_ptrDBconn->Execute(bstrSQL, NULL, XTPADODB::adOptionUnspecified);
  98. DBGDATA_ASSERT(ptrRSevents != NULL);
  99. if (ptrRSevents == NULL) 
  100. return new CXTPCalendarEvents();
  101. CXTPCalendarEventsPtr ptrEvents = _SQLDataHelper.CreateEventsFromData(ptrRSevents, TRUE);
  102. ASSERT(ptrRSevents->GetState() == XTPADODB::adStateClosed);
  103. if (!ptrEvents) 
  104. ptrEvents = new CXTPCalendarEvents();
  105. return ptrEvents;
  106. }
  107. catch (_com_error &e)
  108. {
  109. TRACE_ProviderError(m_ptrDBconn);
  110. TRACE_ComError(e);
  111. }
  112. catch (...)
  113. {}
  114. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoRetrieveDayEvents(Date= %s) n"), (LPCTSTR)dtDay.Format());
  115. return NULL;
  116. }
  117. CXTPCalendarEventPtr CCalendarDataProviderSQL::DoRead_Event(DWORD dwEventID)
  118. {
  119. if (!IsOpen() || m_ptrDBconn == NULL)
  120. {
  121. ASSERT(FALSE);
  122. return NULL;
  123. }
  124. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  125. CString strSQL;
  126. strSQL.Format(_T("SELECT * FROM CalendarEvents WHERE EventID = %d"), dwEventID);
  127. try
  128. {
  129. XTPADODB::_RecordsetPtr ptrRSevent = m_ptrDBconn->Execute(_bstr_t(strSQL), NULL, XTPADODB::adOptionUnspecified);
  130. DBGDATA_ASSERT(ptrRSevent != NULL);
  131. if (ptrRSevent == NULL) 
  132. return NULL;
  133. CXTPCalendarEventPtr ptrEvent = _SQLDataHelper.CreateEventFromData(ptrRSevent, TRUE);
  134. ASSERT(ptrRSevent->GetState() == XTPADODB::adStateClosed);
  135. return ptrEvent;
  136. }
  137. catch (_com_error &e)
  138. {
  139. TRACE_ProviderError(m_ptrDBconn);
  140. TRACE_ComError(e);
  141. }
  142. catch (...)
  143. {}
  144. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoRead_Event(ID= %d) n"), dwEventID);
  145. return NULL;
  146. }
  147. BOOL CCalendarDataProviderSQL::DoCreate_Event(CXTPCalendarEvent* pEvent, DWORD& rdwNewEventID)
  148. {
  149. if (!IsOpen() || m_ptrDBconn == NULL || !pEvent)
  150. {
  151. return FALSE;
  152. }
  153. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  154. _bstr_t bstrSQL = _T("SELECT * FROM CalendarEvents WHERE EventID = 0");
  155. try
  156. {
  157. XTPADODB::_RecordsetPtr ptrRSevent;
  158. HRESULT hr = ptrRSevent.CreateInstance(__uuidof(XTPADODB::Recordset));
  159. ASSERT(SUCCEEDED(hr));
  160. if (FAILED(hr) || ptrRSevent == NULL)
  161. {
  162. TRACE(_T("ERROR: Cannot create XTPADODB::Recordset. (HRESULT = %08lx) n"), hr);
  163. return FALSE;
  164. }
  165. _variant_t vtConnDisp((IDispatch*)m_ptrDBconn.GetInterfacePtr());
  166. ptrRSevent->Open(bstrSQL, vtConnDisp, XTPADODB::adOpenStatic, XTPADODB::adLockOptimistic, XTPADODB::adOpenRecordUnspecified);
  167.         
  168. m_ptrDBconn->BeginTrans();
  169. //'-----------------------------------------------------
  170. ASSERT(ptrRSevent->bEOF && ptrRSevent->bBOF);
  171.     
  172. ptrRSevent->AddNew();
  173.         
  174. _SQLDataHelper.PutEventToData(pEvent, ptrRSevent);
  175. ptrRSevent->Update();
  176.     
  177. //'--------------------------------------------    
  178. ptrRSevent->Close();
  179.     
  180. m_ptrDBconn->CommitTrans();
  181.     
  182. //'-- update Auto field EventID
  183. bstrSQL = _T("SELECT MAX(EventID) AS NewEventID FROM CalendarEvents");
  184. XTPADODB::_RecordsetPtr ptrRSnewID = m_ptrDBconn->Execute(bstrSQL, NULL, XTPADODB::adOptionUnspecified);
  185. ASSERT(ptrRSnewID != NULL);
  186. if (ptrRSnewID != NULL) 
  187. {
  188. ASSERT(!ptrRSnewID->bEOF);
  189. if (!ptrRSnewID->bEOF)
  190. {
  191. rdwNewEventID = (DWORD)(long)ptrRSnewID->Fields->GetItem(_T("NewEventID"))->Value;
  192. }
  193. ptrRSnewID->Close();
  194. }
  195. return TRUE;
  196. }
  197. catch (_com_error &e)
  198. {
  199. TRACE_ProviderError(m_ptrDBconn);
  200. TRACE_ComError(e);
  201. }
  202. catch (...)
  203. {}
  204. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoCreate_Event() n"));
  205. return FALSE;
  206. }
  207. BOOL CCalendarDataProviderSQL::DoUpdate_Event (CXTPCalendarEvent* pEvent)
  208. {
  209. ASSERT(pEvent);
  210. if (!IsOpen() || m_ptrDBconn == NULL || !pEvent)
  211. {
  212. return FALSE;
  213. }
  214. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  215. CString strSQL;
  216. strSQL.Format(_T("SELECT * FROM CalendarEvents WHERE EventID = %d"), pEvent->GetEventID());
  217. try
  218. {
  219. XTPADODB::_RecordsetPtr ptrRSevent;
  220. HRESULT hr = ptrRSevent.CreateInstance(__uuidof(XTPADODB::Recordset));
  221. ASSERT(SUCCEEDED(hr));
  222. if (FAILED(hr) || ptrRSevent == NULL)
  223. {
  224. TRACE(_T("ERROR: Cannot create XTPADODB::Recordset. (HRESULT = %08lx) n"), hr);
  225. return FALSE;
  226. }
  227. _variant_t vtConnDisp((IDispatch*)m_ptrDBconn.GetInterfacePtr());
  228. ptrRSevent->Open(_bstr_t(strSQL), vtConnDisp, XTPADODB::adOpenStatic, XTPADODB::adLockOptimistic, XTPADODB::adOpenRecordUnspecified);
  229.        
  230. m_ptrDBconn->BeginTrans();
  231. //'-----------------------------------------------------
  232. ASSERT(!ptrRSevent->bEOF && !ptrRSevent->bBOF);
  233.     
  234. _SQLDataHelper.PutEventToData(pEvent, ptrRSevent);
  235. ptrRSevent->Update();
  236.     
  237. //'--------------------------------------------    
  238. ptrRSevent->Close();
  239.     
  240. m_ptrDBconn->CommitTrans();
  241.     
  242. return TRUE;
  243. }
  244. catch (_com_error &e)
  245. {
  246. TRACE_ProviderError(m_ptrDBconn);
  247. TRACE_ComError(e);
  248. }
  249. catch (...)
  250. {}
  251. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoUpdate_Event() n"));
  252. return FALSE;
  253. }
  254. BOOL CCalendarDataProviderSQL::DoDelete_Event (CXTPCalendarEvent* pEvent)
  255. {
  256. ASSERT(pEvent);
  257. if (!IsOpen() || m_ptrDBconn == NULL || !pEvent)
  258. {
  259. return FALSE;
  260. }
  261. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  262. CString strSQL;
  263. strSQL.Format(_T("DELETE FROM CalendarEvents WHERE EventID = %d"), pEvent->GetEventID());
  264. try
  265. {
  266. m_ptrDBconn->Execute(_bstr_t(strSQL), NULL, XTPADODB::adExecuteNoRecords);
  267. return TRUE;
  268. }
  269. catch (_com_error &e)
  270. {
  271. TRACE_ProviderError(m_ptrDBconn);
  272. TRACE_ComError(e);
  273. }
  274. catch (...)
  275. {}
  276. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoDelete_Event() n"));
  277. return FALSE;
  278. }
  279. CXTPCalendarRecurrencePatternPtr CCalendarDataProviderSQL::DoRead_RPattern(DWORD dwPatternID)
  280. {
  281. if (!IsOpen() || m_ptrDBconn == NULL)
  282. {
  283. ASSERT(FALSE);
  284. return NULL;
  285. }
  286. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  287. CString strSQL;
  288. strSQL.Format(_T("SELECT * FROM CalendarRecurrencePatterns WHERE RecurrencePatternID = %d"), dwPatternID);
  289. try
  290. {
  291. XTPADODB::_RecordsetPtr ptrRS = m_ptrDBconn->Execute(_bstr_t(strSQL), NULL, XTPADODB::adOptionUnspecified);
  292. DBGDATA_ASSERT(ptrRS != NULL);
  293. if (ptrRS == NULL) 
  294. return NULL;
  295. CXTPCalendarRecurrencePatternPtr ptrPattern = _SQLDataHelper.CreatePatternFromData(ptrRS);
  296. ASSERT(ptrRS->GetState() == XTPADODB::adStateClosed);
  297. return ptrPattern;
  298. }
  299. catch (_com_error &e)
  300. {
  301. TRACE_ProviderError(m_ptrDBconn);
  302. TRACE_ComError(e);
  303. }
  304. catch (...)
  305. {}
  306. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoRead_RPattern(ID= %d) n"), dwPatternID);
  307. return NULL;
  308. }
  309. BOOL CCalendarDataProviderSQL::DoCreate_RPattern(CXTPCalendarRecurrencePattern* pPattern, DWORD& rdwNewPatternID)
  310. {
  311. if (!IsOpen() || m_ptrDBconn == NULL || !pPattern)
  312. {
  313. return FALSE;
  314. }
  315. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  316. _bstr_t bstrSQL = _T("SELECT * FROM CalendarRecurrencePatterns WHERE RecurrencePatternID = 0");
  317. try
  318. {
  319. XTPADODB::_RecordsetPtr ptrRS;
  320. HRESULT hr = ptrRS.CreateInstance(__uuidof(XTPADODB::Recordset));
  321. ASSERT(SUCCEEDED(hr));
  322. if (FAILED(hr) || ptrRS == NULL)
  323. {
  324. TRACE(_T("ERROR: Cannot create XTPADODB::Recordset. (HRESULT = %08lx) n"), hr);
  325. return FALSE;
  326. }
  327. _variant_t vtConnDisp((IDispatch*)m_ptrDBconn.GetInterfacePtr());
  328. ptrRS->Open(bstrSQL, vtConnDisp, XTPADODB::adOpenStatic, XTPADODB::adLockOptimistic, XTPADODB::adOpenRecordUnspecified);
  329.         
  330. m_ptrDBconn->BeginTrans();
  331. //'-----------------------------------------------------
  332. ASSERT(ptrRS->bEOF && ptrRS->bBOF);
  333.     
  334. ptrRS->AddNew();
  335.         
  336. _SQLDataHelper.PutPatternToData(pPattern, ptrRS);
  337. ptrRS->Update();
  338.     
  339. //'--------------------------------------------    
  340. ptrRS->Close();
  341.     
  342. m_ptrDBconn->CommitTrans();
  343.     
  344. //'-- update Auto field EventID
  345. bstrSQL = _T("SELECT MAX(RecurrencePatternID) AS NewID FROM CalendarRecurrencePatterns");
  346. XTPADODB::_RecordsetPtr ptrRSnewID = m_ptrDBconn->Execute(bstrSQL, NULL, XTPADODB::adOptionUnspecified);
  347. ASSERT(ptrRSnewID != NULL);
  348. if (ptrRSnewID != NULL) 
  349. {
  350. ASSERT(!ptrRSnewID->bEOF);
  351. if (!ptrRSnewID->bEOF)
  352. {
  353. rdwNewPatternID = (DWORD)(long)ptrRSnewID->Fields->GetItem(_T("NewID"))->Value;
  354. }
  355. ptrRSnewID->Close();
  356. }
  357. return TRUE;
  358. }
  359. catch (_com_error &e)
  360. {
  361. TRACE_ProviderError(m_ptrDBconn);
  362. TRACE_ComError(e);
  363. }
  364. catch (...)
  365. {}
  366. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoCreate_Event() n"));
  367. return FALSE;
  368. }
  369. BOOL CCalendarDataProviderSQL::DoUpdate_RPattern(CXTPCalendarRecurrencePattern* pPattern)
  370. {
  371. if (!IsOpen() || m_ptrDBconn == NULL || !pPattern)
  372. {
  373. return FALSE;
  374. }
  375. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  376. CString strSQL;
  377. strSQL.Format(_T("SELECT * FROM CalendarRecurrencePatterns WHERE RecurrencePatternID = %d"), pPattern->GetPatternID());
  378. try
  379. {
  380. XTPADODB::_RecordsetPtr ptrRS;
  381. HRESULT hr = ptrRS.CreateInstance(__uuidof(XTPADODB::Recordset));
  382. ASSERT(SUCCEEDED(hr));
  383. if (FAILED(hr) || ptrRS == NULL)
  384. {
  385. TRACE(_T("ERROR: Cannot create XTPADODB::Recordset. (HRESULT = %08lx) n"), hr);
  386. return FALSE;
  387. }
  388. _variant_t vtConnDisp((IDispatch*)m_ptrDBconn.GetInterfacePtr());
  389. ptrRS->Open(_bstr_t(strSQL), vtConnDisp, XTPADODB::adOpenStatic, XTPADODB::adLockOptimistic, XTPADODB::adOpenRecordUnspecified);
  390.         
  391. m_ptrDBconn->BeginTrans();
  392. //'-----------------------------------------------------
  393. ASSERT(!ptrRS->bEOF && !ptrRS->bBOF);
  394.              
  395. _SQLDataHelper.PutPatternToData(pPattern, ptrRS);
  396. ptrRS->Update();
  397.     
  398. //'--------------------------------------------    
  399. ptrRS->Close();
  400.     
  401. m_ptrDBconn->CommitTrans();
  402.     
  403. return TRUE;
  404. }
  405. catch (_com_error &e)
  406. {
  407. TRACE_ProviderError(m_ptrDBconn);
  408. TRACE_ComError(e);
  409. }
  410. catch (...)
  411. {}
  412. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoUpdate_RPattern() n"));
  413. return FALSE;
  414. }
  415. BOOL CCalendarDataProviderSQL::DoDelete_RPattern(CXTPCalendarRecurrencePattern* pPattern)
  416. {
  417. ASSERT(pPattern);
  418. if (!IsOpen() || m_ptrDBconn == NULL || !pPattern)
  419. {
  420. return FALSE;
  421. }
  422. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  423. CString strSQL;
  424. strSQL.Format(_T("DELETE FROM CalendarRecurrencePatterns WHERE RecurrencePatternID = %d"), pPattern->GetPatternID());
  425. try
  426. {
  427. m_ptrDBconn->Execute(_bstr_t(strSQL), NULL, XTPADODB::adExecuteNoRecords);
  428. return TRUE;
  429. }
  430. catch (_com_error &e)
  431. {
  432. TRACE_ProviderError(m_ptrDBconn);
  433. TRACE_ComError(e);
  434. }
  435. catch (...)
  436. {}
  437. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoDelete_RPattern() n"));
  438. return NULL;
  439. }
  440. CXTPCalendarEventsPtr CCalendarDataProviderSQL::DoGetAllEvents_raw()
  441. {
  442. if (!IsOpen() || m_ptrDBconn == NULL)
  443. {
  444. ASSERT(FALSE);
  445. return NULL;
  446. }
  447. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  448. CString strSQL;
  449. strSQL.Format(_T("SELECT * FROM CalendarEvents WHERE RecurrenceState = %d OR RecurrenceState = %d"),
  450.   xtpCalendarRecurrenceNotRecurring, xtpCalendarRecurrenceMaster);
  451. try
  452. {
  453. XTPADODB::_RecordsetPtr ptrRSevents = m_ptrDBconn->Execute(_bstr_t(strSQL), NULL, XTPADODB::adOptionUnspecified);
  454. DBGDATA_ASSERT(ptrRSevents != NULL);
  455. if (ptrRSevents == NULL) 
  456. return new CXTPCalendarEvents();
  457. CXTPCalendarEventsPtr ptrEvents = _SQLDataHelper.CreateEventsFromData(ptrRSevents, TRUE);
  458. ASSERT(ptrRSevents->GetState() == XTPADODB::adStateClosed);
  459. if (!ptrEvents) 
  460. ptrEvents = new CXTPCalendarEvents();
  461. return ptrEvents;
  462. }
  463. catch (_com_error &e)
  464. {
  465. TRACE_ProviderError(m_ptrDBconn);
  466. TRACE_ComError(e);
  467. }
  468. catch (...)
  469. {}
  470. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoGetAllEvents_raw() n"));
  471. return NULL;
  472. }
  473. CXTPCalendarEventsPtr CCalendarDataProviderSQL::DoGetUpcomingEvents(COleDateTime dtFrom, COleDateTimeSpan spPeriod)
  474. {
  475. // The following code is also allowed: 
  476. // return DoGetAllEvents_raw();
  477. // 
  478. // Of cause it is not optimal, but if you like it ....
  479. // or just for some testing purposes it will work fine. 
  480. // (of cause DoGetAllEvents_raw must be implemented)
  481. if (!IsOpen() || m_ptrDBconn == NULL)
  482. {
  483. ASSERT(FALSE);
  484. return NULL;
  485. }
  486. CSQLDataHelper _SQLDataHelper(this, m_ptrDBconn);
  487. BOOL bOptimized = TRUE;
  488. CString strSQL = CSQLDataHelper::MakeGetUpcomingEventsSQL(dtFrom, (int)spPeriod.GetTotalMinutes(), bOptimized);
  489. //TRACE(_T("n%s"), strSQL.Left(500));
  490. //TRACE(_T("%sn"), strSQL.Mid(500));
  491. try
  492. {
  493. XTPADODB::_RecordsetPtr ptrRSevents = m_ptrDBconn->Execute(_bstr_t(strSQL), NULL, XTPADODB::adOptionUnspecified);
  494. DBGDATA_ASSERT(ptrRSevents != NULL);
  495. if (ptrRSevents == NULL) 
  496. return new CXTPCalendarEvents();
  497. CXTPCalendarEventsPtr ptrEvents = _SQLDataHelper.CreateEventsFromData(ptrRSevents, TRUE);
  498. ASSERT(ptrRSevents->GetState() == XTPADODB::adStateClosed);
  499. if (!ptrEvents) 
  500. ptrEvents = new CXTPCalendarEvents();
  501. return ptrEvents;
  502. }
  503. catch (_com_error &e)
  504. {
  505. TRACE_ProviderError(m_ptrDBconn);
  506. TRACE_ComError(e);
  507. }
  508. catch (...)
  509. {}
  510. TRACE(_T("ERROR: Exeption in CCalendarDataProviderSQL::DoGetUpcomingEvents() n"));
  511. return NULL;
  512. }
  513.   
  514. void CCalendarDataProviderSQL::DoRemoveAllEvents()
  515. {
  516. // its easy to implement.
  517. // See DoDelete_Event and DoDelete_RPattern
  518. }