@@ -736,91 +736,104 @@ pg_dependencies_send(PG_FUNCTION_ARGS)
736
736
* dependency_is_compatible_clause
737
737
* Determines if the clause is compatible with functional dependencies
738
738
*
739
- * Only OpExprs with two arguments using an equality operator are supported.
740
- * When returning True attnum is set to the attribute number of the Var within
741
- * the supported clause.
742
- *
743
- * Currently we only support Var = Const, or Const = Var. It may be possible
744
- * to expand on this later.
739
+ * Only clauses that have the form of equality to a pseudoconstant, or can be
740
+ * interpreted that way, are currently accepted. Furthermore the variable
741
+ * part of the clause must be a simple Var belonging to the specified
742
+ * relation, whose attribute number we return in *attnum on success.
745
743
*/
746
744
static bool
747
745
dependency_is_compatible_clause (Node * clause , Index relid , AttrNumber * attnum )
748
746
{
749
747
RestrictInfo * rinfo = (RestrictInfo * ) clause ;
748
+ Var * var ;
750
749
751
750
if (!IsA (rinfo , RestrictInfo ))
752
751
return false;
753
752
754
- /* Pseudoconstants are not really interesting here. */
753
+ /* Pseudoconstants are not interesting (they couldn't contain a Var) */
755
754
if (rinfo -> pseudoconstant )
756
755
return false;
757
756
758
- /* clauses referencing multiple varnos are incompatible */
757
+ /* Clauses referencing multiple, or no, varnos are incompatible */
759
758
if (bms_membership (rinfo -> clause_relids ) != BMS_SINGLETON )
760
759
return false;
761
760
762
761
if (is_opclause (rinfo -> clause ))
763
762
{
763
+ /* If it's an opclause, check for Var = Const or Const = Var. */
764
764
OpExpr * expr = (OpExpr * ) rinfo -> clause ;
765
- Var * var ;
766
- bool varonleft = true;
767
- bool ok ;
768
765
769
- /* Only expressions with two arguments are considered compatible . */
766
+ /* Only expressions with two arguments are candidates . */
770
767
if (list_length (expr -> args ) != 2 )
771
768
return false;
772
769
773
- /* see if it actually has the right */
774
- ok = (NumRelids ((Node * ) expr ) == 1 ) &&
775
- (is_pseudo_constant_clause (lsecond (expr -> args )) ||
776
- (varonleft = false,
777
- is_pseudo_constant_clause (linitial (expr -> args ))));
778
-
779
- /* unsupported structure (two variables or so) */
780
- if (!ok )
770
+ /* Make sure non-selected argument is a pseudoconstant. */
771
+ if (is_pseudo_constant_clause (lsecond (expr -> args )))
772
+ var = linitial (expr -> args );
773
+ else if (is_pseudo_constant_clause (linitial (expr -> args )))
774
+ var = lsecond (expr -> args );
775
+ else
781
776
return false;
782
777
783
778
/*
784
- * If it's not "=" operator, just ignore the clause, as it's not
779
+ * If it's not an "=" operator, just ignore the clause, as it's not
785
780
* compatible with functional dependencies.
786
781
*
787
782
* This uses the function for estimating selectivity, not the operator
788
783
* directly (a bit awkward, but well ...).
784
+ *
785
+ * XXX this is pretty dubious; probably it'd be better to check btree
786
+ * or hash opclass membership, so as not to be fooled by custom
787
+ * selectivity functions, and to be more consistent with decisions
788
+ * elsewhere in the planner.
789
789
*/
790
790
if (get_oprrest (expr -> opno ) != F_EQSEL )
791
791
return false;
792
792
793
- var = (varonleft ) ? linitial (expr -> args ) : lsecond (expr -> args );
794
-
793
+ /* OK to proceed with checking "var" */
794
+ }
795
+ else if (not_clause ((Node * ) rinfo -> clause ))
796
+ {
795
797
/*
796
- * We may ignore any RelabelType node above the operand. (There won't
797
- * be more than one, since eval_const_expressions() has been applied
798
- * already.)
798
+ * "NOT x" can be interpreted as "x = false", so get the argument and
799
+ * proceed with seeing if it's a suitable Var.
799
800
*/
800
- if (IsA (var , RelabelType ))
801
- var = (Var * ) ((RelabelType * ) var )-> arg ;
801
+ var = (Var * ) get_notclausearg (rinfo -> clause );
802
+ }
803
+ else
804
+ {
805
+ /*
806
+ * A boolean expression "x" can be interpreted as "x = true", so
807
+ * proceed with seeing if it's a suitable Var.
808
+ */
809
+ var = (Var * ) rinfo -> clause ;
810
+ }
802
811
803
- /* We only support plain Vars for now */
804
- if (!IsA (var , Var ))
805
- return false;
812
+ /*
813
+ * We may ignore any RelabelType node above the operand. (There won't be
814
+ * more than one, since eval_const_expressions has been applied already.)
815
+ */
816
+ if (IsA (var , RelabelType ))
817
+ var = (Var * ) ((RelabelType * ) var )-> arg ;
806
818
807
- /* Ensure var is from the correct relation */
808
- if (var -> varno != relid )
809
- return false;
819
+ /* We only support plain Vars for now */
820
+ if (! IsA ( var , Var ) )
821
+ return false;
810
822
811
- /* we also better ensure the Var is from the current level */
812
- if (var -> varlevelsup > 0 )
813
- return false;
823
+ /* Ensure Var is from the correct relation */
824
+ if (var -> varno != relid )
825
+ return false;
814
826
815
- /* Also skip system attributes (we don't allow stats on those). */
816
- if (! AttrNumberIsForUserDefinedAttr ( var -> varattno ) )
817
- return false;
827
+ /* We also better ensure the Var is from the current level */
828
+ if (var -> varlevelsup != 0 )
829
+ return false;
818
830
819
- * attnum = var -> varattno ;
820
- return true;
821
- }
831
+ /* Also ignore system attributes (we don't allow stats on those) */
832
+ if (! AttrNumberIsForUserDefinedAttr ( var -> varattno ))
833
+ return false;
822
834
823
- return false;
835
+ * attnum = var -> varattno ;
836
+ return true;
824
837
}
825
838
826
839
/*
@@ -891,12 +904,12 @@ find_strongest_dependency(StatisticExtInfo *stats, MVDependencies *dependencies,
891
904
892
905
/*
893
906
* dependencies_clauselist_selectivity
894
- * Return the estimated selectivity of the given clauses using
895
- * functional dependency statistics, or 1.0 if no useful functional
907
+ * Return the estimated selectivity of (a subset of) the given clauses
908
+ * using functional dependency statistics, or 1.0 if no useful functional
896
909
* dependency statistic exists.
897
910
*
898
911
* 'estimatedclauses' is an output argument that gets a bit set corresponding
899
- * to the (zero-based) list index of clauses that are included in the
912
+ * to the (zero-based) list index of each clause that is included in the
900
913
* estimated selectivity.
901
914
*
902
915
* Given equality clauses on attributes (a,b) we find the strongest dependency
@@ -932,6 +945,9 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
932
945
AttrNumber * list_attnums ;
933
946
int listidx ;
934
947
948
+ /* initialize output argument */
949
+ * estimatedclauses = NULL ;
950
+
935
951
/* check if there's any stats that might be useful for us. */
936
952
if (!has_stats_of_kind (rel -> statlist , STATS_EXT_DEPENDENCIES ))
937
953
return 1.0 ;
0 commit comments