mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	patternsel() was improperly stripping RelabelType from the derived
expressions it constructed, causing scalarineqsel to become confused if the underlying variable was of a domain type. Per report from Kevin Grittner.
This commit is contained in:
		@@ -15,7 +15,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * IDENTIFICATION
 | 
			
		||||
 *	  $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.178 2005/04/25 01:30:14 tgl Exp $
 | 
			
		||||
 *	  $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.179 2005/06/01 17:05:11 tgl Exp $
 | 
			
		||||
 *
 | 
			
		||||
 *-------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
@@ -163,7 +163,7 @@ static void examine_variable(Query *root, Node *node, int varRelid,
 | 
			
		||||
static double get_variable_numdistinct(VariableStatData *vardata);
 | 
			
		||||
static bool get_variable_maximum(Query *root, VariableStatData *vardata,
 | 
			
		||||
					 Oid sortop, Datum *max);
 | 
			
		||||
static Selectivity prefix_selectivity(Query *root, VariableStatData *vardata,
 | 
			
		||||
static Selectivity prefix_selectivity(Query *root, Node *variable,
 | 
			
		||||
				   Oid opclass, Const *prefix);
 | 
			
		||||
static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
 | 
			
		||||
static Datum string_to_datum(const char *str, Oid datatype);
 | 
			
		||||
@@ -812,6 +812,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 | 
			
		||||
	List	   *args = (List *) PG_GETARG_POINTER(2);
 | 
			
		||||
	int			varRelid = PG_GETARG_INT32(3);
 | 
			
		||||
	VariableStatData vardata;
 | 
			
		||||
	Node	   *variable;
 | 
			
		||||
	Node	   *other;
 | 
			
		||||
	bool		varonleft;
 | 
			
		||||
	Datum		constval;
 | 
			
		||||
@@ -836,6 +837,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 | 
			
		||||
		ReleaseVariableStats(vardata);
 | 
			
		||||
		return DEFAULT_MATCH_SEL;
 | 
			
		||||
	}
 | 
			
		||||
	variable = (Node *) linitial(args);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If the constant is NULL, assume operator is strict and return zero,
 | 
			
		||||
@@ -939,7 +941,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 | 
			
		||||
 | 
			
		||||
		if (eqopr == InvalidOid)
 | 
			
		||||
			elog(ERROR, "no = operator for opclass %u", opclass);
 | 
			
		||||
		eqargs = list_make2(vardata.var, prefix);
 | 
			
		||||
		eqargs = list_make2(variable, prefix);
 | 
			
		||||
		result = DatumGetFloat8(DirectFunctionCall4(eqsel,
 | 
			
		||||
													PointerGetDatum(root),
 | 
			
		||||
												 ObjectIdGetDatum(eqopr),
 | 
			
		||||
@@ -958,7 +960,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 | 
			
		||||
		Selectivity selec;
 | 
			
		||||
 | 
			
		||||
		if (pstatus == Pattern_Prefix_Partial)
 | 
			
		||||
			prefixsel = prefix_selectivity(root, &vardata, opclass, prefix);
 | 
			
		||||
			prefixsel = prefix_selectivity(root, variable, opclass, prefix);
 | 
			
		||||
		else
 | 
			
		||||
			prefixsel = 1.0;
 | 
			
		||||
		restsel = pattern_selectivity(rest, ptype);
 | 
			
		||||
@@ -3694,7 +3696,7 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
 | 
			
		||||
 * more useful to use the upper-bound code than not.
 | 
			
		||||
 */
 | 
			
		||||
static Selectivity
 | 
			
		||||
prefix_selectivity(Query *root, VariableStatData *vardata,
 | 
			
		||||
prefix_selectivity(Query *root, Node *variable,
 | 
			
		||||
				   Oid opclass, Const *prefixcon)
 | 
			
		||||
{
 | 
			
		||||
	Selectivity prefixsel;
 | 
			
		||||
@@ -3706,7 +3708,7 @@ prefix_selectivity(Query *root, VariableStatData *vardata,
 | 
			
		||||
								BTGreaterEqualStrategyNumber);
 | 
			
		||||
	if (cmpopr == InvalidOid)
 | 
			
		||||
		elog(ERROR, "no >= operator for opclass %u", opclass);
 | 
			
		||||
	cmpargs = list_make2(vardata->var, prefixcon);
 | 
			
		||||
	cmpargs = list_make2(variable, prefixcon);
 | 
			
		||||
	/* Assume scalargtsel is appropriate for all supported types */
 | 
			
		||||
	prefixsel = DatumGetFloat8(DirectFunctionCall4(scalargtsel,
 | 
			
		||||
												   PointerGetDatum(root),
 | 
			
		||||
@@ -3728,7 +3730,7 @@ prefix_selectivity(Query *root, VariableStatData *vardata,
 | 
			
		||||
									BTLessStrategyNumber);
 | 
			
		||||
		if (cmpopr == InvalidOid)
 | 
			
		||||
			elog(ERROR, "no < operator for opclass %u", opclass);
 | 
			
		||||
		cmpargs = list_make2(vardata->var, greaterstrcon);
 | 
			
		||||
		cmpargs = list_make2(variable, greaterstrcon);
 | 
			
		||||
		/* Assume scalarltsel is appropriate for all supported types */
 | 
			
		||||
		topsel = DatumGetFloat8(DirectFunctionCall4(scalarltsel,
 | 
			
		||||
													PointerGetDatum(root),
 | 
			
		||||
@@ -3743,7 +3745,7 @@ prefix_selectivity(Query *root, VariableStatData *vardata,
 | 
			
		||||
		prefixsel = topsel + prefixsel - 1.0;
 | 
			
		||||
 | 
			
		||||
		/* Adjust for double-exclusion of NULLs */
 | 
			
		||||
		prefixsel += nulltestsel(root, IS_NULL, vardata->var, 0);
 | 
			
		||||
		prefixsel += nulltestsel(root, IS_NULL, variable, 0);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * A zero or slightly negative prefixsel should be converted into
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user