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);