OpenAccessdatabase.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include "StdAfx.h"
  2. #include "OpenAccessdatabase.h"
  3. BOOL Upgrade_mText(CDaoDatabase& db);
  4. BOOL Upgrade_Groups(CDaoDatabase& db);
  5. BOOL Upgrade_ShareData(CDaoDatabase& db);
  6. int GetFieldPos(CDaoRecordset& recs, LPCTSTR fieldName);
  7. BOOL CreateBackup(CString csPath);
  8. COpenAccessdatabase::COpenAccessdatabase(void)
  9. {
  10. }
  11. COpenAccessdatabase::~COpenAccessdatabase(void)
  12. {
  13. }
  14. // m_pErrorInfo:
  15. // - m_lErrorCode 0x00000cc1
  16. // - m_strSource "DAO.Fields"
  17. // - m_strDescription "Item not found in this collection."
  18. #define ON_FIELD_ABSENT(name,onabsent) \
  19. try { table.GetFieldInfo(name,info); } \
  20. catch(CDaoException* e) \
  21. { \
  22. if( !bUpgrade || e->m_pErrorInfo->m_lErrorCode != 0x00000cc1 ) \
  23. throw e; \
  24. if( bUpgraded == FALSE ) \
  25. CreateBackup(csPath); \
  26. bResult &= onabsent; \
  27. bUpgraded = TRUE; \
  28. e->Delete(); \
  29. }
  30. BOOL COpenAccessdatabase::ValidDB(CString csPath, BOOL bUpgrade)
  31. {
  32. BOOL bResult = TRUE;
  33. BOOL bUpgraded = FALSE;
  34. try
  35. {
  36. CDaoDatabase db;
  37. try
  38. {
  39. db.Open(csPath);
  40. }
  41. catch(CDaoException* e)
  42. {
  43. TCHAR szErrorMessage[512];
  44. UINT nHelpContext;
  45. if(e->GetErrorMessage(szErrorMessage, 512, &nHelpContext))
  46. {
  47. if(STRCMP(szErrorMessage, _T("Unable to initialize DAO/Jet db engine.")) == 0)
  48. {
  49. e->Delete();
  50. return ERROR_OPENING_DATABASE;
  51. }
  52. }
  53. e->ReportError();
  54. e->Delete();
  55. return FALSE;
  56. }
  57. CDaoTableDef table(&db);
  58. CDaoFieldInfo info;
  59. table.Open(_T("Main"));
  60. table.GetFieldInfo(_T("lID"), info);
  61. table.GetFieldInfo(_T("lDate"), info);
  62. ON_FIELD_ABSENT(_T("mText"), Upgrade_mText(db)); // +mText, -strText, -strType
  63. table.GetFieldInfo(_T("lShortCut"), info);
  64. table.GetFieldInfo(_T("lDontAutoDelete"), info);
  65. table.GetFieldInfo(_T("lTotalCopySize"), info);
  66. ON_FIELD_ABSENT(_T("bIsGroup"), Upgrade_Groups(db));
  67. table.GetFieldInfo(_T("lParentID"), info); // part of Upgrade_Groups
  68. table.GetFieldInfo(_T("dOrder"), info); // part of Upgrade_Groups
  69. ON_FIELD_ABSENT(_T("lDataID"), Upgrade_ShareData(db)); // +lDataID, -lParentID
  70. table.Close();
  71. table.Open(_T("Data"));
  72. table.GetFieldInfo(_T("lID"), info);
  73. table.GetFieldInfo(_T("lDataID"), info); // part of Upgrade_ShareData()
  74. table.GetFieldInfo(_T("strClipBoardFormat"), info);
  75. table.GetFieldInfo(_T("ooData"), info);
  76. table.Close();
  77. table.Open(_T("Types"));
  78. table.GetFieldInfo(_T("ID"), info);
  79. table.GetFieldInfo(_T("TypeText"), info);
  80. table.Close();
  81. }
  82. catch(CDaoException* e)
  83. {
  84. ASSERT(FALSE);
  85. e->Delete();
  86. return FALSE;
  87. }
  88. // if we upgraded, perform full validation again without upgrading
  89. if( bUpgraded )
  90. return ValidDB(csPath, FALSE);
  91. return bResult;
  92. }
  93. // +mText, -strText, -strType
  94. BOOL Upgrade_mText(CDaoDatabase& db)
  95. {
  96. try
  97. {
  98. db.Execute(_T("ALTER TABLE Main ADD COLUMN mText MEMO"), dbFailOnError);
  99. db.Execute(_T("UPDATE Main SET mText=strText"), dbFailOnError);
  100. db.Execute(_T("ALTER TABLE Main DROP COLUMN strText"), dbFailOnError);
  101. db.Execute(_T("ALTER TABLE Main DROP COLUMN strType"), dbFailOnError);
  102. }
  103. catch(CDaoException* e)
  104. {
  105. ASSERT(FALSE);
  106. e->Delete();
  107. return FALSE;
  108. }
  109. return TRUE;
  110. }
  111. BOOL Upgrade_Groups(CDaoDatabase& db)
  112. {
  113. try
  114. {
  115. CDaoTableDefEx table(&db);
  116. table.Open(_T("Main"));
  117. // Groups
  118. table.CreateField(_T("bIsGroup"), dbBoolean, 1, 0, _T("0")); // for Groups
  119. table.CreateIndex(FALSE, _T("bIsGroup"));
  120. table.CreateField(_T("lParentID"), dbLong, 4, 0, _T("0")); // parent Group Main.lID
  121. table.CreateIndex(FALSE, _T("lParentID"));
  122. table.CreateField(_T("dOrder"), dbDouble, 8, 0, _T("0")); // for Order within Groups
  123. table.CreateIndex(FALSE, _T("dOrder"));
  124. table.Close();
  125. // set defaults (otherwise might be NULL)
  126. db.Execute(_T("UPDATE Main SET bIsGroup = 0, lParentID = 0, dOrder = 0"), dbFailOnError);
  127. }
  128. catch(CDaoException* e)
  129. {
  130. ASSERT(FALSE);
  131. e->Delete();
  132. return FALSE;
  133. }
  134. return TRUE;
  135. }
  136. BOOL Upgrade_ShareData(CDaoDatabase& db)
  137. {
  138. try
  139. {
  140. CDaoTableDefEx table(&db);
  141. table.Open(_T("Main"));
  142. table.CreateField(_T("lDataID"), dbLong, 4, 0, _T("0")); // corresponds to Data.lDataID
  143. table.CreateIndex(FALSE, _T("lDataID"));
  144. table.Close();
  145. table.Open(_T("Data"));
  146. table.CreateField(_T("lDataID"), dbLong, 4, 0, _T("0")); // parent Group Main.lID
  147. table.CreateIndex(FALSE, _T("lDataID"));
  148. table.Close();
  149. // set defaults
  150. db.Execute(_T("UPDATE Main SET lDataID = 0"), dbFailOnError);
  151. db.Execute(_T("UPDATE Data SET lDataID = 0"), dbFailOnError);
  152. // update Main.lDataID and Data.lParentID for sharing Data
  153. //
  154. // - multiple Formats (Data.lID) exist for a single ClipData (Data.lDataID)
  155. // - The value of lDataID is arbitrary, but must be unique to the ClipData.
  156. // - In order to ensure uniqueness, lDataID is assigned the lID of
  157. // the first Format in the Clip's set.
  158. COleVariant var((long)0);
  159. CDaoRecordset main(&db);
  160. long main_fldID;
  161. long main_fldDataID;
  162. long main_lID;
  163. CDaoRecordset data(&db);
  164. long data_fldID;
  165. long data_fldDataID;
  166. long lDataID;
  167. int count = 0;
  168. int i = 0;
  169. int percentPrev = -1;
  170. int percent = -1;
  171. main.Open(dbOpenDynaset, _T("SELECT lID, lDataID FROM Main"));
  172. main_fldID = GetFieldPos(main, _T("lID"));
  173. VERIFY(main_fldID == 0);
  174. main_fldDataID = GetFieldPos(main, _T("lDataID"));
  175. VERIFY(main_fldDataID == 1);
  176. if( !main.IsEOF() )
  177. {
  178. main.MoveLast();
  179. count = main.GetRecordCount();
  180. main.MoveFirst();
  181. }
  182. // for each record in Main and its corresponding records in Data,
  183. // assign a new unique lDataID.
  184. while( !main.IsEOF() )
  185. {
  186. i++;
  187. percentPrev = percent;
  188. percent = (i*100)/count;
  189. main.GetFieldValue(main_fldID,var);
  190. main_lID = var.lVal;
  191. CString cs;
  192. cs.Format(_T("SELECT lID, lDataID FROM Data WHERE lParentID = %d"), main_lID);
  193. data.Open(dbOpenDynaset, cs);
  194. data_fldID = GetFieldPos(data, _T("lID"));
  195. VERIFY(data_fldID == 0);
  196. data_fldDataID = GetFieldPos(data, _T("lDataID"));
  197. VERIFY(data_fldDataID == 1);
  198. // lDataID = the first data record lID
  199. lDataID = 0;
  200. if( !data.IsEOF() )
  201. {
  202. data.GetFieldValue(0,var); // 0 == lID field
  203. lDataID = var.lVal;
  204. }
  205. // assign all Data records the same lDataID
  206. while( !data.IsEOF() )
  207. {
  208. var.lVal = lDataID;
  209. data.Edit();
  210. data.SetFieldValue(1,var); // 1 == lDataID field
  211. data.Update();
  212. data.MoveNext();
  213. }
  214. // assign Main.lDataID
  215. var.lVal = lDataID;
  216. main.Edit();
  217. main.SetFieldValue(1,var); // 1 == lDataID field
  218. main.Update();
  219. main.MoveNext();
  220. data.Close();
  221. }
  222. main.Close();
  223. // delete the old field
  224. db.Execute(_T("ALTER TABLE Data DROP CONSTRAINT lParentID"), dbFailOnError);
  225. db.Execute(_T("ALTER TABLE Data DROP COLUMN lParentID"), dbFailOnError);
  226. }
  227. catch(CDaoException* e)
  228. {
  229. ASSERT(FALSE);
  230. e->Delete();
  231. return FALSE;
  232. }
  233. return TRUE;
  234. }
  235. int GetFieldPos(CDaoRecordset& recs, LPCTSTR fieldName)
  236. {
  237. CDaoFieldInfo fi;
  238. int count = recs.GetFieldCount();
  239. for( int i = 0; i < count; i++ )
  240. {
  241. recs.GetFieldInfo(i, fi);
  242. if( fi.m_strName.Compare( fieldName ) == 0 )
  243. return i; // when found a match, return it
  244. }
  245. return -1;
  246. }
  247. BOOL CreateBackup(CString csPath)
  248. {
  249. CString csOriginal;
  250. int count = 0;
  251. // create a backup of the existing database
  252. do
  253. {
  254. count++;
  255. csOriginal.Format(_T("%s.%03d"), csPath, count);
  256. // in case of some weird infinite loop
  257. if( count > 50 )
  258. {
  259. ASSERT(0);
  260. return FALSE;
  261. }
  262. } while( !::CopyFile(csPath, csOriginal, TRUE) );
  263. return TRUE;
  264. }