/* * Walker function to check if an expression list can be cached. * This is used for both the projection and qual lists. * * Returns true if any non-cacheable functions are found, false otherwise. */ static bool ExprNonCacheableWalker(Node *expr, void *ctx) { Assert(ctx == NULL); if (expr == NULL) { return false; } else if (IsA(expr, FuncExpr)) { Oid fn_oid = ((FuncExpr *) expr)->funcid; if (!isFuncCacheable(fn_oid)) { /* Found expression using non-cacheable function. We're done, end walker */ return true; } } return expression_tree_walker(expr, ExprNonCacheableWalker, ctx); }
/* * Traverse a fully-analyzed tree to verify that parameter symbols * match their types. We need this because some Params might still * be UNKNOWN, if there wasn't anything to force their coercion, * and yet other instances seen later might have gotten coerced. */ static bool check_parameter_resolution_walker(Node *node, ParseState *pstate) { if (node == NULL) return false; if (IsA(node, Param)) { Param *param = (Param *) node; if (param->paramkind == PARAM_EXTERN) { VarParamState *parstate = (VarParamState *) pstate->p_ref_hook_state; int paramno = param->paramid; if (paramno <= 0 || /* shouldn't happen, but... */ paramno > *parstate->numParams) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PARAMETER), errmsg("there is no parameter $%d", paramno), parser_errposition(pstate, param->location))); if (param->paramtype != (*parstate->paramTypes)[paramno - 1]) ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_PARAMETER), errmsg("could not determine data type of parameter $%d", paramno), parser_errposition(pstate, param->location))); } return false; } if (IsA(node, Query)) { /* Recurse into RTE subquery or not-yet-planned sublink subquery */ return query_tree_walker((Query *) node, check_parameter_resolution_walker, (void *) pstate, 0); } return expression_tree_walker(node, check_parameter_resolution_walker, (void *) pstate); }
static bool query_contains_extern_params_walker(Node *node, void *context) { if (node == NULL) return false; if (IsA(node, Param)) { Param *param = (Param *) node; if (param->paramkind == PARAM_EXTERN) return true; return false; } if (IsA(node, Query)) { /* Recurse into RTE subquery or not-yet-planned sublink subquery */ return query_tree_walker((Query *) node, query_contains_extern_params_walker, context, 0); } return expression_tree_walker(node, query_contains_extern_params_walker, context); }
bool my_walker(Node *node, context_walker_set_constraint *context){ if (node == NULL) return false; /* elog(LOG,"tag : %d\n",nodeTag(node)); */ if(IsA(node,BoolExpr)){ BoolExpr * bExpr =(BoolExpr *) node; bool retour = false; List * l_true_save = NULL; List * l_false_save = NULL; List * l_true = NULL; List * l_false = NULL; int nb_arg = bExpr->args->length; switch(bExpr->boolop){ case NOT_EXPR: /*(Unicité des valeur) Setisation sur le true*/ /*Pre Traitement*/ l_true_save = context->list_of_not_null_to_be_true; l_false_save = context->list_of_not_null_to_be_false; context->list_of_not_null_to_be_true = NULL; context->list_of_not_null_to_be_false = NULL; /*Traitement*/ retour = expression_tree_walker(node, my_walker, (void *) context); /*Post Traitement*/ /* elog(LOG,"\n List_false_before : %s\n",nodeToString(context->list_of_not_null_to_be_false)); */ /* elog(LOG,"\n List_true_before : %s\n",nodeToString(context->list_of_not_null_to_be_true)); */ l_true = context->list_of_not_null_to_be_true; l_false = context->list_of_not_null_to_be_false; context->list_of_not_null_to_be_true = list_concat(l_true_save,l_false); context->list_of_not_null_to_be_false = list_concat(l_false_save,l_true); /* elog(LOG,"\n List_false : %s\n",nodeToString(context->list_of_not_null_to_be_false)); */ /* elog(LOG,"\n List_true : %s\n",nodeToString(context->list_of_not_null_to_be_true)); */ return retour; break; case AND_EXPR: /*(Unicité des valeur) Setisation sur le true*/ /*Pre Traitement*/ l_true_save = context->list_of_not_null_to_be_true; l_false_save = context->list_of_not_null_to_be_false; context->list_of_not_null_to_be_true = NULL; context->list_of_not_null_to_be_false = NULL; /*Traitement*/ retour = expression_tree_walker(node, my_walker, (void *) context); /*Post traitement*/ /* elog(LOG,"\n List_false_before : %s\n",nodeToString(context->list_of_not_null_to_be_false)); */ /* elog(LOG,"\n List_true_before : %s\n",nodeToString(context->list_of_not_null_to_be_true)); */ l_true = union_list(context->list_of_not_null_to_be_true); l_false = inter_list(context->list_of_not_null_to_be_false,nb_arg); context->list_list_true = lappend(context->list_list_true,l_true); context->list_list_false = lappend(context->list_list_false,l_false); context->list_of_not_null_to_be_true = list_concat(l_true_save,l_true); context->list_of_not_null_to_be_false = list_concat(l_false_save,l_false); /* elog(LOG,"\n nb_arg : %d\n",nb_arg); */ /* elog(LOG,"\n List_false : %s\n",nodeToString(context->list_of_not_null_to_be_false)); */ /* elog(LOG,"\n List_true : %s\n",nodeToString(context->list_of_not_null_to_be_true)); */ return retour; break; case OR_EXPR: /*(Unicité des valeur) Setisation sur le true*/ /*Pre Traitement*/ l_true_save = context->list_of_not_null_to_be_true; l_false_save = context->list_of_not_null_to_be_false; context->list_of_not_null_to_be_true = NULL; context->list_of_not_null_to_be_false = NULL; /*Traitement*/ retour = expression_tree_walker(node, my_walker, (void *) context); /*Post traitement*/ /* elog(LOG,"\n List_false_before : %s\n",nodeToString(context->list_of_not_null_to_be_false)); */ /* elog(LOG,"\n List_true_before : %s\n",nodeToString(context->list_of_not_null_to_be_true)); */ l_true = inter_list(context->list_of_not_null_to_be_true,nb_arg); l_false = union_list(context->list_of_not_null_to_be_false); context->list_list_true = lappend(context->list_list_true,l_true); context->list_list_false = lappend(context->list_list_false,l_false); context->list_of_not_null_to_be_true = list_concat(l_true_save,l_true); context->list_of_not_null_to_be_false = list_concat(l_false_save,l_false); /* elog(LOG,"\n nb_arg : %d\n",nb_arg); */ /* elog(LOG,"\n List_false : %s\n",nodeToString(context->list_of_not_null_to_be_false)); */ /* elog(LOG,"\n List_true : %s\n",nodeToString(context->list_of_not_null_to_be_true)); */ return retour; break; } } if(context->ready && IsA(node,Var)){ /* elog(LOG," \n HERE1 \n"); */ Var * v = getTrueVar(context->current_trueVar,(Var *)node); /* elog(LOG," \n HERE2 \n"); */ if(!isInListTrueVar(context->list_of_not_null_in_op,v)){ context->list_of_not_null_in_op = lappend(context->list_of_not_null_in_op,v); } return expression_tree_walker(node, my_walker, (void *) context); } if(IsA(node,OpExpr)){ OpExpr * oExpr = (OpExpr *)node; if(oExpr->opno == 518 /*<>*/){ context->ready = true; context->list_of_not_null_in_op = NULL; bool retour = expression_tree_walker(node, my_walker, (void *) context); context->list_of_not_null_to_be_true = list_concat(context->list_of_not_null_to_be_true,context->list_of_not_null_in_op); return retour; } else{ return expression_tree_walker(node, my_walker, (void *) context); } /* elog(LOG,"\n List_op : %s\n",nodeToString(context->list_of_not_null_in_op)); */ } if(IsA(node,Query)){ Query * q = (Query *) node; /*Prétraitement*/ List * save_current_trueVar = context->current_trueVar; context->current_trueVar = NULL; context->current_trueVar = lappend(context->current_trueVar,save_current_trueVar); /*Traitement*/ /*Create trueVars and not_null schema*/ bool result = expression_tree_walker((Node *)q->rtable, my_walker, (void *) context); /* elog(LOG,"\n TRUE ATT :%s\n",nodeToString(context->trueVars)); */ context->trueVars = lappend(context->trueVars,context->current_trueVar); /* elog(LOG,"\nTRUE ATT :%s \n",nodeToString(context->trueVars)); */ /*Propagate*/ result = expression_tree_walker((Node *)q->jointree, my_walker, (void *) context) | result; /* elog(LOG,"\n LIST_LIST_TRUE :%s\n",nodeToString(context->list_list_true)); */ /* elog(LOG,"\n LIST_LIST_FALSE :%s\n",nodeToString(context->list_list_false)); */ /*Post Traitement*/ context->current_trueVar = save_current_trueVar; return result; } if(IsA(node,RangeTblEntry)){ RangeTblEntry * rte = (RangeTblEntry *)node; Oid relid= rte->relid; int number_col = get_relnatts(relid); AttrNumber i = 0; List * relation = NULL; for(i=1;i<=number_col;i++){ /*Create True_var*/ Var * v = makeNode(Var); v->varattno = i; /* v->varattno = context->current_varattno; */ v->vartype = relid; relation = lappend(relation,v); /*Add to not_null if needed*/ if(get_pg_att_not_null(relid,i)){ context->list_of_not_null_att_schem = lappend(context->list_of_not_null_att_schem,v); } } context->current_trueVar = lappend(context->current_trueVar,relation); /* elog(LOG,"\n TEST: %s \n",nodeToString(context->current_trueVar)); */ return false; } return expression_tree_walker(node, my_walker, (void *) context); }