Marginal hack to save a little bit of time in bpcharin() when typmod is -1,
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 May 2005 20:15:59 +0000 (20:15 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 May 2005 20:15:59 +0000 (20:15 +0000)
which is a common case.

src/backend/utils/adt/varchar.c

index 17d775d23b9f7cd76218aeae1c30a19d7e913a51..6d89b3df2f70b9ed488d080804ba7984623eaeea 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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
  * 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
- * we cannot determine the length, we pass in -1 instead and the input string
- * must be null-terminated.
+ * we cannot determine the length, we pass in -1 instead and the input
+ * converter does not enforce any length check.
  *
  * 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
@@ -72,63 +72,62 @@ bpcharin(PG_FUNCTION_ARGS)
    char       *r;
    size_t      len,
                maxlen;
-   int         i;
-   int         charlen;        /* number of charcters in the input string */
 
    /* verify encoding */
    len = strlen(s);
    pg_verifymbstr(s, len, false);
 
-   charlen = pg_mbstrlen(s);
-
    /* If typmod is -1 (or invalid), use the actual string length */
    if (atttypmod < (int32) VARHDRSZ)
-       maxlen = charlen;
+       maxlen = len;
    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);
+       size_t      charlen;        /* number of CHARACTERS in the input */
 
-       /*
-        * 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;
+       maxlen = atttypmod - VARHDRSZ;
+       charlen = pg_mbstrlen(s);
+       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
-           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;
-   }
-   else
-   {
-       /*
-        * XXX: at this point, maxlen is the necessary byte length, not
-        * the number of CHARACTERS!
-        */
-       maxlen = len + (maxlen - charlen);
+       {
+           /*
+            * Now we set maxlen to the necessary byte length, not
+            * the number of CHARACTERS!
+            */
+           maxlen = len + (maxlen - charlen);
+       }
    }
 
    result = palloc(maxlen + VARHDRSZ);
    VARATT_SIZEP(result) = maxlen + VARHDRSZ;
    r = VARDATA(result);
-   for (i = 0; i < len; i++)
-       *r++ = *s++;
+   memcpy(r, s, len);
 
    /* blank pad the string if necessary */
-   for (; i < maxlen; i++)
-       *r++ = ' ';
+   if (maxlen > len)
+       memset(r + len, ' ', maxlen - len);
 
    PG_RETURN_BPCHAR_P(result);
 }
@@ -200,12 +199,16 @@ bpchar(PG_FUNCTION_ARGS)
    int         charlen;        /* number of charcters in the input string
                                 * + VARHDRSZ */
 
+   /* No work if typmod is invalid */
+   if (maxlen < (int32) VARHDRSZ)
+       PG_RETURN_BPCHAR_P(source);
+
    len = VARSIZE(source);
 
    charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ;
 
-   /* No work if typmod is invalid or supplied data matches it already */
-   if (maxlen < (int32) VARHDRSZ || charlen == maxlen)
+   /* No work if supplied data matches typmod already */
+   if (charlen == maxlen)
        PG_RETURN_BPCHAR_P(source);
 
    if (charlen > maxlen)
@@ -249,12 +252,11 @@ bpchar(PG_FUNCTION_ARGS)
    VARATT_SIZEP(result) = maxlen;
    r = VARDATA(result);
 
-   for (i = 0; i < len - VARHDRSZ; i++)
-       *r++ = *s++;
+   memcpy(r, s, len - VARHDRSZ);
 
    /* blank pad the string if necessary */
-   for (; i < maxlen - VARHDRSZ; i++)
-       *r++ = ' ';
+   if (maxlen > len)
+       memset(r + len - VARHDRSZ, ' ', maxlen - len);
 
    PG_RETURN_BPCHAR_P(result);
 }