Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2a7a75e

Browse files
committed
Change lpad() and rpad() to behave more Oracle-compatibly when target
length is less than original string length.
1 parent 288afd9 commit 2a7a75e

File tree

1 file changed

+61
-23
lines changed

1 file changed

+61
-23
lines changed

src/backend/utils/adt/oracle_compat.c

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
/*
22
* Edmund Mergl <E.Mergl@bawue.de>
33
*
4-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.29 2000/12/03 20:45:36 tgl Exp $
4+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.30 2000/12/07 23:22:56 tgl Exp $
55
*
66
*/
77

8-
#include <ctype.h>
9-
108
#include "postgres.h"
119

10+
#include <ctype.h>
11+
1212
#include "utils/builtins.h"
1313

1414

@@ -140,7 +140,8 @@ initcap(PG_FUNCTION_ARGS)
140140
* Purpose:
141141
*
142142
* Returns string1, left-padded to length len with the sequence of
143-
* characters in string2.
143+
* characters in string2. If len is less than the length of string1,
144+
* instead truncate (on the right) to len.
144145
*
145146
********************************************************************/
146147

@@ -153,31 +154,49 @@ lpad(PG_FUNCTION_ARGS)
153154
text *ret;
154155
char *ptr1,
155156
*ptr2,
157+
*ptr2end,
156158
*ptr_ret;
157159
int m,
158-
n;
160+
s1len,
161+
s2len;
162+
163+
/* Negative len is silently taken as zero */
164+
if (len < 0)
165+
len = 0;
166+
167+
s1len = VARSIZE(string1) - VARHDRSZ;
168+
if (s1len < 0)
169+
s1len = 0; /* shouldn't happen */
170+
171+
s2len = VARSIZE(string2) - VARHDRSZ;
172+
if (s2len < 0)
173+
s2len = 0; /* shouldn't happen */
159174

160-
if (((VARSIZE(string1) - VARHDRSZ) < 0) ||
161-
((m = len - (VARSIZE(string1) - VARHDRSZ)) <= 0) ||
162-
((VARSIZE(string2) - VARHDRSZ) <= 0))
163-
PG_RETURN_TEXT_P(string1);
175+
if (s1len > len)
176+
s1len = len; /* truncate string1 to len chars */
177+
178+
if (s2len <= 0)
179+
len = s1len; /* nothing to pad with, so don't pad */
164180

165181
ret = (text *) palloc(VARHDRSZ + len);
166182
VARATT_SIZEP(ret) = VARHDRSZ + len;
167183

184+
m = len - s1len;
185+
168186
ptr2 = VARDATA(string2);
187+
ptr2end = ptr2 + s2len;
169188
ptr_ret = VARDATA(ret);
170189

171190
while (m--)
172191
{
173-
*ptr_ret++ = *ptr2;
174-
ptr2 = (ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1) ? VARDATA(string2) : ++ptr2;
192+
*ptr_ret++ = *ptr2++;
193+
if (ptr2 == ptr2end) /* wrap around at end of s2 */
194+
ptr2 = VARDATA(string2);
175195
}
176196

177-
n = VARSIZE(string1) - VARHDRSZ;
178197
ptr1 = VARDATA(string1);
179198

180-
while (n--)
199+
while (s1len--)
181200
*ptr_ret++ = *ptr1++;
182201

183202
PG_RETURN_TEXT_P(ret);
@@ -195,7 +214,8 @@ lpad(PG_FUNCTION_ARGS)
195214
* Purpose:
196215
*
197216
* Returns string1, right-padded to length len with the sequence of
198-
* characters in string2.
217+
* characters in string2. If len is less than the length of string1,
218+
* instead truncate (on the right) to len.
199219
*
200220
********************************************************************/
201221

@@ -208,31 +228,49 @@ rpad(PG_FUNCTION_ARGS)
208228
text *ret;
209229
char *ptr1,
210230
*ptr2,
231+
*ptr2end,
211232
*ptr_ret;
212233
int m,
213-
n;
234+
s1len,
235+
s2len;
236+
237+
/* Negative len is silently taken as zero */
238+
if (len < 0)
239+
len = 0;
240+
241+
s1len = VARSIZE(string1) - VARHDRSZ;
242+
if (s1len < 0)
243+
s1len = 0; /* shouldn't happen */
214244

215-
if (((VARSIZE(string1) - VARHDRSZ) < 0) ||
216-
((m = len - (VARSIZE(string1) - VARHDRSZ)) <= 0) ||
217-
((VARSIZE(string2) - VARHDRSZ) <= 0))
218-
PG_RETURN_TEXT_P(string1);
245+
s2len = VARSIZE(string2) - VARHDRSZ;
246+
if (s2len < 0)
247+
s2len = 0; /* shouldn't happen */
248+
249+
if (s1len > len)
250+
s1len = len; /* truncate string1 to len chars */
251+
252+
if (s2len <= 0)
253+
len = s1len; /* nothing to pad with, so don't pad */
219254

220255
ret = (text *) palloc(VARHDRSZ + len);
221256
VARATT_SIZEP(ret) = VARHDRSZ + len;
222257

223-
n = VARSIZE(string1) - VARHDRSZ;
258+
m = len - s1len;
259+
224260
ptr1 = VARDATA(string1);
225261
ptr_ret = VARDATA(ret);
226262

227-
while (n--)
263+
while (s1len--)
228264
*ptr_ret++ = *ptr1++;
229265

230266
ptr2 = VARDATA(string2);
267+
ptr2end = ptr2 + s2len;
231268

232269
while (m--)
233270
{
234-
*ptr_ret++ = *ptr2;
235-
ptr2 = (ptr2 == VARDATA(string2) + VARSIZE(string2) - VARHDRSZ - 1) ? VARDATA(string2) : ++ptr2;
271+
*ptr_ret++ = *ptr2++;
272+
if (ptr2 == ptr2end) /* wrap around at end of s2 */
273+
ptr2 = VARDATA(string2);
236274
}
237275

238276
PG_RETURN_TEXT_P(ret);

0 commit comments

Comments
 (0)