Index: src/backend/utils/adt/oracle_compat.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v
retrieving revision 1.60
diff -c -r1.60 oracle_compat.c
*** src/backend/utils/adt/oracle_compat.c	7 May 2005 15:18:17 -0000	1.60
--- src/backend/utils/adt/oracle_compat.c	31 Jul 2005 11:11:28 -0000
***************
*** 149,154 ****
--- 149,209 ----
  #endif   /* USE_WIDE_UPPER_LOWER */
  
  
+ #ifdef WIN32
+ /* Win32 UTF8/UTF16 conversion helpers */
+ static wchar_t *win32_utf8texttoutf16(const text *txt)
+ {
+ 	int			nbytes = VARSIZE(txt) - VARHDRSZ;	
+ 	wchar_t    *result;
+ 	int         r;
+ 
+ 	if (nbytes < 0 ||
+ 			nbytes > (int) (INT_MAX / sizeof(wchar_t)) -1)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_OUT_OF_MEMORY),
+ 				 errmsg("out of memory")));
+ 
+ 	/* Output workspace cannot have more codes than input bytes */
+ 	result = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
+ 
+ 	/* Do the conversion */
+ 	r = MultiByteToWideChar(CP_UTF8, 0, VARDATA(txt),  nbytes,
+ 				result, nbytes * sizeof(wchar_t));
+ 	if (!r)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
+ 				 errmsg("invalid multibyte character for locale"),
+ 				 errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
+ 
+ 	result[r] = 0;	
+ 	return result;
+ }
+ 
+ static text *win32_utf16toutf8text(const wchar_t *txt)
+ {
+ 	text		*result;
+ 	int			 nbytes;
+ 	int			 r;
+ 	
+ 	nbytes = WideCharToMultiByte(CP_UTF8, 0, txt, -1, NULL, 0, NULL, NULL);
+ 	if (nbytes == 0)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
+ 				 errmsg("invalid utf16 character for locale: %lu",GetLastError())));
+ 
+ 	result = palloc(nbytes+VARHDRSZ);
+ 
+ 	r = WideCharToMultiByte(CP_UTF8, 0, txt, -1, VARDATA(result), nbytes, NULL, NULL);
+ 	if (r == 0)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
+ 				 errmsg("invalid utf16 character for locale: %lu",GetLastError())));
+ 
+ 	VARATT_SIZEP(result) = nbytes + VARHDRSZ - 1; /* -1 = ignore null */
+ 	return result;
+ }
+ #endif /* WIN32 */
+ 
  /********************************************************************
   *
   * lower
***************
*** 179,184 ****
--- 234,251 ----
  		wchar_t    *workspace;
  		int			i;
  
+ #ifdef WIN32
+ 		/* Win32 does not have UTF-8, so we need to map to UTF-16 */
+ 		if (GetDatabaseEncoding() == PG_UTF8)
+ 		{
+ 			workspace = win32_utf8texttoutf16(string);
+ 			_wcslwr(workspace);
+ 			result = win32_utf16toutf8text(workspace);
+ 			pfree(workspace);
+ 			PG_RETURN_TEXT_P(result);
+ 		}
+ #endif
+ 		
  		workspace = texttowcs(string);
  
  		for (i = 0; workspace[i] != 0; i++)
***************
*** 245,250 ****
--- 312,329 ----
  		wchar_t    *workspace;
  		int			i;
  
+ #ifdef WIN32
+ 		/* Win32 does not have UTF-8, so we need to map to UTF-16 */
+ 		if (GetDatabaseEncoding() == PG_UTF8)
+ 		{
+ 			workspace = win32_utf8texttoutf16(string);
+ 			_wcsupr(workspace);
+ 			result = win32_utf16toutf8text(workspace);
+ 			pfree(workspace);
+ 			PG_RETURN_TEXT_P(result);
+ 		}
+ #endif
+ 
  		workspace = texttowcs(string);
  
  		for (i = 0; workspace[i] != 0; i++)
***************
*** 315,320 ****
--- 394,405 ----
  		int			wasalnum = 0;
  		int			i;
  
+ #ifdef WIN32
+ 		/* Win32 does not have UTF-8, so we need to map to UTF-16 */
+ 		if (GetDatabaseEncoding() == PG_UTF8)
+ 			workspace = win32_utf8texttoutf16(string);
+ 		else
+ #endif
  		workspace = texttowcs(string);
  
  		for (i = 0; workspace[i] != 0; i++)
***************
*** 326,331 ****
--- 411,422 ----
  			wasalnum = iswalnum(workspace[i]);
  		}
  
+ #ifdef WIN32
+ 		/* Map back to UTF-8 */
+ 		if (GetDatabaseEncoding() == PG_UTF8)
+ 			result = win32_utf16toutf8text(workspace);
+ 		else
+ #endif
  		result = wcstotext(workspace, i);
  
  		pfree(workspace);
Index: src/backend/utils/adt/varlena.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/varlena.c,v
retrieving revision 1.130
diff -c -r1.130 varlena.c
*** src/backend/utils/adt/varlena.c	29 Jul 2005 03:17:55 -0000	1.130
--- src/backend/utils/adt/varlena.c	31 Jul 2005 11:15:49 -0000
***************
*** 848,853 ****
--- 848,901 ----
  		char		a2buf[STACKBUFLEN];
  		char	   *a1p,
  				   *a2p;
+ #ifdef WIN32
+ 		/* Win32 does not have UTF-8, so we need to map to UTF-16 */
+ 		if (GetDatabaseEncoding() == PG_UTF8)
+ 		{
+ 			int a1len = STACKBUFLEN;
+ 			int a2len = STACKBUFLEN;
+ 
+ 			if (len1 >= STACKBUFLEN/2)
+ 			{
+ 				a1len = len1 * 2 + 2;
+ 				a1p = palloc(a1len);
+ 			}
+ 			else
+ 				a1p = a1buf;
+ 			
+ 			if (len2 >= STACKBUFLEN/2)
+ 			{
+ 				a2len = len2 * 2 + 2;
+ 				a2p = palloc(a2len);
+ 			}
+ 			else
+ 				a2p = a2buf;
+ 
+ 			if (!MultiByteToWideChar(CP_UTF8, 0, arg1, -1, (LPWSTR)a1p, a1len/2))
+ 				ereport(ERROR,
+ 						(errmsg("failed to convert string to UTF16: %lu",
+ 							GetLastError())));
+ 			if (!MultiByteToWideChar(CP_UTF8, 0, arg2, -1, (LPWSTR)a2p, a2len/2))
+ 				ereport(ERROR,
+ 						(errmsg("failed to convert string to UTF16: %lu",
+ 							GetLastError())));
+ 			
+ 			errno=0;
+ 			result = wcscoll((LPWSTR)a1p, (LPWSTR)a2p);
+ 			if (result == 2147483647) /* _NLSCMPERROR; missing from mingw headers */
+ 				ereport(ERROR,
+ 						(errmsg("failed to compare unicode strings: %i", errno)));
+ 			if (a1len != STACKBUFLEN)
+ 				pfree(a1p);
+ 			if (a2len != STACKBUFLEN)
+ 				pfree(a2p);
+ 			
+ 			return result;
+ 		}
+ 
+ 		/* Win32 has strncoll(), so use it there to avoid copying */
+ 		return _strncoll(arg1, arg2, (len1>len2)?len2:len1 );
+ #endif
  
  		if (len1 >= STACKBUFLEN)
  			a1p = (char *) palloc(len1 + 1);
