Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9542287

Browse files
committed
Fix patternsel() and callers to do the right thing for NOT LIKE and the other
negated-match operators. patternsel had been using the supplied operator as though it were a positive-match operator, and thus obtaining a wrong result, which was even more wrong after the caller subtracted it from 1. Seems cleanest to give patternsel an explicit "negate" argument so that it knows what's going on. Also install the same factorization scheme for pattern join selectivity estimators; even though they are just stubs at the moment, this may keep someone from making the same type of mistake when they get filled out. Per report from Greg Mullane. Backpatch to 8.2 --- previous releases do not show the problem because patternsel() doesn't actually use the operator directly.
1 parent 371d7bc commit 9542287

File tree

1 file changed

+52
-57
lines changed

1 file changed

+52
-57
lines changed

src/backend/utils/adt/selfuncs.c

+52-57
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.236 2007/08/31 23:35:22 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.237 2007/11/07 21:00:37 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -901,7 +901,7 @@ scalargtsel(PG_FUNCTION_ARGS)
901901
* patternsel - Generic code for pattern-match selectivity.
902902
*/
903903
static double
904-
patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
904+
patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
905905
{
906906
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
907907
Oid operator = PG_GETARG_OID(1);
@@ -921,23 +921,40 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
921921
Const *rest = NULL;
922922
double result;
923923

924+
/*
925+
* If this is for a NOT LIKE or similar operator, get the corresponding
926+
* positive-match operator and work with that. Set result to the
927+
* correct default estimate, too.
928+
*/
929+
if (negate)
930+
{
931+
operator = get_negator(operator);
932+
if (!OidIsValid(operator))
933+
elog(ERROR, "patternsel called for operator without a negator");
934+
result = 1.0 - DEFAULT_MATCH_SEL;
935+
}
936+
else
937+
{
938+
result = DEFAULT_MATCH_SEL;
939+
}
940+
924941
/*
925942
* If expression is not variable op constant, then punt and return a
926943
* default estimate.
927944
*/
928945
if (!get_restriction_variable(root, args, varRelid,
929946
&vardata, &other, &varonleft))
930-
return DEFAULT_MATCH_SEL;
947+
return result;
931948
if (!varonleft || !IsA(other, Const))
932949
{
933950
ReleaseVariableStats(vardata);
934-
return DEFAULT_MATCH_SEL;
951+
return result;
935952
}
936953
variable = (Node *) linitial(args);
937954

938955
/*
939956
* If the constant is NULL, assume operator is strict and return zero, ie,
940-
* operator will never return TRUE.
957+
* operator will never return TRUE. (It's zero even for a negator op.)
941958
*/
942959
if (((Const *) other)->constisnull)
943960
{
@@ -956,7 +973,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
956973
if (consttype != TEXTOID && consttype != BYTEAOID)
957974
{
958975
ReleaseVariableStats(vardata);
959-
return DEFAULT_MATCH_SEL;
976+
return result;
960977
}
961978

962979
/*
@@ -988,7 +1005,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
9881005
break;
9891006
default:
9901007
ReleaseVariableStats(vardata);
991-
return DEFAULT_MATCH_SEL;
1008+
return result;
9921009
}
9931010

9941011
/* divide pattern into fixed prefix and remainder */
@@ -1017,7 +1034,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
10171034
elog(ERROR, "unrecognized consttype: %u",
10181035
prefix->consttype);
10191036
ReleaseVariableStats(vardata);
1020-
return DEFAULT_MATCH_SEL;
1037+
return result;
10211038
}
10221039
prefix = string_to_const(prefixstr, vartype);
10231040
pfree(prefixstr);
@@ -1125,7 +1142,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
11251142

11261143
ReleaseVariableStats(vardata);
11271144

1128-
return result;
1145+
return negate ? (1.0 - result) : result;
11291146
}
11301147

