1515 *
1616 *
1717 * IDENTIFICATION
18- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.173 2005/03/07 04:30:51 momjian Exp $
18+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.174 2005/03/26 20:55:39 tgl Exp $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
@@ -2309,14 +2309,17 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
23092309 * constant-folding will ensure that any Const passed to the operator
23102310 * has been reduced to the correct type). However, the boundstypid is
23112311 * the type of some variable that might be only binary-compatible with
2312- * the declared type; in particular it might be a domain type.Must
2313- * fold the variable type down to base type so we can recognize it.
2314- * (But we can skip that lookup if the variable type matches the
2315- * const.)
2312+ * the declared type; for example it might be a domain type. So we
2313+ * ignore it and work with the valuetypid only.
2314+ *
2315+ * XXX What's really going on here is that we assume that the scalar
2316+ * representations of binary-compatible types are enough alike that we
2317+ * can use a histogram generated with one type's operators to estimate
2318+ * selectivity for the other's. This is outright wrong in some cases ---
2319+ * in particular signed versus unsigned interpretation could trip us up.
2320+ * But it's useful enough in the majority of cases that we do it anyway.
2321+ * Should think about more rigorous ways to do it.
23162322 */
2317- if (boundstypid != valuetypid )
2318- boundstypid = getBaseType (boundstypid );
2319-
23202323switch (valuetypid )
23212324{
23222325/*
@@ -2337,8 +2340,8 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
23372340case REGCLASSOID :
23382341case REGTYPEOID :
23392342* scaledvalue = convert_numeric_to_scalar (value ,valuetypid );
2340- * scaledlobound = convert_numeric_to_scalar (lobound ,boundstypid );
2341- * scaledhibound = convert_numeric_to_scalar (hibound ,boundstypid );
2343+ * scaledlobound = convert_numeric_to_scalar (lobound ,valuetypid );
2344+ * scaledhibound = convert_numeric_to_scalar (hibound ,valuetypid );
23422345return true;
23432346
23442347/*
@@ -2351,8 +2354,8 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
23512354case NAMEOID :
23522355{
23532356unsignedchar * valstr = convert_string_datum (value ,valuetypid );
2354- unsignedchar * lostr = convert_string_datum (lobound ,boundstypid );
2355- unsignedchar * histr = convert_string_datum (hibound ,boundstypid );
2357+ unsignedchar * lostr = convert_string_datum (lobound ,valuetypid );
2358+ unsignedchar * histr = convert_string_datum (hibound ,valuetypid );
23562359
23572360convert_string_to_scalar (valstr ,scaledvalue ,
23582361lostr ,scaledlobound ,
@@ -2387,8 +2390,8 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
23872390case TIMEOID :
23882391case TIMETZOID :
23892392* scaledvalue = convert_timevalue_to_scalar (value ,valuetypid );
2390- * scaledlobound = convert_timevalue_to_scalar (lobound ,boundstypid );
2391- * scaledhibound = convert_timevalue_to_scalar (hibound ,boundstypid );
2393+ * scaledlobound = convert_timevalue_to_scalar (lobound ,valuetypid );
2394+ * scaledhibound = convert_timevalue_to_scalar (hibound ,valuetypid );
23922395return true;
23932396
23942397/*
@@ -2398,8 +2401,8 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
23982401case CIDROID :
23992402case MACADDROID :
24002403* scaledvalue = convert_network_to_scalar (value ,valuetypid );
2401- * scaledlobound = convert_network_to_scalar (lobound ,boundstypid );
2402- * scaledhibound = convert_network_to_scalar (hibound ,boundstypid );
2404+ * scaledlobound = convert_network_to_scalar (lobound ,valuetypid );
2405+ * scaledhibound = convert_network_to_scalar (hibound ,valuetypid );
24032406return true;
24042407}
24052408/* Don't know how to convert */
@@ -2848,8 +2851,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
28482851 *
28492852 * Outputs: (these are valid only if TRUE is returned)
28502853 **vardata: gets information about variable (see examine_variable)
2851- **other: gets other clause argument, stripped of binary relabeling,
2852- *and aggressively reduced to a constant
2854+ **other: gets other clause argument, aggressively reduced to a constant
28532855 **varonleft: set TRUE if variable is on the left, FALSE if on the right
28542856 *
28552857 * Returns TRUE if a variable is identified, otherwise FALSE.
@@ -2939,7 +2941,8 @@ get_join_variables(Query *root, List *args,
29392941 *varRelid: see specs for restriction selectivity functions
29402942 *
29412943 * Outputs: *vardata is filled as follows:
2942- *var: the input expression (with any binary relabeling stripped)
2944+ *var: the input expression (with any binary relabeling stripped, if
2945+ *it is or contains a variable; but otherwise the type is preserved)
29432946 *rel: RelOptInfo for relation containing variable; NULL if expression
29442947 *contains no Vars (NOTE this could point to a RelOptInfo of a
29452948 *subquery, not one in the current query).
@@ -2955,27 +2958,29 @@ static void
29552958examine_variable (Query * root ,Node * node ,int varRelid ,
29562959VariableStatData * vardata )
29572960{
2961+ Node * basenode ;
29582962Relids varnos ;
29592963RelOptInfo * onerel ;
29602964
29612965/* Make sure we don't return dangling pointers in vardata */
29622966MemSet (vardata ,0 ,sizeof (VariableStatData ));
29632967
2964- /*Ignore any binary-compatible relabeling */
2968+ /*Look inside any binary-compatible relabeling */
29652969
29662970if (IsA (node ,RelabelType ))
2967- node = (Node * ) ((RelabelType * )node )-> arg ;
2968-
2969- vardata -> var = node ;
2971+ basenode = (Node * ) ((RelabelType * )node )-> arg ;
2972+ else
2973+ basenode = node ;
29702974
29712975/* Fast path for a simple Var */
29722976
2973- if (IsA (node ,Var )&&
2974- (varRelid == 0 || varRelid == ((Var * )node )-> varno ))
2977+ if (IsA (basenode ,Var )&&
2978+ (varRelid == 0 || varRelid == ((Var * )basenode )-> varno ))
29752979{
2976- Var * var = (Var * )node ;
2980+ Var * var = (Var * )basenode ;
29772981Oid relid ;
29782982
2983+ vardata -> var = basenode ;/* return Var without relabeling */
29792984vardata -> rel = find_base_rel (root ,var -> varno );
29802985vardata -> atttype = var -> vartype ;
29812986vardata -> atttypmod = var -> vartypmod ;
@@ -3009,7 +3014,7 @@ examine_variable(Query *root, Node *node, int varRelid,
30093014 * membership.Note that when varRelid isn't zero, only vars of that
30103015 * relation are considered "real" vars.
30113016 */
3012- varnos = pull_varnos (node );
3017+ varnos = pull_varnos (basenode );
30133018
30143019onerel = NULL ;
30153020
@@ -3024,6 +3029,7 @@ examine_variable(Query *root, Node *node, int varRelid,
30243029onerel = find_base_rel (root ,
30253030 (varRelid ?varRelid :bms_singleton_member (varnos )));
30263031vardata -> rel = onerel ;
3032+ node = basenode ;/* strip any relabeling */
30273033}
30283034/* else treat it as a constant */
30293035break ;
@@ -3032,11 +3038,13 @@ examine_variable(Query *root, Node *node, int varRelid,
30323038{
30333039/* treat it as a variable of a join relation */
30343040vardata -> rel = find_join_rel (root ,varnos );
3041+ node = basenode ;/* strip any relabeling */
30353042}
30363043else if (bms_is_member (varRelid ,varnos ))
30373044{
30383045/* ignore the vars belonging to other relations */
30393046vardata -> rel = find_base_rel (root ,varRelid );
3047+ node = basenode ;/* strip any relabeling */
30403048/* note: no point in expressional-index search here */
30413049}
30423050/* else treat it as a constant */
@@ -3045,6 +3053,7 @@ examine_variable(Query *root, Node *node, int varRelid,
30453053
30463054bms_free (varnos );
30473055
3056+ vardata -> var = node ;
30483057vardata -> atttype = exprType (node );
30493058vardata -> atttypmod = exprTypmod (node );
30503059