#include "postgres.h"
#include <limits.h>
#include "catalog/pg_type.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_param.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
Go to the source code of this file.
Data Structures | |
struct | FixedParamState |
struct | VarParamState |
Typedefs | |
typedef struct FixedParamState | FixedParamState |
typedef struct VarParamState | VarParamState |
Functions | |
static Node * | fixed_paramref_hook (ParseState *pstate, ParamRef *pref) |
static Node * | variable_paramref_hook (ParseState *pstate, ParamRef *pref) |
static Node * | variable_coerce_param_hook (ParseState *pstate, Param *param, Oid targetTypeId, int32 targetTypeMod, int location) |
static bool | check_parameter_resolution_walker (Node *node, ParseState *pstate) |
static bool | query_contains_extern_params_walker (Node *node, void *context) |
void | parse_fixed_parameters (ParseState *pstate, Oid *paramTypes, int numParams) |
void | parse_variable_parameters (ParseState *pstate, Oid **paramTypes, int *numParams) |
void | check_variable_parameters (ParseState *pstate, Query *query) |
bool | query_contains_extern_params (Query *query) |
typedef struct FixedParamState FixedParamState |
typedef struct VarParamState VarParamState |
static bool check_parameter_resolution_walker | ( | Node * | node, | |
ParseState * | pstate | |||
) | [static] |
Definition at line 281 of file parse_param.c.
References ereport, errcode(), errmsg(), ERROR, expression_tree_walker(), IsA, Param::location, NULL, VarParamState::numParams, ParseState::p_ref_hook_state, PARAM_EXTERN, Param::paramid, Param::paramkind, Param::paramtype, VarParamState::paramTypes, parser_errposition(), and query_tree_walker().
Referenced by check_variable_parameters().
{ 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); }
void check_variable_parameters | ( | ParseState * | pstate, | |
Query * | query | |||
) |
Definition at line 263 of file parse_param.c.
References check_parameter_resolution_walker(), VarParamState::numParams, ParseState::p_ref_hook_state, and query_tree_walker().
Referenced by parse_analyze_varparams().
{ 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); }
static Node * fixed_paramref_hook | ( | ParseState * | pstate, | |
ParamRef * | pref | |||
) | [static] |
Definition at line 99 of file parse_param.c.
References ereport, errcode(), errmsg(), ERROR, get_typcollation(), ParamRef::location, makeNode, ParamRef::number, FixedParamState::numParams, OidIsValid, ParseState::p_ref_hook_state, FixedParamState::paramTypes, and parser_errposition().
{ FixedParamState *parstate = (FixedParamState *) pstate->p_ref_hook_state; int paramno = pref->number; Param *param; /* Check parameter number is valid */ if (paramno <= 0 || paramno > parstate->numParams || !OidIsValid(parstate->paramTypes[paramno - 1])) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PARAMETER), errmsg("there is no parameter $%d", paramno), parser_errposition(pstate, pref->location))); param = makeNode(Param); param->paramkind = PARAM_EXTERN; param->paramid = paramno; param->paramtype = parstate->paramTypes[paramno - 1]; param->paramtypmod = -1; param->paramcollid = get_typcollation(param->paramtype); param->location = pref->location; return (Node *) param; }
void parse_fixed_parameters | ( | ParseState * | pstate, | |
Oid * | paramTypes, | |||
int | numParams | |||
) |
Definition at line 67 of file parse_param.c.
References FixedParamState::numParams, ParseState::p_paramref_hook, ParseState::p_ref_hook_state, palloc(), and FixedParamState::paramTypes.
Referenced by parse_analyze().
{ FixedParamState *parstate = palloc(sizeof(FixedParamState)); parstate->paramTypes = paramTypes; parstate->numParams = numParams; pstate->p_ref_hook_state = (void *) parstate; pstate->p_paramref_hook = fixed_paramref_hook; /* no need to use p_coerce_param_hook */ }
void parse_variable_parameters | ( | ParseState * | pstate, | |
Oid ** | paramTypes, | |||
int * | numParams | |||
) |
Definition at line 83 of file parse_param.c.
References VarParamState::numParams, ParseState::p_coerce_param_hook, ParseState::p_paramref_hook, ParseState::p_ref_hook_state, palloc(), and VarParamState::paramTypes.
Referenced by parse_analyze_varparams().
{ VarParamState *parstate = palloc(sizeof(VarParamState)); parstate->paramTypes = paramTypes; parstate->numParams = numParams; pstate->p_ref_hook_state = (void *) parstate; pstate->p_paramref_hook = variable_paramref_hook; pstate->p_coerce_param_hook = variable_coerce_param_hook; }
Definition at line 325 of file parse_param.c.
References NULL, query_contains_extern_params_walker(), and query_tree_walker().
Referenced by transformCreateTableAsStmt().
{ return query_tree_walker(query, query_contains_extern_params_walker, NULL, 0); }
Definition at line 333 of file parse_param.c.
References expression_tree_walker(), IsA, NULL, PARAM_EXTERN, Param::paramkind, and query_tree_walker().
Referenced by query_contains_extern_params().
{ 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); }
static Node * variable_coerce_param_hook | ( | ParseState * | pstate, | |
Param * | param, | |||
Oid | targetTypeId, | |||
int32 | targetTypeMod, | |||
int | location | |||
) | [static] |
Definition at line 181 of file parse_param.c.
References ereport, errcode(), errdetail(), errmsg(), ERROR, format_type_be(), get_typcollation(), Param::location, VarParamState::numParams, ParseState::p_ref_hook_state, PARAM_EXTERN, Param::paramcollid, Param::paramid, Param::paramkind, Param::paramtype, VarParamState::paramTypes, Param::paramtypmod, parser_errposition(), and UNKNOWNOID.
{ if (param->paramkind == PARAM_EXTERN && param->paramtype == UNKNOWNOID) { /* * Input is a Param of previously undetermined type, and we want to * update our knowledge of the Param's type. */ VarParamState *parstate = (VarParamState *) pstate->p_ref_hook_state; Oid *paramTypes = *parstate->paramTypes; 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 (paramTypes[paramno - 1] == UNKNOWNOID) { /* We've successfully resolved the type */ paramTypes[paramno - 1] = targetTypeId; } else if (paramTypes[paramno - 1] == targetTypeId) { /* We previously resolved the type, and it matches */ } else { /* Ooops */ ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_PARAMETER), errmsg("inconsistent types deduced for parameter $%d", paramno), errdetail("%s versus %s", format_type_be(paramTypes[paramno - 1]), format_type_be(targetTypeId)), parser_errposition(pstate, param->location))); } param->paramtype = targetTypeId; /* * Note: it is tempting here to set the Param's paramtypmod to * targetTypeMod, but that is probably unwise because we have no * infrastructure that enforces that the value delivered for a Param * will match any particular typmod. Leaving it -1 ensures that a * run-time length check/coercion will occur if needed. */ param->paramtypmod = -1; /* * This module always sets a Param's collation to be the default for * its datatype. If that's not what you want, you should be using the * more general parser substitution hooks. */ param->paramcollid = get_typcollation(param->paramtype); /* Use the leftmost of the param's and coercion's locations */ if (location >= 0 && (param->location < 0 || location < param->location)) param->location = location; return (Node *) param; } /* Else signal to proceed with normal coercion */ return NULL; }
static Node * variable_paramref_hook | ( | ParseState * | pstate, | |
ParamRef * | pref | |||
) | [static] |
Definition at line 131 of file parse_param.c.
References ereport, errcode(), errmsg(), ERROR, get_typcollation(), InvalidOid, ParamRef::location, makeNode, MemSet, ParamRef::number, VarParamState::numParams, ParseState::p_ref_hook_state, palloc(), VarParamState::paramTypes, parser_errposition(), and repalloc().
{ VarParamState *parstate = (VarParamState *) pstate->p_ref_hook_state; int paramno = pref->number; Oid *pptype; Param *param; /* Check parameter number is in range */ if (paramno <= 0 || paramno > INT_MAX / sizeof(Oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PARAMETER), errmsg("there is no parameter $%d", paramno), parser_errposition(pstate, pref->location))); if (paramno > *parstate->numParams) { /* Need to enlarge param array */ if (*parstate->paramTypes) *parstate->paramTypes = (Oid *) repalloc(*parstate->paramTypes, paramno * sizeof(Oid)); else *parstate->paramTypes = (Oid *) palloc(paramno * sizeof(Oid)); /* Zero out the previously-unreferenced slots */ MemSet(*parstate->paramTypes + *parstate->numParams, 0, (paramno - *parstate->numParams) * sizeof(Oid)); *parstate->numParams = paramno; } /* Locate param's slot in array */ pptype = &(*parstate->paramTypes)[paramno - 1]; /* If not seen before, initialize to UNKNOWN type */ if (*pptype == InvalidOid) *pptype = UNKNOWNOID; param = makeNode(Param); param->paramkind = PARAM_EXTERN; param->paramid = paramno; param->paramtype = *pptype; param->paramtypmod = -1; param->paramcollid = get_typcollation(param->paramtype); param->location = pref->location; return (Node *) param; }