#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;
}
1.7.1