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:
parent
4da4114ee4
commit
cf4e283f7d
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user