Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb6108fe

Browse files
committed
Fix planner to pass correct collation to operator selectivity estimators.
We can do this without creating an API break for estimation functionsby passing the collation using the existing fmgr functionality forpassing an input collation as a hidden parameter.The need for this was foreseen at the outset, but we didn't get around tomaking it happen in 9.1 because of the decision to sort all pg_statistichistograms according to the database's default collation. That meant thatselectivity estimators generally need to use the default collation too,even if they're estimating for an operator that will do somethingdifferent. The reason it's suddenly become more interesting is thatregexp interpretation also uses a collation (for its LC_TYPE not LC_COLLATEproperty), and we no longer want to use the wrong collation when examiningregexps during planning. It's not that the selectivity estimate is likelyto change much from this; rather that we are thinking of caching compiledregexps during planner estimation, and we won't get the intended benefitif we cache them with a different collation than the executor will use.Back-patch to 9.1, both because the regexp change is likely to getback-patched and because we might as well get this right in allcollation-supporting branches, in case any third-party code wants torely on getting the collation. The patch turns out to be minusculenow that I've done it ...
1 parent3f35526 commitb6108fe

File tree

4 files changed

+83
-51
lines changed

4 files changed

+83
-51
lines changed

‎src/backend/optimizer/path/clausesel.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ clause_selectivity(PlannerInfo *root,
579579
list_make2(var,
580580
makeBoolConst(true,
581581
false)),
582+
InvalidOid,
582583
varRelid);
583584
}
584585
}
@@ -650,21 +651,24 @@ clause_selectivity(PlannerInfo *root,
650651
}
651652
elseif (is_opclause(clause)||IsA(clause,DistinctExpr))
652653
{
653-
Oidopno= ((OpExpr*)clause)->opno;
654+
OpExpr*opclause= (OpExpr*)clause;
655+
Oidopno=opclause->opno;
654656

655657
if (treat_as_join_clause(clause,rinfo,varRelid,sjinfo))
656658
{
657659
/* Estimate selectivity for a join clause. */
658660
s1=join_selectivity(root,opno,
659-
((OpExpr*)clause)->args,
661+
opclause->args,
662+
opclause->inputcollid,
660663
jointype,
661664
sjinfo);
662665
}
663666
else
664667
{
665668
/* Estimate selectivity for a restriction clause. */
666669
s1=restriction_selectivity(root,opno,
667-
((OpExpr*)clause)->args,
670+
opclause->args,
671+
opclause->inputcollid,
668672
varRelid);
669673
}
670674

‎src/backend/optimizer/util/plancat.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,7 @@ Selectivity
907907
restriction_selectivity(PlannerInfo*root,
908908
Oidoperatorid,
909909
List*args,
910+
Oidinputcollid,
910911
intvarRelid)
911912
{
912913
RegProcedureoprrest=get_oprrest(operatorid);
@@ -919,11 +920,12 @@ restriction_selectivity(PlannerInfo *root,
919920
if (!oprrest)
920921
return (Selectivity)0.5;
921922

922-
result=DatumGetFloat8(OidFunctionCall4(oprrest,
923-
PointerGetDatum(root),
924-
ObjectIdGetDatum(operatorid),
925-
PointerGetDatum(args),
926-
Int32GetDatum(varRelid)));
923+
result=DatumGetFloat8(OidFunctionCall4Coll(oprrest,
924+
inputcollid,
925+
PointerGetDatum(root),
926+
ObjectIdGetDatum(operatorid),
927+
PointerGetDatum(args),
928+
Int32GetDatum(varRelid)));
927929

928930
if (result<0.0||result>1.0)
929931
elog(ERROR,"invalid restriction selectivity: %f",result);
@@ -942,6 +944,7 @@ Selectivity
942944
join_selectivity(PlannerInfo*root,
943945
Oidoperatorid,
944946
List*args,
947+
Oidinputcollid,
945948
JoinTypejointype,
946949
SpecialJoinInfo*sjinfo)
947950
{
@@ -955,12 +958,13 @@ join_selectivity(PlannerInfo *root,
955958
if (!oprjoin)
956959
return (Selectivity)0.5;
957960

958-
result=DatumGetFloat8(OidFunctionCall5(oprjoin,
959-
PointerGetDatum(root),
960-
ObjectIdGetDatum(operatorid),
961-
PointerGetDatum(args),
962-
Int16GetDatum(jointype),
963-
PointerGetDatum(sjinfo)));
961+
result=DatumGetFloat8(OidFunctionCall5Coll(oprjoin,
962+
inputcollid,
963+
PointerGetDatum(root),
964+
ObjectIdGetDatum(operatorid),
965+
PointerGetDatum(args),
966+
Int16GetDatum(jointype),
967+
PointerGetDatum(sjinfo)));
964968

965969
if (result<0.0||result>1.0)
966970
elog(ERROR,"invalid join selectivity: %f",result);

‎src/backend/utils/adt/selfuncs.c

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@
8383
* joins, however, the selectivity is defined as the fraction of the left-hand
8484
* side relation's rows that are expected to have a match (ie, at least one
8585
* row with a TRUE result) in the right-hand side.
86+
*
87+
* For both oprrest and oprjoin functions, the operator's input collation OID
88+
* (if any) is passed using the standard fmgr mechanism, so that the estimator
89+
* function can fetch it with PG_GET_COLLATION(). Note, however, that all
90+
* statistics in pg_statistic are currently built using the database's default
91+
* collation. Thus, in most cases where we are looking at statistics, we
92+
* should ignore the actual operator collation and use DEFAULT_COLLATION_OID.
93+
* We expect that the error induced by doing this is usually not large enough
94+
* to justify complicating matters.
8695
*----------
8796
*/
8897

@@ -1087,6 +1096,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
10871096
Oidoperator=PG_GETARG_OID(1);
10881097
List*args= (List*)PG_GETARG_POINTER(2);
10891098
intvarRelid=PG_GETARG_INT32(3);
1099+
Oidcollation=PG_GET_COLLATION();
10901100
VariableStatDatavardata;
10911101
Node*other;
10921102
boolvaronleft;
@@ -1187,12 +1197,15 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
11871197
}
11881198

11891199
/*
1190-
* Divide pattern into fixed prefix and remainder.XXX we have to assume
1191-
* default collation here, because we don't have access to the actual
1192-
* input collation for the operator. FIXME ...
1200+
* Divide pattern into fixed prefix and remainder. Unlike many of the
1201+
* other functions in this file, we use the pattern operator's actual
1202+
* collation for this step. This is not because we expect the collation
1203+
* to make a big difference in the selectivity estimate (it seldom would),
1204+
* but because we want to be sure we cache compiled regexps under the
1205+
* right cache key, so that they can be re-used at runtime.
11931206
*/
11941207
patt= (Const*)other;
1195-
pstatus=pattern_fixed_prefix(patt,ptype,DEFAULT_COLLATION_OID,
1208+
pstatus=pattern_fixed_prefix(patt,ptype,collation,
11961209
&prefix,&rest);
11971210

11981211
/*
@@ -1776,18 +1789,20 @@ scalararraysel(PlannerInfo *root,
17761789
elem_nulls[i],
17771790
elmbyval));
17781791
if (is_join_clause)
1779-
s2=DatumGetFloat8(FunctionCall5(&oprselproc,
1780-
PointerGetDatum(root),
1781-
ObjectIdGetDatum(operator),
1782-
PointerGetDatum(args),
1783-
Int16GetDatum(jointype),
1784-
PointerGetDatum(sjinfo)));
1792+
s2=DatumGetFloat8(FunctionCall5Coll(&oprselproc,
1793+
clause->inputcollid,
1794+
PointerGetDatum(root),
1795+
ObjectIdGetDatum(operator),
1796+
PointerGetDatum(args),
1797+
Int16GetDatum(jointype),
1798+
PointerGetDatum(sjinfo)));
17851799
else
1786-
s2=DatumGetFloat8(FunctionCall4(&oprselproc,
1787-
PointerGetDatum(root),
1788-
ObjectIdGetDatum(operator),
1789-
PointerGetDatum(args),
1790-
Int32GetDatum(varRelid)));
1800+
s2=DatumGetFloat8(FunctionCall4Coll(&oprselproc,
1801+
clause->inputcollid,
1802+
PointerGetDatum(root),
1803+
ObjectIdGetDatum(operator),
1804+
PointerGetDatum(args),
1805+
Int32GetDatum(varRelid)));
17911806
if (useOr)
17921807
s1=s1+s2-s1*s2;
17931808
else
@@ -1818,18 +1833,20 @@ scalararraysel(PlannerInfo *root,
18181833
*/
18191834
args=list_make2(leftop,elem);
18201835
if (is_join_clause)
1821-
s2=DatumGetFloat8(FunctionCall5(&oprselproc,
1822-
PointerGetDatum(root),
1823-
ObjectIdGetDatum(operator),
1824-
PointerGetDatum(args),
1825-
Int16GetDatum(jointype),
1826-
PointerGetDatum(sjinfo)));
1836+
s2=DatumGetFloat8(FunctionCall5Coll(&oprselproc,
1837+
clause->inputcollid,
1838+
PointerGetDatum(root),
1839+
ObjectIdGetDatum(operator),
1840+
PointerGetDatum(args),
1841+
Int16GetDatum(jointype),
1842+
PointerGetDatum(sjinfo)));
18271843
else
1828-
s2=DatumGetFloat8(FunctionCall4(&oprselproc,
1829-
PointerGetDatum(root),
1830-
ObjectIdGetDatum(operator),
1831-
PointerGetDatum(args),
1832-
Int32GetDatum(varRelid)));
1844+
s2=DatumGetFloat8(FunctionCall4Coll(&oprselproc,
1845+
clause->inputcollid,
1846+
PointerGetDatum(root),
1847+
ObjectIdGetDatum(operator),
1848+
PointerGetDatum(args),
1849+
Int32GetDatum(varRelid)));
18331850
if (useOr)
18341851
s1=s1+s2-s1*s2;
18351852
else
@@ -1854,18 +1871,20 @@ scalararraysel(PlannerInfo *root,
18541871
dummyexpr->collation=clause->inputcollid;
18551872
args=list_make2(leftop,dummyexpr);
18561873
if (is_join_clause)
1857-
s2=DatumGetFloat8(FunctionCall5(&oprselproc,
1858-
PointerGetDatum(root),
1859-
ObjectIdGetDatum(operator),
1860-
PointerGetDatum(args),
1861-
Int16GetDatum(jointype),
1862-
PointerGetDatum(sjinfo)));
1874+
s2=DatumGetFloat8(FunctionCall5Coll(&oprselproc,
1875+
clause->inputcollid,
1876+
PointerGetDatum(root),
1877+
ObjectIdGetDatum(operator),
1878+
PointerGetDatum(args),
1879+
Int16GetDatum(jointype),
1880+
PointerGetDatum(sjinfo)));
18631881
else
1864-
s2=DatumGetFloat8(FunctionCall4(&oprselproc,
1865-
PointerGetDatum(root),
1866-
ObjectIdGetDatum(operator),
1867-
PointerGetDatum(args),
1868-
Int32GetDatum(varRelid)));
1882+
s2=DatumGetFloat8(FunctionCall4Coll(&oprselproc,
1883+
clause->inputcollid,
1884+
PointerGetDatum(root),
1885+
ObjectIdGetDatum(operator),
1886+
PointerGetDatum(args),
1887+
Int32GetDatum(varRelid)));
18691888
s1=useOr ?0.0 :1.0;
18701889

18711890
/*
@@ -1937,6 +1956,7 @@ rowcomparesel(PlannerInfo *root,
19371956
{
19381957
Selectivitys1;
19391958
Oidopno=linitial_oid(clause->opnos);
1959+
Oidinputcollid=linitial_oid(clause->inputcollids);
19401960
List*opargs;
19411961
boolis_join_clause;
19421962

@@ -1977,6 +1997,7 @@ rowcomparesel(PlannerInfo *root,
19771997
/* Estimate selectivity for a join clause. */
19781998
s1=join_selectivity(root,opno,
19791999
opargs,
2000+
inputcollid,
19802001
jointype,
19812002
sjinfo);
19822003
}
@@ -1985,6 +2006,7 @@ rowcomparesel(PlannerInfo *root,
19852006
/* Estimate selectivity for a restriction clause. */
19862007
s1=restriction_selectivity(root,opno,
19872008
opargs,
2009+
inputcollid,
19882010
varRelid);
19892011
}
19902012

‎src/include/optimizer/plancat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ extern bool has_unique_index(RelOptInfo *rel, AttrNumber attno);
4343
externSelectivityrestriction_selectivity(PlannerInfo*root,
4444
Oidoperatorid,
4545
List*args,
46+
Oidinputcollid,
4647
intvarRelid);
4748

4849
externSelectivityjoin_selectivity(PlannerInfo*root,
4950
Oidoperatorid,
5051
List*args,
52+
Oidinputcollid,
5153
JoinTypejointype,
5254
SpecialJoinInfo*sjinfo);
5355

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp