@@ -91,7 +91,8 @@ static Pattern_Prefix_Status pattern_fixed_prefix(Const *patt,
91
91
Selectivity * rest_selec );
92
92
static Selectivity prefix_selectivity (PlannerInfo * root ,
93
93
VariableStatData * vardata ,
94
- Oid vartype , Oid opfamily , Const * prefixcon );
94
+ Oid eqopr , Oid ltopr , Oid geopr ,
95
+ Const * prefixcon );
95
96
static Selectivity like_selectivity (const char * patt , int pattlen ,
96
97
bool case_insensitive );
97
98
static Selectivity regex_selectivity (const char * patt , int pattlen ,
@@ -470,7 +471,10 @@ patternsel_common(PlannerInfo *root,
470
471
Datum constval ;
471
472
Oid consttype ;
472
473
Oid vartype ;
473
- Oid opfamily ;
474
+ Oid rdatatype ;
475
+ Oid eqopr ;
476
+ Oid ltopr ;
477
+ Oid geopr ;
474
478
Pattern_Prefix_Status pstatus ;
475
479
Const * patt ;
476
480
Const * prefix = NULL ;
@@ -527,29 +531,51 @@ patternsel_common(PlannerInfo *root,
527
531
/*
528
532
* Similarly, the exposed type of the left-hand side should be one of
529
533
* those we know. (Do not look at vardata.atttype, which might be
530
- * something binary-compatible but different.) We can use it to choose
531
- * the index opfamily from which we must draw the comparison operators.
534
+ * something binary-compatible but different.) We can use it to identify
535
+ * the comparison operators and the required type of the comparison
536
+ * constant, much as in match_pattern_prefix().
532
537
*
533
- * NOTE: It would be more correct to use the PATTERN opfamilies than the
534
- * simple ones, but at the moment ANALYZE will not generate statistics for
535
- * the PATTERN operators. But our results are so approximate anyway that
536
- * it probably hardly matters.
538
+ * NOTE: this logic does not consider collations. Ideally we'd force use
539
+ * of "C" collation, but since ANALYZE only generates statistics for the
540
+ * column's specified collation, we have little choice but to use those.
541
+ * But our results are so approximate anyway that it probably hardly
542
+ * matters.
537
543
*/
538
544
vartype = vardata .vartype ;
539
545
540
546
switch (vartype )
541
547
{
542
548
case TEXTOID :
549
+ eqopr = TextEqualOperator ;
550
+ ltopr = TextLessOperator ;
551
+ geopr = TextGreaterEqualOperator ;
552
+ rdatatype = TEXTOID ;
553
+ break ;
543
554
case NAMEOID :
544
- opfamily = TEXT_BTREE_FAM_OID ;
555
+
556
+ /*
557
+ * Note that here, we need the RHS type to be text, so that the
558
+ * comparison value isn't improperly truncated to NAMEDATALEN.
559
+ */
560
+ eqopr = NameEqualTextOperator ;
561
+ ltopr = NameLessTextOperator ;
562
+ geopr = NameGreaterEqualTextOperator ;
563
+ rdatatype = TEXTOID ;
545
564
break ;
546
565
case BPCHAROID :
547
- opfamily = BPCHAR_BTREE_FAM_OID ;
566
+ eqopr = BpcharEqualOperator ;
567
+ ltopr = BpcharLessOperator ;
568
+ geopr = BpcharGreaterEqualOperator ;
569
+ rdatatype = BPCHAROID ;
548
570
break ;
549
571
case BYTEAOID :
550
- opfamily = BYTEA_BTREE_FAM_OID ;
572
+ eqopr = ByteaEqualOperator ;
573
+ ltopr = ByteaLessOperator ;
574
+ geopr = ByteaGreaterEqualOperator ;
575
+ rdatatype = BYTEAOID ;
551
576
break ;
552
577
default :
578
+ /* Can't get here unless we're attached to the wrong operator */
553
579
ReleaseVariableStats (vardata );
554
580
return result ;
555
581
}
@@ -579,41 +605,23 @@ patternsel_common(PlannerInfo *root,
579
605
& prefix , & rest_selec );
580
606
581
607
/*
582
- * If necessary, coerce the prefix constant to the right type.
608
+ * If necessary, coerce the prefix constant to the right type. The only
609
+ * case where we need to do anything is when converting text to bpchar.
610
+ * Those two types are binary-compatible, so relabeling the Const node is
611
+ * sufficient.
583
612
*/
584
- if (prefix && prefix -> consttype != vartype )
613
+ if (prefix && prefix -> consttype != rdatatype )
585
614
{
586
- char * prefixstr ;
587
-
588
- switch (prefix -> consttype )
589
- {
590
- case TEXTOID :
591
- prefixstr = TextDatumGetCString (prefix -> constvalue );
592
- break ;
593
- case BYTEAOID :
594
- prefixstr = DatumGetCString (DirectFunctionCall1 (byteaout ,
595
- prefix -> constvalue ));
596
- break ;
597
- default :
598
- elog (ERROR , "unrecognized consttype: %u" ,
599
- prefix -> consttype );
600
- ReleaseVariableStats (vardata );
601
- return result ;
602
- }
603
- prefix = string_to_const (prefixstr , vartype );
604
- pfree (prefixstr );
615
+ Assert (prefix -> consttype == TEXTOID &&
616
+ rdatatype == BPCHAROID );
617
+ prefix -> consttype = rdatatype ;
605
618
}
606
619
607
620
if (pstatus == Pattern_Prefix_Exact )
608
621
{
609
622
/*
610
- * Pattern specifies an exact match, so pretend operator is '='
623
+ * Pattern specifies an exact match, so estimate as for '='
611
624
*/
612
- Oid eqopr = get_opfamily_member (opfamily , vartype , vartype ,
613
- BTEqualStrategyNumber );
614
-
615
- if (eqopr == InvalidOid )
616
- elog (ERROR , "no = operator for opfamily %u" , opfamily );
617
625
result = var_eq_const (& vardata , eqopr , prefix -> constvalue ,
618
626
false, true, false);
619
627
}
@@ -656,8 +664,9 @@ patternsel_common(PlannerInfo *root,
656
664
Selectivity prefixsel ;
657
665
658
666
if (pstatus == Pattern_Prefix_Partial )
659
- prefixsel = prefix_selectivity (root , & vardata , vartype ,
660
- opfamily , prefix );
667
+ prefixsel = prefix_selectivity (root , & vardata ,
668
+ eqopr , ltopr , geopr ,
669
+ prefix );
661
670
else
662
671
prefixsel = 1.0 ;
663
672
heursel = prefixsel * rest_selec ;
@@ -1181,15 +1190,14 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation,
1181
1190
* Estimate the selectivity of a fixed prefix for a pattern match.
1182
1191
*
1183
1192
* A fixed prefix "foo" is estimated as the selectivity of the expression
1184
- * "variable >= 'foo' AND variable < 'fop'" (see also indxpath.c) .
1193
+ * "variable >= 'foo' AND variable < 'fop'".
1185
1194
*
1186
1195
* The selectivity estimate is with respect to the portion of the column
1187
1196
* population represented by the histogram --- the caller must fold this
1188
1197
* together with info about MCVs and NULLs.
1189
1198
*
1190
- * We use the >= and < operators from the specified btree opfamily to do the
1191
- * estimation. The given variable and Const must be of the associated
1192
- * datatype.
1199
+ * We use the specified btree comparison operators to do the estimation.
1200
+ * The given variable and Const must be of the associated datatype(s).
1193
1201
*
1194
1202
* XXX Note: we make use of the upper bound to estimate operator selectivity
1195
1203
* even if the locale is such that we cannot rely on the upper-bound string.
@@ -1198,20 +1206,17 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation,
1198
1206
*/
1199
1207
static Selectivity
1200
1208
prefix_selectivity (PlannerInfo * root , VariableStatData * vardata ,
1201
- Oid vartype , Oid opfamily , Const * prefixcon )
1209
+ Oid eqopr , Oid ltopr , Oid geopr ,
1210
+ Const * prefixcon )
1202
1211
{
1203
1212
Selectivity prefixsel ;
1204
- Oid cmpopr ;
1205
1213
FmgrInfo opproc ;
1206
1214
AttStatsSlot sslot ;
1207
1215
Const * greaterstrcon ;
1208
1216
Selectivity eq_sel ;
1209
1217
1210
- cmpopr = get_opfamily_member (opfamily , vartype , vartype ,
1211
- BTGreaterEqualStrategyNumber );
1212
- if (cmpopr == InvalidOid )
1213
- elog (ERROR , "no >= operator for opfamily %u" , opfamily );
1214
- fmgr_info (get_opcode (cmpopr ), & opproc );
1218
+ /* Estimate the selectivity of "x >= prefix" */
1219
+ fmgr_info (get_opcode (geopr ), & opproc );
1215
1220
1216
1221
prefixsel = ineq_histogram_selectivity (root , vardata ,
1217
1222
& opproc , true, true,
@@ -1237,11 +1242,7 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata,
1237
1242
/* sslot.stacoll is set up */ ;
1238
1243
else
1239
1244
sslot .stacoll = DEFAULT_COLLATION_OID ;
1240
- cmpopr = get_opfamily_member (opfamily , vartype , vartype ,
1241
- BTLessStrategyNumber );
1242
- if (cmpopr == InvalidOid )
1243
- elog (ERROR , "no < operator for opfamily %u" , opfamily );
1244
- fmgr_info (get_opcode (cmpopr ), & opproc );
1245
+ fmgr_info (get_opcode (ltopr ), & opproc );
1245
1246
greaterstrcon = make_greater_string (prefixcon , & opproc , sslot .stacoll );
1246
1247
if (greaterstrcon )
1247
1248
{
@@ -1277,11 +1278,7 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata,
1277
1278
* probably off the end of the histogram, and thus we probably got a very
1278
1279
* small estimate from the >= condition; so we still need to clamp.
1279
1280
*/
1280
- cmpopr = get_opfamily_member (opfamily , vartype , vartype ,
1281
- BTEqualStrategyNumber );
1282
- if (cmpopr == InvalidOid )
1283
- elog (ERROR , "no = operator for opfamily %u" , opfamily );
1284
- eq_sel = var_eq_const (vardata , cmpopr , prefixcon -> constvalue ,
1281
+ eq_sel = var_eq_const (vardata , eqopr , prefixcon -> constvalue ,
1285
1282
false, true, false);
1286
1283
1287
1284
prefixsel = Max (prefixsel , eq_sel );
0 commit comments