@@ -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 notreally interestinghere. */
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 areconsidered compatible . */
766
+ /* Only expressions with two arguments arecandidates . */
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 notan "=" 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 thecurrent level */
812
- if (var -> varlevelsup > 0 )
813
- return false;
823
+ /*Ensure Var is from thecorrect 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 ofclauses thatare included in the
912
+ * to the (zero-based) list index ofeach clause thatis 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 ;