8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 23:23:04 +01:00

Do not reuse arbitrary nodes' impure space in aggregate. Relates to CORE-3255.

This commit is contained in:
asfernandes 2011-02-09 00:29:46 +00:00
parent aa74283e5d
commit 67f9c9b31d
2 changed files with 33 additions and 34 deletions

View File

@ -79,6 +79,15 @@ void AggregatedStream::open(thread_db* tdbb) const
impure->pending = 0; impure->pending = 0;
VIO_record(tdbb, &request->req_rpb[m_stream], m_format, tdbb->getDefaultPool()); VIO_record(tdbb, &request->req_rpb[m_stream], m_format, tdbb->getDefaultPool());
unsigned impureCount = m_group ? m_group->getCount() : 0;
impureCount += m_order ? m_order->getCount() : 0;
if (!impure->impureValues)
{
impure->impureValues = FB_NEW(*tdbb->getDefaultPool()) impure_value[impureCount];
memset(impure->impureValues, 0, sizeof(impure_value) * impureCount);
}
m_next->open(tdbb); m_next->open(tdbb);
} }
@ -271,8 +280,7 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, Aggrega
if (--tdbb->tdbb_quantum < 0) if (--tdbb->tdbb_quantum < 0)
JRD_reschedule(tdbb, 0, true); JRD_reschedule(tdbb, 0, true);
impure_value vtemp; Impure* const impure = request->getImpure<Impure>(m_impure);
vtemp.vlu_string = NULL;
// if we found the last record last time, we're all done // if we found the last record last time, we're all done
@ -317,38 +325,43 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, Aggrega
} }
} }
unsigned impureOffset = 0;
const NestConst<ValueExprNode>* ptrValue, *endValue; const NestConst<ValueExprNode>* ptrValue, *endValue;
dsc* desc; dsc* desc;
if (m_group) if (m_group)
{ {
for (ptrValue = m_group->begin(), endValue = m_group->end(); ptrValue != endValue; ++ptrValue) for (ptrValue = m_group->begin(), endValue = m_group->end();
ptrValue != endValue;
++ptrValue, ++impureOffset)
{ {
const ValueExprNode* from = *ptrValue; const ValueExprNode* from = *ptrValue;
impure_value* impure = request->getImpure<impure_value>(from->impureOffset); impure_value* target = &impure->impureValues[impureOffset];
desc = EVL_expr(tdbb, request, from); desc = EVL_expr(tdbb, request, from);
if (request->req_flags & req_null) if (request->req_flags & req_null)
impure->vlu_desc.dsc_address = NULL; target->vlu_desc.dsc_address = NULL;
else else
EVL_make_value(tdbb, desc, impure); EVL_make_value(tdbb, desc, target);
} }
} }
if (m_order) if (m_order)
{ {
for (ptrValue = m_order->begin(), endValue = m_order->end(); ptrValue != endValue; ++ptrValue) for (ptrValue = m_order->begin(), endValue = m_order->end();
ptrValue != endValue;
++ptrValue, ++impureOffset)
{ {
const ValueExprNode* from = *ptrValue; const ValueExprNode* from = *ptrValue;
impure_value* impure = request->getImpure<impure_value>(from->impureOffset); impure_value* target = &impure->impureValues[impureOffset];
desc = EVL_expr(tdbb, request, from); desc = EVL_expr(tdbb, request, from);
if (request->req_flags & req_null) if (request->req_flags & req_null)
impure->vlu_desc.dsc_address = NULL; target->vlu_desc.dsc_address = NULL;
else else
EVL_make_value(tdbb, desc, impure); EVL_make_value(tdbb, desc, target);
} }
} }
@ -358,6 +371,7 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, Aggrega
while (state != STATE_EOF_FOUND) while (state != STATE_EOF_FOUND)
{ {
impureOffset = 0;
state = STATE_PENDING; state = STATE_PENDING;
if (first) if (first)
@ -371,22 +385,16 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, Aggrega
{ {
for (ptrValue = m_group->begin(), endValue = m_group->end(); for (ptrValue = m_group->begin(), endValue = m_group->end();
ptrValue != endValue; ptrValue != endValue;
++ptrValue) ++ptrValue, ++impureOffset)
{ {
const ValueExprNode* from = *ptrValue; const ValueExprNode* from = *ptrValue;
impure_value* impure = request->getImpure<impure_value>(from->impureOffset); impure_value* vtemp = &impure->impureValues[impureOffset];
if (impure->vlu_desc.dsc_address)
EVL_make_value(tdbb, &impure->vlu_desc, &vtemp);
else
vtemp.vlu_desc.dsc_address = NULL;
desc = EVL_expr(tdbb, request, from); desc = EVL_expr(tdbb, request, from);
if (request->req_flags & req_null) if (request->req_flags & req_null)
{ {
impure->vlu_desc.dsc_address = NULL; if (vtemp->vlu_desc.dsc_address)
if (vtemp.vlu_desc.dsc_address)
{ {
if (m_order) if (m_order)
state = STATE_GROUPING; state = STATE_GROUPING;
@ -395,8 +403,7 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, Aggrega
} }
else else
{ {
EVL_make_value(tdbb, desc, impure); if (!vtemp->vlu_desc.dsc_address || MOV_compare(&vtemp->vlu_desc, desc) != 0)
if (!vtemp.vlu_desc.dsc_address || MOV_compare(&vtemp.vlu_desc, desc))
{ {
if (m_order) if (m_order)
state = STATE_GROUPING; state = STATE_GROUPING;
@ -410,28 +417,21 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, Aggrega
{ {
for (ptrValue = m_order->begin(), endValue = m_order->end(); for (ptrValue = m_order->begin(), endValue = m_order->end();
ptrValue != endValue; ptrValue != endValue;
++ptrValue) ++ptrValue, ++impureOffset)
{ {
const ValueExprNode* from = *ptrValue; const ValueExprNode* from = *ptrValue;
impure_value* impure = request->getImpure<impure_value>(from->impureOffset); impure_value* vtemp = &impure->impureValues[impureOffset];
if (impure->vlu_desc.dsc_address)
EVL_make_value(tdbb, &impure->vlu_desc, &vtemp);
else
vtemp.vlu_desc.dsc_address = NULL;
desc = EVL_expr(tdbb, request, from); desc = EVL_expr(tdbb, request, from);
if (request->req_flags & req_null) if (request->req_flags & req_null)
{ {
impure->vlu_desc.dsc_address = NULL; if (vtemp->vlu_desc.dsc_address)
if (vtemp.vlu_desc.dsc_address)
goto break_out; goto break_out;
} }
else else
{ {
EVL_make_value(tdbb, desc, impure); if (!vtemp->vlu_desc.dsc_address || MOV_compare(&vtemp->vlu_desc, desc) != 0)
if (!vtemp.vlu_desc.dsc_address || MOV_compare(&vtemp.vlu_desc, desc))
goto break_out; goto break_out;
} }
} }
@ -470,8 +470,6 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, Aggrega
// Finish up any residual computations and get out // Finish up any residual computations and get out
delete vtemp.vlu_string;
for (const NestConst<ValueExprNode>* source = m_map->sourceList.begin(), for (const NestConst<ValueExprNode>* source = m_map->sourceList.begin(),
*target = m_map->targetList.begin(); *target = m_map->targetList.begin();
source != sourceEnd; source != sourceEnd;

View File

@ -603,6 +603,7 @@ namespace Jrd
{ {
State state; State state;
FB_UINT64 pending; FB_UINT64 pending;
impure_value* impureValues;
}; };
public: public: