summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-03-04 20:23:13 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2015-03-04 20:23:13 -0500
commit7f3014dce56c7975113809f2ff5e92cf7c1563a3 (patch)
tree2491223338ee9953f039a76fda6379b3e27c52d0 /src
parent45f2c2fc4e4adcf75cd689e18dab77ebe622fc2e (diff)
Change plpgsql's cast cache to consider source typmod as significant.
I had thought that there was no need to maintain separate cache entries for different source typmods, but further experimentation shows that there is an advantage to doing so in some cases. In particular, if a domain has a typmod (say, "CREATE DOMAIN d AS numeric(20,0)"), failing to notice the source typmod leads to applying a length-coercion step even when the source has the correct typmod.
Diffstat (limited to 'src')
-rw-r--r--src/pl/plpgsql/src/pl_exec.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 315d28b8fae..f24f55a2ff4 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -57,6 +57,7 @@ typedef struct
/* NB: we assume this struct contains no padding bytes */
Oid srctype; /* source type for cast */
Oid dsttype; /* destination type for cast */
+ int32 srctypmod; /* source typmod for cast */
int32 dsttypmod; /* destination typmod for cast */
} plpgsql_CastHashKey;
@@ -231,7 +232,7 @@ static Datum exec_cast_value(PLpgSQL_execstate *estate,
Oid valtype, int32 valtypmod,
Oid reqtype, int32 reqtypmod);
static ExprState *get_cast_expression(PLpgSQL_execstate *estate,
- Oid srctype, Oid dsttype, int32 dsttypmod);
+ Oid srctype, int32 srctypmod, Oid dsttype, int32 dsttypmod);
static void exec_init_tuple_store(PLpgSQL_execstate *estate);
static void exec_set_found(PLpgSQL_execstate *estate, bool state);
static void plpgsql_create_econtext(PLpgSQL_execstate *estate);
@@ -5733,7 +5734,9 @@ exec_cast_value(PLpgSQL_execstate *estate,
{
ExprState *cast_expr;
- cast_expr = get_cast_expression(estate, valtype, reqtype, reqtypmod);
+ cast_expr = get_cast_expression(estate,
+ valtype, valtypmod,
+ reqtype, reqtypmod);
if (cast_expr)
{
ExprContext *econtext = estate->eval_econtext;
@@ -5769,7 +5772,7 @@ exec_cast_value(PLpgSQL_execstate *estate,
*/
static ExprState *
get_cast_expression(PLpgSQL_execstate *estate,
- Oid srctype, Oid dsttype, int32 dsttypmod)
+ Oid srctype, int32 srctypmod, Oid dsttype, int32 dsttypmod)
{
HTAB *cast_hash = estate->func->cast_hash;
plpgsql_CastHashKey cast_key;
@@ -5799,6 +5802,7 @@ get_cast_expression(PLpgSQL_execstate *estate,
/* Look for existing entry */
cast_key.srctype = srctype;
cast_key.dsttype = dsttype;
+ cast_key.srctypmod = srctypmod;
cast_key.dsttypmod = dsttypmod;
cast_entry = (plpgsql_CastHashEntry *) hash_search(cast_hash,
(void *) &cast_key,
@@ -5815,7 +5819,7 @@ get_cast_expression(PLpgSQL_execstate *estate,
*/
placeholder = makeNode(CaseTestExpr);
placeholder->typeId = srctype;
- placeholder->typeMod = -1;
+ placeholder->typeMod = srctypmod;
placeholder->collation = get_typcollation(srctype);
if (OidIsValid(estate->func->fn_input_collation) &&
OidIsValid(placeholder->collation))