@ -176,7 +176,7 @@ static bool estimate_multivariate_ndistinct(PlannerInfo *root,
static bool convert_to_scalar ( Datum value , Oid valuetypid , double * scaledvalue ,
Datum lobound , Datum hibound , Oid boundstypid ,
double * scaledlobound , double * scaledhibound ) ;
static double convert_numeric_to_scalar ( Datum value , Oid typid ) ;
static double convert_numeric_to_scalar ( Datum value , Oid typid , bool * failure ) ;
static void convert_string_to_scalar ( char * value ,
double * scaledvalue ,
char * lobound ,
@ -193,8 +193,9 @@ static double convert_one_string_to_scalar(char *value,
int rangelo , int rangehi ) ;
static double convert_one_bytea_to_scalar ( unsigned char * value , int valuelen ,
int rangelo , int rangehi ) ;
static char * convert_string_datum ( Datum value , Oid typid ) ;
static double convert_timevalue_to_scalar ( Datum value , Oid typid ) ;
static char * convert_string_datum ( Datum value , Oid typid , bool * failure ) ;
static double convert_timevalue_to_scalar ( Datum value , Oid typid ,
bool * failure ) ;
static void examine_simple_variable ( PlannerInfo * root , Var * var ,
VariableStatData * vardata ) ;
static bool get_variable_range ( PlannerInfo * root , VariableStatData * vardata ,
@ -556,7 +557,8 @@ neqsel(PG_FUNCTION_ARGS)
*
* This routine works for any datatype ( or pair of datatypes ) known to
* convert_to_scalar ( ) . If it is applied to some other datatype ,
* it will return a default estimate .
* it will return an approximate estimate based on assuming that the constant
* value falls in the middle of the bin identified by binary search .
*/
static double
scalarineqsel ( PlannerInfo * root , Oid operator , bool isgt , bool iseq ,
@ -4033,10 +4035,15 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
Datum lobound , Datum hibound , Oid boundstypid ,
double * scaledlobound , double * scaledhibound )
{
bool failure = false ;
/*
* Both the valuetypid and the boundstypid should exactly match the
* declared input type ( s ) of the operator we are invoked for , so we just
* error out if either is not recognized .
* declared input type ( s ) of the operator we are invoked for . However ,
* extensions might try to use scalarineqsel as estimator for operators
* with input type ( s ) we don ' t handle here ; in such cases , we want to
* return false , not fail . In any case , we mustn ' t assume that valuetypid
* and boundstypid are identical .
*
* XXX The histogram we are interpolating between points of could belong
* to a column that ' s only binary - compatible with the declared type . In
@ -4071,10 +4078,13 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case REGDICTIONARYOID :
case REGROLEOID :
case REGNAMESPACEOID :
* scaledvalue = convert_numeric_to_scalar ( value , valuetypid ) ;
* scaledlobound = convert_numeric_to_scalar ( lobound , boundstypid ) ;
* scaledhibound = convert_numeric_to_scalar ( hibound , boundstypid ) ;
return true ;
* scaledvalue = convert_numeric_to_scalar ( value , valuetypid ,
& failure ) ;
* scaledlobound = convert_numeric_to_scalar ( lobound , boundstypid ,
& failure ) ;
* scaledhibound = convert_numeric_to_scalar ( hibound , boundstypid ,
& failure ) ;
return ! failure ;
/*
* Built - in string types
@ -4085,9 +4095,20 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case TEXTOID :
case NAMEOID :
{
char * valstr = convert_string_datum ( value , valuetypid ) ;
char * lostr = convert_string_datum ( lobound , boundstypid ) ;
char * histr = convert_string_datum ( hibound , boundstypid ) ;
char * valstr = convert_string_datum ( value , valuetypid ,
& failure ) ;
char * lostr = convert_string_datum ( lobound , boundstypid ,
& failure ) ;
char * histr = convert_string_datum ( hibound , boundstypid ,
& failure ) ;
/*
* Bail out if any of the values is not of string type . We
* might leak converted strings for the other value ( s ) , but
* that ' s not worth troubling over .
*/
if ( failure )
return false ;
convert_string_to_scalar ( valstr , scaledvalue ,
lostr , scaledlobound ,
@ -4103,6 +4124,9 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
*/
case BYTEAOID :
{
/* We only support bytea vs bytea comparison */
if ( boundstypid ! = BYTEAOID )
return false ;
convert_bytea_to_scalar ( value , scaledvalue ,
lobound , scaledlobound ,
hibound , scaledhibound ) ;
@ -4121,10 +4145,13 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case TINTERVALOID :
case TIMEOID :
case TIMETZOID :
* scaledvalue = convert_timevalue_to_scalar ( value , valuetypid ) ;
* scaledlobound = convert_timevalue_to_scalar ( lobound , boundstypid ) ;
* scaledhibound = convert_timevalue_to_scalar ( hibound , boundstypid ) ;
return true ;
* scaledvalue = convert_timevalue_to_scalar ( value , valuetypid ,
& failure ) ;
* scaledlobound = convert_timevalue_to_scalar ( lobound , boundstypid ,
& failure ) ;
* scaledhibound = convert_timevalue_to_scalar ( hibound , boundstypid ,
& failure ) ;
return ! failure ;
/*
* Built - in network types
@ -4133,10 +4160,13 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case CIDROID :
case MACADDROID :
case MACADDR8OID :
* scaledvalue = convert_network_to_scalar ( value , valuetypid ) ;
* scaledlobound = convert_network_to_scalar ( lobound , boundstypid ) ;
* scaledhibound = convert_network_to_scalar ( hibound , boundstypid ) ;
return true ;
* scaledvalue = convert_network_to_scalar ( value , valuetypid ,
& failure ) ;
* scaledlobound = convert_network_to_scalar ( lobound , boundstypid ,
& failure ) ;
* scaledhibound = convert_network_to_scalar ( hibound , boundstypid ,
& failure ) ;
return ! failure ;
}
/* Don't know how to convert */
* scaledvalue = * scaledlobound = * scaledhibound = 0 ;
@ -4145,9 +4175,12 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
/*
* Do convert_to_scalar ( ) ' s work for any numeric data type .
*
* On failure ( e . g . , unsupported typid ) , set * failure to true ;
* otherwise , that variable is not changed .
*/
static double
convert_numeric_to_scalar ( Datum value , Oid typid )
convert_numeric_to_scalar ( Datum value , Oid typid , bool * failure )
{
switch ( typid )
{
@ -4183,11 +4216,7 @@ convert_numeric_to_scalar(Datum value, Oid typid)
return ( double ) DatumGetObjectId ( value ) ;
}
/*
* Can ' t get here unless someone tries to use scalarineqsel ( ) on an
* operator with one numeric and one non - numeric operand .
*/
elog ( ERROR , " unsupported type: %u " , typid ) ;
* failure = true ;
return 0 ;
}
@ -4336,11 +4365,14 @@ convert_one_string_to_scalar(char *value, int rangelo, int rangehi)
/*
* Convert a string - type Datum into a palloc ' d , null - terminated string .
*
* On failure ( e . g . , unsupported typid ) , set * failure to true ;
* otherwise , that variable is not changed . ( We ' ll return NULL on failure . )
*
* When using a non - C locale , we must pass the string through strxfrm ( )
* before continuing , so as to generate correct locale - specific results .
*/
static char *
convert_string_datum ( Datum value , Oid typid )
convert_string_datum ( Datum value , Oid typid , bool * failure )
{
char * val ;
@ -4364,12 +4396,7 @@ convert_string_datum(Datum value, Oid typid)
break ;
}
default :
/*
* Can ' t get here unless someone tries to use scalarineqsel ( ) on
* an operator with one string and one non - string operand .
*/
elog ( ERROR , " unsupported type: %u " , typid ) ;
* failure = true ;
return NULL ;
}
@ -4446,16 +4473,19 @@ convert_bytea_to_scalar(Datum value,
Datum hibound ,
double * scaledhibound )
{
bytea * valuep = DatumGetByteaPP ( value ) ;
bytea * loboundp = DatumGetByteaPP ( lobound ) ;
bytea * hiboundp = DatumGetByteaPP ( hibound ) ;
int rangelo ,
rangehi ,
valuelen = VARSIZE ( DatumGetPointer ( value ) ) - VARHDRSZ ,
loboundlen = VARSIZE ( DatumGetPointer ( lobound ) ) - VARHDRSZ ,
hiboundlen = VARSIZE ( DatumGetPointer ( hibound ) ) - VARHDRSZ ,
valuelen = VARSIZE_ANY_EXHDR ( valuep ) ,
loboundlen = VARSIZE_ANY_EXHDR ( loboundp ) ,
hiboundlen = VARSIZE_ANY_EXHDR ( hiboundp ) ,
i ,
minlen ;
unsigned char * valstr = ( unsigned char * ) VARDATA ( DatumGetPointer ( value ) ) ,
* lostr = ( unsigned char * ) VARDATA ( DatumGetPointer ( lobound ) ) ,
* histr = ( unsigned char * ) VARDATA ( DatumGetPointer ( hibound ) ) ;
unsigned char * valstr = ( unsigned char * ) VARDATA_ANY ( valuep ) ;
unsigned char * lostr = ( unsigned char * ) VARDATA_ANY ( loboundp ) ;
unsigned char * histr = ( unsigned char * ) VARDATA_ANY ( hiboundp ) ;
/*
* Assume bytea data is uniformly distributed across all byte values .
@ -4522,9 +4552,12 @@ convert_one_bytea_to_scalar(unsigned char *value, int valuelen,
/*
* Do convert_to_scalar ( ) ' s work for any timevalue data type .
*
* On failure ( e . g . , unsupported typid ) , set * failure to true ;
* otherwise , that variable is not changed .
*/
static double
convert_timevalue_to_scalar ( Datum value , Oid typid )
convert_timevalue_to_scalar ( Datum value , Oid typid , bool * failure )
{
switch ( typid )
{
@ -4570,11 +4603,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
}
}
/*
* Can ' t get here unless someone tries to use scalarineqsel ( ) on an
* operator with one timevalue and one non - timevalue operand .
*/
elog ( ERROR , " unsupported type: %u " , typid ) ;
* failure = true ;
return 0 ;
}