📄 query.cpp
字号:
//
CString CQuery::GetQueryName()
{
CString sFeature, sAttr, sName;
int iFeature = 0;
int iAttr = 0;
long lParentFeature = 0;
CFeature feature;
CFeatureType ftype;
// Feature type name
CQueryElement* pElement = this;
while (pElement != NULL)
{
// Determine how many features are selected, if only one then include
// in name
if (pElement->GetDataType() == BDFEATURE)
{
CQueryLink* pLink = (CQueryLink*)pElement;
for (int i = 0; i < pLink->m_aFeatures.GetSize(); i++)
{
if (pLink->m_aFeatures.GetAt(i).GetSelected())
{
iFeature++;
sFeature = pLink->m_aFeatures.GetAt(i).m_sName;
if (lParentFeature == 0)
lParentFeature = pLink->m_aFeatures.GetAt(i).m_lParentFeature;
else if (lParentFeature != pLink->m_aFeatures.GetAt(i).m_lParentFeature)
lParentFeature = -1;
}
}
}
// Determine how many attributes are selected, if only one then include in name
if (pElement->GetSelected() && (pElement->GetDataType() == BDNUMBER ||
pElement->GetDataType() == BDTEXT ||
pElement->GetDataType() == BDLONGTEXT ||
pElement->GetDataType() == BDLINK ||
pElement->GetDataType() == BDBOOLEAN))
{
iAttr++;
sAttr = pElement->GetDesc();
}
if (pElement->GetDataType() == BDQUERYSTATS)
{
iAttr++;
sAttr = pElement->GetDesc();
}
pElement = pElement->GetNextQuery();
}
// Create name
if (iAttr == 1)
{
sName = sAttr;
}
// Add feature name
if (iFeature == 1)
{
sFeature.TrimRight();
sName = sFeature;
}
if (sName == "") sName = GetDesc();
// If only one parent feature then include in the name
if (lParentFeature > 0)
{
BDFTypeParentI(BDHandle(), m_lFType, &ftype);
feature.m_lId = lParentFeature;
feature.m_lFeatureTypeId = ftype.m_lId;
BDFeature(BDHandle(), &feature, BDSELECT);
BDEnd(BDHandle());
feature.m_sName.TrimRight();
sName += ", " + feature.m_sName;
}
// Strip square brackets
CString str = CQuery::StripBrackets(sName);
return str;
}
///////////////////////////////////////////////////////////////////////////////
//
// For each feature in the query add an attribute array to the list
//
BOOL CQueryResult::InitFeatures(CQuery* pQuery)
{
CQueryElement* pElement = pQuery;
while (pElement != NULL)
{
if (pElement->GetDataType() == BDFEATURE)
{
CQueryLink* pLink = (CQueryLink*)pElement;
for (int i = 0; i < pLink->m_aFeatures.GetSize(); i++)
{
CQueryFeature *pFeature = &pLink->m_aFeatures[i];
if (pFeature->GetSelected())
{
CQueryAttrArray* pQAA = new CQueryAttrArray(pFeature->m_sName);
pQAA->m_lFeature = pFeature->m_lId;
pQAA->m_lFeatureActive = pFeature->m_lId;
pQAA->m_sFeature = pFeature->m_sName;
pQAA->m_sFeatureActive = pFeature->m_sName;
pQAA->m_lParentFeatureActive = pFeature->m_lParentFeature;
Add(pQAA);
}
}
break;
};
pElement = pElement->GetNextQuery();
};
return pElement != NULL;
}
///////////////////////////////////////////////////////////////////////////////
BOOL CQueryResult::RetrieveData(CQuery* pQuery)
{
BOOL bOK = TRUE;
CFeature feature;
CFeatureType ftype;
m_bBaseFType = TRUE;
// Firstly determine which attributes are selected for all feature types
CQueryElement* pElement = pQuery;
int iAttr = -1;
while (pElement != NULL)
{
CQueryAttrSel attrsel;
if (pElement->GetSelected())
{
attrsel.m_lAttr = pElement->GetAttrId();
attrsel.m_lFType = pElement->GetFTypeId();
attrsel.m_lDataType = pElement->GetDataType();
};
if (pElement->GetDataType() == BDQUERYSTATS)
{
attrsel.m_lAttr = iAttr--;
attrsel.m_lFType = m_pQuery->GetFTypeId();
attrsel.m_lDataType = BDNUMBER;
}
if (pElement->GetSelected() || pElement->GetDataType() == BDQUERYSTATS)
{
attrsel.m_nGroupBy = pElement->GetGroupBy();
attrsel.m_nSortBy = pElement->GetSortBy();
attrsel.m_nStatGroup = pElement->GetGroupStat();
m_aAttrSel.Add(attrsel);
};
pElement = pElement->GetNextQuery();
};
// Retrieve the data for these attributes, even if no attributes are
// selected as the feature may be removed if conditions are not met
bOK = LoadDataAll(pQuery, pQuery->GetFType());
// Set the date
for (int i = 0; i < GetSize(); i++)
{
if (GetAt(i)->m_dateActive.IsValid())
{
GetAt(i)->m_lDate = GetAt(i)->m_dateActive.GetDateLong();
};
};
// Retrieve attributes for remaining feature types
m_bBaseFType = FALSE;
while (bOK && pQuery != NULL)
{
// Determine if the feature is one to one or one to many
ftype.m_lId = pQuery->GetFType();
BDFeatureType(BDHandle(), &ftype, BDSELECT);
BDEnd(BDHandle());
// Determine next element
pQuery = (CQuery*)pQuery->GetNextQuery();
while (pQuery != NULL && pQuery->GetDataType() != BDFTYPE)
{
pQuery = (CQuery*)pQuery->GetNextQuery();
}
if (pQuery != NULL)
{
// Reset dates
for (i = 0; i < GetSize(); i++)
{
GetAt(i)->m_dateActive = CDateTime(0,0);
};
// Change the active feature to the parent feature for the type
if (ftype.m_bManyToOne)
{
// Update active features
for (int i = 0; i < GetSize(); i++)
{
GetAt(i)->m_lFeatureActive = GetAt(i)->m_lParentFeatureActive;
}
// Reset the parent names incase parent feature cannot be found!
for (i = 0; i < GetSize(); i++)
{
GetAt(i)->m_sFeatureActive = "";
}
// Update name and parent of features
feature.m_lFeatureTypeId = pQuery->GetFType();
BOOL bFound = BDFeature(BDHANDLE(), &feature, BDSELECT2);
while (bFound)
{
for (int i = 0; i < GetSize(); i++)
{
if (GetAt(i)->m_lFeatureActive == feature.m_lId)
{
GetAt(i)->m_lParentFeatureActive = feature.m_lParentFeature;
GetAt(i)->m_sFeatureActive = feature.m_sName;
}
};
bFound = BDGetNext(BDHandle());
}
BDEnd(BDHandle());
};
// Retrieve the data for the parent feature type
ASSERT(pQuery->GetDataType() == BDFTYPE);
bOK = LoadDataAll(pQuery, pQuery->GetFType());
};
};
return bOK;
}
///////////////////////////////////////////////////////////////////////////////
//
// This is a faster way of retrieving large numbers of values.
// Retrieves the attributes for all features rather than querying for every one
//
BOOL CQueryResult::LoadDataAll(CQuery* pQuery, long lFType)
{
CAttrArray aAttr;
CFeature feature;
BOOL bOK = TRUE;
long lFeatureMin, lFeatureMax;
int iCount = 0;
// Display name of ftype
CString s = pQuery->GetDesc();
BDProgressText("Loading " + s.Left(s.Find('[')) + "...");
// No need to load if no features
if (GetSize() == 0) return FALSE;
// Retrieve the selected feature names for the query
for (int i = 0; i < GetSize(); i++)
{
RetrieveFeatures(pQuery, GetAt(i));
}
// If no attributes or conditions selected then no need to load data
// This also handles where parent features have no attributes set
int nRet = IsFTypeSelected(pQuery, lFType);
if (!m_bBaseFType && nRet != yes)
{
return TRUE;
}
// Re-initialise the 'conditions met' flags
for (i = 0; i < GetSize(); i++)
{
CQueryAttrArray* pAttrArray = GetAt(i);
pAttrArray->SetCondMet(FALSE);
}
// Determine the maximum and minimum feature ids
ASSERT(GetSize() > 0);
lFeatureMax = lFeatureMin = GetAt(0)->GetActiveFeature();
for (i = 0; i < GetSize(); i++)
{
lFeatureMin = min(lFeatureMin, GetAt(i)->GetActiveFeature());
lFeatureMax = max(lFeatureMax, GetAt(i)->GetActiveFeature());
}
// Initialise attribute array
BDFTypeAttrInit(BDHandle(), lFType, &aAttr);
// Retrieve all data and then extract what is needed
BDProgressRange(0, GetSize());
CString sFilter;
sFilter = GetQueryFilter(pQuery, aAttr);
BOOL bFound = BDAttributeCond(BDHandle(), &aAttr, lFeatureMin, lFeatureMax, sFilter, BDGETINIT);
while (bFound && bOK)
{
// For each record, determine whether the feature is selected
for (int i = 0; i < GetSize(); i++)
{
CQueryAttrArray* pAttrArray = GetAt(i);
if (aAttr.m_lFeature == pAttrArray->GetActiveFeature())
{
// Check the conditions imposed are valid
if (CheckConditions(pQuery, aAttr)
&& CheckValueCond(pQuery, aAttr)
)
{
// Check the conditions are met
pAttrArray->SetCondMet();
// If so determine whether the data is to replace the existing
// data, or to be created as a new feature
int nStatus = UpdateDates(pQuery, aAttr, pAttrArray);
if (nStatus == Replace)
{
RetrieveAttr(pQuery, aAttr, pAttrArray);
}
// If a new reading then set the count to the penultimate value
// to prevent more than one new value being created
else if (nStatus == New)
{
i = GetSize()-2;
}
// Where the required data already exists, fill in missing attributes
else if (nStatus == Keep)
{
RetrieveMissing(pQuery, aAttr, pAttrArray);
}
if (!BDProgressPos(iCount++)) bOK = FALSE;
if (iCount >= GetSize())
{
iCount = 0;
BDProgressRange(0,GetSize());
};
}
}
}
bFound = BDGetNext(BDHandle());
}
BDEnd(BDHandle());
BDProgressRange(0,0);
// Remove all features with no data
for (i = 0; i < GetSize(); i++)
{
CQueryAttrArray* pAttrArray = GetAt(i);
if (!pAttrArray->GetCondMet())
{
if (!m_pQuery->IsShowAllFeatures())
{
delete pAttrArray;
RemoveAt(i);
i--;
} else
{
InitNullAttr(pQuery, aAttr, pAttrArray);
}
};
};
return bOK;
}
///////////////////////////////////////////////////////////////////////////////
//
// Creates a filter for the SQL query to optimise the retrieval of data
// accordinate to conditions
//
CString CQueryResult::GetQueryFilter(CQuery* pQuery, CAttrArray& aAttr)
{
CString sFilter;
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())
{
// Check numerical conditions
if (aAttr.GetAt(i)->GetDataType() == BDNUMBER)
{
double dValue = *aAttr.GetAt(i)->GetDouble();
double dCondValue = pElement->GetCondValue();
// Column name
if (sFilter != "") sFilter += " and ";
sFilter += "`" + CString(pElement->GetColName()) + "`";
// Condition
switch (pElement->GetCond())
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -