Commit 2a7a75ee authored by Tom Lane's avatar Tom Lane

Change lpad() and rpad() to behave more Oracle-compatibly when target

length is less than original string length.
parent 288afd95
/* /*
* Edmund Mergl <E.Mergl@bawue.de> * Edmund Mergl <E.Mergl@bawue.de>
* *
* $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 <ctype.h>
#include "postgres.h" #include "postgres.h"
#include <ctype.h>
#include "utils/builtins.h" #include "utils/builtins.h"
...@@ -140,7 +140,8 @@ initcap(PG_FUNCTION_ARGS) ...@@ -140,7 +140,8 @@ initcap(PG_FUNCTION_ARGS)
* Purpose: * Purpose:
* *
* Returns string1, left-padded to length len with the sequence of * 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) ...@@ -153,31 +154,49 @@ lpad(PG_FUNCTION_ARGS)
text *ret; text *ret;
char *ptr1, char *ptr1,
*ptr2, *ptr2,
*ptr2end,
*ptr_ret; *ptr_ret;
int m, 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 (s1len > len)
s1len = len; /* truncate string1 to len chars */
if (((VARSIZE(string1) - VARHDRSZ) < 0) || if (s2len <= 0)
((m = len - (VARSIZE(string1) - VARHDRSZ)) <= 0) || len = s1len; /* nothing to pad with, so don't pad */
((VARSIZE(string2) - VARHDRSZ) <= 0))
PG_RETURN_TEXT_P(string1);
ret = (text *) palloc(VARHDRSZ + len); ret = (text *) palloc(VARHDRSZ + len);
VARATT_SIZEP(ret) = VARHDRSZ + len; VARATT_SIZEP(ret) = VARHDRSZ + len;
m = len - s1len;
ptr2 = VARDATA(string2); ptr2 = VARDATA(string2);
ptr2end = ptr2 + s2len;
ptr_ret = VARDATA(ret); ptr_ret = VARDATA(ret);
while (m--) while (m--)
{ {
*ptr_ret++ = *ptr2; *ptr_ret++ = *ptr2++;
ptr2 = (ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1) ? VARDATA(string2) : ++ptr2; if (ptr2 == ptr2end) /* wrap around at end of s2 */
ptr2 = VARDATA(string2);
} }
n = VARSIZE(string1) - VARHDRSZ;
ptr1 = VARDATA(string1); ptr1 = VARDATA(string1);
while (n--) while (s1len--)
*ptr_ret++ = *ptr1++; *ptr_ret++ = *ptr1++;
PG_RETURN_TEXT_P(ret); PG_RETURN_TEXT_P(ret);
...@@ -195,7 +214,8 @@ lpad(PG_FUNCTION_ARGS) ...@@ -195,7 +214,8 @@ lpad(PG_FUNCTION_ARGS)
* Purpose: * Purpose:
* *
* Returns string1, right-padded to length len with the sequence of * 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) ...@@ -208,31 +228,49 @@ rpad(PG_FUNCTION_ARGS)
text *ret; text *ret;
char *ptr1, char *ptr1,
*ptr2, *ptr2,
*ptr2end,
*ptr_ret; *ptr_ret;
int m, 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) || s2len = VARSIZE(string2) - VARHDRSZ;
((m = len - (VARSIZE(string1) - VARHDRSZ)) <= 0) || if (s2len < 0)
((VARSIZE(string2) - VARHDRSZ) <= 0)) s2len = 0; /* shouldn't happen */
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); ret = (text *) palloc(VARHDRSZ + len);
VARATT_SIZEP(ret) = VARHDRSZ + len; VARATT_SIZEP(ret) = VARHDRSZ + len;
n = VARSIZE(string1) - VARHDRSZ; m = len - s1len;
ptr1 = VARDATA(string1); ptr1 = VARDATA(string1);
ptr_ret = VARDATA(ret); ptr_ret = VARDATA(ret);
while (n--) while (s1len--)
*ptr_ret++ = *ptr1++; *ptr_ret++ = *ptr1++;
ptr2 = VARDATA(string2); ptr2 = VARDATA(string2);
ptr2end = ptr2 + s2len;
while (m--) while (m--)
{ {
*ptr_ret++ = *ptr2; *ptr_ret++ = *ptr2++;
ptr2 = (ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1) ? VARDATA(string2) : ++ptr2; if (ptr2 == ptr2end) /* wrap around at end of s2 */
ptr2 = VARDATA(string2);
} }
PG_RETURN_TEXT_P(ret); PG_RETURN_TEXT_P(ret);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment