39
39
static EquivalenceMember * add_eq_member (EquivalenceClass * ec ,
40
40
Expr * expr , Relids relids , Relids nullable_relids ,
41
41
bool is_child , Oid datatype );
42
+ static bool is_exprlist_member (Expr * node , List * exprs );
42
43
static void generate_base_implied_equalities_const (PlannerInfo * root ,
43
44
EquivalenceClass * ec );
44
45
static void generate_base_implied_equalities_no_const (PlannerInfo * root ,
@@ -770,6 +771,167 @@ get_eclass_for_sort_expr(PlannerInfo *root,
770
771
return newec ;
771
772
}
772
773
774
+ /*
775
+ * find_ec_member_matching_expr
776
+ * Locate an EquivalenceClass member matching the given expr, if any;
777
+ * return NULL if no match.
778
+ *
779
+ * "Matching" is defined as "equal after stripping RelabelTypes".
780
+ * This is used for identifying sort expressions, and we need to allow
781
+ * binary-compatible relabeling for some cases involving binary-compatible
782
+ * sort operators.
783
+ *
784
+ * Child EC members are ignored unless they belong to given 'relids'.
785
+ */
786
+ EquivalenceMember *
787
+ find_ec_member_matching_expr (EquivalenceClass * ec ,
788
+ Expr * expr ,
789
+ Relids relids )
790
+ {
791
+ ListCell * lc ;
792
+
793
+ /* We ignore binary-compatible relabeling on both ends */
794
+ while (expr && IsA (expr , RelabelType ))
795
+ expr = ((RelabelType * ) expr )-> arg ;
796
+
797
+ foreach (lc , ec -> ec_members )
798
+ {
799
+ EquivalenceMember * em = (EquivalenceMember * ) lfirst (lc );
800
+ Expr * emexpr ;
801
+
802
+ /*
803
+ * We shouldn't be trying to sort by an equivalence class that
804
+ * contains a constant, so no need to consider such cases any further.
805
+ */
806
+ if (em -> em_is_const )
807
+ continue ;
808
+
809
+ /*
810
+ * Ignore child members unless they belong to the requested rel.
811
+ */
812
+ if (em -> em_is_child &&
813
+ !bms_is_subset (em -> em_relids , relids ))
814
+ continue ;
815
+
816
+ /*
817
+ * Match if same expression (after stripping relabel).
818
+ */
819
+ emexpr = em -> em_expr ;
820
+ while (emexpr && IsA (emexpr , RelabelType ))
821
+ emexpr = ((RelabelType * ) emexpr )-> arg ;
822
+
823
+ if (equal (emexpr , expr ))
824
+ return em ;
825
+ }
826
+
827
+ return NULL ;
828
+ }
829
+
830
+ /*
831
+ * find_computable_ec_member
832
+ * Locate an EquivalenceClass member that can be computed from the
833
+ * expressions appearing in "exprs"; return NULL if no match.
834
+ *
835
+ * "exprs" can be either a list of bare expression trees, or a list of
836
+ * TargetEntry nodes. Either way, it should contain Vars and possibly
837
+ * Aggrefs and WindowFuncs, which are matched to the corresponding elements
838
+ * of the EquivalenceClass's expressions.
839
+ *
840
+ * Unlike find_ec_member_matching_expr, there's no special provision here
841
+ * for binary-compatible relabeling. This is intentional: if we have to
842
+ * compute an expression in this way, setrefs.c is going to insist on exact
843
+ * matches of Vars to the source tlist.
844
+ *
845
+ * Child EC members are ignored unless they belong to given 'relids'.
846
+ * Also, non-parallel-safe expressions are ignored if 'require_parallel_safe'.
847
+ *
848
+ * Note: some callers pass root == NULL for notational reasons. This is OK
849
+ * when require_parallel_safe is false.
850
+ */
851
+ EquivalenceMember *
852
+ find_computable_ec_member (PlannerInfo * root ,
853
+ EquivalenceClass * ec ,
854
+ List * exprs ,
855
+ Relids relids ,
856
+ bool require_parallel_safe )
857
+ {
858
+ ListCell * lc ;
859
+
860
+ foreach (lc , ec -> ec_members )
861
+ {
862
+ EquivalenceMember * em = (EquivalenceMember * ) lfirst (lc );
863
+ List * exprvars ;
864
+ ListCell * lc2 ;
865
+
866
+ /*
867
+ * We shouldn't be trying to sort by an equivalence class that
868
+ * contains a constant, so no need to consider such cases any further.
869
+ */
870
+ if (em -> em_is_const )
871
+ continue ;
872
+
873
+ /*
874
+ * Ignore child members unless they belong to the requested rel.
875
+ */
876
+ if (em -> em_is_child &&
877
+ !bms_is_subset (em -> em_relids , relids ))
878
+ continue ;
879
+
880
+ /*
881
+ * Match if all Vars and quasi-Vars are available in "exprs".
882
+ */
883
+ exprvars = pull_var_clause ((Node * ) em -> em_expr ,
884
+ PVC_INCLUDE_AGGREGATES |
885
+ PVC_INCLUDE_WINDOWFUNCS |
886
+ PVC_INCLUDE_PLACEHOLDERS );
887
+ foreach (lc2 , exprvars )
888
+ {
889
+ if (!is_exprlist_member (lfirst (lc2 ), exprs ))
890
+ break ;
891
+ }
892
+ list_free (exprvars );
893
+ if (lc2 )
894
+ continue ; /* we hit a non-available Var */
895
+
896
+ /*
897
+ * If requested, reject expressions that are not parallel-safe. We
898
+ * check this last because it's a rather expensive test.
899
+ */
900
+ if (require_parallel_safe &&
901
+ !is_parallel_safe (root , (Node * ) em -> em_expr ))
902
+ continue ;
903
+
904
+ return em ; /* found usable expression */
905
+ }
906
+
907
+ return NULL ;
908
+ }
909
+
910
+ /*
911
+ * is_exprlist_member
912
+ * Subroutine for find_computable_ec_member: is "node" in "exprs"?
913
+ *
914
+ * Per the requirements of that function, "exprs" might or might not have
915
+ * TargetEntry superstructure.
916
+ */
917
+ static bool
918
+ is_exprlist_member (Expr * node , List * exprs )
919
+ {
920
+ ListCell * lc ;
921
+
922
+ foreach (lc , exprs )
923
+ {
924
+ Expr * expr = (Expr * ) lfirst (lc );
925
+
926
+ if (expr && IsA (expr , TargetEntry ))
927
+ expr = ((TargetEntry * ) expr )-> expr ;
928
+
929
+ if (equal (node , expr ))
930
+ return true;
931
+ }
932
+ return false;
933
+ }
934
+
773
935
/*
774
936
* Find an equivalence class member expression, all of whose Vars, come from
775
937
* the indicated relation.
@@ -800,71 +962,78 @@ find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel)
800
962
}
801
963
802
964
/*
803
- * Find an equivalence class member expression that can be safely used to build
804
- * a sort node using the provided relation. The rules are a subset of those
805
- * applied in prepare_sort_from_pathkeys since that function deals with sorts
806
- * that must be delayed until the last stages of query execution, while here
807
- * we only care about proactive sorts.
965
+ * Find an equivalence class member expression that can be used to build
966
+ * a sort node using the provided relation; return NULL if no candidate.
967
+ *
968
+ * To succeed, we must find an EC member that prepare_sort_from_pathkeys knows
969
+ * how to sort on, given the rel's reltarget as input. There are also a few
970
+ * additional constraints based on the fact that the desired sort will be done
971
+ * within the scan/join part of the plan. Also, non-parallel-safe expressions
972
+ * are ignored if 'require_parallel_safe'.
808
973
*/
809
974
Expr *
810
975
find_em_expr_usable_for_sorting_rel (PlannerInfo * root , EquivalenceClass * ec ,
811
976
RelOptInfo * rel , bool require_parallel_safe )
812
977
{
813
- ListCell * lc_em ;
978
+ PathTarget * target = rel -> reltarget ;
979
+ EquivalenceMember * em ;
980
+ ListCell * lc ;
814
981
815
982
/*
816
- * If there is more than one equivalence member matching these
817
- * requirements we'll be content to choose any one of them.
983
+ * Reject volatile ECs immediately; such sorts must always be postponed.
818
984
*/
819
- foreach (lc_em , ec -> ec_members )
820
- {
821
- EquivalenceMember * em = lfirst (lc_em );
822
- Expr * em_expr = em -> em_expr ;
985
+ if (ec -> ec_has_volatile )
986
+ return NULL ;
823
987
824
- /*
825
- * We shouldn't be trying to sort by an equivalence class that
826
- * contains a constant, so no need to consider such cases any further.
827
- */
828
- if ( em -> em_is_const )
829
- continue ;
988
+ /*
989
+ * Try to find an EM directly matching some reltarget member.
990
+ */
991
+ foreach ( lc , target -> exprs )
992
+ {
993
+ Expr * targetexpr = ( Expr * ) lfirst ( lc ) ;
830
994
831
- /*
832
- * Any Vars in the equivalence class member need to come from this
833
- * relation. This is a superset of prepare_sort_from_pathkeys ignoring
834
- * child members unless they belong to the rel being sorted.
835
- */
836
- if (!bms_is_subset (em -> em_relids , rel -> relids ))
995
+ em = find_ec_member_matching_expr (ec , targetexpr , rel -> relids );
996
+ if (!em )
837
997
continue ;
838
998
839
999
/*
840
- * If requested, reject expressions that are not parallel-safe.
1000
+ * Reject expressions involving set-returning functions, as those
1001
+ * can't be computed early either. (Note: this test and the following
1002
+ * one are effectively checking properties of targetexpr, so there's
1003
+ * no point in asking whether some other EC member would be better.)
841
1004
*/
842
- if (require_parallel_safe && ! is_parallel_safe ( root , (Node * ) em_expr ))
1005
+ if (IS_SRF_CALL ( (Node * ) em -> em_expr ))
843
1006
continue ;
844
1007
845
1008
/*
846
- * Disallow SRFs so that all of them can be evaluated at the correct
847
- * time as determined by make_sort_input_target .
1009
+ * If requested, reject expressions that are not parallel-safe. We
1010
+ * check this last because it's a rather expensive test .
848
1011
*/
849
- if (IS_SRF_CALL ((Node * ) em_expr ))
1012
+ if (require_parallel_safe &&
1013
+ !is_parallel_safe (root , (Node * ) em -> em_expr ))
850
1014
continue ;
851
1015
852
- /*
853
- * As long as the expression isn't volatile then
854
- * prepare_sort_from_pathkeys is able to generate a new target entry,
855
- * so there's no need to verify that one already exists.
856
- *
857
- * While prepare_sort_from_pathkeys has to be concerned about matching
858
- * up a volatile expression to the proper tlist entry, it doesn't seem
859
- * valuable here to expend the work trying to find a match in the
860
- * target's exprs since such a sort will have to be postponed anyway.
861
- */
862
- if (!ec -> ec_has_volatile )
863
- return em -> em_expr ;
1016
+ return em -> em_expr ;
864
1017
}
865
1018
866
- /* We didn't find any suitable equivalence class expression */
867
- return NULL ;
1019
+ /*
1020
+ * Try to find a expression computable from the reltarget.
1021
+ */
1022
+ em = find_computable_ec_member (root , ec , target -> exprs , rel -> relids ,
1023
+ require_parallel_safe );
1024
+ if (!em )
1025
+ return NULL ;
1026
+
1027
+ /*
1028
+ * Reject expressions involving set-returning functions, as those can't be
1029
+ * computed early either. (There's no point in looking for another EC
1030
+ * member in this case; since SRFs can't appear in WHERE, they cannot
1031
+ * belong to multi-member ECs.)
1032
+ */
1033
+ if (IS_SRF_CALL ((Node * ) em -> em_expr ))
1034
+ return NULL ;
1035
+
1036
+ return em -> em_expr ;
868
1037
}
869
1038
870
1039
/*
0 commit comments