mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Marginal hack to save a little bit of time in bpcharin() when typmod is -1,
which is a common case.
This commit is contained in:
@ -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 @@
|
|||||||
* 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)
|
|||||||
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;
|
|
||||||
else
|
|
||||||
maxlen = atttypmod - VARHDRSZ;
|
|
||||||
|
|
||||||
if (charlen > maxlen)
|
|
||||||
{
|
|
||||||
/* Verify that extra characters are spaces, and clip them off */
|
|
||||||
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX: at this point, maxlen is the necessary byte length, not
|
|
||||||
* the number of CHARACTERS!
|
|
||||||
*/
|
|
||||||
maxlen = len;
|
maxlen = len;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
size_t charlen; /* number of CHARACTERS in the input */
|
||||||
* XXX: at this point, maxlen is the necessary byte length, not
|
|
||||||
* the number of CHARACTERS!
|
maxlen = atttypmod - VARHDRSZ;
|
||||||
*/
|
charlen = pg_mbstrlen(s);
|
||||||
maxlen = len + (maxlen - charlen);
|
if (charlen > maxlen)
|
||||||
|
{
|
||||||
|
/* Verify that extra characters are spaces, and clip them off */
|
||||||
|
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Now we set maxlen to 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)
|
|||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user