summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/varchar.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-06-01 17:49:17 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-06-01 17:49:17 +0000
commit7c0c9b3ccec4718c1c7cef7b5282fd56b727d965 (patch)
treefe6b73c413c50920a15d9efd65b850e44552b5a1 /src/backend/utils/adt/varchar.c
parent597ca67e5eb42521dd41fc385bc10e450b81630d (diff)
New improved version of bpcharin() may have got the truncation case
right, but it failed to get the padding case right. This was obscured by subsequent application of bpchar() in all but one regression test case, and that one didn't fail in an obvious way --- trailing blanks are hard to see. Add another test case to make it more obvious if it breaks again.
Diffstat (limited to 'src/backend/utils/adt/varchar.c')
-rw-r--r--src/backend/utils/adt/varchar.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 467a5cf7de3..cdd76afb55d 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.78 2001/05/21 16:54:46 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.79 2001/06/01 17:49:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -65,10 +65,8 @@ Datum
bpcharin(PG_FUNCTION_ARGS)
{
char *s = PG_GETARG_CSTRING(0);
-
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
-
#endif
int32 atttypmod = PG_GETARG_INT32(2);
BpChar *result;
@@ -77,45 +75,46 @@ bpcharin(PG_FUNCTION_ARGS)
int i;
len = strlen(s);
- maxlen = atttypmod - VARHDRSZ;
- if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
+ /* If typmod is -1 (or invalid), use the actual string length */
+ if (atttypmod < (int32) VARHDRSZ)
+ maxlen = len;
+ else
+ maxlen = atttypmod - VARHDRSZ;
+
+ if (len > maxlen)
{
+ /* Verify that extra characters are spaces, and clip them off */
#ifdef MULTIBYTE
size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
len = mbmaxlen;
+ else
+ elog(ERROR, "value too long for type character(%d)", maxlen);
+ Assert(len <= maxlen);
#else
if (strspn(s + maxlen, " ") == len - maxlen)
- /* clip extra spaces */
len = maxlen;
-#endif
else
elog(ERROR, "value too long for type character(%d)", maxlen);
+#endif
}
- else
- /* If typmod is -1 (or invalid), use the actual string length */
- maxlen = len;
result = palloc(maxlen + VARHDRSZ);
VARATT_SIZEP(result) = maxlen + VARHDRSZ;
r = VARDATA(result);
- for (i = 0; i < len; i++, r++, s++)
- {
- *r = *s;
- if (*r == '\0')
- break;
- }
-
-#ifdef CYR_RECODE
- convertstr(VARDATA(result), len, 0);
-#endif
+ for (i = 0; i < len; i++)
+ *r++ = *s++;
/* blank pad the string if necessary */
for (; i < maxlen; i++)
*r++ = ' ';
+#ifdef CYR_RECODE
+ convertstr(VARDATA(result), len, 0);
+#endif
+
PG_RETURN_BPCHAR_P(result);
}
@@ -162,11 +161,12 @@ bpchar(PG_FUNCTION_ARGS)
len = VARSIZE(source);
/* No work if typmod is invalid or supplied data matches it already */
- if (len < (int32) VARHDRSZ || len == maxlen)
+ if (maxlen < (int32) VARHDRSZ || len == maxlen)
PG_RETURN_BPCHAR_P(source);
if (len > maxlen)
{
+ /* Verify that extra characters are spaces, and clip them off */
#ifdef MULTIBYTE
size_t maxmblen;
@@ -179,13 +179,13 @@ bpchar(PG_FUNCTION_ARGS)
maxlen - VARHDRSZ);
len = maxmblen;
+ Assert(len <= maxlen);
#else
for (i = maxlen - VARHDRSZ; i < len - VARHDRSZ; i++)
if (*(VARDATA(source) + i) != ' ')
elog(ERROR, "value too long for type character(%d)",
maxlen - VARHDRSZ);
- /* clip extra spaces */
len = maxlen;
#endif
}
@@ -196,7 +196,7 @@ bpchar(PG_FUNCTION_ARGS)
VARATT_SIZEP(result) = maxlen;
r = VARDATA(result);
- for (i = 0; (i < maxlen - VARHDRSZ) && (i < len - VARHDRSZ); i++)
+ for (i = 0; i < len - VARHDRSZ; i++)
*r++ = *s++;
/* blank pad the string if necessary */
@@ -340,10 +340,8 @@ Datum
varcharin(PG_FUNCTION_ARGS)
{
char *s = PG_GETARG_CSTRING(0);
-
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
-
#endif
int32 atttypmod = PG_GETARG_INT32(2);
VarChar *result;
@@ -354,6 +352,7 @@ varcharin(PG_FUNCTION_ARGS)
if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
{
+ /* Verify that extra characters are spaces, and clip them off */
#ifdef MULTIBYTE
size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
@@ -361,7 +360,6 @@ varcharin(PG_FUNCTION_ARGS)
len = mbmaxlen;
#else
if (strspn(s + maxlen, " ") == len - maxlen)
- /* clip extra spaces */
len = maxlen;
#endif
else
@@ -419,6 +417,7 @@ varchar(PG_FUNCTION_ARGS)
int i;
len = VARSIZE(source);
+ /* No work if typmod is invalid or supplied data fits it already */
if (maxlen < (int32) VARHDRSZ || len <= maxlen)
PG_RETURN_VARCHAR_P(source);