|
15 | 15 | *
|
16 | 16 | *
|
17 | 17 | * IDENTIFICATION
|
18 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.199 2006/04/20 17:50:18 tgl Exp $ |
| 18 | + * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.200 2006/04/26 18:28:29 momjian Exp $ |
19 | 19 | *
|
20 | 20 | *-------------------------------------------------------------------------
|
21 | 21 | */
|
@@ -4852,3 +4852,182 @@ gistcostestimate(PG_FUNCTION_ARGS)
|
4852 | 4852 |
|
4853 | 4853 | PG_RETURN_VOID();
|
4854 | 4854 | }
|
| 4855 | + |
| 4856 | + |
| 4857 | +#define DEFAULT_PARENT_SEL 0.001 |
| 4858 | + |
| 4859 | +/* |
| 4860 | + * parentsel - Selectivity of parent relationship for ltree data types. |
| 4861 | + */ |
| 4862 | +Datum |
| 4863 | +parentsel(PG_FUNCTION_ARGS) |
| 4864 | +{ |
| 4865 | + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); |
| 4866 | + Oid operator = PG_GETARG_OID(1); |
| 4867 | + List *args = (List *) PG_GETARG_POINTER(2); |
| 4868 | + int varRelid = PG_GETARG_INT32(3); |
| 4869 | + VariableStatData vardata; |
| 4870 | + Node *other; |
| 4871 | + bool varonleft; |
| 4872 | + Datum *values; |
| 4873 | + int nvalues; |
| 4874 | + float4 *numbers; |
| 4875 | + int nnumbers; |
| 4876 | + double selec = 0.0; |
| 4877 | + |
| 4878 | + /* |
| 4879 | + * If expression is not variable <@ something or something <@ variable, |
| 4880 | + * then punt and return a default estimate. |
| 4881 | + */ |
| 4882 | + if (!get_restriction_variable(root, args, varRelid, |
| 4883 | + &vardata, &other, &varonleft)) |
| 4884 | + PG_RETURN_FLOAT8(DEFAULT_PARENT_SEL); |
| 4885 | + |
| 4886 | + /* |
| 4887 | + * If the something is a NULL constant, assume operator is strict and |
| 4888 | + * return zero, ie, operator will never return TRUE. |
| 4889 | + */ |
| 4890 | + if (IsA(other, Const) && |
| 4891 | + ((Const *) other)->constisnull) |
| 4892 | + { |
| 4893 | + ReleaseVariableStats(vardata); |
| 4894 | + PG_RETURN_FLOAT8(0.0); |
| 4895 | + } |
| 4896 | + |
| 4897 | + if (HeapTupleIsValid(vardata.statsTuple)) |
| 4898 | + { |
| 4899 | + Form_pg_statistic stats; |
| 4900 | + double mcvsum = 0.0; |
| 4901 | + double mcvsel = 0.0; |
| 4902 | + double hissel = 0.0; |
| 4903 | + |
| 4904 | + stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple); |
| 4905 | + |
| 4906 | + if (IsA(other, Const)) |
| 4907 | + { |
| 4908 | + /* Variable is being compared to a known non-null constant */ |
| 4909 | + Datum constval = ((Const *) other)->constvalue; |
| 4910 | + bool match = false; |
| 4911 | + int i; |
| 4912 | + |
| 4913 | + /* |
| 4914 | + * Is the constant "<@" to any of the column's most common values? |
| 4915 | + */ |
| 4916 | + if (get_attstatsslot(vardata.statsTuple, |
| 4917 | + vardata.atttype, vardata.atttypmod, |
| 4918 | + STATISTIC_KIND_MCV, InvalidOid, |
| 4919 | + &values, &nvalues, |
| 4920 | + &numbers, &nnumbers)) |
| 4921 | + { |
| 4922 | + FmgrInfo contproc; |
| 4923 | + |
| 4924 | + fmgr_info(get_opcode(operator), &contproc); |
| 4925 | + |
| 4926 | + for (i = 0; i < nvalues; i++) |
| 4927 | + { |
| 4928 | + /* be careful to apply operator right way 'round */ |
| 4929 | + if (varonleft) |
| 4930 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 4931 | + values[i], |
| 4932 | + constval)); |
| 4933 | + else |
| 4934 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 4935 | + constval, |
| 4936 | + values[i])); |
| 4937 | + |
| 4938 | + /* calculate total selectivity of all most-common-values */ |
| 4939 | + mcvsum += numbers[i]; |
| 4940 | + |
| 4941 | + /* calculate selectivity of matching most-common-values */ |
| 4942 | + if (match) |
| 4943 | + mcvsel += numbers[i]; |
| 4944 | + } |
| 4945 | + } |
| 4946 | + else |
| 4947 | + { |
| 4948 | + /* no most-common-values info available */ |
| 4949 | + values = NULL; |
| 4950 | + numbers = NULL; |
| 4951 | + i = nvalues = nnumbers = 0; |
| 4952 | + } |
| 4953 | + |
| 4954 | + free_attstatsslot(vardata.atttype, values, nvalues, NULL, 0); |
| 4955 | + |
| 4956 | + /* |
| 4957 | + * Is the constant "<@" to any of the column's histogram values? |
| 4958 | + */ |
| 4959 | + if (get_attstatsslot(vardata.statsTuple, |
| 4960 | + vardata.atttype, vardata.atttypmod, |
| 4961 | + STATISTIC_KIND_HISTOGRAM, InvalidOid, |
| 4962 | + &values, &nvalues, |
| 4963 | + NULL, NULL)) |
| 4964 | + { |
| 4965 | + FmgrInfo contproc; |
| 4966 | + |
| 4967 | + fmgr_info(get_opcode(operator), &contproc); |
| 4968 | + |
| 4969 | + for (i = 0; i < nvalues; i++) |
| 4970 | + { |
| 4971 | + /* be careful to apply operator right way 'round */ |
| 4972 | + if (varonleft) |
| 4973 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 4974 | + values[i], |
| 4975 | + constval)); |
| 4976 | + else |
| 4977 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 4978 | + constval, |
| 4979 | + values[i])); |
| 4980 | + /* count matching histogram values */ |
| 4981 | + if (match) |
| 4982 | + hissel++; |
| 4983 | + } |
| 4984 | + |
| 4985 | + if (hissel > 0.0) |
| 4986 | + { |
| 4987 | + /* |
| 4988 | + * some matching values found inside histogram, divide |
| 4989 | + * matching entries number by total histogram entries to |
| 4990 | + * get the histogram related selectivity |
| 4991 | + */ |
| 4992 | + hissel /= nvalues; |
| 4993 | + } |
| 4994 | + } |
| 4995 | + else |
| 4996 | + { |
| 4997 | + /* no histogram info available */ |
| 4998 | + values = NULL; |
| 4999 | + i = nvalues = 0; |
| 5000 | + } |
| 5001 | + |
| 5002 | + free_attstatsslot(vardata.atttype, values, nvalues, |
| 5003 | + NULL, 0); |
| 5004 | + |
| 5005 | + |
| 5006 | + /* |
| 5007 | + * calculate selectivity based on MCV and histogram result |
| 5008 | + * histogram selectivity needs to be scaled down if there are any |
| 5009 | + * most-common-values |
| 5010 | + */ |
| 5011 | + selec = mcvsel + hissel * (1.0 - mcvsum); |
| 5012 | + |
| 5013 | + /* |
| 5014 | + * don't return 0.0 selectivity unless all table values are inside |
| 5015 | + * mcv |
| 5016 | + */ |
| 5017 | + if (selec == 0.0 && mcvsum != 1.0) |
| 5018 | + selec = DEFAULT_PARENT_SEL; |
| 5019 | + } |
| 5020 | + else |
| 5021 | + selec = DEFAULT_PARENT_SEL; |
| 5022 | + } |
| 5023 | + else |
| 5024 | + selec = DEFAULT_PARENT_SEL; |
| 5025 | + |
| 5026 | + ReleaseVariableStats(vardata); |
| 5027 | + |
| 5028 | + /* result should be in range, but make sure... */ |
| 5029 | + CLAMP_PROBABILITY(selec); |
| 5030 | + |
| 5031 | + PG_RETURN_FLOAT8((float8) selec); |
| 5032 | +} |
| 5033 | + |
0 commit comments