aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/varbit.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-07-10 21:14:00 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-07-10 21:14:00 +0000
commitd78397d301172cccce14d5d789f296c47dd47c5e (patch)
tree4104dc887976aee14286c0c0a7be03f84af43b7d /src/backend/utils/adt/varbit.c
parent2e330699fae72c40f5237ce0f4fc210c483d2816 (diff)
downloadpostgresql-d78397d301172cccce14d5d789f296c47dd47c5e.tar.gz
postgresql-d78397d301172cccce14d5d789f296c47dd47c5e.zip
Change typreceive function API so that receive functions get the same
optional arguments as text input functions, ie, typioparam OID and atttypmod. Make all the datatypes that use typmod enforce it the same way in typreceive as they do in typinput. This fixes a problem with failure to enforce length restrictions during COPY FROM BINARY.
Diffstat (limited to 'src/backend/utils/adt/varbit.c')
-rw-r--r--src/backend/utils/adt/varbit.c61
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;