/* * Check to see if a fully-parsed query tree contains any PARAM_EXTERN Params. */ bool query_contains_extern_params(Query *query) { return query_tree_walker(query, query_contains_extern_params_walker, NULL, 0); }
/* * Check for consistent assignment of variable parameters after completion * of parsing with parse_variable_parameters. * * Note: this code intentionally does not check that all parameter positions * were used, nor that all got non-UNKNOWN types assigned. Caller of parser * should enforce that if it's important. */ void check_variable_parameters(ParseState *pstate, Query *query) { VarParamState *parstate = (VarParamState *) pstate->p_ref_hook_state; /* If numParams is zero then no Params were generated, so no work */ if (*parstate->numParams > 0) (void) query_tree_walker(query, check_parameter_resolution_walker, (void *) pstate, 0); }
/* * assign_query_collations() * Mark all expressions in the given Query with collation information. * * This should be applied to each Query after completion of parse analysis * for expressions. Note that we do not recurse into sub-Queries, since * those should have been processed when built. */ void assign_query_collations(ParseState *pstate, Query *query) { /* * We just use query_tree_walker() to visit all the contained expressions. * We can skip the rangetable and CTE subqueries, though, since RTEs and * subqueries had better have been processed already (else Vars referring * to them would not get created with the right collation). */ (void) query_tree_walker(query, assign_query_collations_walker, (void *) pstate, QTW_IGNORE_RANGE_TABLE | QTW_IGNORE_CTE_SUBQUERIES); }
/* * 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); }