From 50626efe0aef19fa31fd9ccf79570a24b84bbf01 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 7 Jan 2010 20:17:44 +0000 Subject: [PATCH] Fix 3-parameter form of bit substring() to throw error for negative length, as required by SQL standard. --- src/backend/utils/adt/varbit.c | 34 +++++++++++++++++++++++++------- src/include/catalog/catversion.h | 4 ++-- src/include/catalog/pg_proc.h | 4 ++-- src/include/utils/varbit.h | 3 ++- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index d98a8a613e..7f39866f00 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.62 2010/01/07 19:53:11 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.63 2010/01/07 20:17:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,9 @@ #define HEXDIG(z) ((z)<10 ? ((z)+'0') : ((z)-10+'A')) +static VarBit *bitsubstring(VarBit *arg, int32 s, int32 l, + bool length_not_specified); + /* common code for bittypmodin and varbittypmodin */ static int32 @@ -927,9 +930,23 @@ bitcat(PG_FUNCTION_ARGS) Datum bitsubstr(PG_FUNCTION_ARGS) { - VarBit *arg = PG_GETARG_VARBIT_P(0); - int32 s = PG_GETARG_INT32(1); - int32 l = PG_GETARG_INT32(2); + PG_RETURN_VARBIT_P(bitsubstring(PG_GETARG_VARBIT_P(0), + PG_GETARG_INT32(1), + PG_GETARG_INT32(2), + false)); +} + +Datum +bitsubstr_no_len(PG_FUNCTION_ARGS) +{ + PG_RETURN_VARBIT_P(bitsubstring(PG_GETARG_VARBIT_P(0), + PG_GETARG_INT32(1), + -1, true)); +} + +static VarBit * +bitsubstring(VarBit *arg, int32 s, int32 l, bool length_not_specified) +{ VarBit *result; int bitlen, rbitlen, @@ -947,14 +964,17 @@ bitsubstr(PG_FUNCTION_ARGS) bitlen = VARBITLEN(arg); s1 = Max(s, 1); /* If we do not have an upper bound, use end of string */ - if (l < 0) + if (length_not_specified) { e1 = bitlen + 1; } else { e = s + l; - /* guard against overflow, even though we don't allow L<0 here */ + /* + * A negative value for L is the only way for the end position + * to be before the start. SQL99 says to throw an error. + */ if (e < s) ereport(ERROR, (errcode(ERRCODE_SUBSTRING_ERROR), @@ -1011,7 +1031,7 @@ bitsubstr(PG_FUNCTION_ARGS) } } - PG_RETURN_VARBIT_P(result); + return result; } /* bitlength, bitoctetlength diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index b6505feeef..b81a777e0b 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.569 2010/01/06 05:18:18 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.570 2010/01/07 20:17:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201001061 +#define CATALOG_VERSION_NO 201001071 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 1717296951..b39c02f7f2 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.559 2010/01/05 01:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.560 2010/01/07 20:17:44 tgl Exp $ * * NOTES * The script catalog/genbki.pl reads this file and generates .bki @@ -2400,7 +2400,7 @@ DESCR("adjust varbit() to typmod length"); DATA(insert OID = 1698 ( position PGNSP PGUID 12 1 0 0 f f f t f i 2 0 23 "1560 1560" _null_ _null_ _null_ _null_ bitposition _null_ _null_ _null_ )); DESCR("return position of sub-bitstring"); -DATA(insert OID = 1699 ( substring PGNSP PGUID 14 1 0 0 f f f t f i 2 0 1560 "1560 23" _null_ _null_ _null_ _null_ "select pg_catalog.substring($1, $2, -1)" _null_ _null_ _null_ )); +DATA(insert OID = 1699 ( substring PGNSP PGUID 12 1 0 0 f f f t f i 2 0 1560 "1560 23" _null_ _null_ _null_ _null_ bitsubstr_no_len _null_ _null_ _null_ )); DESCR("return portion of bitstring"); diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h index a7aaa57902..df51c9b415 100644 --- a/src/include/utils/varbit.h +++ b/src/include/utils/varbit.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/varbit.h,v 1.29 2010/01/02 16:58:10 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/varbit.h,v 1.30 2010/01/07 20:17:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -88,6 +88,7 @@ extern Datum bitshiftleft(PG_FUNCTION_ARGS); extern Datum bitshiftright(PG_FUNCTION_ARGS); extern Datum bitcat(PG_FUNCTION_ARGS); extern Datum bitsubstr(PG_FUNCTION_ARGS); +extern Datum bitsubstr_no_len(PG_FUNCTION_ARGS); extern Datum bitlength(PG_FUNCTION_ARGS); extern Datum bitoctetlength(PG_FUNCTION_ARGS); extern Datum bitfromint4(PG_FUNCTION_ARGS);