1515 *
1616 *
1717 * IDENTIFICATION
18- * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.132 2003/02/08 20:20:55 tgl Exp $
18+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.133 2003/03/23 01:49:02 tgl Exp $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
9494#include "optimizer/prep.h"
9595#include "optimizer/tlist.h"
9696#include "optimizer/var.h"
97+ #include "parser/parse_expr.h"
9798#include "parser/parse_func.h"
9899#include "parser/parse_oper.h"
99100#include "parser/parsetree.h"
@@ -176,7 +177,8 @@ static bool get_restriction_var(List *args, int varRelid,
176177Var * * var ,Node * * other ,
177178bool * varonleft );
178179static void get_join_vars (List * args ,Var * * var1 ,Var * * var2 );
179- static Selectivity prefix_selectivity (Query * root ,Var * var ,Const * prefix );
180+ static Selectivity prefix_selectivity (Query * root ,Var * var ,Oid vartype ,
181+ Const * prefix );
180182static Selectivity pattern_selectivity (Const * patt ,Pattern_Type ptype );
181183static bool string_lessthan (const char * str1 ,const char * str2 ,
182184Oid datatype );
@@ -227,7 +229,8 @@ eqsel(PG_FUNCTION_ARGS)
227229 * If the something is a NULL constant, assume operator is strict and
228230 * return zero, ie, operator will never return TRUE.
229231 */
230- if (IsA (other ,Const )&& ((Const * )other )-> constisnull )
232+ if (IsA (other ,Const )&&
233+ ((Const * )other )-> constisnull )
231234PG_RETURN_FLOAT8 (0.0 );
232235
233236/* get stats for the attribute, if available */
@@ -834,6 +837,8 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
834837bool varonleft ;
835838Oid relid ;
836839Datum constval ;
840+ Oid consttype ;
841+ Oid vartype ;
837842Pattern_Prefix_Status pstatus ;
838843Const * patt = NULL ;
839844Const * prefix = NULL ;
@@ -861,13 +866,25 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
861866if (((Const * )other )-> constisnull )
862867return 0.0 ;
863868constval = ((Const * )other )-> constvalue ;
869+ consttype = ((Const * )other )-> consttype ;
870+
871+ /*
872+ * The right-hand const is type text or bytea for all supported
873+ * operators. We do not expect to see binary-compatible types here,
874+ * since const-folding should have relabeled the const to exactly match
875+ * the operator's declared type.
876+ */
877+ if (consttype != TEXTOID && consttype != BYTEAOID )
878+ return DEFAULT_MATCH_SEL ;
864879
865880/*
866- * the right-hand const is type text or bytea for all supported
867- * operators
881+ * The var, on the other hand, might be a binary-compatible type;
882+ * particularly a domain. Try to fold it if it's not recognized
883+ * immediately.
868884 */
869- Assert (((Const * )other )-> consttype == TEXTOID ||
870- ((Const * )other )-> consttype == BYTEAOID );
885+ vartype = var -> vartype ;
886+ if (vartype != consttype )
887+ vartype = getBaseType (vartype );
871888
872889/* divide pattern into fixed prefix and remainder */
873890patt = (Const * )other ;
@@ -878,12 +895,12 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
878895/*
879896 * Pattern specifies an exact match, so pretend operator is '='
880897 */
881- Oid eqopr = find_operator ("=" ,var -> vartype );
898+ Oid eqopr = find_operator ("=" ,vartype );
882899List * eqargs ;
883900
884901if (eqopr == InvalidOid )
885902elog (ERROR ,"patternsel: no = operator for type %u" ,
886- var -> vartype );
903+ vartype );
887904eqargs = makeList2 (var ,prefix );
888905result = DatumGetFloat8 (DirectFunctionCall4 (eqsel ,
889906PointerGetDatum (root ),
@@ -903,7 +920,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
903920Selectivity selec ;
904921
905922if (pstatus == Pattern_Prefix_Partial )
906- prefixsel = prefix_selectivity (root ,var ,prefix );
923+ prefixsel = prefix_selectivity (root ,var ,vartype , prefix );
907924else
908925prefixsel = 1.0 ;
909926restsel = pattern_selectivity (rest ,ptype );
@@ -1033,7 +1050,8 @@ booltestsel(Query *root, BoolTestType booltesttype, Node *arg,
10331050if (IsA (arg ,RelabelType ))
10341051arg = (Node * ) ((RelabelType * )arg )-> arg ;
10351052
1036- if (IsA (arg ,Var )&& (varRelid == 0 || varRelid == ((Var * )arg )-> varno ))
1053+ if (IsA (arg ,Var )&&
1054+ (varRelid == 0 || varRelid == ((Var * )arg )-> varno ))
10371055var = (Var * )arg ;
10381056else
10391057{
@@ -1775,6 +1793,8 @@ mergejoinscansel(Query *root, Node *clause,
17751793{
17761794Var * left ,
17771795* right ;
1796+ Oid lefttype ,
1797+ righttype ;
17781798Oid opno ,
17791799lsortop ,
17801800rsortop ,
@@ -1799,6 +1819,24 @@ mergejoinscansel(Query *root, Node *clause,
17991819if (!right )
18001820return ;/* shouldn't happen */
18011821
1822+ /* Save the direct input types of the operator */
1823+ lefttype = exprType ((Node * )left );
1824+ righttype = exprType ((Node * )right );
1825+
1826+ /*
1827+ * Now skip any binary-compatible relabeling; there can only be one level
1828+ * since constant-expression folder eliminates adjacent RelabelTypes.
1829+ *
1830+ * XXX can't enable this quite yet, it exposes regproc uncertainty problems
1831+ * in regression tests. FIXME soon.
1832+ */
1833+ #if 0
1834+ if (IsA (left ,RelabelType ))
1835+ left = (Var * ) ((RelabelType * )left )-> arg ;
1836+ if (IsA (right ,RelabelType ))
1837+ right = (Var * ) ((RelabelType * )right )-> arg ;
1838+ #endif
1839+
18021840/* Can't do anything if inputs are not Vars */
18031841if (!IsA (left ,Var )||
18041842!IsA (right ,Var ))
@@ -1841,13 +1879,13 @@ mergejoinscansel(Query *root, Node *clause,
18411879 * non-default estimates, else stick with our 1.0.
18421880 */
18431881selec = scalarineqsel (root ,leop , false,left ,
1844- rightmax ,right -> vartype );
1882+ rightmax ,righttype );
18451883if (selec != DEFAULT_INEQ_SEL )
18461884* leftscan = selec ;
18471885
18481886/* And similarly for the right variable. */
18491887selec = scalarineqsel (root ,revleop , false,right ,
1850- leftmax ,left -> vartype );
1888+ leftmax ,lefttype );
18511889if (selec != DEFAULT_INEQ_SEL )
18521890* rightscan = selec ;
18531891
@@ -2263,6 +2301,19 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
22632301Datum lobound ,Datum hibound ,Oid boundstypid ,
22642302double * scaledlobound ,double * scaledhibound )
22652303{
2304+ /*
2305+ * In present usage, we can assume that the valuetypid exactly matches
2306+ * the declared input type of the operator we are invoked for (because
2307+ * constant-folding will ensure that any Const passed to the operator
2308+ * has been reduced to the correct type). However, the boundstypid is
2309+ * the type of some variable that might be only binary-compatible with
2310+ * the declared type; in particular it might be a domain type. Must
2311+ * fold the variable type down to base type so we can recognize it.
2312+ * (But we can skip that lookup if the variable type matches the const.)
2313+ */
2314+ if (boundstypid != valuetypid )
2315+ boundstypid = getBaseType (boundstypid );
2316+
22662317switch (valuetypid )
22672318{
22682319/*
@@ -3234,31 +3285,36 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
32343285 * A fixed prefix "foo" is estimated as the selectivity of the expression
32353286 * "var >= 'foo' AND var < 'fop'" (see also indxqual.c).
32363287 *
3288+ * Because of constant-folding, we can assume that the prefixcon constant's
3289+ * type exactly matches the operator's declared input type; but it's not
3290+ * safe to make the same assumption for the Var, so the type to use for the
3291+ * Var must be passed in separately.
3292+ *
32373293 * XXX Note: we make use of the upper bound to estimate operator selectivity
32383294 * even if the locale is such that we cannot rely on the upper-bound string.
32393295 * The selectivity only needs to be approximately right anyway, so it seems
32403296 * more useful to use the upper-bound code than not.
32413297 */
32423298static Selectivity
3243- prefix_selectivity (Query * root ,Var * var ,Const * prefixcon )
3299+ prefix_selectivity (Query * root ,Var * var ,Oid vartype , Const * prefixcon )
32443300{
32453301Selectivity prefixsel ;
32463302Oid cmpopr ;
32473303char * prefix ;
32483304List * cmpargs ;
32493305Const * greaterstrcon ;
32503306
3251- cmpopr = find_operator (">=" ,var -> vartype );
3307+ cmpopr = find_operator (">=" ,vartype );
32523308if (cmpopr == InvalidOid )
32533309elog (ERROR ,"prefix_selectivity: no >= operator for type %u" ,
3254- var -> vartype );
3310+ vartype );
32553311if (prefixcon -> consttype != BYTEAOID )
32563312prefix = DatumGetCString (DirectFunctionCall1 (textout ,prefixcon -> constvalue ));
32573313else
32583314prefix = DatumGetCString (DirectFunctionCall1 (byteaout ,prefixcon -> constvalue ));
32593315
32603316/* If var is type NAME, must adjust type of comparison constant */
3261- if (var -> vartype == NAMEOID )
3317+ if (vartype == NAMEOID )
32623318prefixcon = string_to_const (prefix ,NAMEOID );
32633319
32643320cmpargs = makeList2 (var ,prefixcon );
@@ -3279,10 +3335,10 @@ prefix_selectivity(Query *root, Var *var, Const *prefixcon)
32793335{
32803336Selectivity topsel ;
32813337
3282- cmpopr = find_operator ("<" ,var -> vartype );
3338+ cmpopr = find_operator ("<" ,vartype );
32833339if (cmpopr == InvalidOid )
32843340elog (ERROR ,"prefix_selectivity: no < operator for type %u" ,
3285- var -> vartype );
3341+ vartype );
32863342cmpargs = makeList2 (var ,greaterstrcon );
32873343/* Assume scalarltsel is appropriate for all supported types */
32883344topsel = DatumGetFloat8 (DirectFunctionCall4 (scalarltsel ,