@@ -91,7 +91,8 @@ static Pattern_Prefix_Status pattern_fixed_prefix(Const *patt,
9191 Selectivity * rest_selec );
9292static Selectivity prefix_selectivity (PlannerInfo * root ,
9393 VariableStatData * vardata ,
94- Oid vartype , Oid opfamily , Const * prefixcon );
94+ Oid eqopr , Oid ltopr , Oid geopr ,
95+ Const * prefixcon );
9596static Selectivity like_selectivity (const char * patt , int pattlen ,
9697 bool case_insensitive );
9798static Selectivity regex_selectivity (const char * patt , int pattlen ,
@@ -470,7 +471,10 @@ patternsel_common(PlannerInfo *root,
470471 Datum constval ;
471472 Oid consttype ;
472473 Oid vartype ;
473- Oid opfamily ;
474+ Oid rdatatype ;
475+ Oid eqopr ;
476+ Oid ltopr ;
477+ Oid geopr ;
474478 Pattern_Prefix_Status pstatus ;
475479 Const * patt ;
476480 Const * prefix = NULL ;
@@ -527,29 +531,51 @@ patternsel_common(PlannerInfo *root,
527531 /*
528532 * Similarly, the exposed type of the left-hand side should be one of
529533 * 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().
532537 *
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.
537543 */
538544 vartype = vardata .vartype ;
539545
540546 switch (vartype )
541547 {
542548 case TEXTOID :
549+ eqopr = TextEqualOperator ;
550+ ltopr = TextLessOperator ;
551+ geopr = TextGreaterEqualOperator ;
552+ rdatatype = TEXTOID ;
553+ break ;
543554 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 ;
545564 break ;
546565 case BPCHAROID :
547- opfamily = BPCHAR_BTREE_FAM_OID ;
566+ eqopr = BpcharEqualOperator ;
567+ ltopr = BpcharLessOperator ;
568+ geopr = BpcharGreaterEqualOperator ;
569+ rdatatype = BPCHAROID ;
548570 break ;
549571 case BYTEAOID :
550- opfamily = BYTEA_BTREE_FAM_OID ;
572+ eqopr = ByteaEqualOperator ;
573+ ltopr = ByteaLessOperator ;
574+ geopr = ByteaGreaterEqualOperator ;
575+ rdatatype = BYTEAOID ;
551576 break ;
552577 default :
578+ /* Can't get here unless we're attached to the wrong operator */
553579 ReleaseVariableStats (vardata );
554580 return result ;
555581 }
@@ -579,41 +605,23 @@ patternsel_common(PlannerInfo *root,
579605 & prefix , & rest_selec );
580606
581607 /*
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.
583612 */
584- if (prefix && prefix -> consttype != vartype )
613+ if (prefix && prefix -> consttype != rdatatype )
585614 {
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 ;
605618 }
606619
607620 if (pstatus == Pattern_Prefix_Exact )
608621 {
609622 /*
610- * Pattern specifies an exact match, so pretend operator is '='
623+ * Pattern specifies an exact match, so estimate as for '='
611624 */
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 );
617625 result = var_eq_const (& vardata , eqopr , prefix -> constvalue ,
618626 false, true, false);
619627 }
@@ -656,8 +664,9 @@ patternsel_common(PlannerInfo *root,
656664 Selectivity prefixsel ;
657665
658666 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 );
661670 else
662671 prefixsel = 1.0 ;
663672 heursel = prefixsel * rest_selec ;
@@ -1181,15 +1190,14 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation,
11811190 * Estimate the selectivity of a fixed prefix for a pattern match.
11821191 *
11831192 * 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'".
11851194 *
11861195 * The selectivity estimate is with respect to the portion of the column
11871196 * population represented by the histogram --- the caller must fold this
11881197 * together with info about MCVs and NULLs.
11891198 *
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).
11931201 *
11941202 * XXX Note: we make use of the upper bound to estimate operator selectivity
11951203 * 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,
11981206 */
11991207static Selectivity
12001208prefix_selectivity (PlannerInfo * root , VariableStatData * vardata ,
1201- Oid vartype , Oid opfamily , Const * prefixcon )
1209+ Oid eqopr , Oid ltopr , Oid geopr ,
1210+ Const * prefixcon )
12021211{
12031212 Selectivity prefixsel ;
1204- Oid cmpopr ;
12051213 FmgrInfo opproc ;
12061214 AttStatsSlot sslot ;
12071215 Const * greaterstrcon ;
12081216 Selectivity eq_sel ;
12091217
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 );
12151220
12161221 prefixsel = ineq_histogram_selectivity (root , vardata ,
12171222 & opproc , true, true,
@@ -1237,11 +1242,7 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata,
12371242 /* sslot.stacoll is set up */ ;
12381243 else
12391244 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 );
12451246 greaterstrcon = make_greater_string (prefixcon , & opproc , sslot .stacoll );
12461247 if (greaterstrcon )
12471248 {
@@ -1277,11 +1278,7 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata,
12771278 * probably off the end of the histogram, and thus we probably got a very
12781279 * small estimate from the >= condition; so we still need to clamp.
12791280 */
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 ,
12851282 false, true, false);
12861283
12871284 prefixsel = Max (prefixsel , eq_sel );
0 commit comments