11311148
/*
@@ -1134,7 +1151,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
11341151
Datum
11351152
regexeqsel(PG_FUNCTION_ARGS)
11361153
{
1137-
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex));
1154+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex, false));
11381155
}
11391156

11401157
/*
@@ -1143,7 +1160,7 @@ regexeqsel(PG_FUNCTION_ARGS)
11431160
Datum
11441161
icregexeqsel(PG_FUNCTION_ARGS)
11451162
{
1146-
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC));
1163+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC, false));
11471164
}
11481165

11491166
/*
@@ -1152,7 +1169,7 @@ icregexeqsel(PG_FUNCTION_ARGS)
11521169
Datum
11531170
likesel(PG_FUNCTION_ARGS)
11541171
{
1155-
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like));
1172+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like, false));
11561173
}
11571174

11581175
/*
@@ -1161,7 +1178,7 @@ likesel(PG_FUNCTION_ARGS)
11611178
Datum
11621179
iclikesel(PG_FUNCTION_ARGS)
11631180
{
1164-
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC));
1181+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC, false));
11651182
}
11661183

11671184
/*
@@ -1170,11 +1187,7 @@ iclikesel(PG_FUNCTION_ARGS)
11701187
Datum
11711188
regexnesel(PG_FUNCTION_ARGS)
11721189
{
1173-
double result;
1174-
1175-
result = patternsel(fcinfo, Pattern_Type_Regex);
1176-
result = 1.0 - result;
1177-
PG_RETURN_FLOAT8(result);
1190+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex, true));
11781191
}
11791192

11801193
/*
@@ -1183,11 +1196,7 @@ regexnesel(PG_FUNCTION_ARGS)
11831196
Datum
11841197
icregexnesel(PG_FUNCTION_ARGS)
11851198
{
1186-
double result;
1187-
1188-
result = patternsel(fcinfo, Pattern_Type_Regex_IC);
1189-
result = 1.0 - result;
1190-
PG_RETURN_FLOAT8(result);
1199+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC, true));
11911200
}
11921201

11931202
/*
@@ -1196,11 +1205,7 @@ icregexnesel(PG_FUNCTION_ARGS)
11961205
Datum
11971206
nlikesel(PG_FUNCTION_ARGS)
11981207
{
1199-
double result;
1200-
1201-
result = patternsel(fcinfo, Pattern_Type_Like);
1202-
result = 1.0 - result;
1203-
PG_RETURN_FLOAT8(result);
1208+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like, true));
12041209
}
12051210

12061211
/*
@@ -1209,11 +1214,7 @@ nlikesel(PG_FUNCTION_ARGS)
12091214
Datum
12101215
icnlikesel(PG_FUNCTION_ARGS)
12111216
{
1212-
double result;
1213-
1214-
result = patternsel(fcinfo, Pattern_Type_Like_IC);
1215-
result = 1.0 - result;
1216-
PG_RETURN_FLOAT8(result);
1217+
PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC, true));
12171218
}
12181219

12191220
/*
@@ -2081,13 +2082,23 @@ scalargtjoinsel(PG_FUNCTION_ARGS)
20812082
PG_RETURN_FLOAT8(DEFAULT_INEQ_SEL);
20822083
}
20832084

2085+
/*
2086+
* patternjoinsel - Generic code for pattern-match join selectivity.
2087+
*/
2088+
static double
2089+
patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
2090+
{
2091+
/* For the moment we just punt. */
2092+
return negate ? (1.0 - DEFAULT_MATCH_SEL) : DEFAULT_MATCH_SEL;
2093+
}
2094+
20842095
/*
20852096
* regexeqjoinsel - Join selectivity of regular-expression pattern match.
20862097
*/
20872098
Datum
20882099
regexeqjoinsel(PG_FUNCTION_ARGS)
20892100
{
2090-
PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
2101+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex, false));
20912102
}
20922103

20932104
/*
@@ -2096,7 +2107,7 @@ regexeqjoinsel(PG_FUNCTION_ARGS)
20962107
Datum
20972108
icregexeqjoinsel(PG_FUNCTION_ARGS)
20982109
{
2099-
PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
2110+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex_IC, false));
21002111
}
21012112

21022113
/*
@@ -2105,7 +2116,7 @@ icregexeqjoinsel(PG_FUNCTION_ARGS)
21052116
Datum
21062117
likejoinsel(PG_FUNCTION_ARGS)
21072118
{
2108-
PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
2119+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like, false));
21092120
}
21102121

21112122
/*
@@ -2114,7 +2125,7 @@ likejoinsel(PG_FUNCTION_ARGS)
21142125
Datum
21152126
iclikejoinsel(PG_FUNCTION_ARGS)
21162127
{
2117-
PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
2128+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like_IC, false));
21182129
}
21192130

21202131
/*
@@ -2123,11 +2134,7 @@ iclikejoinsel(PG_FUNCTION_ARGS)
21232134
Datum
21242135
regexnejoinsel(PG_FUNCTION_ARGS)
21252136
{
2126-
float8 result;
2127-
2128-
result = DatumGetFloat8(regexeqjoinsel(fcinfo));
2129-
result = 1.0 - result;
2130-
PG_RETURN_FLOAT8(result);
2137+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex, true));
21312138
}
21322139

21332140
/*
@@ -2136,11 +2143,7 @@ regexnejoinsel(PG_FUNCTION_ARGS)
21362143
Datum
21372144
icregexnejoinsel(PG_FUNCTION_ARGS)
21382145
{
2139-
float8 result;
2140-
2141-
result = DatumGetFloat8(icregexeqjoinsel(fcinfo));
2142-
result = 1.0 - result;
2143-
PG_RETURN_FLOAT8(result);
2146+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex_IC, true));
21442147
}
21452148

21462149
/*
@@ -2149,11 +2152,7 @@ icregexnejoinsel(PG_FUNCTION_ARGS)
21492152
Datum
21502153
nlikejoinsel(PG_FUNCTION_ARGS)
21512154
{
2152-
float8 result;
2153-
2154-
result = DatumGetFloat8(likejoinsel(fcinfo));
2155-
result = 1.0 - result;
2156-
PG_RETURN_FLOAT8(result);
2155+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like, true));
21572156
}
21582157

21592158
/*
@@ -2162,11 +2161,7 @@ nlikejoinsel(PG_FUNCTION_ARGS)
21622161
Datum
21632162
icnlikejoinsel(PG_FUNCTION_ARGS)
21642163
{
2165-
float8 result;
2166-
2167-
result = DatumGetFloat8(iclikejoinsel(fcinfo));
2168-
result = 1.0 - result;
2169-
PG_RETURN_FLOAT8(result);
2164+
PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like_IC, true));
21702165
}
21712166

21722167
/*

0 commit comments

Comments
 (0)