dbflt.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include <float.h>
  12. #ifdef AFX_DB_SEG
  13. #pragma code_seg(AFX_DB_SEG)
  14. #endif
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. // Helpers for floating point operations
  20. const float afxFloatPseudoNull = AFX_RFX_SINGLE_PSEUDO_NULL;
  21. const double afxDoublePseudoNull = AFX_RFX_DOUBLE_PSEUDO_NULL;
  22. extern void AFXAPI AfxTextFloatFormat(CDataExchange* pDX, int nIDC,
  23. void* pData, double value, int nSizeGcvt);
  24. extern BOOL AFXAPI AfxFieldText(CDataExchange* pDX, int nIDC, void* pv,
  25. CRecordset* pRecordset);
  26. void AFXAPI RFX_Single(CFieldExchange* pFX, LPCTSTR szName,
  27. float& value)
  28. {
  29. ASSERT(AfxIsValidAddress(pFX, sizeof(CFieldExchange)));
  30. ASSERT(AfxIsValidString(szName));
  31. UINT nField;
  32. if (!pFX->IsFieldType(&nField))
  33. return;
  34. LONG* plLength = pFX->m_prs->GetFieldLengthBuffer(nField - 1, pFX->m_nFieldType);
  35. switch (pFX->m_nOperation)
  36. {
  37. case CFieldExchange::BindFieldToColumn:
  38. {
  39. #ifdef _DEBUG
  40. // Assumes all bound fields BEFORE unbound fields
  41. CODBCFieldInfo* pODBCInfo =
  42. &pFX->m_prs->m_rgODBCFieldInfos[nField - 1];
  43. if (pODBCInfo->m_nSQLType != SQL_C_FLOAT)
  44. {
  45. // Warn of possible field schema mismatch
  46. if (afxTraceFlags & traceDatabase)
  47. TRACE1("Warning: float converted from SQL type %ld.\n",
  48. pODBCInfo->m_nSQLType);
  49. }
  50. #endif
  51. }
  52. // fall through
  53. default:
  54. LDefault:
  55. pFX->Default(szName, &value, plLength, SQL_C_FLOAT,
  56. sizeof(value), 13);
  57. return;
  58. case CFieldExchange::Fixup:
  59. if (*plLength == SQL_NULL_DATA)
  60. {
  61. pFX->m_prs->SetNullFieldStatus(nField - 1);
  62. value = afxFloatPseudoNull;
  63. }
  64. return;
  65. case CFieldExchange::SetFieldNull:
  66. if ((pFX->m_pvField == NULL &&
  67. pFX->m_nFieldType == CFieldExchange::outputColumn) ||
  68. pFX->m_pvField == &value)
  69. {
  70. if (pFX->m_bField)
  71. {
  72. pFX->m_prs->SetNullFieldStatus(nField - 1);
  73. value = afxFloatPseudoNull;
  74. *plLength = SQL_NULL_DATA;
  75. }
  76. else
  77. {
  78. pFX->m_prs->ClearNullFieldStatus(nField - 1);
  79. *plLength = sizeof(value);
  80. }
  81. #ifdef _DEBUG
  82. pFX->m_nFieldFound = nField;
  83. #endif
  84. }
  85. return;
  86. case CFieldExchange::MarkForAddNew:
  87. // can force writing of psuedo-null value (as a non-null) by setting field dirty
  88. if (value != afxFloatPseudoNull)
  89. {
  90. pFX->m_prs->SetDirtyFieldStatus(nField - 1);
  91. pFX->m_prs->ClearNullFieldStatus(nField - 1);
  92. }
  93. return;
  94. case CFieldExchange::MarkForUpdate:
  95. if (value != afxFloatPseudoNull)
  96. pFX->m_prs->ClearNullFieldStatus(nField - 1);
  97. goto LDefault;
  98. case CFieldExchange::AllocCache:
  99. {
  100. CFieldInfo* pInfo = &pFX->m_prs->m_rgFieldInfos[nField - 1];
  101. // Data cached by value, no allocation necessary
  102. pInfo->m_nDataType = AFX_RFX_SINGLE;
  103. }
  104. return;
  105. #ifdef _DEBUG
  106. case CFieldExchange::DumpField:
  107. {
  108. *pFX->m_pdcDump << "\n" << szName << " = " << value;
  109. }
  110. return;
  111. #endif //_DEBUG
  112. }
  113. }
  114. void AFXAPI RFX_Double(CFieldExchange* pFX, LPCTSTR szName,
  115. double& value)
  116. {
  117. ASSERT(AfxIsValidAddress(pFX, sizeof(CFieldExchange)));
  118. ASSERT(AfxIsValidString(szName));
  119. UINT nField;
  120. if (!pFX->IsFieldType(&nField))
  121. return;
  122. LONG* plLength = pFX->m_prs->GetFieldLengthBuffer(nField - 1, pFX->m_nFieldType);
  123. switch (pFX->m_nOperation)
  124. {
  125. case CFieldExchange::BindFieldToColumn:
  126. {
  127. #ifdef _DEBUG
  128. // Assumes all bound fields BEFORE unbound fields
  129. CODBCFieldInfo* pODBCInfo =
  130. &pFX->m_prs->m_rgODBCFieldInfos[nField - 1];
  131. if (pODBCInfo->m_nSQLType != SQL_C_DOUBLE &&
  132. pODBCInfo->m_nSQLType != SQL_FLOAT)
  133. {
  134. // Warn of possible field schema mismatch
  135. if (afxTraceFlags & traceDatabase)
  136. TRACE1("Warning: double converted from SQL type %ld.\n",
  137. pODBCInfo->m_nSQLType);
  138. }
  139. #endif
  140. }
  141. // fall through
  142. default:
  143. LDefault:
  144. pFX->Default(szName, &value, plLength, SQL_C_DOUBLE,
  145. sizeof(value), 22);
  146. return;
  147. case CFieldExchange::Fixup:
  148. if (*plLength == SQL_NULL_DATA)
  149. {
  150. pFX->m_prs->SetNullFieldStatus(nField - 1);
  151. value = afxDoublePseudoNull;
  152. }
  153. return;
  154. case CFieldExchange::SetFieldNull:
  155. if ((pFX->m_pvField == NULL &&
  156. pFX->m_nFieldType == CFieldExchange::outputColumn) ||
  157. pFX->m_pvField == &value)
  158. {
  159. if (pFX->m_bField)
  160. {
  161. pFX->m_prs->SetNullFieldStatus(nField - 1);
  162. value = afxDoublePseudoNull;
  163. *plLength = SQL_NULL_DATA;
  164. }
  165. else
  166. {
  167. pFX->m_prs->ClearNullFieldStatus(nField - 1);
  168. *plLength = sizeof(value);
  169. }
  170. #ifdef _DEBUG
  171. pFX->m_nFieldFound = nField;
  172. #endif
  173. }
  174. return;
  175. case CFieldExchange::MarkForAddNew:
  176. // can force writing of psuedo-null value (as a non-null) by setting field dirty
  177. if (value != afxDoublePseudoNull)
  178. {
  179. pFX->m_prs->SetDirtyFieldStatus(nField - 1);
  180. pFX->m_prs->ClearNullFieldStatus(nField - 1);
  181. }
  182. return;
  183. case CFieldExchange::MarkForUpdate:
  184. if (value != afxDoublePseudoNull)
  185. pFX->m_prs->ClearNullFieldStatus(nField - 1);
  186. goto LDefault;
  187. case CFieldExchange::AllocCache:
  188. {
  189. CFieldInfo* pInfo = &pFX->m_prs->m_rgFieldInfos[nField - 1];
  190. pInfo->m_pvDataCache = new double;
  191. pInfo->m_nDataType = AFX_RFX_DOUBLE;
  192. }
  193. return;
  194. #ifdef _DEBUG
  195. case CFieldExchange::DumpField:
  196. {
  197. *pFX->m_pdcDump << "\n" << szName << " = " << value;
  198. }
  199. return;
  200. #endif //_DEBUG
  201. }
  202. }
  203. /////////////////////////////////////////////////////////////////////////////
  204. void AFXAPI RFX_Single_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  205. float** prgFltVals, long** prgLengths)
  206. {
  207. ASSERT(AfxIsValidAddress(pFX, sizeof(CFieldExchange)));
  208. ASSERT(AfxIsValidString(szName));
  209. UINT nField;
  210. if (!pFX->IsFieldType(&nField))
  211. return;
  212. switch (pFX->m_nOperation)
  213. {
  214. case CFieldExchange::AllocMultiRowBuffer:
  215. {
  216. // The buffer pointer better be initialized to NULL
  217. // or cleanup in exceptional cases mail fail
  218. ASSERT(*prgFltVals == NULL);
  219. ASSERT(*prgLengths == NULL);
  220. int nRowsetSize = pFX->m_prs->GetRowsetSize();
  221. // Allocate buffers to hold data and length
  222. *prgFltVals = new float[nRowsetSize];
  223. *prgLengths = new long[nRowsetSize];
  224. }
  225. break;
  226. case CFieldExchange::DeleteMultiRowBuffer:
  227. delete [] *prgFltVals;
  228. *prgFltVals = NULL;
  229. delete [] *prgLengths;
  230. *prgLengths = NULL;
  231. break;
  232. default:
  233. AfxRFXBulkDefault(pFX, szName, *prgFltVals, *prgLengths,
  234. SQL_C_FLOAT, sizeof(float));
  235. break;
  236. }
  237. }
  238. void AFXAPI RFX_Double_Bulk(CFieldExchange* pFX, LPCTSTR szName,
  239. double** prgDblVals, long** prgLengths)
  240. {
  241. ASSERT(AfxIsValidAddress(pFX, sizeof(CFieldExchange)));
  242. ASSERT(AfxIsValidString(szName));
  243. UINT nField;
  244. if (!pFX->IsFieldType(&nField))
  245. return;
  246. switch (pFX->m_nOperation)
  247. {
  248. case CFieldExchange::AllocMultiRowBuffer:
  249. {
  250. // The buffer pointer better be initialized to NULL
  251. // or cleanup in exceptional cases mail fail
  252. ASSERT(*prgDblVals == NULL);
  253. ASSERT(*prgLengths == NULL);
  254. int nRowsetSize = pFX->m_prs->GetRowsetSize();
  255. // Allocate buffers to hold data and length
  256. *prgDblVals = new double[nRowsetSize];
  257. *prgLengths = new long[nRowsetSize];
  258. }
  259. break;
  260. case CFieldExchange::DeleteMultiRowBuffer:
  261. delete [] *prgDblVals;
  262. *prgDblVals = NULL;
  263. delete [] *prgLengths;
  264. *prgLengths = NULL;
  265. break;
  266. default:
  267. AfxRFXBulkDefault(pFX, szName, *prgDblVals, *prgLengths,
  268. SQL_C_DOUBLE, sizeof(double));
  269. break;
  270. }
  271. }
  272. /////////////////////////////////////////////////////////////////////////////
  273. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, float& value,
  274. CRecordset* pRecordset)
  275. {
  276. if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  277. AfxTextFloatFormat(pDX, nIDC, &value, value, FLT_DIG);
  278. }
  279. void AFXAPI DDX_FieldText(CDataExchange* pDX, int nIDC, double& value,
  280. CRecordset* pRecordset)
  281. {
  282. if (!AfxFieldText(pDX, nIDC, &value, pRecordset))
  283. AfxTextFloatFormat(pDX, nIDC, &value, value, DBL_DIG);
  284. }
  285. /////////////////////////////////////////////////////////////////////////////