home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / dbflt.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  9KB  |  339 lines

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