/* * pg_set_regex_collation: set collation for these functions to obey * * This is called when beginning compilation or execution of a regexp. * Since there's no need for re-entrancy of regexp operations, it's okay * to store the results in static variables. */ void pg_set_regex_collation(Oid collation) { if (lc_ctype_is_c(collation)) { /* C/POSIX collations use this path regardless of database encoding */ pg_regex_strategy = PG_REGEX_LOCALE_C; pg_regex_locale = 0; pg_regex_collation = C_COLLATION_OID; } else { if (collation == DEFAULT_COLLATION_OID) pg_regex_locale = 0; else if (OidIsValid(collation)) { /* * NB: pg_newlocale_from_collation will fail if not HAVE_LOCALE_T; * the case of pg_regex_locale != 0 but not HAVE_LOCALE_T does not * have to be considered below. */ pg_regex_locale = pg_newlocale_from_collation(collation); } else { /* * This typically means that the parser could not resolve a * conflict of implicit collations, so report it that way. */ ereport(ERROR, (errcode(ERRCODE_INDETERMINATE_COLLATION), errmsg("could not determine which collation to use for regular expression"), errhint("Use the COLLATE clause to set the collation explicitly."))); } #ifdef USE_WIDE_UPPER_LOWER if (GetDatabaseEncoding() == PG_UTF8) { if (pg_regex_locale) pg_regex_strategy = PG_REGEX_LOCALE_WIDE_L; else pg_regex_strategy = PG_REGEX_LOCALE_WIDE; } else #endif /* USE_WIDE_UPPER_LOWER */ { if (pg_regex_locale) pg_regex_strategy = PG_REGEX_LOCALE_1BYTE_L; else pg_regex_strategy = PG_REGEX_LOCALE_1BYTE; } pg_regex_collation = collation; } }
static inline int Generic_Text_IC_like(text *str, text *pat, Oid collation) { char *s, *p; int slen, plen; /* * For efficiency reasons, in the single byte case we don't call lower() * on the pattern and text, but instead call SB_lower_char on each * character. In the multi-byte case we don't have much choice :-( */ if (pg_database_encoding_max_length() > 1) { /* lower's result is never packed, so OK to use old macros here */ pat = DatumGetTextP(DirectFunctionCall1Coll(lower, collation, PointerGetDatum(pat))); p = VARDATA(pat); plen = (VARSIZE(pat) - VARHDRSZ); str = DatumGetTextP(DirectFunctionCall1Coll(lower, collation, PointerGetDatum(str))); s = VARDATA(str); slen = (VARSIZE(str) - VARHDRSZ); if (GetDatabaseEncoding() == PG_UTF8) return UTF8_MatchText(s, slen, p, plen, 0, true); else return MB_MatchText(s, slen, p, plen, 0, true); } else { /* * Here we need to prepare locale information for SB_lower_char. This * should match the methods used in str_tolower(). */ pg_locale_t locale = 0; bool locale_is_c = false; if (lc_ctype_is_c(collation)) locale_is_c = true; else if (collation != DEFAULT_COLLATION_OID) { if (!OidIsValid(collation)) { /* * This typically means that the parser could not resolve a * conflict of implicit collations, so report it that way. */ ereport(ERROR, (errcode(ERRCODE_INDETERMINATE_COLLATION), errmsg("could not determine which collation to use for ILIKE"), errhint("Use the COLLATE clause to set the collation explicitly."))); } locale = pg_newlocale_from_collation(collation); } p = VARDATA_ANY(pat); plen = VARSIZE_ANY_EXHDR(pat); s = VARDATA_ANY(str); slen = VARSIZE_ANY_EXHDR(str); return SB_IMatchText(s, slen, p, plen, locale, locale_is_c); } }