1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

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.
This commit is contained in:
Robert Haas
2012-02-07 12:41:42 -05:00
parent 3cc0800829
commit f7d7dade8a
4 changed files with 40 additions and 2 deletions

View File

@ -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.