diff -cpr HEAD/src/backend/utils/adt/selfuncs.c fix_strxfrm/src/backend/utils/adt/selfuncs.c *** HEAD/src/backend/utils/adt/selfuncs.c Mon Apr 9 09:26:35 2007 --- fix_strxfrm/src/backend/utils/adt/selfuncs.c Mon Apr 9 18:11:56 2007 *************** convert_string_datum(Datum value, Oid ty *** 3126,3131 **** --- 3126,3188 ---- size_t xfrmlen; size_t xfrmlen2; + #ifdef WIN32 + /* Win32 does not have UTF-8, so we need to map to UTF-16 */ + if (GetDatabaseEncoding() == PG_UTF8) + { + LPWSTR wval; + LPWSTR wxfrmstr; + size_t len; + + len = strlen(val); + if (len == 0) + return val; + + /* + * Convert UTF-8 to UTF-16 + */ + wval = (LPWSTR) palloc((len + 1) * sizeof(WCHAR)); + if (!MultiByteToWideChar(CP_UTF8, 0, val, -1, wval, len + 1)) + ereport(ERROR, + (errmsg("could not convert string to UTF-16: error %lu", + GetLastError()))); + + /* + * Perform locale-aware conversion + * + * There is a bug in the result value of wcsxfrm() + * http://support.microsoft.com/kb/331014/ + * However, we can involuntary use the result to decide allocation + * size because length in bytes are always longher than length + * in wide characters. + */ + xfrmlen = wcsxfrm(NULL, wval, 0); + if (xfrmlen >= INT_MAX) + ereport(ERROR, + (errmsg("wcsxfrm(%s) failed: error %lu", + val, GetLastError()))); + wxfrmstr = (LPWSTR) palloc((xfrmlen + 1) * sizeof(WCHAR)); + xfrmlen2 = wcsxfrm(wxfrmstr, wval, xfrmlen + 1); + Assert(xfrmlen2 <= xfrmlen); + pfree(wval); + + /* + * Re-convert UTF-16 to UTF-8 + * Do not use xfrmlen2 to avoid the above bug! + */ + len = wcslen(wxfrmstr) * pg_encoding_max_length(PG_UTF8) + 1; + pfree(val); + val = (char *) palloc(len); + if (!WideCharToMultiByte(CP_UTF8, 0, wxfrmstr, -1, val, len, NULL, NULL)) + ereport(ERROR, + (errmsg("could not convert string to UTF-8: error %lu", + GetLastError()))); + + pfree(wxfrmstr); + return val; + } + #endif /* WIN32 */ + /* * Note: originally we guessed at a suitable output buffer size, and * only needed to call strxfrm twice if our guess was too small. *************** convert_string_datum(Datum value, Oid ty *** 3152,3157 **** --- 3209,3217 ---- #else xfrmlen = strxfrm(NULL, val, 0); #endif + if (xfrmlen >= INT_MAX) + ereport(ERROR, + (errmsg("strxfrm(%s) failed", val))); xfrmstr = (char *) palloc(xfrmlen + 1); xfrmlen2 = strxfrm(xfrmstr, val, xfrmlen + 1); Assert(xfrmlen2 <= xfrmlen);