Github user wengyanqing commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1348#discussion_r175950023 --- Diff: contrib/vexecutor/vcheck.c --- @@ -54,7 +61,274 @@ typedef struct VecFuncHashEntry vFuncMap *vFunc; } VecFuncHashEntry; +typedef struct VecTypeHashEntry +{ + Oid src; + Oid dest; +}VecTypeHashEntry; + +/* Map between the vectorized types and non-vectorized types */ +static HTAB *hashMapN2V = NULL; + +/* + * We check the expressions tree recursively becuase the args can be a sub expression, + * we must check the return type of sub expression to fit the parent expressions. + * so the retType in Vectorized is a temporary values, after we check on expression, + * we set the retType of this expression, and transfer this value to his parent. + */ +typedef struct VectorizedContext +{ + plan_tree_base_prefix base; /* Required prefix for plan_tree_walker/mutator */ + Oid retType; + bool replace; +}VectorizedContext; + +/* + * Check all the expressions if they can be vectorized + * NOTE: if an expressions is vectorized, we return false...,because we should check + * all the expressions in the Plan node, if we return true, then the walker will be + * over... + */ +static bool +CheckVectorizedExpression(Node *node, VectorizedContext *ctx) +{ + if(NULL == node) + return false; + + if(is_plan_node(node)) + return false; + + //check the type of Var if it can be vectorized + if(IsA(node, Var)) + { + Var *var = (Var*)node; + Oid vtype = GetVtype(var->vartype); + if(InvalidOid == vtype) + return true; + ctx->retType = vtype; + if(ctx->replace) + var->vartype = vtype; + return false; + } + + //Const treat as can be vectorzied, its return type is non-vectorized type + //because we support the function like this: vtype op(vtype, const); + if(IsA(node, Const)) + { + Const *c = (Const*)node; + ctx->retType = c->consttype; + return false; + } + + //OpExpr:args, return types should can be vectorized, + //and there must exists an vectorized function to implement the operator + if(IsA(node, OpExpr)) + { + OpExpr *op = (OpExpr*)node; + Node *argnode = NULL; + Oid ltype, rtype, rettype; + Form_pg_operator voper; + HeapTuple tuple; + + //OpExpr mostly have two args, check the first one + argnode = linitial(op->args); + if(CheckVectorizedExpression(argnode, ctx)) + return true; + + ltype = ctx->retType; + + //check the second one + argnode = lsecond(op->args); + if(CheckVectorizedExpression(argnode, ctx)) + return true; + + rtype = ctx->retType; + + //check the return type + rettype = GetVtype(op->opresulttype); + if(InvalidOid == rettype) + return true; + + + //get the vectorized operator functions + //NOTE:we have no ParseState now, Give the NULL value is OK but not good... + tuple = oper(NULL, list_make1(makeString(get_opname(op->opno))), + ltype, rtype, false, -1); + if(NULL == tuple) + return true; + + voper = (Form_pg_operator)GETSTRUCT(tuple); + if(voper->oprresult != rettype) + return true; + + if(ctx->replace) + { + op->opresulttype = rettype; + op->opfuncid = voper->oprcode; + } + + ctx->retType = rettype; + return false; + } + + //now, other nodes treat as can not be vectorized + return plan_tree_walker(node, CheckVectorizedExpression, ctx);; +} + +/* + * check an plan node, all the expressions in it should be checked + * set the flag if an plan node can be vectorized + */ +static bool +CheckPlanNodeWalker(PlannerInfo *root, Plan *plan) +{ + VectorizedContext ctx; + + if(plan->vectorized) + return true; + + ctx.replace =false; + + ctx.retType = InvalidOid; + plan->vectorized = !plan_tree_walker((Node*)plan, + CheckVectorizedExpression, + &ctx); + + + return false; +} + +/* + * check the plan tree + */ +static Plan* +CheckPlanVectorzied(PlannerInfo *root, Plan *plan) +{ + if(NULL == plan) + return plan; + + CheckPlanVectorzied(root, plan->lefttree); + CheckPlanVectorzied(root, plan->righttree); + CheckPlanNodeWalker(root, plan); + + return plan; +} + +/* + * Replace the non-vectorirzed type to vectorized type + */ +static bool +ReplacePlanNodeWalker(PlannerInfo *root, Plan *plan) +{ + VectorizedContext ctx; + + if(!plan->vectorized) + return false; + + if(!HasVecExecOprator(nodeTag(plan))) + { + plan->vectorized = false; + return false; + } + + ctx.replace =true; + + ctx.retType = InvalidOid; + plan_tree_walker((Node*)plan, + CheckVectorizedExpression, + &ctx); + + return false; +} + +/* + * check the plan tree + */ +static Plan* +ReplacePlanVectorzied(PlannerInfo *root, Plan *plan) +{ + if(NULL == plan) + return plan; + + ReplacePlanVectorzied(root, plan->lefttree); + ReplacePlanVectorzied(root, plan->righttree); + ReplacePlanNodeWalker(root, plan); + + return plan; +} + +Plan* +CheckAndReplacePlanVectorized(PlannerInfo *root, Plan *plan) --- End diff -- How to check initPlans of main Plan node?
---