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

Separate aggregate/union maps from window maps

This commit is contained in:
asfernandes 2010-01-21 18:33:18 +00:00
parent 4da4114ee4
commit cf4e283f7d
3 changed files with 79 additions and 72 deletions

View File

@ -657,6 +657,7 @@ public:
currCtes(p),
recursiveCtx(0),
recursiveCtxId(0),
processingWindow(false),
ctes(p),
cteAliases(p),
currCteAlias(NULL),
@ -768,6 +769,7 @@ public:
DsqlNodStack currCtes; // current processing CTE's
class dsql_ctx* recursiveCtx; // context of recursive CTE
USHORT recursiveCtxId; // id of recursive union stream context
bool processingWindow; // processing window functions
private:
Firebird::HalfStaticArray<dsql_nod*, 4> ctes; // common table expressions
@ -823,9 +825,9 @@ public:
dsql_ctx* visibleInContext;
};
struct NodeMap
struct PartitionMap
{
NodeMap(dsql_nod* aPartition)
PartitionMap(dsql_nod* aPartition)
: partition(aPartition),
partitionRemapped(NULL),
map(NULL),
@ -844,17 +846,17 @@ class dsql_ctx : public pool_alloc<dsql_type_ctx>
{
public:
explicit dsql_ctx(MemoryPool& p)
: ctx_maps(p),
ctx_main_derived_contexts(p),
: ctx_main_derived_contexts(p),
ctx_childs_derived_table(p),
ctx_imp_join(p)
ctx_imp_join(p),
ctx_win_maps(p)
{
}
dsql_rel* ctx_relation; // Relation for context
dsql_prc* ctx_procedure; // Procedure for context
dsql_nod* ctx_proc_inputs; // Procedure input parameters
mutable Firebird::Array<NodeMap*> ctx_maps; // Maps for aggregates and windows
dsql_map* ctx_map; // Maps for aggregates and unions
dsql_nod* ctx_rse; // Sub-rse for aggregates
dsql_ctx* ctx_parent; // Parent context for aggregates
const TEXT* ctx_alias; // Context alias (can include concatenated derived table alias)
@ -868,13 +870,14 @@ public:
DsqlContextStack ctx_childs_derived_table; // Childs derived table context
Firebird::GenericMap<Firebird::Pair<Firebird::Left<
Firebird::MetaName, ImplicitJoin*> > > ctx_imp_join; // Map of USING fieldname to ImplicitJoin
Firebird::Array<PartitionMap*> ctx_win_maps; // Maps for window functions
dsql_ctx& operator=(dsql_ctx& v)
{
ctx_relation = v.ctx_relation;
ctx_procedure = v.ctx_procedure;
ctx_proc_inputs = v.ctx_proc_inputs;
ctx_maps.assign(v.ctx_maps);
ctx_map = v.ctx_map;
ctx_rse = v.ctx_rse;
ctx_parent = v.ctx_parent;
ctx_alias = v.ctx_alias;
@ -886,12 +889,13 @@ public:
ctx_main_derived_contexts.assign(v.ctx_main_derived_contexts);
ctx_childs_derived_table.assign(v.ctx_childs_derived_table);
ctx_imp_join.assign(v.ctx_imp_join);
ctx_win_maps.assign(v.ctx_win_maps);
return *this;
}
bool getImplicitJoinField(const Firebird::MetaName& name, dsql_nod*& node);
NodeMap* getNodeMap(DsqlCompilerScratch* dsqlScratch, dsql_nod* partitionNode) const;
PartitionMap* getPartitionMap(DsqlCompilerScratch* dsqlScratch, dsql_nod* partitionNode);
};
// Flag values for ctx_flags
@ -907,10 +911,10 @@ const USHORT CTX_recursive = 0x10; // Context has secondary number (ctx_recursiv
class dsql_map : public pool_alloc<dsql_type_map>
{
public:
dsql_map* map_next; // Next map in item
dsql_nod* map_node; // Value for map item
USHORT map_position; // Position in map
NodeMap* map_nodemap;
dsql_map* map_next; // Next map in item
dsql_nod* map_node; // Value for map item
USHORT map_position; // Position in map
PartitionMap* map_partition; // Partition
};
// Message block used in communicating with a running request

View File

@ -314,9 +314,14 @@ void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
case nod_map:
{
const dsql_map* map = (dsql_map*) node->nod_arg[e_map_map];
context = (dsql_ctx*) node->nod_arg[e_map_context];
stuff(dsqlScratch->getStatement(), blr_fid);
stuff(dsqlScratch->getStatement(), map->map_nodemap->context);
if (map->map_partition)
stuff(dsqlScratch->getStatement(), map->map_partition->context);
else
{
context = (dsql_ctx*) node->nod_arg[e_map_context];
stuff_context(dsqlScratch, context);
}
stuff_word(dsqlScratch->getStatement(), map->map_position);
}
return;
@ -1282,10 +1287,12 @@ static void gen_aggregate( DsqlCompilerScratch* dsqlScratch, const dsql_nod* nod
if (window)
{
fb_assert(context->ctx_maps.hasData());
stuff(statement, context->ctx_maps.getCount()); // number of windows
fb_assert(context->ctx_win_maps.hasData());
stuff(statement, context->ctx_win_maps.getCount()); // number of windows
for (Array<NodeMap*>::iterator i = context->ctx_maps.begin(); i != context->ctx_maps.end(); ++i)
for (Array<PartitionMap*>::iterator i = context->ctx_win_maps.begin();
i != context->ctx_win_maps.end();
++i)
{
stuff(statement, blr_partition_by);
dsql_nod* partition = (*i)->partition;
@ -1330,15 +1337,7 @@ static void gen_aggregate( DsqlCompilerScratch* dsqlScratch, const dsql_nod* nod
stuff(statement, 0);
}
dsql_map* map = NULL;
if (context->ctx_maps.hasData())
{
fb_assert(context->ctx_maps.getCount() == 1);
map = (*context->ctx_maps.begin())->map;
}
gen_map(dsqlScratch, map);
gen_map(dsqlScratch, context->ctx_map);
}
}
@ -3085,13 +3084,7 @@ static void stuff_context(DsqlCompilerScratch* dsqlScratch, const dsql_ctx* cont
ERRD_post(Arg::Gds(isc_too_many_contexts));
}
USHORT ctxNumber;
if (context->ctx_maps.hasData())
ctxNumber = context->getNodeMap(dsqlScratch, NULL)->context;
else
ctxNumber = context->ctx_context;
stuff(dsqlScratch->getStatement(), ctxNumber);
stuff(dsqlScratch->getStatement(), context->ctx_context);
if (context->ctx_flags & CTX_recursive)
{

View File

@ -8204,16 +8204,7 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
}
rse = parent_rse;
// Here we shouldn't have any window mapping. We could have 1 or no map for the aggregate.
size_t mapCount = parent_context->ctx_maps.getCount();
fb_assert(mapCount <= 1);
// If we have a map, copy it context number to ctx_context. If we haven't, generate it here.
// This is important for GEN/stuff_context.
if (mapCount == 1)
parent_context->ctx_context = parent_context->ctx_maps[0]->context;
else
parent_context->ctx_context = dsqlScratch->contextNumber++;
parent_context->ctx_context = dsqlScratch->contextNumber++;
}
bool sortWindow = rse->nod_arg[e_rse_sort] &&
@ -8223,6 +8214,8 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
if ((rse->nod_arg[e_rse_items] && aggregate_found(dsqlScratch, rse->nod_arg[e_rse_items], true)) ||
sortWindow)
{
AutoSetRestore<bool> autoProcessingWindow(&dsqlScratch->processingWindow, true);
parent_context = FB_NEW(*tdbb->getDefaultPool()) dsql_ctx(*tdbb->getDefaultPool());
parent_context->ctx_scope_level = dsqlScratch->scopeLevel;
dsql_nod* window = MAKE_node(nod_aggregate, e_agg_count);
@ -8277,14 +8270,14 @@ static dsql_nod* pass1_rse_impl( DsqlCompilerScratch* dsqlScratch, dsql_nod* inp
remap_fields(dsqlScratch, rse->nod_arg[e_rse_items], true, parent_context);
// Remap the nodes to the partition context.
for (size_t i = 0, mapCount = parent_context->ctx_maps.getCount(); i < mapCount; ++i)
for (size_t i = 0, mapCount = parent_context->ctx_win_maps.getCount(); i < mapCount; ++i)
{
NodeMap* nodeMap = parent_context->ctx_maps[i];
if (nodeMap->partition)
PartitionMap* partitionMap = parent_context->ctx_win_maps[i];
if (partitionMap->partition)
{
nodeMap->partitionRemapped = PASS1_node(dsqlScratch, nodeMap->partition);
nodeMap->partitionRemapped = remap_fields(dsqlScratch, nodeMap->partitionRemapped,
true, parent_context, nodeMap->partition);
partitionMap->partitionRemapped = PASS1_node(dsqlScratch, partitionMap->partition);
partitionMap->partitionRemapped = remap_fields(dsqlScratch,
partitionMap->partitionRemapped, true, parent_context, partitionMap->partition);
}
}
@ -8964,12 +8957,11 @@ static dsql_nod* pass1_union( DsqlCompilerScratch* dsqlScratch, dsql_nod* input,
map_node->nod_arg[e_map_map] = (dsql_nod*) map;
// set up the dsql_map* between the sub-rses and the union context.
NodeMap* nodeMap = union_context->getNodeMap(dsqlScratch, NULL);
map->map_position = count++;
map->map_node = *uptr++;
map->map_next = nodeMap->map;
map->map_nodemap = nodeMap;
nodeMap->map = map;
map->map_next = union_context->ctx_map;
map->map_partition = NULL;
union_context->ctx_map = map;
}
union_rse->nod_arg[e_rse_items] = union_items;
} // end scope block
@ -9858,20 +9850,31 @@ static dsql_nod* post_map(DsqlCompilerScratch* dsqlScratch, dsql_nod* node, dsql
thread_db* tdbb = JRD_get_thread_data();
NodeMap* nodeMap = context->getNodeMap(dsqlScratch, partitionNode);
PartitionMap* partitionMap = NULL;
dsql_map* map = NULL;
if (dsqlScratch->processingWindow)
{
partitionMap = context->getPartitionMap(dsqlScratch, partitionNode);
map = partitionMap->map;
}
else
map = context->ctx_map;
int count = 0;
for (map = nodeMap->map; map; map = map->map_next)
while (map)
{
if (node_match(node, map->map_node, false))
break;
++count;
map = map->map_next;
}
if (!map)
{
dsql_map** next = &nodeMap->map;
dsql_map** next = partitionMap ? &partitionMap->map : &context->ctx_map;
if (*next)
{
@ -9882,7 +9885,7 @@ static dsql_nod* post_map(DsqlCompilerScratch* dsqlScratch, dsql_nod* node, dsql
map = *next = FB_NEW(*tdbb->getDefaultPool()) dsql_map;
map->map_position = (USHORT) count;
map->map_node = node;
map->map_nodemap = nodeMap;
map->map_partition = partitionMap;
}
dsql_nod* new_node = MAKE_node(nod_map, e_map_count);
@ -10906,30 +10909,32 @@ bool dsql_ctx::getImplicitJoinField(const Firebird::MetaName& name, dsql_nod*& n
return true;
}
// Returns (creating, if necessary) the NodeMap of a given partition (that may be NULL).
NodeMap* dsql_ctx::getNodeMap(DsqlCompilerScratch* dsqlScratch, dsql_nod* partitionNode) const
// Returns (creating, if necessary) the PartitionMap of a given partition (that may be NULL).
PartitionMap* dsql_ctx::getPartitionMap(DsqlCompilerScratch* dsqlScratch, dsql_nod* partitionNode)
{
thread_db* tdbb = JRD_get_thread_data();
NodeMap* nodeMap = NULL;
PartitionMap* partitionMap = NULL;
for (Array<NodeMap*>::iterator i = ctx_maps.begin(); !nodeMap && i != ctx_maps.end(); ++i)
for (Array<PartitionMap*>::iterator i = ctx_win_maps.begin();
!partitionMap && i != ctx_win_maps.end();
++i)
{
if (((*i)->partition == NULL && partitionNode == NULL) ||
node_match((*i)->partition, partitionNode, false))
{
nodeMap = *i;
partitionMap = *i;
}
}
if (!nodeMap)
if (!partitionMap)
{
nodeMap = FB_NEW(*tdbb->getDefaultPool()) NodeMap(partitionNode);
ctx_maps.add(nodeMap);
nodeMap->context = dsqlScratch->contextNumber++;
partitionMap = FB_NEW(*tdbb->getDefaultPool()) PartitionMap(partitionNode);
ctx_win_maps.add(partitionMap);
partitionMap->context = dsqlScratch->contextNumber++;
}
return nodeMap;
return partitionMap;
}
#ifdef DSQL_DEBUG
@ -11687,12 +11692,17 @@ void DSQL_pretty(const dsql_nod* node, int column)
const dsql_ctx* context = (dsql_ctx*) node->nod_arg[e_agg_context];
trace_line("%s context %d\n", buffer, context->ctx_context);
for (NodeMap** nodeMap = context->ctx_maps.begin(); nodeMap != context->ctx_maps.end();
++nodeMap)
{
trace_line("%s nodemap\n", buffer);
trace_line("%s map\n", buffer);
if (context->ctx_map != NULL)
DSQL_pretty(context->ctx_map->map_node, column + 2);
dsql_map* map = (*nodeMap)->map;
for (PartitionMap* const* partitionMap = context->ctx_win_maps.begin();
partitionMap != context->ctx_win_maps.end();
++partitionMap)
{
trace_line("%s partitionMap\n", buffer);
dsql_map* map = (*partitionMap)->map;
if (map != NULL)
trace_line("%s map\n", buffer);