From f7d7dade8afe19847510efe44be191c35e1ce26c Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Tue, 7 Feb 2012 12:41:42 -0500 Subject: Add a transform function for varbit typmod coercisions. This enables ALTER TABLE to skip table and index rebuilds when the new type is unconstraint varbit, or when the allowable number of bits is not decreasing. Noah Misch, with review and a fix for an OID collision by me. --- src/backend/utils/adt/varbit.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/backend/utils/adt/varbit.c') diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index adb08369ed2..1227e5a5082 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -18,6 +18,8 @@ #include "access/htup.h" #include "libpq/pqformat.h" +#include "nodes/nodeFuncs.h" +#include "parser/parse_clause.h" #include "utils/array.h" #include "utils/varbit.h" @@ -645,6 +647,39 @@ varbit_send(PG_FUNCTION_ARGS) PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); } +/* + * varbit_transform() + * 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 +varbit_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); + int32 new_max = new_typmod; + + if (new_max <= 0 || (old_max >= 0 && old_max <= new_max)) + ret = relabel_to_typmod(source, new_typmod); + } + + PG_RETURN_POINTER(ret); +} + /* * varbit() * Converts a varbit() type to a specific internal length. -- cgit v1.2.3