Hi,

Moving it in contrib/ltree would be more difficult to me because it depends on other functions declared in selfuncs.c (get_restriction_variable, etc).

I'd be willing to consider exporting those functions from selfuncs.c.

In the meanwhile here is the latest patch which uses both mcv and histogram values.


BTW, when restoring my test database I've found out that there were many errors on ALTER INDEX "something" OWNER TO ... :

ERROR:  "something" is not a table, view, or sequence

This using 8.1devel pg_restore and a 8.0.3 compressed dump. I could be wrong, but I didn't get those errors a few days ago (some cvs updates ago).


Best regards
--
Matteo Beccati
http://phpadsnew.com/
http://phppgads.com/
Index: contrib/ltree/ltree.sql.in
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/ltree/ltree.sql.in,v
retrieving revision 1.9
diff -c -r1.9 ltree.sql.in
*** contrib/ltree/ltree.sql.in  30 Mar 2004 15:45:32 -0000      1.9
--- contrib/ltree/ltree.sql.in  6 Aug 2005 13:10:35 -0000
***************
*** 230,236 ****
        RIGHTARG = ltree,
        PROCEDURE = ltree_isparent,
          COMMUTATOR = '<@',
!         RESTRICT = contsel,
        JOIN = contjoinsel
  );
  
--- 230,236 ----
        RIGHTARG = ltree,
        PROCEDURE = ltree_isparent,
          COMMUTATOR = '<@',
!         RESTRICT = parentsel,
        JOIN = contjoinsel
  );
  
***************
*** 248,254 ****
        RIGHTARG = ltree,
        PROCEDURE = ltree_risparent,
          COMMUTATOR = '@>',
!         RESTRICT = contsel,
        JOIN = contjoinsel
  );
  
--- 248,254 ----
        RIGHTARG = ltree,
        PROCEDURE = ltree_risparent,
          COMMUTATOR = '@>',
!         RESTRICT = parentsel,
        JOIN = contjoinsel
  );
  
Index: src/backend/utils/adt/selfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v
retrieving revision 1.187
diff -c -r1.187 selfuncs.c
*** src/backend/utils/adt/selfuncs.c    21 Jul 2005 04:41:43 -0000      1.187
--- src/backend/utils/adt/selfuncs.c    6 Aug 2005 13:10:46 -0000
***************
*** 1306,1311 ****
--- 1306,1488 ----
        return (Selectivity) selec;
  }
  
