Commit db86f296 authored by Tom Lane's avatar Tom Lane

Marginal hack to save a little bit of time in bpcharin() when typmod is -1,

which is a common case.
parent 7cac5027
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.109 2005/04/12 04:26:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.110 2005/05/29 20:15:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,8 +36,8 @@ ...@@ -36,8 +36,8 @@
* length also. (eg. in INSERTs, we have the tupleDescriptor which contains * length also. (eg. in INSERTs, we have the tupleDescriptor which contains
* the length of the attributes and hence the exact length of the char() or * the length of the attributes and hence the exact length of the char() or
* varchar(). We pass this to bpcharin() or varcharin().) In the case where * varchar(). We pass this to bpcharin() or varcharin().) In the case where
* we cannot determine the length, we pass in -1 instead and the input string * we cannot determine the length, we pass in -1 instead and the input
* must be null-terminated. * converter does not enforce any length check.
* *
* We actually implement this as a varlena so that we don't have to pass in * We actually implement this as a varlena so that we don't have to pass in
* the length for the comparison functions. (The difference between these * the length for the comparison functions. (The difference between these
...@@ -72,63 +72,62 @@ bpcharin(PG_FUNCTION_ARGS) ...@@ -72,63 +72,62 @@ bpcharin(PG_FUNCTION_ARGS)
char *r; char *r;
size_t len, size_t len,
maxlen; maxlen;
int i;
int charlen; /* number of charcters in the input string */
/* verify encoding */ /* verify encoding */
len = strlen(s); len = strlen(s);
pg_verifymbstr(s, len, false); pg_verifymbstr(s, len, false);
charlen = pg_mbstrlen(s);
/* If typmod is -1 (or invalid), use the actual string length */ /* If typmod is -1 (or invalid), use the actual string length */
if (atttypmod < (int32) VARHDRSZ) if (atttypmod < (int32) VARHDRSZ)
maxlen = charlen; maxlen = len;
else else
maxlen = atttypmod - VARHDRSZ;
if (charlen > maxlen)
{ {
/* Verify that extra characters are spaces, and clip them off */ size_t charlen; /* number of CHARACTERS in the input */
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
/* maxlen = atttypmod - VARHDRSZ;
* at this point, len is the actual BYTE length of the input charlen = pg_mbstrlen(s);
* string, maxlen is the max number of CHARACTERS allowed for this if (charlen > maxlen)
* bpchar type. {
*/ /* Verify that extra characters are spaces, and clip them off */
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen) size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
len = mbmaxlen;
/*
* at this point, len is the actual BYTE length of the input
* string, maxlen is the max number of CHARACTERS allowed for this
* bpchar type.
*/
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
len = mbmaxlen;
else
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("value too long for type character(%d)",
(int) maxlen)));
/*
* Now we set maxlen to the necessary byte length, not
* the number of CHARACTERS!
*/
maxlen = len;
}
else else
ereport(ERROR, {
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), /*
errmsg("value too long for type character(%d)", * Now we set maxlen to the necessary byte length, not
(int) maxlen))); * the number of CHARACTERS!
*/
/* maxlen = len + (maxlen - charlen);
* XXX: at this point, maxlen is the necessary byte length, not }
* the number of CHARACTERS!
*/
maxlen = len;
}
else
{
/*
* XXX: at this point, maxlen is the necessary byte length, not
* the number of CHARACTERS!
*/
maxlen = len + (maxlen - charlen);
} }
result = palloc(maxlen + VARHDRSZ); result = palloc(maxlen + VARHDRSZ);
VARATT_SIZEP(result) = maxlen + VARHDRSZ; VARATT_SIZEP(result) = maxlen + VARHDRSZ;
r = VARDATA(result); r = VARDATA(result);
for (i = 0; i < len; i++) memcpy(r, s, len);
*r++ = *s++;
/* blank pad the string if necessary */ /* blank pad the string if necessary */
for (; i < maxlen; i++) if (maxlen > len)
*r++ = ' '; memset(r + len, ' ', maxlen - len);
PG_RETURN_BPCHAR_P(result); PG_RETURN_BPCHAR_P(result);
} }
...@@ -200,12 +199,16 @@ bpchar(PG_FUNCTION_ARGS) ...@@ -200,12 +199,16 @@ bpchar(PG_FUNCTION_ARGS)
int charlen; /* number of charcters in the input string int charlen; /* number of charcters in the input string
* + VARHDRSZ */ * + VARHDRSZ */
/* No work if typmod is invalid */
if (maxlen < (int32) VARHDRSZ)
PG_RETURN_BPCHAR_P(source);
len = VARSIZE(source); len = VARSIZE(source);
charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ; charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ;
/* No work if typmod is invalid or supplied data matches it already */ /* No work if supplied data matches typmod already */
if (maxlen < (int32) VARHDRSZ || charlen == maxlen) if (charlen == maxlen)
PG_RETURN_BPCHAR_P(source); PG_RETURN_BPCHAR_P(source);
if (charlen > maxlen) if (charlen > maxlen)
...@@ -249,12 +252,11 @@ bpchar(PG_FUNCTION_ARGS) ...@@ -249,12 +252,11 @@ bpchar(PG_FUNCTION_ARGS)
VARATT_SIZEP(result) = maxlen; VARATT_SIZEP(result) = maxlen;
r = VARDATA(result); r = VARDATA(result);
for (i = 0; i < len - VARHDRSZ; i++) memcpy(r, s, len - VARHDRSZ);
*r++ = *s++;
/* blank pad the string if necessary */ /* blank pad the string if necessary */
for (; i < maxlen - VARHDRSZ; i++) if (maxlen > len)
*r++ = ' '; memset(r + len - VARHDRSZ, ' ', maxlen - len);
PG_RETURN_BPCHAR_P(result); PG_RETURN_BPCHAR_P(result);
} }
......
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