The attached patch changes the existing behaviour of length(char(n)).
Currently, this is what happens:

template1=# select length('blah'::char(10));
 length
--------
     10
(1 row)

With this patch:

template1=# select length('blah'::char(10));
 length
--------
      4
(1 row)

This behaviour was proposed by Tom back in November last year. (I have
tried to handle multibyte correctly but probably haven't -- hence my email
hackers instead of patches).

The spec doesn't give us any insight (as far as I can tell) as to how we
should do it length(char(n)), but the above seems consistent with other
parts of the code (eg, comparison functions, concatenation).

SQL200X has these choice paragraphs for those who are interested:

         <length expression> returns the length of a given character string,
         as an exact numeric value, in characters or octets according to the
         choice of function.

And:

                        the result is the number of explicit or implicit
              <char length units> in <char length expression>, counted in
              accordance with the definition of those units in the relevant
              normatively referenced document.

I have no idea what the 'normatively referenced document' is, but grep-ing
through all of SQL200X, 99 and 92 didn't reveal anything too interesting.


Gavin
Index: src/backend/utils/adt/varchar.c
===================================================================
RCS file: /usr/local/cvsroot/pgsql-server/src/backend/utils/adt/varchar.c,v
retrieving revision 1.103
diff -2 -c -r1.103 varchar.c
*** src/backend/utils/adt/varchar.c     29 Nov 2003 19:51:59 -0000      1.103
--- src/backend/utils/adt/varchar.c     27 Jan 2004 06:18:33 -0000
***************
*** 511,522 ****
  {
        BpChar     *arg = PG_GETARG_BPCHAR_P(0);
  
        /* optimization for single byte encoding */
        if (pg_database_encoding_max_length() <= 1)
!               PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);
  
!       PG_RETURN_INT32(
!                         pg_mbstrlen_with_len(VARDATA(arg), VARSIZE(arg) - VARHDRSZ)
!               );
  }
  
--- 511,530 ----
  {
        BpChar     *arg = PG_GETARG_BPCHAR_P(0);
+       int                     len;
+       char       *str;
  
+       len = bcTruelen(arg);
+       
        /* optimization for single byte encoding */
        if (pg_database_encoding_max_length() <= 1)
!               PG_RETURN_INT32(len);
  
!       str = palloc(len);
!       StrNCpy(str,VARDATA(arg),len);
! 
!       len = pg_mbstrlen_with_len(str, len);
!       pfree(str);
! 
!       PG_RETURN_INT32(len);
  }
  
---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]

Reply via email to