29#include <gnu/libc-version.h>
81#define TEXTBUFLEN 1024
86 const char *arg2, ssize_t len2,
89 const char *src, ssize_t srclen,
96static int strncoll_libc_win32_utf8(
const char *arg1, ssize_t len1,
97 const char *arg2, ssize_t len2,
101static size_t char2wchar(
wchar_t *to,
size_t tolen,
const char *from,
105 const char *src, ssize_t srclen,
108 const char *src, ssize_t srclen,
111 const char *src, ssize_t srclen,
114 const char *src, ssize_t srclen,
117 const char *src, ssize_t srclen,
120 const char *src, ssize_t srclen,
181 return isxdigit_l((
unsigned char) wc,
locale->lt);
183 return _isxdigit_l((
unsigned char) wc,
locale->lt);
245 return iswxdigit_l((wint_t) wc,
locale->lt);
247 return _iswxdigit_l((wint_t) wc,
locale->lt);
291 if (
sizeof(
wchar_t) >= 4 || wc <= (
pg_wchar) 0xFFFF)
319 if (
sizeof(
wchar_t) >= 4 || wc <= (
pg_wchar) 0xFFFF)
345 .max_chr = UCHAR_MAX,
372 .max_chr = UCHAR_MAX,
400 .strnxfrm_prefix = NULL,
412 .strxfrm_is_safe =
true,
414 .strxfrm_is_safe =
false,
420 .
strncoll = strncoll_libc_win32_utf8,
422 .strnxfrm_prefix = NULL,
424 .strxfrm_is_safe =
true,
426 .strxfrm_is_safe =
false,
436 srclen = strlen(src);
438 if (srclen + 1 <= destsize)
443 memcpy(
dest, src, srclen);
453 for (p =
dest; *p; p++)
457 if (*p >=
'A' && *p <=
'Z')
482 srclen = strlen(src);
485 if ((srclen + 1) > (INT_MAX /
sizeof(
wchar_t)))
487 (
errcode(ERRCODE_OUT_OF_MEMORY),
488 errmsg(
"out of memory")));
491 workspace = (
wchar_t *)
palloc((srclen + 1) *
sizeof(wchar_t));
493 char2wchar(workspace, srclen + 1, src, srclen, loc);
495 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
496 workspace[curr_char] =
towlower_l(workspace[curr_char], loc);
502 result =
palloc(max_size + 1);
504 result_size =
wchar2char(result, workspace, max_size + 1, loc);
506 if (result_size + 1 > destsize)
509 memcpy(
dest, result, result_size);
510 dest[result_size] =
'\0';
523 srclen = strlen(src);
525 if (srclen + 1 <= destsize)
528 int wasalnum =
false;
531 memcpy(
dest, src, srclen);
541 for (p =
dest; *p; p++)
547 if (*p >=
'A' && *p <=
'Z')
554 if (*p >=
'a' && *p <=
'z')
567 wasalnum =
isalnum_l((
unsigned char) *p, loc);
579 int wasalnum =
false;
587 srclen = strlen(src);
590 if ((srclen + 1) > (INT_MAX /
sizeof(
wchar_t)))
592 (
errcode(ERRCODE_OUT_OF_MEMORY),
593 errmsg(
"out of memory")));
596 workspace = (
wchar_t *)
palloc((srclen + 1) *
sizeof(wchar_t));
598 char2wchar(workspace, srclen + 1, src, srclen, loc);
600 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
603 workspace[curr_char] =
towlower_l(workspace[curr_char], loc);
605 workspace[curr_char] =
towupper_l(workspace[curr_char], loc);
606 wasalnum =
iswalnum_l(workspace[curr_char], loc);
613 result =
palloc(max_size + 1);
615 result_size =
wchar2char(result, workspace, max_size + 1, loc);
617 if (result_size + 1 > destsize)
620 memcpy(
dest, result, result_size);
621 dest[result_size] =
'\0';
634 srclen = strlen(src);
636 if (srclen + 1 <= destsize)
641 memcpy(
dest, src, srclen);
651 for (p =
dest; *p; p++)
655 if (*p >=
'a' && *p <=
'z')
680 srclen = strlen(src);
683 if ((srclen + 1) > (INT_MAX /
sizeof(
wchar_t)))
685 (
errcode(ERRCODE_OUT_OF_MEMORY),
686 errmsg(
"out of memory")));
689 workspace = (
wchar_t *)
palloc((srclen + 1) *
sizeof(wchar_t));
691 char2wchar(workspace, srclen + 1, src, srclen, loc);
693 for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
694 workspace[curr_char] =
towupper_l(workspace[curr_char], loc);
700 result =
palloc(max_size + 1);
702 result_size =
wchar2char(result, workspace, max_size + 1, loc);
704 if (result_size + 1 > destsize)
707 memcpy(
dest, result, result_size);
708 dest[result_size] =
'\0';
724 if (
collid == DEFAULT_COLLATION_OID)
733 Anum_pg_database_datcollate);
736 Anum_pg_database_datctype);
751 Anum_pg_collation_collcollate);
754 Anum_pg_collation_collctype);
766 (strcmp(collate,
"POSIX") == 0);
767 result->
ctype_is_c = (strcmp(ctype,
"C") == 0) ||
768 (strcmp(ctype,
"POSIX") == 0);
774 result->
collate = &collate_methods_libc_win32_utf8;
805 if (strcmp(collate, ctype) == 0)
807 if (strcmp(ctype,
"C") != 0 && strcmp(ctype,
"POSIX") != 0)
812 loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collate,
815 loc = _create_locale(LC_ALL, collate);
827 if (strcmp(collate,
"C") != 0 && strcmp(collate,
"POSIX") != 0)
830 loc1 = newlocale(LC_COLLATE_MASK, collate, NULL);
835 if (strcmp(ctype,
"C") != 0 && strcmp(ctype,
"POSIX") != 0)
838 loc = newlocale(LC_CTYPE_MASK, ctype, loc1);
856 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
857 errmsg(
"collations with different collate and ctype values are not supported on this platform")));
872strncoll_libc(
const char *arg1, ssize_t len1,
const char *arg2, ssize_t len2,
877 size_t bufsize1 = (len1 == -1) ? 0 : len1 + 1;
878 size_t bufsize2 = (len2 == -1) ? 0 : len2 + 1;
895 memcpy(buf1, arg1, len1);
906 char *buf2 =
buf + bufsize1;
908 memcpy(buf2, arg2, len2);
944 memcpy(
buf, src, srclen);
953 Assert(result >= destsize ||
dest[result] ==
'\0');
961 char *collversion = NULL;
967#if defined(__GLIBC__)
969 collversion =
pstrdup(gnu_get_libc_version());
970#elif defined(LC_VERSION_MASK)
974 loc = newlocale(LC_COLLATE_MASK, collcollate, NULL);
978 pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc));
983 (
errmsg(
"could not load locale \"%s\"", collcollate)));
990 NLSVERSIONINFOEX version = {
sizeof(NLSVERSIONINFOEX)};
991 WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH];
993 MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate,
994 LOCALE_NAME_MAX_LENGTH);
995 if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version))
1004 if (GetLastError() == ERROR_INVALID_PARAMETER)
1008 (
errmsg(
"could not get collation version for locale \"%s\": error code %lu",
1012 collversion =
psprintf(
"%lu.%lu,%lu.%lu",
1013 (version.dwNLSVersion >> 8) & 0xFFFF,
1014 version.dwNLSVersion & 0xFF,
1015 (version.dwDefinedVersion >> 8) & 0xFFFF,
1016 version.dwDefinedVersion & 0xFF);
1033strncoll_libc_win32_utf8(
const char *arg1, ssize_t len1,
const char *arg2,
1048 len1 = strlen(arg1);
1050 len2 = strlen(arg2);
1052 a1len = len1 * 2 + 2;
1053 a2len = len2 * 2 + 2;
1066 r = MultiByteToWideChar(CP_UTF8, 0, arg1, len1,
1067 (LPWSTR) a1p, a1len / 2);
1070 (
errmsg(
"could not convert string to UTF-16: error code %lu",
1073 ((LPWSTR) a1p)[r] = 0;
1079 r = MultiByteToWideChar(CP_UTF8, 0, arg2, len2,
1080 (LPWSTR) a2p, a2len / 2);
1083 (
errmsg(
"could not convert string to UTF-16: error code %lu",
1086 ((LPWSTR) a2p)[r] = 0;
1090 if (result == 2147483647)
1092 (
errmsg(
"could not compare Unicode strings: %m")));
1123 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1124 errmsg(
"could not create locale \"%s\": %m",
1126 (save_errno == ENOENT ?
1127 errdetail(
"The operating system could not find any locale data for the locale name \"%s\".",
1135#ifndef HAVE_MBSTOWCS_L
1140 return _mbstowcs_l(
dest, src, n, loc);
1143 locale_t save_locale = uselocale(loc);
1145 result = mbstowcs(
dest, src, n);
1146 uselocale(save_locale);
1151#ifndef HAVE_WCSTOMBS_L
1156 return _wcstombs_l(
dest, src, n, loc);
1159 locale_t save_locale = uselocale(loc);
1161 result = wcstombs(
dest, src, n);
1162 uselocale(save_locale);
1197 result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
1214 result = wcstombs(to, from, tolen);
1235char2wchar(
wchar_t *to,
size_t tolen,
const char *from,
size_t fromlen,
1252 result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
1274 result = mbstowcs(to,
str, tolen);
1298 (
errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
1299 errmsg(
"invalid multibyte character for locale"),
1300 errhint(
"The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
#define TextDatumGetCString(d)
#define IS_HIGHBIT_SET(ch)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
if(TABLE==NULL||TABLE_index==NULL)
int GetDatabaseEncoding(void)
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
int pg_database_encoding_max_length(void)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void pfree(void *pointer)
char * pnstrdup(const char *in, Size len)
static bool wc_isalpha_libc_mb(pg_wchar wc, pg_locale_t locale)
static size_t strtitle_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static bool wc_ispunct_libc_sb(pg_wchar wc, pg_locale_t locale)
static const struct ctype_methods ctype_methods_libc_other_mb
static const struct ctype_methods ctype_methods_libc_utf8
static pg_wchar toupper_libc_mb(pg_wchar wc, pg_locale_t locale)
static size_t strupper_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static bool wc_isprint_libc_mb(pg_wchar wc, pg_locale_t locale)
static bool wc_isdigit_libc_sb(pg_wchar wc, pg_locale_t locale)
pg_locale_t create_pg_locale_libc(Oid collid, MemoryContext context)
size_t wchar2char(char *to, const wchar_t *from, size_t tolen, locale_t loc)
static bool wc_isspace_libc_sb(pg_wchar wc, pg_locale_t locale)
static bool wc_islower_libc_sb(pg_wchar wc, pg_locale_t locale)
static bool wc_isupper_libc_mb(pg_wchar wc, pg_locale_t locale)
static pg_wchar toupper_libc_sb(pg_wchar wc, pg_locale_t locale)
static bool wc_isgraph_libc_mb(pg_wchar wc, pg_locale_t locale)
static size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen, locale_t loc)
static bool wc_isalnum_libc_mb(pg_wchar wc, pg_locale_t locale)
static bool wc_isalnum_libc_sb(pg_wchar wc, pg_locale_t locale)
static bool wc_isalpha_libc_sb(pg_wchar wc, pg_locale_t locale)
static bool wc_isprint_libc_sb(pg_wchar wc, pg_locale_t locale)
char * get_collation_actual_version_libc(const char *collcollate)
static bool wc_isupper_libc_sb(pg_wchar wc, pg_locale_t locale)
static locale_t make_libc_collator(const char *collate, const char *ctype)
static bool wc_isgraph_libc_sb(pg_wchar wc, pg_locale_t locale)
static pg_wchar tolower_libc_sb(pg_wchar wc, pg_locale_t locale)
static size_t wcstombs_l(char *dest, const wchar_t *src, size_t n, locale_t loc)
static const struct collate_methods collate_methods_libc
static bool wc_ispunct_libc_mb(pg_wchar wc, pg_locale_t locale)
static size_t strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static int strncoll_libc(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, pg_locale_t locale)
static size_t strlower_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static bool wc_islower_libc_mb(pg_wchar wc, pg_locale_t locale)
static const struct ctype_methods ctype_methods_libc_sb
static size_t strnxfrm_libc(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static bool wc_isxdigit_libc_sb(pg_wchar wc, pg_locale_t locale)
void report_newlocale_failure(const char *localename)
static pg_wchar tolower_libc_mb(pg_wchar wc, pg_locale_t locale)
static bool wc_isdigit_libc_mb(pg_wchar wc, pg_locale_t locale)
static char char_tolower_libc(unsigned char ch, pg_locale_t locale)
static bool char_is_cased_libc(char ch, pg_locale_t locale)
static bool wc_isspace_libc_mb(pg_wchar wc, pg_locale_t locale)
static size_t strtitle_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
static bool wc_isxdigit_libc_mb(pg_wchar wc, pg_locale_t locale)
static size_t mbstowcs_l(wchar_t *dest, const char *src, size_t n, locale_t loc)
static size_t strlower_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
int pg_strcasecmp(const char *s1, const char *s2)
static unsigned char pg_ascii_tolower(unsigned char ch)
static unsigned char pg_ascii_toupper(unsigned char ch)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
static Datum ObjectIdGetDatum(Oid X)
char * psprintf(const char *fmt,...)
int(* strncoll)(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, pg_locale_t locale)
size_t(* strlower)(char *dest, size_t destsize, const char *src, ssize_t srclen, pg_locale_t locale)
const struct ctype_methods * ctype
const struct collate_methods * collate
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)