Tom Lane wrote:
> Euler Taveira de Oliveira <[EMAIL PROTECTED]> writes:
> > Tom Lane wrote:
> >> Also, it seems a bit inconsistent to be relying on
> >> oracle_compat.c for upper/lower but not initcap.
> >> 
> > I saw this inconsistence while I'm doing the patch. What about moving 
> > that upper/lower/initcap and wcs* code to another file. pg_locale.c? 
> 
> That doesn't seem a particularly appropriate place for them.  pg_locale
> is about dealing with the locale state, not about doing actual
> operations based on the locale data.
> 
> I was just thinking of having oracle_compat expose an initcap routine.

You mean like the attached?

I moved str_initcap() over into oracle_compat.c and then had initcap()
convert to/from TEXT to call it.  The code is a little weird because
str_initcap() needs to convert to text to use texttowcs(), so in
multibyte encodings initcap converts the string to text, then to char,
then to text to call texttowcs().  I didn't see a cleaner way to do
this.

-- 
  Bruce Momjian  <[EMAIL PROTECTED]>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v
retrieving revision 1.141
diff -c -c -r1.141 formatting.c
*** src/backend/utils/adt/formatting.c	20 May 2008 01:41:02 -0000	1.141
--- src/backend/utils/adt/formatting.c	13 Jun 2008 22:01:18 -0000
***************
*** 927,933 ****
  static int	strdigits_len(char *str);
  static char *str_toupper(char *buff);
  static char *str_tolower(char *buff);
- static char *str_initcap(char *buff);
  
  static int	seq_search(char *name, char **array, int type, int max, int *len);
  static void do_to_timestamp(text *date_txt, text *fmt,
--- 927,932 ----
***************
*** 1484,1549 ****
  }
    
  /* ----------
-  * wide-character-aware initcap function
-  * ----------
-  */
- static char *
- str_initcap(char *buff)
- {
- 	char		*result;
- 	bool		wasalnum = false;
- 
- 	if (!buff)
- 		return NULL;
- 
- #ifdef USE_WIDE_UPPER_LOWER
- 	if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
- 	{
- 		wchar_t		*workspace;
- 		text		*in_text;
- 		text		*out_text;
- 		int			i;
- 
- 		in_text = cstring_to_text(buff);
- 		workspace = texttowcs(in_text);
- 
- 		for (i = 0; workspace[i] != 0; i++)
- 		{
- 			if (wasalnum)
- 				workspace[i] = towlower(workspace[i]);
- 			else
- 				workspace[i] = towupper(workspace[i]);
- 			wasalnum = iswalnum(workspace[i]);
- 		}
- 
- 		out_text = wcstotext(workspace, i);
- 		result = text_to_cstring(out_text);
- 
- 		pfree(workspace);
- 		pfree(in_text);
- 		pfree(out_text);
- 	}
- 	else
- #endif		/* USE_WIDE_UPPER_LOWER */
- 	{
- 		char *p;
- 
- 		result = pstrdup(buff);
- 
- 		for (p = result; *p; p++)
- 		{
- 			if (wasalnum)
- 				*p = pg_tolower((unsigned char) *p);
- 			else
- 				*p = pg_toupper((unsigned char) *p);
- 			wasalnum = isalnum((unsigned char) *p);
- 		}
- 	}
- 
- 	return result;
- }
- 
- /* ----------
   * Sequential search with to upper/lower conversion
   * ----------
   */
