1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-31 17:02:12 +03:00

Add notion of a "transform function" that can simplify function calls.

Initially, we use this only to eliminate calls to the varchar()
function in cases where the length is not being reduced and, therefore,
the function call is equivalent to a RelabelType operation.  The most
significant effect of this is that we can avoid a table rewrite when
changing a varchar(X) column to a varchar(Y) column, where Y > X.

Noah Misch, reviewed by me and Alexey Klyukin
This commit is contained in:
Robert Haas
2011-06-21 22:15:24 -04:00
parent 771a9f69f7
commit 8f9fe6edce
11 changed files with 2401 additions and 2280 deletions

View File

@@ -18,6 +18,8 @@
#include "access/hash.h"
#include "access/tuptoaster.h"
#include "libpq/pqformat.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_clause.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "mb/pg_wchar.h"
@@ -548,6 +550,38 @@ varcharsend(PG_FUNCTION_ARGS)
}
/*
* Flatten calls to our length coercion function that leave the new maximum
* length >= the previous maximum length. We ignore the isExplicit argument,
* which only affects truncation.
*/
Datum
varchar_transform(PG_FUNCTION_ARGS)
{
FuncExpr *expr = (FuncExpr *) PG_GETARG_POINTER(0);
Node *typmod;
Node *ret = NULL;
if (!IsA(expr, FuncExpr))
PG_RETURN_POINTER(ret);
Assert(list_length(expr->args) == 3);
typmod = lsecond(expr->args);
if (IsA(typmod, Const))
{
Node *source = linitial(expr->args);
int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
int32 old_max = exprTypmod(source) - VARHDRSZ;
int32 new_max = new_typmod - VARHDRSZ;
if (new_max < 0 || (old_max >= 0 && old_max <= new_max))
ret = relabel_to_typmod(source, new_typmod);
}
PG_RETURN_POINTER(ret);
}
/*
* Converts a VARCHAR type to the specified size.
*