From: Tom Lane Date: Thu, 7 Dec 2000 23:22:56 +0000 (+0000) Subject: Change lpad() and rpad() to behave more Oracle-compatibly when target X-Git-Tag: REL7_1_BETA2~231 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a7a75ee7e59c510e9ff7ee4158ba0accd59c9ce;p=postgresql Change lpad() and rpad() to behave more Oracle-compatibly when target length is less than original string length. --- diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index e851102620..5a83c56687 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -1,14 +1,14 @@ /* * Edmund Mergl * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.29 2000/12/03 20:45:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.30 2000/12/07 23:22:56 tgl Exp $ * */ -#include - #include "postgres.h" +#include + #include "utils/builtins.h" @@ -140,7 +140,8 @@ initcap(PG_FUNCTION_ARGS) * Purpose: * * Returns string1, left-padded to length len with the sequence of - * characters in string2. + * characters in string2. If len is less than the length of string1, + * instead truncate (on the right) to len. * ********************************************************************/ @@ -153,31 +154,49 @@ lpad(PG_FUNCTION_ARGS) text *ret; char *ptr1, *ptr2, + *ptr2end, *ptr_ret; int m, - n; + s1len, + s2len; + + /* Negative len is silently taken as zero */ + if (len < 0) + len = 0; + + s1len = VARSIZE(string1) - VARHDRSZ; + if (s1len < 0) + s1len = 0; /* shouldn't happen */ + + s2len = VARSIZE(string2) - VARHDRSZ; + if (s2len < 0) + s2len = 0; /* shouldn't happen */ - if (((VARSIZE(string1) - VARHDRSZ) < 0) || - ((m = len - (VARSIZE(string1) - VARHDRSZ)) <= 0) || - ((VARSIZE(string2) - VARHDRSZ) <= 0)) - PG_RETURN_TEXT_P(string1); + if (s1len > len) + s1len = len; /* truncate string1 to len chars */ + + if (s2len <= 0) + len = s1len; /* nothing to pad with, so don't pad */ ret = (text *) palloc(VARHDRSZ + len); VARATT_SIZEP(ret) = VARHDRSZ + len; + m = len - s1len; + ptr2 = VARDATA(string2); + ptr2end = ptr2 + s2len; ptr_ret = VARDATA(ret); while (m--) { - *ptr_ret++ = *ptr2; - ptr2 = (ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1) ? VARDATA(string2) : ++ptr2; + *ptr_ret++ = *ptr2++; + if (ptr2 == ptr2end) /* wrap around at end of s2 */ + ptr2 = VARDATA(string2); } - n = VARSIZE(string1) - VARHDRSZ; ptr1 = VARDATA(string1); - while (n--) + while (s1len--) *ptr_ret++ = *ptr1++; PG_RETURN_TEXT_P(ret); @@ -195,7 +214,8 @@ lpad(PG_FUNCTION_ARGS) * Purpose: * * Returns string1, right-padded to length len with the sequence of - * characters in string2. + * characters in string2. If len is less than the length of string1, + * instead truncate (on the right) to len. * ********************************************************************/ @@ -208,31 +228,49 @@ rpad(PG_FUNCTION_ARGS) text *ret; char *ptr1, *ptr2, + *ptr2end, *ptr_ret; int m, - n; + s1len, + s2len; + + /* Negative len is silently taken as zero */ + if (len < 0) + len = 0; + + s1len = VARSIZE(string1) - VARHDRSZ; + if (s1len < 0) + s1len = 0; /* shouldn't happen */ - if (((VARSIZE(string1) - VARHDRSZ) < 0) || - ((m = len - (VARSIZE(string1) - VARHDRSZ)) <= 0) || - ((VARSIZE(string2) - VARHDRSZ) <= 0)) - PG_RETURN_TEXT_P(string1); + s2len = VARSIZE(string2) - VARHDRSZ; + if (s2len < 0) + s2len = 0; /* shouldn't happen */ + + if (s1len > len) + s1len = len; /* truncate string1 to len chars */ + + if (s2len <= 0) + len = s1len; /* nothing to pad with, so don't pad */ ret = (text *) palloc(VARHDRSZ + len); VARATT_SIZEP(ret) = VARHDRSZ + len; - n = VARSIZE(string1) - VARHDRSZ; + m = len - s1len; + ptr1 = VARDATA(string1); ptr_ret = VARDATA(ret); - while (n--) + while (s1len--) *ptr_ret++ = *ptr1++; ptr2 = VARDATA(string2); + ptr2end = ptr2 + s2len; while (m--) { - *ptr_ret++ = *ptr2; - ptr2 = (ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1) ? VARDATA(string2) : ++ptr2; + *ptr_ret++ = *ptr2++; + if (ptr2 == ptr2end) /* wrap around at end of s2 */ + ptr2 = VARDATA(string2); } PG_RETURN_TEXT_P(ret);