Files
openGauss-server/src/gausskernel/runtime/vecexecutor/vecnode/vecplainagg.cpp
2021-09-23 15:19:37 +08:00

278 lines
8.2 KiB
C++

/*
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ---------------------------------------------------------------------------------------
*
* vecplainagg.cpp
* Routines to handle vector plain aggregae nodes.
*
* IDENTIFICATION
* Code/src/gausskernel/runtime/vecexecutor/vecnode/vecplainagg.cpp
*
* ---------------------------------------------------------------------------------------
*/
#include "postgres.h"
#include "knl/knl_variable.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/node/nodeAgg.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
#include "parser/parse_agg.h"
#include "parser/parse_coerce.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/tuplesort.h"
#include "utils/datum.h"
#include "utils/numeric.h"
#include "utils/numeric_gs.h"
#include "vecexecutor/vechashagg.h"
#include "vecexecutor/vechashtable.h"
#include "vecexecutor/vecexecutor.h"
#include "vecexecutor/vecfunc.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "nodes/execnodes.h"
#include "pgxc/pgxc.h"
#include "utils/int8.h"
#include "vecexecutor/vecplainagg.h"
void PlainAggRunner::BindingFp()
{
if (m_hasDistinct) {
plainAggregation = &PlainAggRunner::RunPlain<true>;
} else {
plainAggregation = &PlainAggRunner::RunPlain<false>;
}
}
/*
* @Description: plain Agg constructed function.
*/
PlainAggRunner::PlainAggRunner(VecAggState* runtime) : BaseAggRunner(runtime, false)
{
hashCell* cell = NULL;
Assert(m_key == 0);
m_runtime->phase = &m_runtime->phases[m_runtime->current_phase];
/* Init sort state to distinct operate. count(distinct) e.g */
initialize_sortstate(
u_sess->attr.attr_memory.work_mem, 0, runtime->ss.ps.plan->plan_node_id, SET_DOP(runtime->ss.ps.plan->dop));
m_hashTbl = New(CurrentMemoryContext) vechashtable(Max(m_runtime->phase->numsets, 1));
for (int i = 0; i < m_hashTbl->m_size; i++) {
cell = (hashCell*)palloc0(m_cellSize);
m_hashTbl->m_data[i] = cell;
cell->flag.m_next = NULL;
/* set the init value. */
for (int k = 0; k < m_aggNum; k++) {
if (m_aggCount[k]) {
cell->m_val[m_aggIdx[k]].val = 0;
SET_NOTNULL(cell->m_val[m_aggIdx[k]].flag);
} else
SET_NULL(cell->m_val[m_aggIdx[k]].flag);
}
}
BindingFp();
}
/*
* @Description: compute agg.
*/
template <bool hasDistinct>
void PlainAggRunner::buildPlaintAgg(VectorBatch* outer_batch, bool first_batch)
{
ScalarVector* p_vector = NULL;
hashCell* cell = NULL;
hashCell** hash_data = m_hashTbl->m_data;
int numset = Max(m_runtime->phase->numsets, 1);
for (int i = 0; i < numset; i++) {
cell = hash_data[i];
for (int k = 0; k < BatchMaxSize; k++) {
m_Loc[k] = cell;
}
if (m_cellVarLen > 0 && first_batch) {
for (int k = 0; k < m_cellVarLen; k++) {
p_vector = &outer_batch->m_arr[m_cellBatchMap[k]];
cell->m_val[k].val = p_vector->m_vals[0];
cell->m_val[k].flag = p_vector->m_flag[0];
}
}
if (hasDistinct) {
m_sortDistinct[i].m_distinctLoc = cell;
AppendBatchForSortAgg(outer_batch, 0, outer_batch->m_rows, i);
BatchNoSortAgg(outer_batch);
} else {
BatchAggregation(outer_batch);
}
}
}
/*
* @Description: get data, compute agg and return result.
*/
template <bool hasDistinct>
VectorBatch* PlainAggRunner::RunPlain()
{
if (m_finish) {
return NULL;
}
VectorBatch* outer_batch = NULL;
VectorBatch* res_batch = NULL;
PlanState* outPlan = NULL;
bool first_batch = true;
hashCell** hash_data = m_hashTbl->m_data;
outPlan = outerPlanState(m_runtime);
while (true) {
switch (m_runState) {
case AGG_PREPARE: {
for (;;) {
outer_batch = VectorEngine(outPlan);
if (unlikely(BatchIsNull(outer_batch))) {
if (hasDistinct) {
int numset = Max(m_runtime->phase->numsets, 1);
for (int i = 0; i < numset; i++) {
BatchSortAggregation(i,
u_sess->attr.attr_memory.work_mem,
false,
m_runtime->ss.ps.plan->plan_node_id,
SET_DOP(m_runtime->ss.ps.plan->dop));
}
}
break;
}
/* Compute aggregation */
buildPlaintAgg<hasDistinct>(outer_batch, first_batch);
first_batch = false;
}
m_projected_set = 0;
m_runState = AGG_FETCH;
break;
}
case AGG_FETCH: {
int numset = Max(m_runtime->phase->numsets, 1);
if (m_projected_set < numset) {
m_runtime->projected_set = m_projected_set;
m_scanBatch->Reset();
ResetExprContext(m_runtime->ss.ps.ps_ExprContext);
InvokeFp(m_buildScanBatch)(hash_data[m_projected_set]);
res_batch = ProducerBatch();
m_projected_set++;
return res_batch;
}
m_finish = true;
return NULL;
}
default:
break;
}
}
}
/*
* @Description: entrance function of plain agg.
*/
VectorBatch* PlainAggRunner::Run()
{
return InvokeFp(plainAggregation)();
}
/*
* @Description: plain agg reset.
* @in node: Current agg node.
*/
bool PlainAggRunner::ResetNecessary(VecAggState* node)
{
VecAgg* aggnode = (VecAgg*)node->ss.ps.plan;
m_finish = false;
/*
* If lefttree chgParam is not null, or parameter changes affect
* input expressions of the aggregated functions; we need rescan
* lower node.
*/
if (node->ss.ps.lefttree->chgParam == NULL && aggnode->aggParams == NULL) {
m_runState = AGG_FETCH;
m_projected_set = 0;
return false;
}
/* And rebuild empty hashtable if needed */
m_runState = AGG_PREPARE;
int hash_size = m_hashTbl->m_size;
delete m_hashTbl;
m_hashTbl = New(CurrentMemoryContext) vechashtable(hash_size);
hashCell** hash_data = m_hashTbl->m_data;
hashCell* cell = NULL;
for (int i = 0; i < hash_size; i++) {
cell = (hashCell*)palloc0(m_cellSize);
hash_data[i] = cell;
cell->flag.m_next = NULL;
/* set the init value. */
for (int k = 0; k < m_aggNum; k++) {
if (m_aggCount[k]) {
cell->m_val[m_aggIdx[k]].val = 0;
SET_NOTNULL(cell->m_val[m_aggIdx[k]].flag);
} else
SET_NULL(cell->m_val[m_aggIdx[k]].flag);
}
}
return true;
}
/*
* @Description: plain agg end, free resources.
*/
void PlainAggRunner::endPlainAgg()
{
int setno;
int num_grouping_sets = Max(m_runtime->maxsets, 1);
if (m_sortDistinct) {
for (setno = 0; setno < num_grouping_sets; setno++) {
for (int i = 0; i < m_aggNum; i++) {
if (m_sortDistinct[setno].batchsortstate[i]) {
batchsort_end(m_sortDistinct[setno].batchsortstate[i]);
m_sortDistinct[setno].batchsortstate[i] = NULL;
}
}
}
}
}