+ #define DEFAULT_PARENT_SEL 0.001
+ 
+ /*
+  *            parentsel               - Selectivity of parent relationship 
for ltree data types.
+  */
+ Datum
+ parentsel(PG_FUNCTION_ARGS)
+ {
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
+       Oid                     operator = PG_GETARG_OID(1);
+       List       *args = (List *) PG_GETARG_POINTER(2);
+       int                     varRelid = PG_GETARG_INT32(3);
+       VariableStatData vardata;
+       Node       *other;
+       bool            varonleft;
+       Datum      *values;
+       int                     nvalues;
+       float4     *numbers;
+       int                     nnumbers;
+       double          selec = 0.0;
+ 
+       /*
+        * If expression is not variable <@ something or something <@ variable,
+        * then punt and return a default estimate.
+        */
+       if (!get_restriction_variable(root, args, varRelid,
+                                                                 &vardata, 
&other, &varonleft))
+               PG_RETURN_FLOAT8(DEFAULT_PARENT_SEL);
+ 
+       /*
+        * If the something is a NULL constant, assume operator is strict and
+        * return zero, ie, operator will never return TRUE.
+        */
+       if (IsA(other, Const) &&
+               ((Const *) other)->constisnull)
+       {
+               ReleaseVariableStats(vardata);
+               PG_RETURN_FLOAT8(0.0);
+       }
+ 
+       if (HeapTupleIsValid(vardata.statsTuple))
+       {
+               Form_pg_statistic stats;
+               double          mcvsum = 0.0;
+               double          mcvsel = 0.0;
+               double          hissel = 0.0;
+ 
+               stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
+ 
+               if (IsA(other, Const))
+               {
+                       /* Variable is being compared to a known non-null 
constant */
+                       Datum           constval = ((Const *) 
other)->constvalue;
+                       bool            match = false;
+                       int                     i;
+ 
+                       /*
+                        * Is the constant "<@" to any of the column's most 
common
+                        * values?
+                        */
+                       if (get_attstatsslot(vardata.statsTuple,
+                                                                
vardata.atttype, vardata.atttypmod,
+                                                                
STATISTIC_KIND_MCV, InvalidOid,
+                                                                &values, 
&nvalues,
+                                                                &numbers, 
&nnumbers))
+                       {
+                               FmgrInfo        contproc;
+ 
+                               fmgr_info(get_opcode(operator), &contproc);
+ 
+                               for (i = 0; i < nvalues; i++)
+                               {
+                                       /* be careful to apply operator right 
way 'round */
+                                       if (varonleft)
+                                               match = 
DatumGetBool(FunctionCall2(&contproc,
+                                                                               
                                   values[i],
+                                                                               
                                   constval));
+                                       else
+                                               match = 
DatumGetBool(FunctionCall2(&contproc,
+                                                                               
                                   constval,
+                                                                               
                                   values[i]));
+ 
+                                       /* calculate total selectivity of all 
most-common-values */
+                                       mcvsum += numbers[i];
+ 
+                                       /* calculate selectivity of matching 
most-common-values */
+                                       if (match)
+                                               mcvsel += numbers[i];
+                               }
+                       }
+                       else
+                       {
+                               /* no most-common-values info available */
+                               values = NULL;
+                               numbers = NULL;
+                               i = nvalues = nnumbers = 0;
+                       }
+ 
+                       free_attstatsslot(vardata.atttype, values, nvalues,
+                                                         NULL, 0);
+ 
+ 
+                       /*
+                        * Is the constant "<@" to any of the column's histogram
+                        * values?
+                        */
+                       if (get_attstatsslot(vardata.statsTuple,
+                                                                
vardata.atttype, vardata.atttypmod,
+                                                                
STATISTIC_KIND_HISTOGRAM, InvalidOid,
+                                                                &values, 
&nvalues,
+                                                                NULL, NULL))
+                       {
+                               FmgrInfo        contproc;
+ 
+                               fmgr_info(get_opcode(operator), &contproc);
+ 
+                               for (i = 0; i < nvalues; i++)
+                               {
+                                       /* be careful to apply operator right 
way 'round */
+                                       if (varonleft)
+                                               match = 
DatumGetBool(FunctionCall2(&contproc,
+                                                                               
                                   values[i],
+                                                                               
                                   constval));
+                                       else
+                                               match = 
DatumGetBool(FunctionCall2(&contproc,
+                                                                               
                                   constval,
+                                                                               
                                   values[i]));
+                                       /* count matching histogram values */
+                                       if (match)
+                                               hissel++;
+                               }
+ 
+                               if (hissel > 0.0)
+                               {
+                                       /*
+                                        * some matching values found inside 
histogram, divide matching entries number 
+                                        * by total histogram entries to get 
the histogram related selectivity
+                                        */
+                                       hissel /= nvalues;
+                               }
+                       }
+                       else
+                       {
+                               /* no histogram info available */
+                               values = NULL;
+                               i = nvalues = 0;
+                       }
+ 
+                       free_attstatsslot(vardata.atttype, values, nvalues,
+                                                         NULL, 0);
+ 
+ 
+                       /*
+                        * calculate selectivity based on MCV and histogram 
result
+                        * histogram selectivity needs to be scaled down if 
there are any most-common-values
+                        */
+                       selec = mcvsel + hissel * (1.0 - mcvsum);
+ 
+                       /* don't return 0.0 selectivity unless all table values 
are inside mcv */
+                       if (selec == 0.0 && mcvsum != 1.0)
+                               selec = DEFAULT_PARENT_SEL;
+               }
+               else
+                       selec = DEFAULT_PARENT_SEL;
+       }
+       else
+               selec = DEFAULT_PARENT_SEL;
+ 
+ 
+       ReleaseVariableStats(vardata);
+ 
+       /* result should be in range, but make sure... */
+       CLAMP_PROBABILITY(selec);
+ 
+       PG_RETURN_FLOAT8((float8) selec);
+ }
+ 
  /*
   *            eqjoinsel               - Join selectivity of "="
   */
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.380
diff -c -r1.380 pg_proc.h
*** src/include/catalog/pg_proc.h       2 Aug 2005 16:11:57 -0000       1.380
--- src/include/catalog/pg_proc.h       6 Aug 2005 13:10:59 -0000
***************
*** 3750,3755 ****
--- 3750,3758 ----
  DATA(insert OID = 2592 (  gist_circle_compress        PGNSP PGUID 12 f f t f 
i 1 2281 "2281" _null_ _null_ _null_     gist_circle_compress - _null_ ));
  DESCR("GiST support");
  
+ DATA(insert OID = 2600 (  parentsel              PGNSP PGUID 12 f f t f s 4 
701 "2281 26 2281 23" _null_ _null_ _null_        parentsel - _null_ ));
+ DESCR("enhanced restriction selectivity for ltree isparent comparison 
operators");
+ 
  
  /*
   * Symbolic values for provolatile column: these indicate whether the result
Index: src/include/utils/selfuncs.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/selfuncs.h,v
retrieving revision 1.23
diff -c -r1.23 selfuncs.h
*** src/include/utils/selfuncs.h        5 Jun 2005 22:32:58 -0000       1.23
--- src/include/utils/selfuncs.h        6 Aug 2005 13:11:00 -0000
***************
*** 95,100 ****
--- 95,102 ----
  extern Datum nlikesel(PG_FUNCTION_ARGS);
  extern Datum icnlikesel(PG_FUNCTION_ARGS);
  
+ extern Datum parentsel(PG_FUNCTION_ARGS);
+ 
  extern Datum eqjoinsel(PG_FUNCTION_ARGS);
  extern Datum neqjoinsel(PG_FUNCTION_ARGS);
  extern Datum scalarltjoinsel(PG_FUNCTION_ARGS);

---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster

Reply via email to