Exemplo n.º 1
0
/*
 * 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;
	}
}
Exemplo n.º 2
0
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);
	}
}