diff options
Diffstat (limited to 'src/backend/utils/adt/varchar.c')
-rw-r--r-- | src/backend/utils/adt/varchar.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 5cf927e27f2..c866af022f2 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -21,6 +21,7 @@ #include "catalog/pg_type.h" #include "libpq/pqformat.h" #include "nodes/nodeFuncs.h" +#include "nodes/supportnodes.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/varlena.h" @@ -547,32 +548,41 @@ varcharsend(PG_FUNCTION_ARGS) /* - * varchar_transform() - * Flatten calls to varchar's length coercion function that set the new maximum - * length >= the previous maximum length. We can ignore the isExplicit - * argument, since that only affects truncation cases. + * varchar_support() + * + * Planner support function for the varchar() length coercion function. + * + * Currently, the only interesting thing we can do is flatten calls that set + * the new maximum length >= the previous maximum length. We can ignore the + * isExplicit argument, since that only affects truncation cases. */ Datum -varchar_transform(PG_FUNCTION_ARGS) +varchar_support(PG_FUNCTION_ARGS) { - FuncExpr *expr = castNode(FuncExpr, PG_GETARG_POINTER(0)); + Node *rawreq = (Node *) PG_GETARG_POINTER(0); Node *ret = NULL; - Node *typmod; - Assert(list_length(expr->args) >= 2); + if (IsA(rawreq, SupportRequestSimplify)) + { + SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; + FuncExpr *expr = req->fcall; + Node *typmod; - typmod = (Node *) lsecond(expr->args); + Assert(list_length(expr->args) >= 2); - if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull) - { - Node *source = (Node *) linitial(expr->args); - int32 old_typmod = exprTypmod(source); - int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue); - int32 old_max = old_typmod - VARHDRSZ; - int32 new_max = new_typmod - VARHDRSZ; - - if (new_typmod < 0 || (old_typmod >= 0 && old_max <= new_max)) - ret = relabel_to_typmod(source, new_typmod); + typmod = (Node *) lsecond(expr->args); + + if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull) + { + Node *source = (Node *) linitial(expr->args); + int32 old_typmod = exprTypmod(source); + int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue); + int32 old_max = old_typmod - VARHDRSZ; + int32 new_max = new_typmod - VARHDRSZ; + + if (new_typmod < 0 || (old_typmod >= 0 && old_max <= new_max)) + ret = relabel_to_typmod(source, new_typmod); + } } PG_RETURN_POINTER(ret); |