--- 1483,1488 ----
Index: src/backend/utils/adt/oracle_compat.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v
retrieving revision 1.79
diff -c -c -r1.79 oracle_compat.c
*** src/backend/utils/adt/oracle_compat.c	19 May 2008 18:08:16 -0000	1.79
--- src/backend/utils/adt/oracle_compat.c	13 Jun 2008 22:01:18 -0000
***************
*** 471,478 ****
  Datum
  initcap(PG_FUNCTION_ARGS)
  {
! #ifdef USE_WIDE_UPPER_LOWER
  
  	/*
  	 * Use wide char code only when max encoding length > 1 and ctype != C.
  	 * Some operating systems fail with multi-byte encodings and a C locale.
--- 471,496 ----
  Datum
  initcap(PG_FUNCTION_ARGS)
  {
! 	text	   *string = PG_GETARG_TEXT_PP(0);
! 	char	   *str2;
! 
! 	str2 = str_initcap(DatumGetCString(string));
! 	string = cstring_to_text(str2);
! 	pfree(str2);
! 	PG_RETURN_TEXT_P(string);
! }
! 
  
+ char *
+ str_initcap(char *str)
+ {
+ 	char		*result;
+ 	int			wasalnum = 0;
+ 
+ 	if (!str)
+ 		return NULL;
+ 
+ #ifdef USE_WIDE_UPPER_LOWER
  	/*
  	 * Use wide char code only when max encoding length > 1 and ctype != C.
  	 * Some operating systems fail with multi-byte encodings and a C locale.
***************
*** 480,492 ****
  	 */
  	if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
  	{
- 		text	   *string = PG_GETARG_TEXT_PP(0);
- 		text	   *result;
  		wchar_t    *workspace;
! 		int			wasalnum = 0;
  		int			i;
  
! 		workspace = texttowcs(string);
  
  		for (i = 0; workspace[i] != 0; i++)
  		{
--- 498,510 ----
  	 */
  	if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
  	{
  		wchar_t    *workspace;
! 		text		*in_text;
! 		text		*out_text;
  		int			i;
  
! 		in_text = cstring_to_text(str);
! 		workspace = texttowcs(in_text);
  
  		for (i = 0; workspace[i] != 0; i++)
  		{
***************
*** 497,533 ****
  			wasalnum = iswalnum(workspace[i]);
  		}
  
! 		result = wcstotext(workspace, i);
  
  		pfree(workspace);
  
! 		PG_RETURN_TEXT_P(result);
  	}
  	else
  #endif   /* USE_WIDE_UPPER_LOWER */
  	{
- 		text	   *string = PG_GETARG_TEXT_P_COPY(0);
- 		int			wasalnum = 0;
  		char	   *ptr;
- 		int			m;
  
  		/*
  		 * Since we copied the string, we can scribble directly on the value
  		 */
! 		ptr = VARDATA(string);
! 		m = VARSIZE(string) - VARHDRSZ;
! 
! 		while (m-- > 0)
  		{
  			if (wasalnum)
  				*ptr = tolower((unsigned char) *ptr);
  			else
  				*ptr = toupper((unsigned char) *ptr);
  			wasalnum = isalnum((unsigned char) *ptr);
- 			ptr++;
  		}
  
! 		PG_RETURN_TEXT_P(string);
  	}
  }
  
--- 515,548 ----
  			wasalnum = iswalnum(workspace[i]);
  		}
  
! 		out_text = wcstotext(workspace, i);
! 		result = text_to_cstring(out_text);
  
  		pfree(workspace);
+ 		pfree(in_text);
+ 		pfree(out_text);
  
! 		return result;
  	}
  	else
  #endif   /* USE_WIDE_UPPER_LOWER */
  	{
  		char	   *ptr;
  
+ 		result = pstrdup(str);
  		/*
  		 * Since we copied the string, we can scribble directly on the value
  		 */
! 		for (ptr = result; *ptr; ptr++)
  		{
  			if (wasalnum)
  				*ptr = tolower((unsigned char) *ptr);
  			else
  				*ptr = toupper((unsigned char) *ptr);
  			wasalnum = isalnum((unsigned char) *ptr);
  		}
  
! 		return result;
  	}
  }
  
Index: src/include/utils/builtins.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.316
diff -c -c -r1.316 builtins.h
*** src/include/utils/builtins.h	27 May 2008 00:13:09 -0000	1.316
--- src/include/utils/builtins.h	13 Jun 2008 22:01:19 -0000
***************
*** 727,732 ****
--- 727,733 ----
  extern Datum lower(PG_FUNCTION_ARGS);
  extern Datum upper(PG_FUNCTION_ARGS);
  extern Datum initcap(PG_FUNCTION_ARGS);
+ extern char *str_initcap(char *str);
  extern Datum lpad(PG_FUNCTION_ARGS);
  extern Datum rpad(PG_FUNCTION_ARGS);
  extern Datum btrim(PG_FUNCTION_ARGS);
-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches

Reply via email to