提交 87521715 编写于 作者: N Nikos Armenatzoglou

Codegen advance_aggregates for SUM transition function

Generate code for advance_aggregates function that supports
SUM on int4 and float8 datatypes.
This implementation doesn't support:
i) percentile and ordered aggregates, and
ii) NULL and pass-by-ref arguments.
上级 2043d95b
......@@ -179,6 +179,7 @@ set(GPCODEGEN_SRC
op_expr_tree_generator.cc
pg_date_func_generator.cc
var_expr_tree_generator.cc
advance_aggregates_codegen.cc
)
# Integrate with GPDB build system.
......
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2016 Pivotal Software, Inc.
//
// @filename:
// advance_aggregates_codegen.cc
//
// @doc:
// Generates code for AdvanceAggregates function.
//
//---------------------------------------------------------------------------
#include "codegen/advance_aggregates_codegen.h"
#include "codegen/op_expr_tree_generator.h"
#include "codegen/pg_func_generator_interface.h"
#include "codegen/utils/gp_codegen_utils.h"
#include "codegen/utils/utility.h"
extern "C" {
#include "postgres.h" // NOLINT(build/include)
#include "executor/nodeAgg.h"
#include "utils/palloc.h"
#include "executor/executor.h"
#include "nodes/nodes.h"
}
namespace llvm {
class BasicBlock;
class Function;
class Value;
} // namespace llvm
using gpcodegen::AdvanceAggregatesCodegen;
constexpr char AdvanceAggregatesCodegen::kAdvanceAggregatesPrefix[];
AdvanceAggregatesCodegen::AdvanceAggregatesCodegen(
CodegenManager* manager,
AdvanceAggregatesFn regular_func_ptr,
AdvanceAggregatesFn* ptr_to_regular_func_ptr,
AggState *aggstate)
: BaseCodegen(manager,
kAdvanceAggregatesPrefix,
regular_func_ptr,
ptr_to_regular_func_ptr),
aggstate_(aggstate) {
}
bool AdvanceAggregatesCodegen::GenerateAdvanceTransitionFunction(
gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Value* llvm_pergroup_arg,
int aggno,
llvm::Function* advance_aggregates_func,
llvm::BasicBlock* error_block,
llvm::Value *llvm_in_arg_ptr) {
auto irb = codegen_utils->ir_builder();
AggStatePerAgg peraggstate = &aggstate_->peragg[aggno];
// External functions
llvm::Function* llvm_MemoryContextSwitchTo =
codegen_utils->GetOrRegisterExternalFunction(MemoryContextSwitchTo,
"MemoryContextSwitchTo");
// Generation-time constants
llvm::Value *llvm_tuplecontext = codegen_utils->GetConstant<MemoryContext>(
aggstate_->tmpcontext->ecxt_per_tuple_memory);
// TODO(nikos): Current implementation does not support NULL attributes.
// Instead it errors out. Thus we do not need to check and implement the
// case that transition function is strict.
// oldContext = MemoryContextSwitchTo(tuplecontext);
llvm::Value *llvm_oldContext = irb->CreateCall(llvm_MemoryContextSwitchTo,
{llvm_tuplecontext});
// Retrieve pergroup's useful members
llvm::Value* llvm_pergroupstate = irb->CreateGEP(
llvm_pergroup_arg, {codegen_utils->GetConstant(
sizeof(AggStatePerGroupData) * aggno)});
llvm::Value* llvm_pergroupstate_transValue_ptr =
codegen_utils->GetPointerToMember(
llvm_pergroupstate, &AggStatePerGroupData::transValue);
llvm::Value* llvm_pergroupstate_transValueIsNull_ptr =
codegen_utils->GetPointerToMember(
llvm_pergroupstate, &AggStatePerGroupData::transValueIsNull);
llvm::Value* llvm_pergroupstate_noTransValue_ptr =
codegen_utils->GetPointerToMember(
llvm_pergroupstate, &AggStatePerGroupData::noTransValue);
if (!peraggstate->transtypeByVal) {
elog(DEBUG1, "We do not support pass-by-ref datatypes.");
return false;
}
// FunctionCallInvoke(fcinfo); {{
// We do not need to use a FunctionCallInfoData struct, since the supported
// aggregate functions are simple enough.
gpcodegen::PGFuncGeneratorInfo pg_func_info(
advance_aggregates_func,
error_block,
{irb->CreateLoad(llvm_pergroupstate_transValue_ptr),
irb->CreateLoad(llvm_in_arg_ptr)});
gpcodegen::PGFuncGeneratorInterface* pg_func_gen =
gpcodegen::OpExprTreeGenerator::GetPGFuncGenerator(
peraggstate->transfn.fn_oid);
if (nullptr == pg_func_gen) {
elog(DEBUG1, "We do not support built-in function with oid = %d",
peraggstate->transfn.fn_oid);
return false;
}
llvm::Value *newVal = nullptr;
bool isGenerated = pg_func_gen->GenerateCode(codegen_utils,
pg_func_info, &newVal);
if (!isGenerated) {
elog(DEBUG1, "Function with oid = %d was not generated successfully!",
peraggstate->transfn.fn_oid);
return false;
}
llvm::Value *result = codegen_utils->CreateCppTypeToDatumCast(newVal);
// }} FunctionCallInvoke
// MemoryContextSwitchTo(oldContext);
irb->CreateCall(llvm_MemoryContextSwitchTo, {llvm_oldContext});
// }}} advance_transition_function
// pergroupstate->transValue = newval
irb->CreateStore(result, llvm_pergroupstate_transValue_ptr);
// Currently we do not support null attributes.
// Thus we set transValueIsNull and noTransValue to false by default.
// TODO(nikos): Support null attributes.
irb->CreateStore(codegen_utils->GetConstant<bool>(false),
llvm_pergroupstate_transValueIsNull_ptr);
irb->CreateStore(codegen_utils->GetConstant<bool>(false),
llvm_pergroupstate_noTransValue_ptr);
return true;
}
bool AdvanceAggregatesCodegen::GenerateAdvanceAggregates(
gpcodegen::GpCodegenUtils* codegen_utils) {
assert(NULL != codegen_utils);
if (nullptr == aggstate_) {
return false;
}
auto irb = codegen_utils->ir_builder();
llvm::Function* advance_aggregates_func = CreateFunction<AdvanceAggregatesFn>(
codegen_utils, GetUniqueFuncName());
// BasicBlock of function entry.
llvm::BasicBlock* entry_block = codegen_utils->CreateBasicBlock(
"entry block", advance_aggregates_func);
llvm::BasicBlock* implementation_block = codegen_utils->CreateBasicBlock(
"implementation block", advance_aggregates_func);
llvm::BasicBlock* error_aggstate_block = codegen_utils->CreateBasicBlock(
"error aggstate block", advance_aggregates_func);
llvm::BasicBlock* overflow_block = codegen_utils->CreateBasicBlock(
"overflow block", advance_aggregates_func);
llvm::BasicBlock* null_attribute_block = codegen_utils->CreateBasicBlock(
"null attribute block", advance_aggregates_func);
// External functions
llvm::Function* llvm_ExecTargetList =
codegen_utils->GetOrRegisterExternalFunction(ExecTargetList,
"ExecTargetList");
llvm::Function* llvm_ExecVariableList =
codegen_utils->GetOrRegisterExternalFunction(ExecVariableList,
"ExecVariableList");
// Function argument to advance_aggregates
llvm::Value* llvm_aggstate_arg = ArgumentByPosition(
advance_aggregates_func, 0);
llvm::Value* llvm_pergroup_arg = ArgumentByPosition(
advance_aggregates_func, 1);
// Generation-time constants
llvm::Value* llvm_aggstate = codegen_utils->GetConstant(aggstate_);
// entry block
// ----------
irb->SetInsertPoint(entry_block);
#ifdef CODEGEN_DEBUG
codegen_utils->CreateElog(DEBUG1, "Codegen'ed advance_aggregates called!");
#endif
// Compare aggstate given during code generation and the one passed
// in as an argument to advance_aggregates
irb->CreateCondBr(
irb->CreateICmpEQ(llvm_aggstate, llvm_aggstate_arg),
implementation_block /* true */,
error_aggstate_block /* false */);
// implementation block
// ----------
irb->SetInsertPoint(implementation_block);
// Since we do not support ordered functions, we do not need to store
// the value of the variables, which are used as input to the aggregate
// function, in a slot. Instead we simply store them in a stuck variable.
llvm::Value *llvm_in_arg_ptr = irb->CreateAlloca(
codegen_utils->GetType<Datum>());
llvm::Value *llvm_in_argnull_ptr = irb->CreateAlloca(
codegen_utils->GetType<bool>());
for (int aggno = 0; aggno < aggstate_->numaggs; aggno++) {
// Generate the code of each aggregate function in a different block.
llvm::BasicBlock* advance_aggregate_block = codegen_utils->
CreateBasicBlock("advance_aggregate_block_aggno_"
+ std::to_string(aggno), advance_aggregates_func);
irb->CreateBr(advance_aggregate_block);
// advance_aggregate block
// ----------
// We generate code for advance_transition_function.
irb->SetInsertPoint(advance_aggregate_block);
AggStatePerAgg peraggstate = &aggstate_->peragg[aggno];
if (peraggstate->numSortCols > 0) {
elog(DEBUG1, "We don't codegen DISTINCT and/or ORDER BY case");
return false;
}
Aggref *aggref = peraggstate->aggref;
if (!aggref) {
elog(DEBUG1, "We don't codegen non-aggref functions");
return false;
}
int nargs = list_length(aggref->args);
assert(nargs == peraggstate->numArguments);
assert(peraggstate->evalproj);
if (peraggstate->evalproj->pi_isVarList) {
irb->CreateCall(llvm_ExecVariableList, {
codegen_utils->GetConstant<ProjectionInfo *>(peraggstate->evalproj),
llvm_in_arg_ptr,
llvm_in_argnull_ptr});
} else {
irb->CreateCall(llvm_ExecTargetList, {
codegen_utils->GetConstant(peraggstate->evalproj->pi_targetlist),
codegen_utils->GetConstant(peraggstate->evalproj->pi_exprContext),
llvm_in_arg_ptr,
llvm_in_argnull_ptr,
codegen_utils->GetConstant(peraggstate->evalproj->pi_itemIsDone),
codegen_utils->GetConstant<ExprDoneCond *>(nullptr)});
}
llvm::BasicBlock* advance_transition_function_block = codegen_utils->
CreateBasicBlock("advance_transition_function_block_aggno_"
+ std::to_string(aggno), advance_aggregates_func);
// Error out if attribute is NULL.
// TODO(nikos): Support null attributes.
irb->CreateCondBr(irb->CreateLoad(llvm_in_argnull_ptr),
null_attribute_block /*true*/,
advance_transition_function_block /*false*/);
// advance_transition_function block
// ----------
// We generate code for advance_transition_function.
irb->SetInsertPoint(advance_transition_function_block);
bool isGenerated = GenerateAdvanceTransitionFunction(
codegen_utils, llvm_pergroup_arg, aggno, advance_aggregates_func,
overflow_block, llvm_in_arg_ptr);
if (!isGenerated)
return false;
} // End of for loop
irb->CreateRetVoid();
// Error aggstate block
// ---------------
irb->SetInsertPoint(error_aggstate_block);
codegen_utils->CreateElog(ERROR, "Codegened advance_aggregates: "
"use of different aggstate.");
irb->CreateRetVoid();
// NULL attribute block
// ---------------
irb->SetInsertPoint(null_attribute_block);
codegen_utils->CreateElog(ERROR, "Codegened advance_aggregates: "
"NULL attributes are not supported.");
irb->CreateRetVoid();
// Overflow block
// ---------------
irb->SetInsertPoint(overflow_block);
// We error out during the execution of built-in function.
irb->CreateRetVoid();
return true;
}
bool AdvanceAggregatesCodegen::GenerateCodeInternal(
GpCodegenUtils* codegen_utils) {
bool isGenerated = GenerateAdvanceAggregates(codegen_utils);
if (isGenerated) {
elog(DEBUG1, "AdvanceAggregates was generated successfully!");
return true;
} else {
elog(DEBUG1, "AdvanceAggregates generation failed!");
return false;
}
}
......@@ -22,6 +22,7 @@
#include "codegen/exec_variable_list_codegen.h"
#include "codegen/expr_tree_generator.h"
#include "codegen/utils/gp_codegen_utils.h"
#include "codegen/advance_aggregates_codegen.h"
extern "C" {
#include "lib/stringinfo.h"
......@@ -31,6 +32,7 @@ using gpcodegen::CodegenManager;
using gpcodegen::BaseCodegen;
using gpcodegen::ExecVariableListCodegen;
using gpcodegen::ExecEvalExprCodegen;
using gpcodegen::AdvanceAggregatesCodegen;
// Current code generator manager that oversees all code generators
static void* ActiveCodeGeneratorManager = nullptr;
......@@ -165,5 +167,12 @@ void* ExecEvalExprCodegenEnroll(
return generator;
}
void* AdvanceAggregatesCodegenEnroll(
AdvanceAggregatesFn regular_func_ptr,
AdvanceAggregatesFn* ptr_to_chosen_func_ptr,
AggState *aggstate) {
AdvanceAggregatesCodegen* generator = CodegenEnroll<AdvanceAggregatesCodegen>(
regular_func_ptr, ptr_to_chosen_func_ptr, aggstate);
return generator;
}
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2016 Pivotal Software, Inc.
//
// @filename:
// advance_aggregates_codegen.h
//
// @doc:
// Headers for AdvanceAggregates codegen.
//
//---------------------------------------------------------------------------
#ifndef GPCODEGEN_ADVANCEAGGREGATES_CODEGEN_H_ // NOLINT(build/header_guard)
#define GPCODEGEN_ADVANCEAGGREGATES_CODEGEN_H_
#include "codegen/base_codegen.h"
#include "codegen/codegen_wrapper.h"
namespace gpcodegen {
/** \addtogroup gpcodegen
* @{
*/
class AdvanceAggregatesCodegen: public BaseCodegen<AdvanceAggregatesFn> {
public:
/**
* @brief Constructor
*
* @param regular_func_ptr Regular version of the target function.
* @param ptr_to_chosen_func_ptr Reference to the function pointer that the
* caller will call.
* @param aggstate The AggState to use for generating code.
*
* @note The ptr_to_chosen_func_ptr can refer to either the generated
* function or the corresponding regular version.
*
**/
explicit AdvanceAggregatesCodegen(
CodegenManager* manager,
AdvanceAggregatesFn regular_func_ptr,
AdvanceAggregatesFn* ptr_to_regular_func_ptr,
AggState *aggstate);
virtual ~AdvanceAggregatesCodegen() = default;
protected:
/**
* @brief Generate code for advance_aggregates.
*
* @param codegen_utils
*
* @return true on successful generation; false otherwise.
*
* This implementation does not support percentile and ordered aggregates.
*
* If at execution time, we see any of the above types of attributes,
* we fall backs to the regular function.
*
*/
bool GenerateCodeInternal(gpcodegen::GpCodegenUtils* codegen_utils) final;
private:
AggState *aggstate_;
static constexpr char kAdvanceAggregatesPrefix[] = "AdvanceAggregates";
/**
* @brief Generates runtime code that implements advance_aggregates.
*
* @param codegen_utils Utility to ease the code generation process.
* @return true on successful generation.
**/
bool GenerateAdvanceAggregates(gpcodegen::GpCodegenUtils* codegen_utils);
/**
* @brief Generates runtime code that implements advance_transition_function.
* It is called by GenerateAdvanceAggregates to generate code for a given
* aggregate function.
*
* @param codegen_utils Utility to ease the code generation process.
* @param llvm_pergroup_arg LLVM pointer to pergroup argument of regular
* advance_aggregates
* @param aggno ith aggregate function
* @param advance_aggregates_func LLVM function pointer to the code generated
* advance_aggregate function
* @param error_block LLVM block for treating errors
* @param llvm_arg argument of aggregate function
*
* @return true on successful generation; false otherwise.
*/
bool GenerateAdvanceTransitionFunction(
gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Value* llvm_pergroup_arg,
int aggno,
llvm::Function* advance_aggregates_func,
llvm::BasicBlock* error_block,
llvm::Value *llvm_arg);
};
/** @} */
} // namespace gpcodegen
#endif // GPCODEGEN_ADVANCEAGGREGATES_CODEGEN_H_
......@@ -45,6 +45,16 @@ class OpExprTreeGenerator : public ExprTreeGenerator {
ExprTreeGeneratorInfo* gen_info,
std::unique_ptr<ExprTreeGenerator>* expr_tree);
/**
* @brief Checks if a built-in function can be code generated.
*
* @param oid The oid of the function.
* @return If function is supported, then returns a pointer to the
* PGFuncGeneratorInterface of the function; nullptr otherwise.
**/
static gpcodegen::PGFuncGeneratorInterface* GetPGFuncGenerator(
unsigned int oid);
bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils,
const ExprTreeGeneratorInfo& gen_info,
llvm::Value* llvm_isnull_ptr,
......
......@@ -72,12 +72,24 @@ void OpExprTreeGenerator::InitializeSupportedFunction() {
"int4pl",
&PGArithFuncGenerator<int32_t, int32_t, int32_t>::AddWithOverflow));
supported_function_[1841] = std::unique_ptr<PGFuncGeneratorInterface>(
new PGGenericFuncGenerator<int64_t, int32_t>(
1841,
"int4_sum",
&PGArithFuncGenerator<int64_t, int64_t, int32_t>::AddWithOverflow));
supported_function_[181] = std::unique_ptr<PGFuncGeneratorInterface>(
new PGGenericFuncGenerator<int32_t, int32_t>(
181,
"int4mi",
&PGArithFuncGenerator<int32_t, int32_t, int32_t>::SubWithOverflow));
supported_function_[463] = std::unique_ptr<PGFuncGeneratorInterface>(
new PGGenericFuncGenerator<int64_t, int64_t>(
463,
"int8pl",
&PGArithFuncGenerator<int64_t, int64_t, int64_t>::AddWithOverflow));
supported_function_[216] = std::unique_ptr<PGFuncGeneratorInterface>(
new PGGenericFuncGenerator<float8, float8>(
216,
......@@ -107,6 +119,16 @@ void OpExprTreeGenerator::InitializeSupportedFunction() {
&PGDateFuncGenerator::DateLETimestamp));
}
PGFuncGeneratorInterface* OpExprTreeGenerator::GetPGFuncGenerator(
unsigned int oid) {
InitializeSupportedFunction();
auto itr = supported_function_.find(oid);
if (itr == supported_function_.end()) {
return nullptr;
}
return itr->second.get();
}
OpExprTreeGenerator::OpExprTreeGenerator(
const ExprState* expr_state,
std::vector<
......@@ -126,9 +148,8 @@ bool OpExprTreeGenerator::VerifyAndCreateExprTree(
OpExpr* op_expr = reinterpret_cast<OpExpr*>(expr_state->expr);
expr_tree->reset(nullptr);
CodeGenFuncMap::iterator itr = supported_function_.find(op_expr->opfuncid);
if (itr == supported_function_.end()) {
// Operators are stored in pg_proc table. See postgres.bki for more details.
PGFuncGeneratorInterface* pg_func_gen = GetPGFuncGenerator(op_expr->opfuncid);
if (nullptr == pg_func_gen) {
elog(DEBUG1, "Unsupported operator %d.", op_expr->opfuncid);
return false;
}
......@@ -137,7 +158,7 @@ bool OpExprTreeGenerator::VerifyAndCreateExprTree(
assert(nullptr != arguments);
// In ExecEvalFuncArgs
assert(list_length(arguments) ==
static_cast<int>(itr->second->GetTotalArgCount()));
static_cast<int>(pg_func_gen->GetTotalArgCount()));
ListCell *arg = nullptr;
bool supported_tree = true;
......
......@@ -868,7 +868,7 @@ agg_hash_initial_pass(AggState *aggstate)
}
/* Advance the aggregates */
advance_aggregates(aggstate, hashtable->groupaggs->aggs, &(aggstate->mem_manager));
call_AdvanceAggregates(aggstate, hashtable->groupaggs->aggs, &(aggstate->mem_manager));
hashtable->num_tuples++;
......
......@@ -589,7 +589,9 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
EnrollProjInfoTargetList(result, peraggstate->evalproj);
}
}
enroll_AdvanceAggregates_codegen(advance_aggregates,
&aggstate->AdvanceAggregates_gen_info.AdvanceAggregates_fn,
aggstate); }
}
END_MEMORY_ACCOUNT();
break;
......
......@@ -5982,7 +5982,10 @@ ExecCleanTargetListLength(List *targetlist)
* of *isDone = ExprMultipleResult signifies a set element, and a return
* of *isDone = ExprEndResult signifies end of the set of tuple.
*/
static bool
#ifndef USE_CODEGEN
static
#endif
bool
ExecTargetList(List *targetlist,
ExprContext *econtext,
Datum *values,
......
......@@ -1323,7 +1323,7 @@ agg_retrieve_direct(AggState *aggstate)
if (!aggstate->has_partial_agg)
{
has_partial_agg = true;
advance_aggregates(aggstate, pergroup, &(aggstate->mem_manager));
call_AdvanceAggregates(aggstate, pergroup, &(aggstate->mem_manager));
}
/* Reset per-input-tuple context after each tuple */
......@@ -1399,7 +1399,7 @@ agg_retrieve_direct(AggState *aggstate)
{
has_partial_agg = true;
tmpcontext->ecxt_outertuple = outerslot;
advance_aggregates(aggstate, pergroup, &(aggstate->mem_manager));
call_AdvanceAggregates(aggstate, pergroup, &(aggstate->mem_manager));
}
passthru_ready = true;
......@@ -1439,7 +1439,7 @@ agg_retrieve_direct(AggState *aggstate)
ResetExprContext(tmpcontext);
tmpcontext->ecxt_outertuple = outerslot;
advance_aggregates(aggstate, perpassthru, &(aggstate->mem_manager));
call_AdvanceAggregates(aggstate, perpassthru, &(aggstate->mem_manager));
}
......
......@@ -31,7 +31,9 @@ struct ProjectionInfo;
struct ExprContext;
struct ExprState;
struct PlanState;
struct AggState;
struct MemoryManagerContainer;
struct AggStatePerGroupData;
/*
* Enum used to mimic ExprDoneCond in ExecEvalExpr function pointer.
*/
......@@ -39,6 +41,7 @@ typedef enum tmp_enum{
TmpResult
}tmp_enum;
typedef void (*AdvanceAggregatesFn) (struct AggState *aggstate, /*struct AggStatePerGroup*/struct AggStatePerGroupData *pergroup, struct MemoryManagerContainer *mem_manager);
typedef void (*ExecVariableListFn) (struct ProjectionInfo *projInfo, Datum *values, bool *isnull);
typedef Datum (*ExecEvalExprFn) (struct ExprState *expression, struct ExprContext *econtext, bool *isNull, /*ExprDoneCond*/ tmp_enum *isDone);
typedef Datum (*SlotGetAttrFn) (struct TupleTableSlot *slot, int attnum, bool *isnull);
......@@ -62,7 +65,8 @@ typedef Datum (*SlotGetAttrFn) (struct TupleTableSlot *slot, int attnum, bool *i
#define init_codegen()
#define call_ExecVariableList(projInfo, values, isnull) ExecVariableList(projInfo, values, isnull)
#define enroll_ExecVariableList_codegen(regular_func, ptr_to_chosen_func, proj_info, slot)
#define call_AdvanceAggregates(aggstate, pergroup, mem_manager) advance_aggregates(aggstate, pergroup, mem_manager)
#define enroll_AdvanceAggregates_codegen(regular_func, ptr_to_chosen_func, aggstate)
#else
/*
......@@ -176,6 +180,14 @@ ExecEvalExprCodegenEnroll(ExecEvalExprFn regular_func_ptr,
struct ExprContext *econtext,
struct PlanState* plan_state);
/*
* Enroll and returns the pointer to AdvanceAggregateGenerator
*/
void*
AdvanceAggregatesCodegenEnroll(AdvanceAggregatesFn regular_func_ptr,
AdvanceAggregatesFn* ptr_to_regular_func_ptr,
struct AggState *aggstate);
#ifdef __cplusplus
} // extern "C"
#endif
......@@ -225,6 +237,14 @@ ExecEvalExprCodegenEnroll(ExecEvalExprFn regular_func_ptr,
*/
#define call_ExecVariableList(projInfo, values, isnull) \
projInfo->ExecVariableList_gen_info.ExecVariableList_fn(projInfo, values, isnull)
/*
* Call AdvanceAggregates using function pointer AdvanceAggregates_fn.
* Function pointer may point to regular version or generated function
*/
#define call_AdvanceAggregates(aggstate, pergroup, mem_manager) \
aggstate->AdvanceAggregates_gen_info.AdvanceAggregates_fn(aggstate, pergroup, mem_manager)
/*
* Enrollment macros
* The enrollment process also ensures that the generated function pointer
......@@ -240,6 +260,11 @@ ExecEvalExprCodegenEnroll(ExecEvalExprFn regular_func_ptr,
(ExecEvalExprFn)regular_func, (ExecEvalExprFn*)ptr_to_regular_func_ptr, exprstate, econtext, plan_state); \
Assert(exprstate->evalfunc == regular_func); \
#define enroll_AdvanceAggregates_codegen(regular_func, ptr_to_regular_func_ptr, aggstate) \
aggstate->AdvanceAggregates_gen_info.code_generator = AdvanceAggregatesCodegenEnroll( \
regular_func, ptr_to_regular_func_ptr, aggstate); \
Assert(aggstate->AdvanceAggregates_gen_info.AdvanceAggregates_fn == regular_func); \
#endif //USE_CODEGEN
#endif // CODEGEN_WRAPPER_H_
......@@ -293,6 +293,9 @@ extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
extern ExprState *ExecPrepareExpr(Expr *node, EState *estate);
extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
extern int ExecTargetListLength(List *targetlist);
#ifdef USE_CODEGEN
extern bool ExecTargetList(List *targetlist, ExprContext *econtext, Datum *values, bool *isnull, ExprDoneCond *itemIsDone, ExprDoneCond *isDone);
#endif
extern int ExecCleanTargetListLength(List *targetlist);
extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo,
ExprDoneCond *isDone);
......
......@@ -2344,6 +2344,15 @@ typedef struct SortState
* expressions and run the aggregate transition functions.
* -------------------------
*/
typedef struct AdvanceAggregatesCodegenInfo
{
/* Pointer to store AdvanceAggregatesCodegen from Codegen */
void* code_generator;
/* Function pointer that points to either regular or generated advance_aggregates */
AdvanceAggregatesFn AdvanceAggregates_fn;
} AdvanceAggregatesCodegenInfo;
/* these structs are private in nodeAgg.c: */
typedef struct AggStatePerAggData *AggStatePerAgg;
typedef struct AggStatePerGroupData *AggStatePerGroup;
......@@ -2392,6 +2401,9 @@ typedef struct AggState
/* set if the operator created workfiles */
bool workfiles_created;
#ifdef USE_CODEGEN
AdvanceAggregatesCodegenInfo AdvanceAggregates_gen_info;
#endif
} AggState;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册