diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-01-07 20:17:44 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-01-07 20:17:44 +0000 |
commit | 50626efe0aef19fa31fd9ccf79570a24b84bbf01 (patch) | |
tree | 9c6f42ddbb766a618731a446fe0b6c2a4e5476d9 /src/backend/utils/adt/varbit.c | |
parent | e4a6ebf7dece1481b1432c8ac43124487bebf3d9 (diff) | |
download | postgresql-50626efe0aef19fa31fd9ccf79570a24b84bbf01.tar.gz postgresql-50626efe0aef19fa31fd9ccf79570a24b84bbf01.zip |
Fix 3-parameter form of bit substring() to throw error for negative length,
as required by SQL standard.
Diffstat (limited to 'src/backend/utils/adt/varbit.c')
-rw-r--r-- | src/backend/utils/adt/varbit.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index d98a8a613ee..7f39866f005 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 |