📄 query.cpp
字号:
case CQueryElement::greater : sFilter += " > "; break;
case CQueryElement::less : sFilter += " < "; break;
case CQueryElement::greaterequal : sFilter += " >= "; break;
case CQueryElement::lessequal : sFilter += " <= "; break;
case CQueryElement::equal : sFilter += " = "; break;
case CQueryElement::notequal : sFilter += " <> "; break;
}
// Value
CString sValue;
sValue.Format("%lf", pElement->GetCondValue());
sFilter += sValue;
}
// Text based
else if (aAttr.GetAt(i)->GetDataType() == BDTEXT ||
aAttr.GetAt(i)->GetDataType() == BDLONGTEXT)
{
// Note: memo field is only included for version 3 databases as version 2
// stores memo as longbinary fields which cannot be searched
ASSERT(aAttr.GetAt(i)->GetDataType() != BDLONGTEXT ||
BDGetVersion(BDHandle()) >= 3);
// Column name
if (sFilter != "") sFilter += " and ";
sFilter += "`" + CString(pElement->GetColName()) + "`";
// Condition
switch (pElement->GetCond())
{
case CQueryElement::equal : sFilter += " = "; break;
case CQueryElement::notequal : sFilter += " <> "; break;
case CQueryElement::contains : sFilter += " like "; break;
case CQueryElement::notcontains : sFilter += " not like "; break;
case CQueryElement::like : sFilter += " like "; break;
}
// Value
if (pElement->GetCond() == CQueryElement::contains ||
pElement->GetCond() == CQueryElement::notcontains)
{
sFilter += "'%" + CString(pElement->GetCondValueStr()) + "%'";
}
// Replace wildcard asterisks (*) with percent (%)
else if (pElement->GetCond() == CQueryElement::like)
{
sFilter += "'" + CString(pElement->GetCondValueStr()) + "'";
for (int i =0; i < sFilter.GetLength(); i++)
{
if (sFilter[i] == '*') sFilter.SetAt(i, '%');
}
}
else
{
sFilter += "'" + CString(pElement->GetCondValueStr()) + "'";
};
}
}
}
}
pElement = pElement->GetNextQuery();
}
return sFilter;
}
///////////////////////////////////////////////////////////////////////////////
//
// Validate that boolean or only data with selected links are retrieved
//
BOOL CQueryResult::CheckConditions(CQuery* pQuery, CAttrArray& aAttr)
{
BOOL bOK = TRUE;
// Validate dates, if not valid ignore data but not an error
if (m_bBaseFType)
{
CDateTime datetime(aAttr.m_lDate, 0);
if (m_pQuery->GetDateCond() == CQuery::FirstDateRange ||
m_pQuery->GetDateCond() == CQuery::LastDateRange ||
m_pQuery->GetDateCond() == CQuery::AllDatesRange)
{
if (datetime < m_pQuery->GetStartDate() ||
datetime > m_pQuery->GetEndDate())
{
bOK = FALSE;
}
}
if (m_pQuery->GetDateCond() == CQuery::AllDatesAfter &&
datetime < m_pQuery->GetStartDate())
{
bOK = FALSE;
}
if (m_pQuery->GetDateCond() == CQuery::AllDatesBefore &&
datetime > m_pQuery->GetStartDate())
{
bOK = FALSE;
}
};
// Validate attributes
CQueryElement* pElement = pQuery->GetNextQuery();
while (bOK && pElement != NULL && pElement->GetDataType() != BDFTYPE &&
pElement->GetDataType() != BDQUERYSTATS)
{
// Attributes
for (int j = 0; j < aAttr.GetSize(); j++)
{
if (aAttr[j]->GetAttrId() == pElement->GetAttrId())
{
long lValue = 0;
long lDataType = aAttr[j]->GetDataType();
if (lDataType == BDBOOLEAN) lValue = *aAttr[j]->GetBoolean();
if (lDataType == BDLINK) lValue = *aAttr[j]->GetLink();
if (lDataType == BDLINK || lDataType == BDBOOLEAN)
{
// Search for the selected attributes
BOOL bFound = FALSE;
CQueryLink* pLink = (CQueryLink*)pElement;
int nSelected = 0;
// Search for the link among selected links in query
for (int i = 0; i < pLink->m_aFeatures.GetSize() && !bFound; i++)
{
if (pLink->m_aFeatures.GetAt(i).GetSelected())
{
nSelected++;
if (pLink->m_aFeatures.GetAt(i).m_lId == lValue)
{
bFound = TRUE;
};
};
}
// If all links are selected and the link contains the value 'null' then
// accept it
if (lDataType == BDLINK && lValue == AFX_RFX_LONG_PSEUDO_NULL &&
nSelected == pLink->m_aFeatures.GetSize())
{
bFound = TRUE;
}
else if (lDataType == BDBOOLEAN && lValue == AFX_RFX_BOOL_PSEUDO_NULL &&
nSelected == 2)
{
bFound = TRUE;
}
if (!bFound)
{
bOK = FALSE;
};
};
};
};
// Get next element
pElement = pElement->GetNextQuery();
}
return bOK;
}
///////////////////////////////////////////////////////////////////////////////
BOOL CQueryResult::CheckValueCond(CQuery* pQuery, CAttrArray& aAttr)
{
// Search for value based conditions in the query
CQueryElement* pElement = pQuery->GetNextQuery();
while (pElement != NULL)
{
if (pElement->GetCond() != CQueryElement::none)
{
// Find the corresponding attribute
for (int i = 0; i < aAttr.GetSize(); i++)
{
if (aAttr.GetAt(i)->GetAttrId() == pElement->GetAttrId() &&
aAttr.GetAt(i)->GetFTypeId() == pElement->GetFTypeId())
{
BOOL bOK = TRUE;
// Check text based conditions for links as the SQL code for this would be
// messy as the functionality is currently spit across the database API and the
// NRDB Pro application
if (aAttr.GetAt(i)->GetDataType() == BDLINK)
{
CString sValue = aAttr.GetAt(i)->AsString();
CString sCondValue = pElement->GetCondValueStr();
// None case sensitive comparison (CString::Find is case sensitive?)
sValue.MakeUpper();
sCondValue.MakeUpper();
switch (pElement->GetCond())
{
case CQueryElement::equal : bOK = (sValue == sCondValue); break;
case CQueryElement::notequal : bOK = (sValue != sCondValue); break;
case CQueryElement::contains: bOK = sValue.Find(sCondValue) != -1; break;
case CQueryElement::notcontains: bOK = sValue.Find(sCondValue) == -1; break;
}
}
if (!bOK) return FALSE;
}
}
}
pElement = pElement->GetNextQuery();
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// Determines if any attributes or conditions of the ftype are selected in the
// query
//
BOOL CQueryResult::IsFTypeSelected(CQuery* pQuery, long lFType)
{
BOOL bFType = FALSE;
CQueryElement* pElement = pQuery;
while (pElement != NULL)
{
if (pElement->GetFTypeId() == lFType)
{
// Check if attribute selected
if (pElement->GetSelected())
{
if (pElement->GetDataType() == BDFTYPE ||
pElement->GetDataType() == BDFEATURE)
{
bFType = TRUE;
} else
{
return yes;
};
};
// Check if conditional
if (pElement->GetDataType() == BDLINK ||
pElement->GetDataType() == BDBOOLEAN)
{
CQueryLink* pLink = (CQueryLink*)pElement;
for (int i = 0; i < pLink->m_aFeatures.GetSize(); i++)
{
if (!pLink->m_aFeatures[i].GetSelected()) return yes;
}
}
// Check for numerical conditions
if (pElement->GetCond() != CQueryElement::none)
{
return yes;
}
}
// Check if statistics require the feature type
if (pElement->GetDataType() == BDQUERYSTATS)
{
CQueryStats* pStats = (CQueryStats*)pElement;
if (pStats->GetFTypeId() == lFType ||
pStats->GetFTypeId2() == lFType)
{
return yes;
}
}
pElement = pElement->GetNextQuery();
}
if (bFType) return ftype;
else return no;
}
///////////////////////////////////////////////////////////////////////////////
//
// CQueryResult::UpdateDates
//
// This function, according to the date condition, will replace the existing
// attributes retrieved, or
int CQueryResult::UpdateDates(CQuery* pQuery, CAttrArray& aAttr, CQueryAttrArray* pAttrArray)
{
BOOL nStatus = Replace;
// Check the dates
if (pAttrArray->GetSize() > 0 && pAttrArray->m_dateActive.IsValid())
{
CDateTime dtC = pAttrArray->m_dateActive;
CDateTime dtN = CDateTime(aAttr.m_lDate, 0);
switch (m_pQuery->GetDateCond())
{
case CQuery::FirstDate : case CQuery::FirstDateRange :
if (dtN > dtC) nStatus = Keep;
if (dtN == dtC) nStatus = New;
break;
case CQuery::LastDate : case CQuery::LastDateRange :
if (dtN < dtC) nStatus = Keep;
if (dtN == dtC) nStatus = New;
break;
default :
if (m_bBaseFType) nStatus = New;
break;
};
}
// If okay then delete the existing attributes with this feature
// type
if (nStatus == Replace)
{
// Remove all attributes for this ftype except BDFEATURE
for (int i = 0; i < pAttrArray->GetSize(); i++)
{
CAttribute* pAttr = pAttrArray->GetAt(i);
if (pAttr->GetFTypeId() == pQuery->GetFType() &&
pAttr->GetDataType() != BDFEATURE)
{
delete pAttr;
pAttrArray->RemoveAt(i);
i--;
}
};
};
// When dates are the same create a 2nd feature, this will be added to the
// end of the queryresult list and so will have its attributes updated later
// in the list
if (nStatus == New)
{
CQueryAttrArray* pQAA = new CQueryAttrArray(*pAttrArray);
pQAA->m_lDate = 0; // Causes data to be overwritten
pQAA->m_dateActive = CDateTime(0,0);
for (int i = 0; i < pQAA->GetSize(); i++)
{
CAttribute* pAttr = pQAA->GetAt(i);
if (pAttr->GetDataType() != BDFEATURE)
{
delete pAttr;
pQAA->RemoveAt(i);
i--;
}
}
Add(pQAA);
}
return nStatus;
}
///////////////////////////////////////////////////////////////////////////////
//
// Retrieve the features named in the query. This is separate from data as
// some parent attributes may have no attributes set
//
void CQueryResult::RetrieveFeatures(CQuery* pQuery, CQueryAttrArray* pAttrArray)
{
// Ensure that the feature does not already exist
// (one to one or both BDFTYPE & BDFEATURE selected)
for (int i = 0; i < pAttrArray->GetSize(); i++)
{
if (pAttrArray->GetAt(i)->GetAttrId() == BDFEATURE &&
pAttrArray->GetAt(i)->GetFTypeId() == pQuery->GetFType())
{
return;
}
}
// Searh to see if the ftype is selected
CQueryElement* pElement = pQuery;
while (pElement != NULL)
{
if ((pElement->GetDataType() == BDFTYPE ||
pElement->GetDataType() == BDFEATURE) &&
pElement->GetSelected())
{
// Insert the feature at the beginning
CAttribute* pAttr = new CAttribute(BDFEATURE);
pAttr->SetAttrId(BDFEATURE);
pAttr->SetFTypeId(pQuery->GetFType());
pAttr->SetDesc(pAttrArray->m_sFeatureActive);
pAttrArray->InsertAt(0, pAttr);
break;
}
// Get next element
pElement = pElement->GetNextQuery();
if (pElement != NULL && pElement->GetDataType() == BDFTYPE) break;
}
}
///////////////////////////////////////////////////////////////////////////////
BOOL CQueryResult::RetrieveAttr(CQuery* pQuery, CAttrArray& aAttr,
CQueryAttrArray* pAttrArray)
{
BOOL bOK = TRUE;
BOOL bFound = FALSE;
CString sDate, sTime;
// Determine which attributes are required
CQueryElement* pElement = pQuery;
ASSERT(pElement != NULL);
do
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -