diff options
Diffstat (limited to 'src/backend/utils/adt/varbit.c')
-rw-r--r-- | src/backend/utils/adt/varbit.c | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index bdbf43c8993..1996638d28e 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.44 2004/12/31 22:01:22 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.45 2005/07/10 21:13:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -221,8 +221,49 @@ bit_out(PG_FUNCTION_ARGS) Datum bit_recv(PG_FUNCTION_ARGS) { - /* Exactly the same as varbit_recv, so share code */ - return varbit_recv(fcinfo); + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 atttypmod = PG_GETARG_INT32(2); + VarBit *result; + int len, + bitlen; + int ipad; + bits8 mask; + + bitlen = pq_getmsgint(buf, sizeof(int32)); + if (bitlen < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid length in external bit string"))); + + /* + * Sometimes atttypmod is not supplied. If it is supplied we need to + * make sure that the bitstring fits. + */ + if (atttypmod > 0 && bitlen != atttypmod) + ereport(ERROR, + (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH), + errmsg("bit string length %d does not match type bit(%d)", + bitlen, atttypmod))); + + len = VARBITTOTALLEN(bitlen); + result = (VarBit *) palloc(len); + VARATT_SIZEP(result) = len; + VARBITLEN(result) = bitlen; + + pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result)); + + /* Make sure last byte is zero-padded if needed */ + ipad = VARBITPAD(result); + if (ipad > 0) + { + mask = BITMASK << ipad; + *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask; + } + + PG_RETURN_VARBIT_P(result); } /* @@ -459,6 +500,10 @@ Datum varbit_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); +#ifdef NOT_USED + Oid typelem = PG_GETARG_OID(1); +#endif + int32 atttypmod = PG_GETARG_INT32(2); VarBit *result; int len, bitlen; @@ -471,6 +516,16 @@ varbit_recv(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid length in external bit string"))); + /* + * Sometimes atttypmod is not supplied. If it is supplied we need to + * make sure that the bitstring fits. + */ + if (atttypmod > 0 && bitlen > atttypmod) + ereport(ERROR, + (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), + errmsg("bit string too long for type bit varying(%d)", + atttypmod))); + len = VARBITTOTALLEN(bitlen); result = (VarBit *) palloc(len); VARATT_SIZEP(result) = len; |