PostgreSQL Source Code git master
Loading...
Searching...
No Matches
dependencies.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * dependencies.c
4 * POSTGRES functional dependencies
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * IDENTIFICATION
10 * src/backend/statistics/dependencies.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include "access/htup_details.h"
19#include "nodes/nodeFuncs.h"
20#include "optimizer/clauses.h"
21#include "optimizer/optimizer.h"
22#include "parser/parsetree.h"
24#include "utils/fmgroids.h"
25#include "utils/lsyscache.h"
26#include "utils/memutils.h"
27#include "utils/selfuncs.h"
28#include "utils/syscache.h"
29#include "utils/typcache.h"
30
31/* size of the struct header fields (magic, type, ndeps) */
32#define SizeOfHeader (3 * sizeof(uint32))
33
34/* size of a serialized dependency (degree, natts, atts) */
35#define SizeOfItem(natts) \
36 (sizeof(double) + sizeof(AttrNumber) * (1 + (natts)))
37
38/* minimal size of a dependency (with two attributes) */
39#define MinSizeOfItem SizeOfItem(2)
40
41/* minimal size of dependencies, when all deps are minimal */
42#define MinSizeOfItems(ndeps) \
43 (SizeOfHeader + (ndeps) * MinSizeOfItem)
44
45/*
46 * Internal state for DependencyGenerator of dependencies. Dependencies are similar to
47 * k-permutations of n elements, except that the order does not matter for the
48 * first (k-1) elements. That is, (a,b=>c) and (b,a=>c) are equivalent.
49 */
51{
52 int k; /* size of the dependency */
53 int n; /* number of possible attributes */
54 int current; /* next dependency to return (index) */
55 AttrNumber ndependencies; /* number of dependencies generated */
56 AttrNumber *dependencies; /* array of pre-generated dependencies */
58
60
62 int index, AttrNumber start, AttrNumber *current);
67static double dependency_degree(StatsBuildData *data, int k, AttrNumber *dependency);
68static bool dependency_is_fully_matched(MVDependency *dependency,
69 Bitmapset *attnums);
70static bool dependency_is_compatible_clause(Node *clause, Index relid,
72static bool dependency_is_compatible_expression(Node *clause, Index relid,
73 List *statlist, Node **expr);
75 int ndependencies, Bitmapset *attnums);
77 int varRelid, JoinType jointype,
78 SpecialJoinInfo *sjinfo,
79 MVDependency **dependencies,
80 int ndependencies,
83
84static void
86 AttrNumber start, AttrNumber *current)
87{
88 /*
89 * The generator handles the first (k-1) elements differently from the
90 * last element.
91 */
92 if (index < (state->k - 1))
93 {
95
96 /*
97 * The first (k-1) values have to be in ascending order, which we
98 * generate recursively.
99 */
100
101 for (i = start; i < state->n; i++)
102 {
103 current[index] = i;
104 generate_dependencies_recurse(state, (index + 1), (i + 1), current);
105 }
106 }
107 else
108 {
109 int i;
110
111 /*
112 * the last element is the implied value, which does not respect the
113 * ascending order. We just need to check that the value is not in the
114 * first (k-1) elements.
115 */
116
117 for (i = 0; i < state->n; i++)
118 {
119 int j;
120 bool match = false;
121
122 current[index] = i;
123
124 for (j = 0; j < index; j++)
125 {
126 if (current[j] == i)
127 {
128 match = true;
129 break;
130 }
131 }
132
133 /*
134 * If the value is not found in the first part of the dependency,
135 * we're done.
136 */
137 if (!match)
138 {
139 state->dependencies = (AttrNumber *) repalloc(state->dependencies,
140 state->k * (state->ndependencies + 1) * sizeof(AttrNumber));
141 memcpy(&state->dependencies[(state->k * state->ndependencies)],
142 current, state->k * sizeof(AttrNumber));
143 state->ndependencies++;
144 }
145 }
146 }
147}
148
149/* generate all dependencies (k-permutations of n elements) */
150static void
152{
154
155 generate_dependencies_recurse(state, 0, 0, current);
156
157 pfree(current);
158}
159
160/*
161 * initialize the DependencyGenerator of variations, and prebuild the variations
162 *
163 * This pre-builds all the variations. We could also generate them in
164 * DependencyGenerator_next(), but this seems simpler.
165 */
168{
170
171 Assert((n >= k) && (k > 0));
172
173 /* allocate the DependencyGenerator state */
175 state->dependencies = palloc_array(AttrNumber, k);
176
177 state->ndependencies = 0;
178 state->current = 0;
179 state->k = k;
180 state->n = n;
181
182 /* now actually pre-generate all the variations */
184
185 return state;
186}
187
188/* free the DependencyGenerator state */
189static void
195
196/* generate next combination */
197static AttrNumber *
199{
200 if (state->current == state->ndependencies)
201 return NULL;
202
203 return &state->dependencies[state->k * state->current++];
204}
205
206
207/*
208 * validates functional dependency on the data
209 *
210 * An actual work horse of detecting functional dependencies. Given a variation
211 * of k attributes, it checks that the first (k-1) are sufficient to determine
212 * the last one.
213 */
214static double
216{
217 int i,
218 nitems;
222
223 /* counters valid within a group */
224 int group_size = 0;
225 int n_violations = 0;
226
227 /* total number of rows supporting (consistent with) the dependency */
228 int n_supporting_rows = 0;
229
230 /* Make sure we have at least two input attributes. */
231 Assert(k >= 2);
232
233 /* sort info for all attributes columns */
234 mss = multi_sort_init(k);
235
236 /*
237 * Translate the array of indexes to regular attnums for the dependency
238 * (we will need this to identify the columns in StatsBuildData).
239 */
241 for (i = 0; i < k; i++)
242 attnums_dep[i] = data->attnums[dependency[i]];
243
244 /*
245 * Verify the dependency (a,b,...)->z, using a rather simple algorithm:
246 *
247 * (a) sort the data lexicographically
248 *
249 * (b) split the data into groups by first (k-1) columns
250 *
251 * (c) for each group count different values in the last column
252 *
253 * We use the column data types' default sort operators and collations;
254 * perhaps at some point it'd be worth using column-specific collations?
255 */
256
257 /* prepare the sort function for the dimensions */
258 for (i = 0; i < k; i++)
259 {
260 VacAttrStats *colstat = data->stats[dependency[i]];
262
264 if (type->lt_opr == InvalidOid) /* shouldn't happen */
265 elog(ERROR, "cache lookup failed for ordering operator for type %u",
266 colstat->attrtypid);
267
268 /* prepare the sort function for this dimension */
269 multi_sort_add_dimension(mss, i, type->lt_opr, colstat->attrcollid);
270 }
271
272 /*
273 * build an array of SortItem(s) sorted using the multi-sort support
274 *
275 * XXX This relies on all stats entries pointing to the same tuple
276 * descriptor. For now that assumption holds, but it might change in the
277 * future for example if we support statistics on multiple tables.
278 */
280
281 /*
282 * Walk through the sorted array, split it into rows according to the
283 * first (k-1) columns. If there's a single value in the last column, we
284 * count the group as 'supporting' the functional dependency. Otherwise we
285 * count it as contradicting.
286 */
287
288 /* start with the first row forming a group */
289 group_size = 1;
290
291 /* loop 1 beyond the end of the array so that we count the final group */
292 for (i = 1; i <= nitems; i++)
293 {
294 /*
295 * Check if the group ended, which may be either because we processed
296 * all the items (i==nitems), or because the i-th item is not equal to
297 * the preceding one.
298 */
299 if (i == nitems ||
300 multi_sort_compare_dims(0, k - 2, &items[i - 1], &items[i], mss) != 0)
301 {
302 /*
303 * If no violations were found in the group then track the rows of
304 * the group as supporting the functional dependency.
305 */
306 if (n_violations == 0)
308
309 /* Reset counters for the new group */
310 n_violations = 0;
311 group_size = 1;
312 continue;
313 }
314 /* first columns match, but the last one does not (so contradicting) */
315 else if (multi_sort_compare_dim(k - 1, &items[i - 1], &items[i], mss) != 0)
316 n_violations++;
317
318 group_size++;
319 }
320
321 /* Compute the 'degree of validity' as (supporting/total). */
322 return (n_supporting_rows * 1.0 / data->numrows);
323}
324
325/*
326 * detects functional dependencies between groups of columns
327 *
328 * Generates all possible subsets of columns (variations) and computes
329 * the degree of validity for each one. For example when creating statistics
330 * on three columns (a,b,c) there are 9 possible dependencies
331 *
332 * two columns three columns
333 * ----------- -------------
334 * (a) -> b (a,b) -> c
335 * (a) -> c (a,c) -> b
336 * (b) -> a (b,c) -> a
337 * (b) -> c
338 * (c) -> a
339 * (c) -> b
340 */
343{
344 int i,
345 k;
346
347 /* result */
348 MVDependencies *dependencies = NULL;
349 MemoryContext cxt;
350
351 Assert(data->nattnums >= 2);
352
353 /* tracks memory allocated by dependency_degree calls */
355 "dependency_degree cxt",
357
358 /*
359 * We'll try build functional dependencies starting from the smallest ones
360 * covering just 2 columns, to the largest ones, covering all columns
361 * included in the statistics object. We start from the smallest ones
362 * because we want to be able to skip already implied ones.
363 */
364 for (k = 2; k <= data->nattnums; k++)
365 {
366 AttrNumber *dependency; /* array with k elements */
367
368 /* prepare a DependencyGenerator of variation */
370
371 /* generate all possible variations of k values (out of n) */
372 while ((dependency = DependencyGenerator_next(DependencyGenerator)))
373 {
374 double degree;
375 MVDependency *d;
377
378 /* release memory used by dependency degree calculation */
380
381 /* compute how valid the dependency seems */
382 degree = dependency_degree(data, k, dependency);
383
386
387 /*
388 * if the dependency seems entirely invalid, don't store it
389 */
390 if (degree == 0.0)
391 continue;
392
393 d = (MVDependency *) palloc0(offsetof(MVDependency, attributes)
394 + k * sizeof(AttrNumber));
395
396 /* copy the dependency (and keep the indexes into stxkeys) */
397 d->degree = degree;
398 d->nattributes = k;
399 for (i = 0; i < k; i++)
400 d->attributes[i] = data->attnums[dependency[i]];
401
402 /* initialize the list of dependencies */
403 if (dependencies == NULL)
404 {
405 dependencies = palloc0_object(MVDependencies);
406
407 dependencies->magic = STATS_DEPS_MAGIC;
408 dependencies->type = STATS_DEPS_TYPE_BASIC;
409 dependencies->ndeps = 0;
410 }
411
412 dependencies->ndeps++;
413 dependencies = (MVDependencies *) repalloc(dependencies,
415 + dependencies->ndeps * sizeof(MVDependency *));
416
417 dependencies->deps[dependencies->ndeps - 1] = d;
418 }
419
420 /*
421 * we're done with variations of k elements, so free the
422 * DependencyGenerator
423 */
425 }
426
428
429 return dependencies;
430}
431
432
433/*
434 * Serialize list of dependencies into a bytea value.
435 */
436bytea *
438{
439 bytea *output;
440 char *tmp;
441 Size len;
442
443 /* we need to store ndeps, with a number of attributes for each one */
445
446 /* and also include space for the actual attribute numbers and degrees */
447 for (uint32 i = 0; i < dependencies->ndeps; i++)
448 len += SizeOfItem(dependencies->deps[i]->nattributes);
449
450 output = (bytea *) palloc0(len);
452
453 tmp = VARDATA(output);
454
455 /* Store the base struct values (magic, type, ndeps) */
456 memcpy(tmp, &dependencies->magic, sizeof(uint32));
457 tmp += sizeof(uint32);
458 memcpy(tmp, &dependencies->type, sizeof(uint32));
459 tmp += sizeof(uint32);
460 memcpy(tmp, &dependencies->ndeps, sizeof(uint32));
461 tmp += sizeof(uint32);
462
463 /* store number of attributes and attribute numbers for each dependency */
464 for (uint32 i = 0; i < dependencies->ndeps; i++)
465 {
466 MVDependency *d = dependencies->deps[i];
467
468 memcpy(tmp, &d->degree, sizeof(double));
469 tmp += sizeof(double);
470
471 memcpy(tmp, &d->nattributes, sizeof(AttrNumber));
472 tmp += sizeof(AttrNumber);
473
474 memcpy(tmp, d->attributes, sizeof(AttrNumber) * d->nattributes);
475 tmp += sizeof(AttrNumber) * d->nattributes;
476
477 /* protect against overflow */
478 Assert(tmp <= ((char *) output + len));
479 }
480
481 /* make sure we've produced exactly the right amount of data */
482 Assert(tmp == ((char *) output + len));
483
484 return output;
485}
486
487/*
488 * Reads serialized dependencies into MVDependencies structure.
489 */
492{
494 MVDependencies *dependencies;
495 char *tmp;
496
497 if (data == NULL)
498 return NULL;
499
501 elog(ERROR, "invalid MVDependencies size %zu (expected at least %zu)",
503
504 /* read the MVDependencies header */
505 dependencies = palloc0_object(MVDependencies);
506
507 /* initialize pointer to the data part (skip the varlena header) */
508 tmp = VARDATA_ANY(data);
509
510 /* read the header fields and perform basic sanity checks */
511 memcpy(&dependencies->magic, tmp, sizeof(uint32));
512 tmp += sizeof(uint32);
513 memcpy(&dependencies->type, tmp, sizeof(uint32));
514 tmp += sizeof(uint32);
515 memcpy(&dependencies->ndeps, tmp, sizeof(uint32));
516 tmp += sizeof(uint32);
517
518 if (dependencies->magic != STATS_DEPS_MAGIC)
519 elog(ERROR, "invalid dependency magic %d (expected %d)",
520 dependencies->magic, STATS_DEPS_MAGIC);
521
522 if (dependencies->type != STATS_DEPS_TYPE_BASIC)
523 elog(ERROR, "invalid dependency type %d (expected %d)",
524 dependencies->type, STATS_DEPS_TYPE_BASIC);
525
526 if (dependencies->ndeps == 0)
527 elog(ERROR, "invalid zero-length item array in MVDependencies");
528
529 /* what minimum bytea size do we expect for those parameters */
530 min_expected_size = MinSizeOfItems(dependencies->ndeps);
531
533 elog(ERROR, "invalid dependencies size %zu (expected at least %zu)",
535
536 /* allocate space for the MCV items */
537 dependencies = repalloc(dependencies, offsetof(MVDependencies, deps)
538 + (dependencies->ndeps * sizeof(MVDependency *)));
539
540 for (uint32 i = 0; i < dependencies->ndeps; i++)
541 {
542 double degree;
543 AttrNumber k;
544 MVDependency *d;
545
546 /* degree of validity */
547 memcpy(&degree, tmp, sizeof(double));
548 tmp += sizeof(double);
549
550 /* number of attributes */
551 memcpy(&k, tmp, sizeof(AttrNumber));
552 tmp += sizeof(AttrNumber);
553
554 /* is the number of attributes valid? */
555 Assert((k >= 2) && (k <= STATS_MAX_DIMENSIONS));
556
557 /* now that we know the number of attributes, allocate the dependency */
558 d = (MVDependency *) palloc0(offsetof(MVDependency, attributes)
559 + (k * sizeof(AttrNumber)));
560
561 d->degree = degree;
562 d->nattributes = k;
563
564 /* copy attribute numbers */
565 memcpy(d->attributes, tmp, sizeof(AttrNumber) * d->nattributes);
566 tmp += sizeof(AttrNumber) * d->nattributes;
567
568 dependencies->deps[i] = d;
569
570 /* still within the bytea */
571 Assert(tmp <= ((char *) data + VARSIZE_ANY(data)));
572 }
573
574 /* we should have consumed the whole bytea exactly */
575 Assert(tmp == ((char *) data + VARSIZE_ANY(data)));
576
577 return dependencies;
578}
579
580/*
581 * Free allocations of a MVDependencies.
582 */
583void
585{
586 for (uint32 i = 0; i < dependencies->ndeps; i++)
587 pfree(dependencies->deps[i]);
588 pfree(dependencies);
589}
590
591/*
592 * Validate a set of MVDependencies against the extended statistics object
593 * definition.
594 *
595 * Every MVDependencies must be checked to ensure that the attnums in the
596 * attributes list correspond to attnums/expressions defined by the
597 * extended statistics object.
598 *
599 * Positive attnums are attributes which must be found in the stxkeys, while
600 * negative attnums correspond to an expression number, no attribute number
601 * can be below (0 - numexprs).
602 */
603bool
605 const int2vector *stxkeys,
606 int numexprs, int elevel)
607{
609
610 /* Scan through each dependency entry */
611 for (uint32 i = 0; i < dependencies->ndeps; i++)
612 {
613 const MVDependency *dep = dependencies->deps[i];
614
615 /*
616 * Cross-check each attribute in a dependency entry with the extended
617 * stats object definition.
618 */
619 for (int j = 0; j < dep->nattributes; j++)
620 {
622 bool ok = false;
623
624 if (attnum > 0)
625 {
626 /* attribute number in stxkeys */
627 for (int k = 0; k < stxkeys->dim1; k++)
628 {
629 if (attnum == stxkeys->values[k])
630 {
631 ok = true;
632 break;
633 }
634 }
635 }
636 else if ((attnum < 0) && (attnum >= attnum_expr_lowbound))
637 {
638 /* attribute number for an expression */
639 ok = true;
640 }
641
642 if (!ok)
643 {
644 ereport(elevel,
646 errmsg("could not validate \"%s\" object: invalid attribute number %d found",
647 "pg_dependencies", attnum)));
648 return false;
649 }
650 }
651 }
652
653 return true;
654}
655
656/*
657 * dependency_is_fully_matched
658 * checks that a functional dependency is fully matched given clauses on
659 * attributes (assuming the clauses are suitable equality clauses)
660 */
661static bool
663{
664 int j;
665
666 /*
667 * Check that the dependency actually is fully covered by clauses. We have
668 * to translate all attribute numbers, as those are referenced
669 */
670 for (j = 0; j < dependency->nattributes; j++)
671 {
672 int attnum = dependency->attributes[j];
673
674 if (!bms_is_member(attnum, attnums))
675 return false;
676 }
677
678 return true;
679}
680
681/*
682 * statext_dependencies_load
683 * Load the functional dependencies for the indicated pg_statistic_ext tuple
684 */
687{
689 bool isnull;
690 Datum deps;
691 HeapTuple htup;
692
695 BoolGetDatum(inh));
696 if (!HeapTupleIsValid(htup))
697 elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
698
701 if (isnull)
702 elog(ERROR,
703 "requested statistics kind \"%c\" is not yet built for statistics object %u",
705
707
708 ReleaseSysCache(htup);
709
710 return result;
711}
712
713/*
714 * dependency_is_compatible_clause
715 * Determines if the clause is compatible with functional dependencies
716 *
717 * Only clauses that have the form of equality to a pseudoconstant, or can be
718 * interpreted that way, are currently accepted. Furthermore the variable
719 * part of the clause must be a simple Var belonging to the specified
720 * relation, whose attribute number we return in *attnum on success.
721 */
722static bool
724{
725 Var *var;
727
728 if (IsA(clause, RestrictInfo))
729 {
730 RestrictInfo *rinfo = (RestrictInfo *) clause;
731
732 /* Pseudoconstants are not interesting (they couldn't contain a Var) */
733 if (rinfo->pseudoconstant)
734 return false;
735
736 /* Clauses referencing multiple, or no, varnos are incompatible */
737 if (bms_membership(rinfo->clause_relids) != BMS_SINGLETON)
738 return false;
739
740 clause = (Node *) rinfo->clause;
741 }
742
743 if (is_opclause(clause))
744 {
745 /* If it's an opclause, check for Var = Const or Const = Var. */
746 OpExpr *expr = (OpExpr *) clause;
747
748 /* Only expressions with two arguments are candidates. */
749 if (list_length(expr->args) != 2)
750 return false;
751
752 /* Make sure non-selected argument is a pseudoconstant. */
754 clause_expr = linitial(expr->args);
755 else if (is_pseudo_constant_clause(linitial(expr->args)))
756 clause_expr = lsecond(expr->args);
757 else
758 return false;
759
760 /*
761 * If it's not an "=" operator, just ignore the clause, as it's not
762 * compatible with functional dependencies.
763 *
764 * This uses the function for estimating selectivity, not the operator
765 * directly (a bit awkward, but well ...).
766 *
767 * XXX this is pretty dubious; probably it'd be better to check btree
768 * or hash opclass membership, so as not to be fooled by custom
769 * selectivity functions, and to be more consistent with decisions
770 * elsewhere in the planner.
771 */
772 if (get_oprrest(expr->opno) != F_EQSEL)
773 return false;
774
775 /* OK to proceed with checking "var" */
776 }
777 else if (IsA(clause, ScalarArrayOpExpr))
778 {
779 /* If it's a scalar array operator, check for Var IN Const. */
780 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) clause;
781
782 /*
783 * Reject ALL() variant, we only care about ANY/IN.
784 *
785 * XXX Maybe we should check if all the values are the same, and allow
786 * ALL in that case? Doesn't seem very practical, though.
787 */
788 if (!expr->useOr)
789 return false;
790
791 /* Only expressions with two arguments are candidates. */
792 if (list_length(expr->args) != 2)
793 return false;
794
795 /*
796 * We know it's always (Var IN Const), so we assume the var is the
797 * first argument, and pseudoconstant is the second one.
798 */
800 return false;
801
802 clause_expr = linitial(expr->args);
803
804 /*
805 * If it's not an "=" operator, just ignore the clause, as it's not
806 * compatible with functional dependencies. The operator is identified
807 * simply by looking at which function it uses to estimate
808 * selectivity. That's a bit strange, but it's what other similar
809 * places do.
810 */
811 if (get_oprrest(expr->opno) != F_EQSEL)
812 return false;
813
814 /* OK to proceed with checking "var" */
815 }
816 else if (is_orclause(clause))
817 {
818 BoolExpr *bool_expr = (BoolExpr *) clause;
819 ListCell *lc;
820
821 /* start with no attribute number */
823
824 foreach(lc, bool_expr->args)
825 {
827
828 /*
829 * Had we found incompatible clause in the arguments, treat the
830 * whole clause as incompatible.
831 */
833 relid, &clause_attnum))
834 return false;
835
838
839 /* ensure all the variables are the same (same attnum) */
840 if (*attnum != clause_attnum)
841 return false;
842 }
843
844 /* the Var is already checked by the recursive call */
845 return true;
846 }
847 else if (is_notclause(clause))
848 {
849 /*
850 * "NOT x" can be interpreted as "x = false", so get the argument and
851 * proceed with seeing if it's a suitable Var.
852 */
853 clause_expr = (Node *) get_notclausearg(clause);
854 }
855 else
856 {
857 /*
858 * A boolean expression "x" can be interpreted as "x = true", so
859 * proceed with seeing if it's a suitable Var.
860 */
861 clause_expr = clause;
862 }
863
864 /*
865 * We may ignore any RelabelType node above the operand. (There won't be
866 * more than one, since eval_const_expressions has been applied already.)
867 */
869 clause_expr = (Node *) ((RelabelType *) clause_expr)->arg;
870
871 /* We only support plain Vars for now */
872 if (!IsA(clause_expr, Var))
873 return false;
874
875 /* OK, we know we have a Var */
876 var = (Var *) clause_expr;
877
878 /* Ensure Var is from the correct relation */
879 if (var->varno != relid)
880 return false;
881
882 /* We also better ensure the Var is from the current level */
883 if (var->varlevelsup != 0)
884 return false;
885
886 /* Also ignore system attributes (we don't allow stats on those) */
888 return false;
889
890 *attnum = var->varattno;
891 return true;
892}
893
894/*
895 * find_strongest_dependency
896 * find the strongest dependency on the attributes
897 *
898 * When applying functional dependencies, we start with the strongest
899 * dependencies. That is, we select the dependency that:
900 *
901 * (a) has all attributes covered by equality clauses
902 *
903 * (b) has the most attributes
904 *
905 * (c) has the highest degree of validity
906 *
907 * This guarantees that we eliminate the most redundant conditions first
908 * (see the comment in dependencies_clauselist_selectivity).
909 */
910static MVDependency *
911find_strongest_dependency(MVDependencies **dependencies, int ndependencies,
912 Bitmapset *attnums)
913{
915
916 /* number of attnums in clauses */
917 int nattnums = bms_num_members(attnums);
918
919 /*
920 * Iterate over the MVDependency items and find the strongest one from the
921 * fully-matched dependencies. We do the cheap checks first, before
922 * matching it against the attnums.
923 */
924 for (int i = 0; i < ndependencies; i++)
925 {
926 for (uint32 j = 0; j < dependencies[i]->ndeps; j++)
927 {
928 MVDependency *dependency = dependencies[i]->deps[j];
929
930 /*
931 * Skip dependencies referencing more attributes than available
932 * clauses, as those can't be fully matched.
933 */
934 if (dependency->nattributes > nattnums)
935 continue;
936
937 if (strongest)
938 {
939 /* skip dependencies on fewer attributes than the strongest. */
940 if (dependency->nattributes < strongest->nattributes)
941 continue;
942
943 /* also skip weaker dependencies when attribute count matches */
944 if (strongest->nattributes == dependency->nattributes &&
945 strongest->degree > dependency->degree)
946 continue;
947 }
948
949 /*
950 * this dependency is stronger, but we must still check that it's
951 * fully matched to these attnums. We perform this check last as
952 * it's slightly more expensive than the previous checks.
953 */
954 if (dependency_is_fully_matched(dependency, attnums))
955 strongest = dependency; /* save new best match */
956 }
957 }
958
959 return strongest;
960}
961
962/*
963 * clauselist_apply_dependencies
964 * Apply the specified functional dependencies to a list of clauses and
965 * return the estimated selectivity of the clauses that are compatible
966 * with any of the given dependencies.
967 *
968 * This will estimate all not-already-estimated clauses that are compatible
969 * with functional dependencies, and which have an attribute mentioned by any
970 * of the given dependencies (either as an implying or implied attribute).
971 *
972 * Given (lists of) clauses on attributes (a,b) and a functional dependency
973 * (a=>b), the per-column selectivities P(a) and P(b) are notionally combined
974 * using the formula
975 *
976 * P(a,b) = f * P(a) + (1-f) * P(a) * P(b)
977 *
978 * where 'f' is the degree of dependency. This reflects the fact that we
979 * expect a fraction f of all rows to be consistent with the dependency
980 * (a=>b), and so have a selectivity of P(a), while the remaining rows are
981 * treated as independent.
982 *
983 * In practice, we use a slightly modified version of this formula, which uses
984 * a selectivity of Min(P(a), P(b)) for the dependent rows, since the result
985 * should obviously not exceed either column's individual selectivity. I.e.,
986 * we actually combine selectivities using the formula
987 *
988 * P(a,b) = f * Min(P(a), P(b)) + (1-f) * P(a) * P(b)
989 *
990 * This can make quite a difference if the specific values matching the
991 * clauses are not consistent with the functional dependency.
992 */
993static Selectivity
995 int varRelid, JoinType jointype,
996 SpecialJoinInfo *sjinfo,
997 MVDependency **dependencies, int ndependencies,
1000{
1001 Bitmapset *attnums;
1002 int i;
1003 int j;
1004 int nattrs;
1006 int attidx;
1007 int listidx;
1008 ListCell *l;
1010
1011 /*
1012 * Extract the attnums of all implying and implied attributes from all the
1013 * given dependencies. Each of these attributes is expected to have at
1014 * least 1 not-already-estimated compatible clause that we will estimate
1015 * here.
1016 */
1017 attnums = NULL;
1018 for (i = 0; i < ndependencies; i++)
1019 {
1020 for (j = 0; j < dependencies[i]->nattributes; j++)
1021 {
1022 AttrNumber attnum = dependencies[i]->attributes[j];
1023
1024 attnums = bms_add_member(attnums, attnum);
1025 }
1026 }
1027
1028 /*
1029 * Compute per-column selectivity estimates for each of these attributes,
1030 * and mark all the corresponding clauses as estimated.
1031 */
1032 nattrs = bms_num_members(attnums);
1034
1035 attidx = 0;
1036 i = -1;
1037 while ((i = bms_next_member(attnums, i)) >= 0)
1038 {
1041
1042 listidx = -1;
1043 foreach(l, clauses)
1044 {
1045 Node *clause = (Node *) lfirst(l);
1046
1047 listidx++;
1048 if (list_attnums[listidx] == i)
1049 {
1052 }
1053 }
1054
1056 jointype, sjinfo, false);
1057 attr_sel[attidx++] = simple_sel;
1058 }
1059
1060 /*
1061 * Now combine these selectivities using the dependency information. For
1062 * chains of dependencies such as a -> b -> c, the b -> c dependency will
1063 * come before the a -> b dependency in the array, so we traverse the
1064 * array backwards to ensure such chains are computed in the right order.
1065 *
1066 * As explained above, pairs of selectivities are combined using the
1067 * formula
1068 *
1069 * P(a,b) = f * Min(P(a), P(b)) + (1-f) * P(a) * P(b)
1070 *
1071 * to ensure that the combined selectivity is never greater than either
1072 * individual selectivity.
1073 *
1074 * Where multiple dependencies apply (e.g., a -> b -> c), we use
1075 * conditional probabilities to compute the overall result as follows:
1076 *
1077 * P(a,b,c) = P(c|a,b) * P(a,b) = P(c|a,b) * P(b|a) * P(a)
1078 *
1079 * so we replace the selectivities of all implied attributes with
1080 * conditional probabilities, that are conditional on all their implying
1081 * attributes. The selectivities of all other non-implied attributes are
1082 * left as they are.
1083 */
1084 for (i = ndependencies - 1; i >= 0; i--)
1085 {
1086 MVDependency *dependency = dependencies[i];
1089 double f;
1090
1091 /* Selectivity of all the implying attributes */
1092 s1 = 1.0;
1093 for (j = 0; j < dependency->nattributes - 1; j++)
1094 {
1095 attnum = dependency->attributes[j];
1096 attidx = bms_member_index(attnums, attnum);
1097 s1 *= attr_sel[attidx];
1098 }
1099
1100 /* Original selectivity of the implied attribute */
1101 attnum = dependency->attributes[j];
1102 attidx = bms_member_index(attnums, attnum);
1103 s2 = attr_sel[attidx];
1104
1105 /*
1106 * Replace s2 with the conditional probability s2 given s1, computed
1107 * using the formula P(b|a) = P(a,b) / P(a), which simplifies to
1108 *
1109 * P(b|a) = f * Min(P(a), P(b)) / P(a) + (1-f) * P(b)
1110 *
1111 * where P(a) = s1, the selectivity of the implying attributes, and
1112 * P(b) = s2, the selectivity of the implied attribute.
1113 */
1114 f = dependency->degree;
1115
1116 if (s1 <= s2)
1117 attr_sel[attidx] = f + (1 - f) * s2;
1118 else
1119 attr_sel[attidx] = f * s2 / s1 + (1 - f) * s2;
1120 }
1121
1122 /*
1123 * The overall selectivity of all the clauses on all these attributes is
1124 * then the product of all the original (non-implied) probabilities and
1125 * the new conditional (implied) probabilities.
1126 */
1127 s1 = 1.0;
1128 for (i = 0; i < nattrs; i++)
1129 s1 *= attr_sel[i];
1130
1132
1133 pfree(attr_sel);
1134 bms_free(attnums);
1135
1136 return s1;
1137}
1138
1139/*
1140 * dependency_is_compatible_expression
1141 * Determines if the expression is compatible with functional dependencies
1142 *
1143 * Similar to dependency_is_compatible_clause, but doesn't enforce that the
1144 * expression is a simple Var. On success, return the matching statistics
1145 * expression into *expr.
1146 */
1147static bool
1148dependency_is_compatible_expression(Node *clause, Index relid, List *statlist, Node **expr)
1149{
1150 ListCell *lc,
1151 *lc2;
1153
1154 if (IsA(clause, RestrictInfo))
1155 {
1156 RestrictInfo *rinfo = (RestrictInfo *) clause;
1157
1158 /* Pseudoconstants are not interesting (they couldn't contain a Var) */
1159 if (rinfo->pseudoconstant)
1160 return false;
1161
1162 /* Clauses referencing multiple, or no, varnos are incompatible */
1163 if (bms_membership(rinfo->clause_relids) != BMS_SINGLETON)
1164 return false;
1165
1166 clause = (Node *) rinfo->clause;
1167 }
1168
1169 if (is_opclause(clause))
1170 {
1171 /* If it's an opclause, check for Var = Const or Const = Var. */
1172 OpExpr *expr = (OpExpr *) clause;
1173
1174 /* Only expressions with two arguments are candidates. */
1175 if (list_length(expr->args) != 2)
1176 return false;
1177
1178 /* Make sure non-selected argument is a pseudoconstant. */
1180 clause_expr = linitial(expr->args);
1181 else if (is_pseudo_constant_clause(linitial(expr->args)))
1182 clause_expr = lsecond(expr->args);
1183 else
1184 return false;
1185
1186 /*
1187 * If it's not an "=" operator, just ignore the clause, as it's not
1188 * compatible with functional dependencies.
1189 *
1190 * This uses the function for estimating selectivity, not the operator
1191 * directly (a bit awkward, but well ...).
1192 *
1193 * XXX this is pretty dubious; probably it'd be better to check btree
1194 * or hash opclass membership, so as not to be fooled by custom
1195 * selectivity functions, and to be more consistent with decisions
1196 * elsewhere in the planner.
1197 */
1198 if (get_oprrest(expr->opno) != F_EQSEL)
1199 return false;
1200
1201 /* OK to proceed with checking "var" */
1202 }
1203 else if (IsA(clause, ScalarArrayOpExpr))
1204 {
1205 /* If it's a scalar array operator, check for Var IN Const. */
1206 ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) clause;
1207
1208 /*
1209 * Reject ALL() variant, we only care about ANY/IN.
1210 *
1211 * FIXME Maybe we should check if all the values are the same, and
1212 * allow ALL in that case? Doesn't seem very practical, though.
1213 */
1214 if (!expr->useOr)
1215 return false;
1216
1217 /* Only expressions with two arguments are candidates. */
1218 if (list_length(expr->args) != 2)
1219 return false;
1220
1221 /*
1222 * We know it's always (Var IN Const), so we assume the var is the
1223 * first argument, and pseudoconstant is the second one.
1224 */
1226 return false;
1227
1228 clause_expr = linitial(expr->args);
1229
1230 /*
1231 * If it's not an "=" operator, just ignore the clause, as it's not
1232 * compatible with functional dependencies. The operator is identified
1233 * simply by looking at which function it uses to estimate
1234 * selectivity. That's a bit strange, but it's what other similar
1235 * places do.
1236 */
1237 if (get_oprrest(expr->opno) != F_EQSEL)
1238 return false;
1239
1240 /* OK to proceed with checking "var" */
1241 }
1242 else if (is_orclause(clause))
1243 {
1244 BoolExpr *bool_expr = (BoolExpr *) clause;
1245
1246 /* start with no expression (we'll use the first match) */
1247 *expr = NULL;
1248
1249 foreach(lc, bool_expr->args)
1250 {
1251 Node *or_expr = NULL;
1252
1253 /*
1254 * Had we found incompatible expression in the arguments, treat
1255 * the whole expression as incompatible.
1256 */
1258 statlist, &or_expr))
1259 return false;
1260
1261 if (*expr == NULL)
1262 *expr = or_expr;
1263
1264 /* ensure all the expressions are the same */
1265 if (!equal(or_expr, *expr))
1266 return false;
1267 }
1268
1269 /* the expression is already checked by the recursive call */
1270 return true;
1271 }
1272 else if (is_notclause(clause))
1273 {
1274 /*
1275 * "NOT x" can be interpreted as "x = false", so get the argument and
1276 * proceed with seeing if it's a suitable Var.
1277 */
1278 clause_expr = (Node *) get_notclausearg(clause);
1279 }
1280 else
1281 {
1282 /*
1283 * A boolean expression "x" can be interpreted as "x = true", so
1284 * proceed with seeing if it's a suitable Var.
1285 */
1286 clause_expr = clause;
1287 }
1288
1289 /*
1290 * We may ignore any RelabelType node above the operand. (There won't be
1291 * more than one, since eval_const_expressions has been applied already.)
1292 */
1294 clause_expr = (Node *) ((RelabelType *) clause_expr)->arg;
1295
1296 /*
1297 * Search for a matching statistics expression.
1298 */
1299 foreach(lc, statlist)
1300 {
1302
1303 /* ignore stats without dependencies */
1304 if (info->kind != STATS_EXT_DEPENDENCIES)
1305 continue;
1306
1307 foreach(lc2, info->exprs)
1308 {
1309 Node *stat_expr = (Node *) lfirst(lc2);
1310
1312 {
1313 *expr = stat_expr;
1314 return true;
1315 }
1316 }
1317 }
1318
1319 return false;
1320}
1321
1322/*
1323 * dependencies_clauselist_selectivity
1324 * Return the estimated selectivity of (a subset of) the given clauses
1325 * using functional dependency statistics, or 1.0 if no useful functional
1326 * dependency statistic exists.
1327 *
1328 * 'estimatedclauses' is an input/output argument that gets a bit set
1329 * corresponding to the (zero-based) list index of each clause that is included
1330 * in the estimated selectivity.
1331 *
1332 * Given equality clauses on attributes (a,b) we find the strongest dependency
1333 * between them, i.e. either (a=>b) or (b=>a). Assuming (a=>b) is the selected
1334 * dependency, we then combine the per-clause selectivities using the formula
1335 *
1336 * P(a,b) = f * P(a) + (1-f) * P(a) * P(b)
1337 *
1338 * where 'f' is the degree of the dependency. (Actually we use a slightly
1339 * modified version of this formula -- see clauselist_apply_dependencies()).
1340 *
1341 * With clauses on more than two attributes, the dependencies are applied
1342 * recursively, starting with the widest/strongest dependencies. For example
1343 * P(a,b,c) is first split like this:
1344 *
1345 * P(a,b,c) = f * P(a,b) + (1-f) * P(a,b) * P(c)
1346 *
1347 * assuming (a,b=>c) is the strongest dependency.
1348 */
1351 List *clauses,
1352 int varRelid,
1353 JoinType jointype,
1354 SpecialJoinInfo *sjinfo,
1355 RelOptInfo *rel,
1357{
1358 Selectivity s1 = 1.0;
1359 ListCell *l;
1362 int listidx;
1365 int total_ndeps;
1366 MVDependency **dependencies;
1367 int ndependencies;
1370
1371 /* unique expressions */
1373 int unique_exprs_cnt;
1374
1375 /* check if there's any stats that might be useful for us. */
1377 return 1.0;
1378
1380
1381 /*
1382 * We allocate space as if every clause was a unique expression, although
1383 * that's probably overkill. Some will be simple column references that
1384 * we'll translate to attnums, and there might be duplicates. But it's
1385 * easier and cheaper to just do one allocation than repalloc later.
1386 */
1388 unique_exprs_cnt = 0;
1389
1390 /*
1391 * Pre-process the clauses list to extract the attnums seen in each item.
1392 * We need to determine if there's any clauses which will be useful for
1393 * dependency selectivity estimations. Along the way we'll record all of
1394 * the attnums for each clause in a list which we'll reference later so we
1395 * don't need to repeat the same work again. We'll also keep track of all
1396 * attnums seen.
1397 *
1398 * We also skip clauses that we already estimated using different types of
1399 * statistics (we treat them as incompatible).
1400 *
1401 * To handle expressions, we assign them negative attnums, as if it was a
1402 * system attribute (this is fine, as we only allow extended stats on user
1403 * attributes). And then we offset everything by the number of
1404 * expressions, so that we can store the values in a bitmapset.
1405 */
1406 listidx = 0;
1407 foreach(l, clauses)
1408 {
1409 Node *clause = (Node *) lfirst(l);
1411 Node *expr = NULL;
1412
1413 /* ignore clause by default */
1415
1417 {
1418 /*
1419 * If it's a simple column reference, just extract the attnum. If
1420 * it's an expression, assign a negative attnum as if it was a
1421 * system attribute.
1422 */
1423 if (dependency_is_compatible_clause(clause, rel->relid, &attnum))
1424 {
1426 }
1427 else if (dependency_is_compatible_expression(clause, rel->relid,
1428 rel->statlist,
1429 &expr))
1430 {
1431 /* special attnum assigned to this expression */
1433
1434 Assert(expr != NULL);
1435
1436 /* If the expression is duplicate, use the same attnum. */
1437 for (int i = 0; i < unique_exprs_cnt; i++)
1438 {
1439 if (equal(unique_exprs[i], expr))
1440 {
1441 /* negative attribute number to expression */
1442 attnum = -(i + 1);
1443 break;
1444 }
1445 }
1446
1447 /* not found in the list, so add it */
1449 {
1451
1452 /* after incrementing the value, to get -1, -2, ... */
1454 }
1455
1456 /* remember which attnum was assigned to this clause */
1458 }
1459 }
1460
1461 listidx++;
1462 }
1463
1464 Assert(listidx == list_length(clauses));
1465
1466 /*
1467 * How much we need to offset the attnums? If there are no expressions,
1468 * then no offset is needed. Otherwise we need to offset enough for the
1469 * lowest value (-unique_exprs_cnt) to become 1.
1470 */
1471 if (unique_exprs_cnt > 0)
1473 else
1474 attnum_offset = 0;
1475
1476 /*
1477 * Now that we know how many expressions there are, we can offset the
1478 * values just enough to build the bitmapset.
1479 */
1480 for (int i = 0; i < list_length(clauses); i++)
1481 {
1483
1484 /* ignore incompatible or already estimated clauses */
1486 continue;
1487
1488 /* make sure the attnum is in the expected range */
1491
1492 /* make sure the attnum is positive (valid AttrNumber) */
1494
1495 /*
1496 * Either it's a regular attribute, or it's an expression, in which
1497 * case we must not have seen it before (expressions are unique).
1498 *
1499 * XXX Check whether it's a regular attribute has to be done using the
1500 * original attnum, while the second check has to use the value with
1501 * an offset.
1502 */
1505
1506 /*
1507 * Remember the offset attnum, both for attributes and expressions.
1508 * We'll pass list_attnums to clauselist_apply_dependencies, which
1509 * uses it to identify clauses in a bitmap. We could also pass the
1510 * offset, but this is more convenient.
1511 */
1513
1515 }
1516
1517 /*
1518 * If there's not at least two distinct attnums and expressions, then
1519 * reject the whole list of clauses. We must return 1.0 so the calling
1520 * function's selectivity is unaffected.
1521 */
1523 {
1526 return 1.0;
1527 }
1528
1529 /*
1530 * Load all functional dependencies matching at least two parameters. We
1531 * can simply consider all dependencies at once, without having to search
1532 * for the best statistics object.
1533 *
1534 * To not waste cycles and memory, we deserialize dependencies only for
1535 * statistics that match at least two attributes. The array is allocated
1536 * with the assumption that all objects match - we could grow the array to
1537 * make it just the right size, but it's likely wasteful anyway thanks to
1538 * moving the freed chunks to freelists etc.
1539 */
1542 total_ndeps = 0;
1543
1544 foreach(l, rel->statlist)
1545 {
1547 int nmatched;
1548 int nexprs;
1549 int k;
1550 MVDependencies *deps;
1551
1552 /* skip statistics that are not of the correct type */
1553 if (stat->kind != STATS_EXT_DEPENDENCIES)
1554 continue;
1555
1556 /* skip statistics with mismatching stxdinherit value */
1557 if (stat->inherit != rte->inh)
1558 continue;
1559
1560 /*
1561 * Count matching attributes - we have to undo the attnum offsets. The
1562 * input attribute numbers are not offset (expressions are not
1563 * included in stat->keys, so it's not necessary). But we need to
1564 * offset it before checking against clauses_attnums.
1565 */
1566 nmatched = 0;
1567 k = -1;
1568 while ((k = bms_next_member(stat->keys, k)) >= 0)
1569 {
1571
1572 /* skip expressions */
1574 continue;
1575
1576 /* apply the same offset as above */
1578
1580 nmatched++;
1581 }
1582
1583 /* count matching expressions */
1584 nexprs = 0;
1585 for (int i = 0; i < unique_exprs_cnt; i++)
1586 {
1587 ListCell *lc;
1588
1589 foreach(lc, stat->exprs)
1590 {
1591 Node *stat_expr = (Node *) lfirst(lc);
1592
1593 /* try to match it */
1595 nexprs++;
1596 }
1597 }
1598
1599 /*
1600 * Skip objects matching fewer than two attributes/expressions from
1601 * clauses.
1602 */
1603 if (nmatched + nexprs < 2)
1604 continue;
1605
1606 deps = statext_dependencies_load(stat->statOid, rte->inh);
1607
1608 /*
1609 * The expressions may be represented by different attnums in the
1610 * stats, we need to remap them to be consistent with the clauses.
1611 * That will make the later steps (e.g. picking the strongest item and
1612 * so on) much simpler and cheaper, because it won't need to care
1613 * about the offset at all.
1614 *
1615 * When we're at it, we can ignore dependencies that are not fully
1616 * matched by clauses (i.e. referencing attributes or expressions that
1617 * are not in the clauses).
1618 *
1619 * We have to do this for all statistics, as long as there are any
1620 * expressions - we need to shift the attnums in all dependencies.
1621 *
1622 * XXX Maybe we should do this always, because it also eliminates some
1623 * of the dependencies early. It might be cheaper than having to walk
1624 * the longer list in find_strongest_dependency later, especially as
1625 * we need to do that repeatedly?
1626 *
1627 * XXX We have to do this even when there are no expressions in
1628 * clauses, otherwise find_strongest_dependency may fail for stats
1629 * with expressions (due to lookup of negative value in bitmap). So we
1630 * need to at least filter out those dependencies. Maybe we could do
1631 * it in a cheaper way (if there are no expr clauses, we can just
1632 * discard all negative attnums without any lookups).
1633 */
1634 if (unique_exprs_cnt > 0 || stat->exprs != NIL)
1635 {
1636 uint32 ndeps = 0;
1637
1638 for (uint32 i = 0; i < deps->ndeps; i++)
1639 {
1640 bool skip = false;
1641 MVDependency *dep = deps->deps[i];
1642
1643 for (int j = 0; j < dep->nattributes; j++)
1644 {
1645 int idx;
1646 Node *expr;
1649
1650 /* undo the per-statistics offset */
1651 attnum = dep->attributes[j];
1652
1653 /*
1654 * For regular attributes we can simply check if it
1655 * matches any clause. If there's no matching clause, we
1656 * can just ignore it. We need to offset the attnum
1657 * though.
1658 */
1660 {
1661 dep->attributes[j] = attnum + attnum_offset;
1662
1663 if (!bms_is_member(dep->attributes[j], clauses_attnums))
1664 {
1665 skip = true;
1666 break;
1667 }
1668
1669 continue;
1670 }
1671
1672 /*
1673 * the attnum should be a valid system attnum (-1, -2,
1674 * ...)
1675 */
1677
1678 /*
1679 * For expressions, we need to do two translations. First
1680 * we have to translate the negative attnum to index in
1681 * the list of expressions (in the statistics object).
1682 * Then we need to see if there's a matching clause. The
1683 * index of the unique expression determines the attnum
1684 * (and we offset it).
1685 */
1686 idx = -(1 + attnum);
1687
1688 /* Is the expression index is valid? */
1689 Assert((idx >= 0) && (idx < list_length(stat->exprs)));
1690
1691 expr = (Node *) list_nth(stat->exprs, idx);
1692
1693 /* try to find the expression in the unique list */
1694 for (int m = 0; m < unique_exprs_cnt; m++)
1695 {
1696 /*
1697 * found a matching unique expression, use the attnum
1698 * (derived from index of the unique expression)
1699 */
1700 if (equal(unique_exprs[m], expr))
1701 {
1702 unique_attnum = -(m + 1) + attnum_offset;
1703 break;
1704 }
1705 }
1706
1707 /*
1708 * Found no matching expression, so we can simply skip
1709 * this dependency, because there's no chance it will be
1710 * fully covered.
1711 */
1713 {
1714 skip = true;
1715 break;
1716 }
1717
1718 /* otherwise remap it to the new attnum */
1719 dep->attributes[j] = unique_attnum;
1720 }
1721
1722 /* if found a matching dependency, keep it */
1723 if (!skip)
1724 {
1725 /* maybe we've skipped something earlier, so move it */
1726 if (ndeps != i)
1727 deps->deps[ndeps] = deps->deps[i];
1728
1729 ndeps++;
1730 }
1731 }
1732
1733 deps->ndeps = ndeps;
1734 }
1735
1736 /*
1737 * It's possible we've removed all dependencies, in which case we
1738 * don't bother adding it to the list.
1739 */
1740 if (deps->ndeps > 0)
1741 {
1743 total_ndeps += deps->ndeps;
1745 }
1746 }
1747
1748 /* if no matching stats could be found then we've nothing to do */
1749 if (nfunc_dependencies == 0)
1750 {
1755 return 1.0;
1756 }
1757
1758 /*
1759 * Work out which dependencies we can apply, starting with the
1760 * widest/strongest ones, and proceeding to smaller/weaker ones.
1761 */
1762 dependencies = palloc_array(MVDependency *, total_ndeps);
1763 ndependencies = 0;
1764
1765 while (true)
1766 {
1767 MVDependency *dependency;
1769
1770 /* the widest/strongest dependency, fully matched by clauses */
1774 if (!dependency)
1775 break;
1776
1777 dependencies[ndependencies++] = dependency;
1778
1779 /* Ignore dependencies using this implied attribute in later loops */
1780 attnum = dependency->attributes[dependency->nattributes - 1];
1782 }
1783
1784 /*
1785 * If we found applicable dependencies, use them to estimate all
1786 * compatible clauses on attributes that they refer to.
1787 */
1788 if (ndependencies != 0)
1789 s1 = clauselist_apply_dependencies(root, clauses, varRelid, jointype,
1790 sjinfo, dependencies, ndependencies,
1792
1793 /* free deserialized functional dependencies (and then the array) */
1794 for (int i = 0; i < nfunc_dependencies; i++)
1796
1797 pfree(dependencies);
1802
1803 return s1;
1804}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:263
int16 AttrNumber
Definition attnum.h:21
#define AttributeNumberIsValid(attributeNumber)
Definition attnum.h:34
#define AttrNumberIsForUserDefinedAttr(attributeNumber)
Definition attnum.h:41
#define InvalidAttrNumber
Definition attnum.h:23
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1425
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:987
void bms_free(Bitmapset *a)
Definition bitmapset.c:240
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:879
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:645
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:934
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:900
int bms_member_index(Bitmapset *a, int x)
Definition bitmapset.c:674
@ BMS_SINGLETON
Definition bitmapset.h:72
@ BMS_MULTIPLE
Definition bitmapset.h:73
#define VARHDRSZ
Definition c.h:840
#define Assert(condition)
Definition c.h:1002
uint32_t uint32
Definition c.h:683
unsigned int Index
Definition c.h:757
size_t Size
Definition c.h:748
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
bool is_pseudo_constant_clause(Node *clause)
Definition clauses.c:2349
Selectivity clauselist_selectivity_ext(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, bool use_extended_stats)
Definition clausesel.c:117
static void generate_dependencies(DependencyGenerator state)
#define SizeOfHeader
MVDependencies * statext_dependencies_deserialize(bytea *data)
MVDependencies * statext_dependencies_load(Oid mvoid, bool inh)
static bool dependency_is_compatible_expression(Node *clause, Index relid, List *statlist, Node **expr)
static AttrNumber * DependencyGenerator_next(DependencyGenerator state)
MVDependencies * statext_dependencies_build(StatsBuildData *data)
static bool dependency_is_compatible_clause(Node *clause, Index relid, AttrNumber *attnum)
bool statext_dependencies_validate(const MVDependencies *dependencies, const int2vector *stxkeys, int numexprs, int elevel)
static bool dependency_is_fully_matched(MVDependency *dependency, Bitmapset *attnums)
bytea * statext_dependencies_serialize(MVDependencies *dependencies)
void statext_dependencies_free(MVDependencies *dependencies)
static void DependencyGenerator_free(DependencyGenerator state)
static Selectivity clauselist_apply_dependencies(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, MVDependency **dependencies, int ndependencies, AttrNumber *list_attnums, Bitmapset **estimatedclauses)
static DependencyGenerator DependencyGenerator_init(int n, int k)
#define SizeOfItem(natts)
Selectivity dependencies_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
static double dependency_degree(StatsBuildData *data, int k, AttrNumber *dependency)
static void generate_dependencies_recurse(DependencyGenerator state, int index, AttrNumber start, AttrNumber *current)
#define MinSizeOfItems(ndeps)
DependencyGeneratorData * DependencyGenerator
static MVDependency * find_strongest_dependency(MVDependencies **dependencies, int ndependencies, Bitmapset *attnums)
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
bool has_stats_of_kind(List *stats, char requiredkind)
int multi_sort_compare_dims(int start, int end, const SortItem *a, const SortItem *b, MultiSortSupport mss)
int multi_sort_compare_dim(int dim, const SortItem *a, const SortItem *b, MultiSortSupport mss)
SortItem * build_sorted_items(StatsBuildData *data, int *nitems, MultiSortSupport mss, int numattrs, AttrNumber *attnums)
MultiSortSupport multi_sort_init(int ndims)
void multi_sort_add_dimension(MultiSortSupport mss, int sortdim, Oid oper, Oid collation)
#define palloc_array(type, count)
Definition fe_memutils.h:91
#define palloc0_array(type, count)
Definition fe_memutils.h:92
#define palloc0_object(type)
Definition fe_memutils.h:90
#define DatumGetByteaPP(X)
Definition fmgr.h:292
return str start
#define HeapTupleIsValid(tuple)
Definition htup.h:78
#define MaxHeapAttributeNumber
#define nitems(x)
Definition indent.h:31
FILE * output
int j
Definition isn.c:78
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
RegProcedure get_oprrest(Oid opno)
Definition lsyscache.c:1871
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:406
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc0(Size size)
Definition mcxt.c:1420
MemoryContext CurrentMemoryContext
Definition mcxt.c:161
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:475
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
static bool is_orclause(const void *clause)
Definition nodeFuncs.h:116
static bool is_opclause(const void *clause)
Definition nodeFuncs.h:76
static bool is_notclause(const void *clause)
Definition nodeFuncs.h:125
static Expr * get_notclausearg(const void *notclause)
Definition nodeFuncs.h:134
#define IsA(nodeptr, _type_)
Definition nodes.h:162
double Selectivity
Definition nodes.h:258
JoinType
Definition nodes.h:296
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:704
int16 attnum
static const struct exclude_list_item skip[]
const void size_t len
const void * data
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define linitial(l)
Definition pg_list.h:178
#define lsecond(l)
Definition pg_list.h:183
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
#define InvalidOid
unsigned int Oid
static int fb(int x)
char * s1
char * s2
tree ctl root
Definition radixtree.h:1857
#define CLAMP_PROBABILITY(p)
Definition selfuncs.h:63
#define STATS_MAX_DIMENSIONS
Definition statistics.h:19
#define STATS_DEPS_MAGIC
Definition statistics.h:43
#define STATS_DEPS_TYPE_BASIC
Definition statistics.h:44
AttrNumber * dependencies
Definition pg_list.h:54
MVDependency * deps[FLEXIBLE_ARRAY_MEMBER]
Definition statistics.h:62
AttrNumber nattributes
Definition statistics.h:53
double degree
Definition statistics.h:52
AttrNumber attributes[FLEXIBLE_ARRAY_MEMBER]
Definition statistics.h:54
Definition nodes.h:133
Oid opno
Definition primnodes.h:835
List * args
Definition primnodes.h:853
Index relid
Definition pathnodes.h:1069
List * statlist
Definition pathnodes.h:1093
Expr * clause
Definition pathnodes.h:2901
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270
Index varlevelsup
Definition primnodes.h:295
Definition type.h:97
Definition c.h:835
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
static ItemArray items
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_LT_OPR
Definition typcache.h:139
static Size VARSIZE_ANY(const void *PTR)
Definition varatt.h:460
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432
const char * type