On 06/08/10 01:13, Tom Lane wrote:
Andrew Dunstan<and...@dunslane.net> writes:
On 08/05/2010 05:11 PM, Tom Lane wrote:
This example doesn't seem terribly compelling. Why would you bother
using USING with constants?
In a more complex example you might use $1 in more than one place in the
query.
Well, that's better than no justification, but it's still pretty weak.
A bigger problem is that doing anything like this will require reversing
the logical path of causation in EXECUTE USING. Right now, we evaluate
the USING expressions first, and then their types feed forward into
parsing the EXECUTE string. What Heikki is suggesting requires
reversing that, at least to some extent. I'm not convinced it's
possible without breaking other cases that are more important.
One approach is to handle the conversion from unknown to the right data
type transparently in the backend. Attached patch adds a
coerce-param-hook for fixed params that returns a CoerceViaIO node to
convert the param to the right type at runtime. That's quite similar to
the way unknown constants are handled.
The patch doesn't currently check that a parameter is only resolved to
one type in the same query, but that can be added.
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index 20abf00..f4381fc 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -55,6 +55,9 @@ 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 Node *fixed_coerce_param_hook(ParseState *pstate, Param *param,
+ Oid targetTypeId, int32 targetTypeMod,
+ int location);
static bool check_parameter_resolution_walker(Node *node, ParseState *pstate);
@@ -71,7 +74,7 @@ parse_fixed_parameters(ParseState *pstate,
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 */
+ pstate->p_coerce_param_hook = fixed_coerce_param_hook;
}
/*
@@ -170,6 +173,43 @@ variable_paramref_hook(ParseState *pstate, ParamRef *pref)
return (Node *) param;
}
+static Node *
+fixed_coerce_param_hook(ParseState *pstate, Param *param,
+ Oid targetTypeId, int32 targetTypeMode,
+ int location)
+{
+ 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.
+ */
+ FixedParamState *parstate = (FixedParamState *) pstate->p_ref_hook_state;
+ int paramno = param->paramid;
+ CoerceViaIO *iocoerce;
+
+ 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)));
+
+ /* Build a CoerceViaIO node */
+ iocoerce = makeNode(CoerceViaIO);
+ iocoerce->arg = (Expr *) param;
+ iocoerce->resulttype = targetTypeId;
+ iocoerce->coerceformat = COERCE_IMPLICIT_CAST;
+ iocoerce->location = location;
+
+ return (Node *) iocoerce;
+ }
+
+ /* Else signal to proceed with normal coercion */
+ return NULL;
+}
+
+
/*
* Coerce a Param to a query-requested datatype, in the varparams case.
*/
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers