📄 query.cpp
字号:
if (pElement->GetSelected())
{
bFound = FALSE;
// Feature name
if ((long)pElement->GetDataType() == BDFEATURE ||
(long)pElement->GetDataType() == BDFTYPE)
{
bFound = TRUE;
}
// Date
if ((long)pElement->GetDataType() == BDDATE)
{
CAttribute* pAttr = new CAttribute(BDDATE);
pAttr->SetAttrId(BDDATE);
pAttr->SetFTypeId(pQuery->GetFType());
pAttr->SetDate(aAttr.m_lDate);
CDateTime date(aAttr.m_lDate, 0);
date.DateAsString(sDate);
pAttr->SetDesc(sDate.GetBuffer(0));
pAttrArray->Add(pAttr);
bFound = TRUE;
}
// Other attributes
for (int j = 0; !bFound && j < aAttr.GetSize(); j++)
{
if (aAttr[j]->GetAttrId() == pElement->GetAttrId())
{
CAttribute* pAttr = new CAttribute(aAttr[j]->GetDataType());
*pAttr = *aAttr[j];
pAttrArray->Add(pAttr);
bFound = TRUE;
};
};
}
// Store the date of the data
pAttrArray->m_dateActive = CDateTime(aAttr.m_lDate, 0);
// Get next element
pElement = pElement->GetNextQuery();
}
while (pElement != NULL && pElement->GetDataType() != BDFTYPE);
// Retrieve data for statistics
pElement = m_pQuery;
while (pElement != NULL)
{
if (pElement->GetDataType() == BDQUERYSTATS)
{
CQueryStats* pStats = (CQueryStats*)pElement;
for (int j = 0; j < aAttr.GetSize(); j++)
{
if ((aAttr[j]->GetAttrId() == pStats->GetAttrId() &&
aAttr[j]->GetFTypeId() == pStats->GetFTypeId()) ||
(aAttr[j]->GetAttrId() == pStats->GetAttrId2() &&
aAttr[j]->GetFTypeId() == pStats->GetFTypeId2()))
{
CAttribute* pAttr = new CAttribute(aAttr[j]->GetDataType());
*pAttr = *aAttr[j];
pAttrArray->Add(pAttr);
bFound = TRUE;
};
};
}
pElement = pElement->GetNextQuery();
};
return bOK;
}
///////////////////////////////////////////////////////////////////////////////
//
// For each attribute, if it has no value assigned then assign its value can
// be replaced with another attribute meeting the required conditions
//
BOOL CQueryResult::RetrieveMissing(CQuery* pQuery, CAttrArray& aAttr,
CQueryAttrArray* pAttrArray)
{
BOOL bOK = TRUE;
for (int i = 0; i < aAttr.GetSize(); i++)
{
for (int j = 0; j < pAttrArray->GetSize(); j++)
{
if (aAttr[i]->GetFTypeId() == pAttrArray->GetAt(j)->GetFTypeId() &&
aAttr[i]->GetAttrId() == pAttrArray->GetAt(j)->GetAttrId())
{
CAttribute* pAttr = pAttrArray->GetAt(j);
if (pAttr->IsNull() && !aAttr[i]->IsNull())
{
// Only do this for coordinate and maplines, otherwise
// user may be confused when value is presented with wrong date
if (pAttr->GetDataType() == BDMAPLINES || pAttr->GetDataType() == BDCOORD)
{
delete pAttr;
pAttr = new CAttribute(aAttr[i]->GetDataType());
*pAttr = *aAttr[i];
pAttrArray->SetAt(j, pAttr);
};
}
}
}
}
return bOK;
}
///////////////////////////////////////////////////////////////////////////////
//
// Retrieves the feature names if selected
//
void CQueryResult::InitNullAttr(CQuery* pQuery, CAttrArray& aAttr, CQueryAttrArray* pAttrArray)
{
// Determine which attributes are required
CQueryElement* pElement = pQuery;
ASSERT(pElement != NULL);
do
{
if (pElement->GetSelected())
{
// Feature name
if ((long)pElement->GetDataType() == BDFEATURE ||
(long)pElement->GetDataType() == BDFTYPE)
{
// Skip
}
else if ((long)pElement->GetDataType() == BDDATE)
{
// Add blank date
CAttribute* pAttr = new CAttribute(BDDATE);
pAttr->SetAttrId(BDDATE);
pAttr->SetFTypeId(pQuery->GetFType());
pAttr->SetDesc("");
pAttrArray->Add(pAttr);
}
else
{
// Add blank attribute
for (int j = 0; j < aAttr.GetSize(); j++)
{
if (aAttr[j]->GetAttrId() == pElement->GetAttrId())
{
CAttribute* pAttr = new CAttribute(aAttr[j]->GetDataType());
pAttr->SetDesc(aAttr[j]->GetDesc());
pAttrArray->Add(pAttr);
break;
};
};
};
};
pElement = pElement->GetNextQuery();
}
while (pElement != NULL && pElement->GetDataType() != BDFTYPE);
}
///////////////////////////////////////////////////////////////////////////////
//
// Performs calculations whereby two attributes for the same feature will
// be combined using a mathematic operator
//
void CQueryResult::CalcRowBasedStats()
{
int iAttr = -1;
// Find whether statistics are required
CQueryElement* pElement = m_pQuery;
while (pElement != NULL)
{
if (pElement->GetDataType() == BDQUERYSTATS)
{
int nDP = 0;
CQueryStats* pStats = (CQueryStats*)pElement;
for (int i = 0; i < GetSize(); i++)
{
CalcRowBasedStats(pStats, *GetAt(i), iAttr, nDP);
}
iAttr--;
}
pElement = pElement->GetNextQuery();
}
}
///////////////////////////////////////////////////////////////////////////////
void CQueryResult::CalcRowBasedStats(CQueryStats* pStats, CQueryAttrArray& aAttr, int iAttr, int nDP)
{
CAttribute *pAttr1 = NULL, *pAttr2 = NULL;
double d1 = 0, d2 = 0;
int iAttr1 = -1, iAttr2 = -1;
// Find attributes used for the statistic
for (int i = 0; i < aAttr.GetSize(); i++)
{
if (aAttr.GetAt(i)->GetFTypeId() == pStats->GetFTypeId() &&
aAttr.GetAt(i)->GetAttrId() == pStats->GetAttrId())
{
pAttr1 = aAttr.GetAt(i);
iAttr1 = i;
}
if (aAttr.GetAt(i)->GetFTypeId() == pStats->GetFTypeId2() &&
aAttr.GetAt(i)->GetAttrId() == pStats->GetAttrId2())
{
pAttr2 = aAttr.GetAt(i);
iAttr2 = i;
}
}
// Determine if a value is to be used
if (pStats->GetAttrId() == 0) d1 = pStats->GetValue1();
if (pStats->GetAttrId2() == 0) d2 = pStats->GetValue2();
// Perform calculation
double dResult = AFX_RFX_DOUBLE_PSEUDO_NULL;
// Numeric statistic
if (pStats->GetAttrId() == 0 || pAttr1->GetDataType() == BDNUMBER)
{
if (pAttr1 != NULL) d1 = *pAttr1->GetDouble();
if (pAttr2 != NULL) d2 = *pAttr2->GetDouble();
// Check for divide by zero
if ((pStats->GetStatistic() == CQueryStats::divide ||
pStats->GetStatistic() == CQueryStats::percent) &&
d1 == 0)
{
// Ignore
}
else if (d1 != AFX_RFX_DOUBLE_PSEUDO_NULL &&
d2 != AFX_RFX_DOUBLE_PSEUDO_NULL)
{
switch(pStats->GetStatistic())
{
case CQueryStats::add : dResult = d1+d2; break;
case CQueryStats::subtract : dResult = d1-d2; break;
case CQueryStats::multiply : dResult = d1*d2; break;
case CQueryStats::divide : if (d2 != 0) dResult = d1/d2; break;
case CQueryStats::percent : if (d2 != 0) dResult = d1/d2*100; break;
}
};
}
dResult = SetDP(dResult, pStats->GetDecPlaces());
// Substitute values for result
CAttribute* pAttr = new CAttribute(BDNUMBER);
pAttr->SetDouble(dResult);
pAttr->SetDesc(pStats->GetDesc());
pAttr->SetAttrId(iAttr);
pAttr->SetFTypeId(m_pQuery->GetFType());
aAttr.Add(pAttr);
// Remove the attributes from the list
if (pAttr1 != NULL)
{
aAttr.RemoveAt(iAttr1);
delete pAttr1;
};
if (pAttr1 != pAttr2 && pAttr2 != NULL)
{
if (iAttr2 > iAttr1 && iAttr1 != -1) iAttr2--;
aAttr.RemoveAt(iAttr2);
delete pAttr2;
};
}
///////////////////////////////////////////////////////////////////////////////
double CQueryResult::SetDP(double dResult, int nDP)
{
int n = 1;
for (int i = 0; i < nDP; i++) n *= 10;
return floor(dResult * n + 0.5) / n;
}
///////////////////////////////////////////////////////////////////////////////
//
// This routine will sort the results of the query according to the selected
// elements
//
void CQueryResult::SortQueryResults()
{
CQueryResult aSorted;
BDProgressRange(0, GetSize());
BDProgressText("Sorting...");
for (int i = 0; i < GetSize(); i++)
{
for (int j = 0; j < aSorted.GetSize(); j++)
{
if (Compare(GetAt(i), aSorted[j]) >= 0)
{
break;
}
}
aSorted.InsertAt(j, GetAt(i));
BDProgressPos(i);
}
// When removing don't use RemoveAllX as pointers are preserved
RemoveAll();
Copy(aSorted);
aSorted.RemoveAll();
BDProgressRange(0, 0);
}
///////////////////////////////////////////////////////////////////////////////
//
// Compares two arrays of attributes according to the items selection in CQuery
// returns 0 if they are equal, or negative if A occurs first or positive if
// B occurs first.
//
int CQueryResult::Compare(CQueryAttrArray* pAttrA, CQueryAttrArray* pAttrB, int nSortId)
{
int nCompare = 0;
int nAttrStats = 0;
BOOL bFound = FALSE;
// Sort by multiple attributes from 1 upwards until none found
for (int i = 0; i < m_aAttrSel.GetSize(); i++)
{
if (m_aAttrSel[i].m_nSortBy == nSortId)
{
bFound = TRUE;
// Search for attribute
for (int j = 0; j < pAttrA->GetSize(); j++)
{
CAttribute* pA = pAttrA->GetAt(j);
CAttribute* pB = pAttrB->GetAt(j);
if (pA->GetAttrId() == m_aAttrSel[i].m_lAttr &&
pA->GetFTypeId() == m_aAttrSel[i].m_lFType)
{
nCompare = Compare(pA, pB);
break;
}
};
break;
}
}
// If the results are the same then check if there is another sort attribute
if (nCompare == 0)
{
for (int i = 0; i < m_aAttrSel.GetSize(); i++)
{
if (m_aAttrSel[i].m_nSortBy == nSortId+1)
{
nCompare = Compare(pAttrA, pAttrB, nSortId+1);
break;
};
}
};
return nCompare;
}
///////////////////////////////////////////////////////////////////////////////
//
// Compares two attributes
int CQueryResult::Compare(CAttribute* pA, CAttribute* pB)
{
int nCompare = 0;
// Numbers
if (pA->GetDataType() == BDNUMBER)
{
if (*pA->GetDouble() != AFX_RFX_DOUBLE_PSEUDO_NULL &&
*pB->GetDouble() != AFX_RFX_DOUBLE_PSEUDO_NULL)
{
if (*pA->GetDouble() < *pB->GetDouble()) nCompare = 1;
else if (*pA->GetDouble() > *pB->GetDouble()) nCompare = -1;
}
else if (*pA->GetDouble() == AFX_RFX_DOUBLE_PSEUDO_NULL &&
*pB->GetDouble() != AFX_RFX_DOUBLE_PSEUDO_NULL)
{
nCompare = 1;
}
else if (*pA->GetDouble() != AFX_RFX_DOUBLE_PSEUDO_NULL &&
*pB->GetDouble() == AFX_RFX_DOUBLE_PSEUDO_NULL)
{
nCompare = -1;
}
}
// Dates
else if (pA->GetDataType() == BDDATE)
{
if (CDateTime(*pA->GetDate(),0) < CDateTime(*pB->GetDate(),0)) nCompare = 1;
else if (CDateTime(*pA->GetDate(),0) > CDateTime(*pB->GetDate(),0)) nCompare = -1;
}
// Compare map lines
else if (pA->GetDataType() == BDMAPLINES)
{
CLongBinary *pLongBin1 = pA->GetLongBinary();
CLongBinary *pLongBin2 = pB->GetLongBinary();
if (pLongBin1->m_dwDataLength == pLongBin2->m_dwDataLength)
{
CLongLines maplines1(*pLongBin1);
CLongLines maplines2(*pLongBin2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -