99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.168 2005/03/01 00:24:52 tgl Exp $
12+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.169 2005/03/02 04:10:53 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
@@ -64,9 +64,7 @@ static bool match_join_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
6464RestrictInfo * rinfo );
6565static Oid indexable_operator (Expr * clause ,Oid opclass ,
6666bool indexkey_on_left );
67- static bool pred_test_restrict_list (Expr * predicate ,List * restrictinfo_list );
68- static bool pred_test_recurse_restrict (Expr * predicate ,Node * clause );
69- static bool pred_test_recurse_pred (Expr * predicate ,Node * clause );
67+ static bool pred_test_recurse (Node * clause ,Node * predicate );
7068static bool pred_test_simple_clause (Expr * predicate ,Node * clause );
7169static Relids indexable_outerrelids (RelOptInfo * rel ,IndexOptInfo * index );
7270static Path * make_innerjoin_index_path (Query * root ,
@@ -749,30 +747,17 @@ check_partial_indexes(Query *root, RelOptInfo *rel)
749747 * Recursively checks whether the clauses in restrictinfo_list imply
750748 * that the given predicate is true.
751749 *
752- * This routine (together with the routines it calls) iterates over
753- * ANDs in the predicate first, then breaks down the restriction list
754- * to its constituent AND/OR elements, and iterates over ORs
755- * in the predicate last. This order is important to make the test
756- * succeed whenever possible. --Nels, Jan '93
757- *
758- * For example, a restriction (a OR b) certainly implies a predicate
759- * (a OR b OR c), but no one element of the predicate is individually
760- * implied by the restriction. By expanding the predicate ORs last
761- * we are able to prove that the whole predicate is implied by each arm
762- * of the restriction. Conversely consider predicate (a AND b) with
763- * restriction (a AND b AND c). This should be implied but we will
764- * fail to prove it if we dissect the restriction first.
765- *
766750 * The top-level List structure of each list corresponds to an AND list.
767- * We assume that canonicalize_qual() has been applied and so there
768- * are no explicit ANDs immediately below the top-level List structure.
769- * (If this is not true we might fail to prove an implication that is
770- * valid, but no worse consequences will ensue.)
751+ * We assume that canonicalize_qual() has been applied and so there are
752+ * no un-flattened ANDs or ORs (e.g., no AND immediately within an AND,
753+ * including AND just below the top-level List structure).
754+ * If this is not true we might fail to prove an implication that is
755+ * valid, but no worse consequences will ensue.
771756 */
772757bool
773758pred_test (List * predicate_list ,List * restrictinfo_list )
774759{
775- ListCell * pred ;
760+ ListCell * item ;
776761
777762/*
778763 * Note: if Postgres tried to optimize queries by forming equivalence
@@ -793,133 +778,189 @@ pred_test(List *predicate_list, List *restrictinfo_list)
793778return false;/* no restriction clauses: the test must
794779 * fail */
795780
796- /* Take care of the AND semantics of the top-level predicate list */
797- foreach (pred ,predicate_list )
781+ /*
782+ * In all cases where the predicate is an AND-clause, pred_test_recurse()
783+ * will prefer to iterate over the predicate's components. So we can
784+ * just do that to start with here, and eliminate the need for
785+ * pred_test_recurse() to handle a bare List on the predicate side.
786+ *
787+ * Logic is: restriction must imply each of the AND'ed predicate items.
788+ */
789+ foreach (item ,predicate_list )
798790{
799- /*
800- * if any clause is not implied, the whole predicate is not
801- * implied.
802- */
803- if (!pred_test_restrict_list (lfirst (pred ),restrictinfo_list ))
791+ if (!pred_test_recurse ((Node * )restrictinfo_list ,lfirst (item )))
804792return false;
805793}
806794return true;
807795}
808796
809797
810- /*
811- * pred_test_restrict_list
812- * Does the "predicate inclusion test" for one AND clause of a predicate
813- * expression. Here we take care of the AND semantics of the top-level
814- * restrictinfo list.
815- */
816- static bool
817- pred_test_restrict_list (Expr * predicate ,List * restrictinfo_list )
818- {
819- ListCell * item ;
820-
821- foreach (item ,restrictinfo_list )
822- {
823- /* if any clause implies the predicate, return true */
824- if (pred_test_recurse_restrict (predicate ,
825- (Node * )lfirst (item )))
826- return true;
827- }
828- return false;
829- }
830-
831-
832- /*
833- * pred_test_recurse_restrict
834- * Does the "predicate inclusion test" for one AND clause of a predicate
835- * expression. Here we recursively deal with the possibility that the
836- * restriction-list element is itself an AND or OR structure; also,
837- * we strip off RestrictInfo nodes to find bare qualifier expressions.
798+ /*----------
799+ * pred_test_recurse
800+ * Does the "predicate inclusion test" for non-NULL restriction and
801+ * predicate clauses.
802+ *
803+ * The logic followed here is ("=>" means "implies"):
804+ *atom A => atom B iff:pred_test_simple_clause says so
805+ *atom A => AND-expr B iff:A => each of B's components
806+ *atom A => OR-expr B iff:A => any of B's components
807+ *AND-expr A => atom B iff:any of A's components => B
808+ *AND-expr A => AND-expr B iff:A => each of B's components
809+ *AND-expr A => OR-expr B iff:A => any of B's components,
810+ **or* any of A's components => B
811+ *OR-expr A => atom B iff:each of A's components => B
812+ *OR-expr A => AND-expr B iff:A => each of B's components
813+ *OR-expr A => OR-expr B iff:each of A's components => any of B's
814+ *
815+ * An "atom" is anything other than an AND or OR node. Notice that we don't
816+ * have any special logic to handle NOT nodes; these should have been pushed
817+ * down or eliminated where feasible by prepqual.c.
818+ *
819+ * We can't recursively expand either side first, but have to interleave
820+ * the expansions per the above rules, to be sure we handle all of these
821+ * examples:
822+ *(x OR y) => (x OR y OR z)
823+ *(x AND y AND z) => (x AND y)
824+ *(x AND y) => ((x AND y) OR z)
825+ *((x OR y) AND z) => (x OR y)
826+ * This is still not an exhaustive test, but it handles most normal cases
827+ * under the assumption that both inputs have been AND/OR flattened.
828+ *
829+ * A bare List node on the restriction side is interpreted as an AND clause,
830+ * in order to handle the top-level restriction List properly. However we
831+ * need not consider a List on the predicate side since pred_test() already
832+ * expanded it.
833+ *
834+ * We have to be prepared to handle RestrictInfo nodes in the restrictinfo
835+ * tree, though not in the predicate tree.
836+ *----------
838837 */
839838static bool
840- pred_test_recurse_restrict ( Expr * predicate ,Node * clause )
839+ pred_test_recurse ( Node * clause ,Node * predicate )
841840{
842- List * items ;
843841ListCell * item ;
844842
845843Assert (clause != NULL );
844+ /* skip through RestrictInfo */
846845if (IsA (clause ,RestrictInfo ))
847846{
848- RestrictInfo * restrictinfo = (RestrictInfo * )clause ;
849-
850- return pred_test_recurse_restrict (predicate ,
851- (Node * )restrictinfo -> clause );
847+ clause = (Node * ) ((RestrictInfo * )clause )-> clause ;
848+ Assert (clause != NULL );
849+ Assert (!IsA (clause ,RestrictInfo ));
852850}
853- else if (or_clause (clause ))
851+ Assert (predicate != NULL );
852+
853+ /*
854+ * Since a restriction List clause is handled the same as an AND clause,
855+ * we can avoid duplicate code like this:
856+ */
857+ if (and_clause (clause ))
858+ clause = (Node * ) ((BoolExpr * )clause )-> args ;
859+
860+ if (IsA (clause ,List ))
854861{
855- items = ((BoolExpr * )clause )-> args ;
856- foreach (item ,items )
862+ if (and_clause (predicate ))
857863{
858- /* if any OR item doesn't imply the predicate, clause doesn't */
859- if (!pred_test_recurse_restrict (predicate ,lfirst (item )))
860- return false;
864+ /* AND-clause => AND-clause if A implies each of B's items */
865+ foreach (item , ((BoolExpr * )predicate )-> args )
866+ {
867+ if (!pred_test_recurse (clause ,lfirst (item )))
868+ return false;
869+ }
870+ return true;
871+ }
872+ else if (or_clause (predicate ))
873+ {
874+ /* AND-clause => OR-clause if A implies any of B's items */
875+ /* Needed to handle (x AND y) => ((x AND y) OR z) */
876+ foreach (item , ((BoolExpr * )predicate )-> args )
877+ {
878+ if (pred_test_recurse (clause ,lfirst (item )))
879+ return true;
880+ }
881+ /* Also check if any of A's items implies B */
882+ /* Needed to handle ((x OR y) AND z) => (x OR y) */
883+ foreach (item , (List * )clause )
884+ {
885+ if (pred_test_recurse (lfirst (item ),predicate ))
886+ return true;
887+ }
888+ return false;
889+ }
890+ else
891+ {
892+ /* AND-clause => atom if any of A's items implies B */
893+ foreach (item , (List * )clause )
894+ {
895+ if (pred_test_recurse (lfirst (item ),predicate ))
896+ return true;
897+ }
898+ return false;
861899}
862- return true;
863900}
864- else if (and_clause (clause ))
901+ else if (or_clause (clause ))
865902{
866- items = ((BoolExpr * )clause )-> args ;
867- foreach (item ,items )
903+ if (or_clause (predicate ))
868904{
869905/*
870- *if any AND item implies the predicate, the whole clause
871- *does
906+ *OR-clause => OR-clause if each of A's items implies any of
907+ *B's items. Messy but can't do it any more simply.
872908 */
873- if (pred_test_recurse_restrict (predicate ,lfirst (item )))
874- return true;
909+ foreach (item , ((BoolExpr * )clause )-> args )
910+ {
911+ Node * citem = lfirst (item );
912+ ListCell * item2 ;
913+
914+ foreach (item2 , ((BoolExpr * )predicate )-> args )
915+ {
916+ if (pred_test_recurse (citem ,lfirst (item2 )))
917+ break ;
918+ }
919+ if (item2 == NULL )
920+ return false;/* doesn't imply any of B's */
921+ }
922+ return true;
923+ }
924+ else
925+ {
926+ /* OR-clause => AND-clause if each of A's items implies B */
927+ /* OR-clause => atom if each of A's items implies B */
928+ foreach (item , ((BoolExpr * )clause )-> args )
929+ {
930+ if (!pred_test_recurse (lfirst (item ),predicate ))
931+ return false;
932+ }
933+ return true;
875934}
876- return false;
877935}
878936else
879- return pred_test_recurse_pred (predicate ,clause );
880- }
881-
882-
883- /*
884- * pred_test_recurse_pred
885- * Does the "predicate inclusion test" for one conjunct of a predicate
886- * expression. Here we recursively deal with the possibility that the
887- * predicate conjunct is itself an AND or OR structure.
888- */
889- static bool
890- pred_test_recurse_pred (Expr * predicate ,Node * clause )
891- {
892- List * items ;
893- ListCell * item ;
894-
895- Assert (predicate != NULL );
896- if (or_clause ((Node * )predicate ))
897937{
898- items = ((BoolExpr * )predicate )-> args ;
899- foreach (item ,items )
938+ if (and_clause (predicate ))
900939{
901- /* if any item is implied, the whole predicate is implied */
902- if (pred_test_recurse_pred (lfirst (item ),clause ))
903- return true;
940+ /* atom => AND-clause if A implies each of B's items */
941+ foreach (item , ((BoolExpr * )predicate )-> args )
942+ {
943+ if (!pred_test_recurse (clause ,lfirst (item )))
944+ return false;
945+ }
946+ return true;
904947}
905- return false;
906- }
907- else if (and_clause ((Node * )predicate ))
908- {
909- items = ((BoolExpr * )predicate )-> args ;
910- foreach (item ,items )
948+ else if (or_clause (predicate ))
911949{
912- /*
913- * if any item is not implied, the whole predicate is not
914- * implied
915- */
916- if (!pred_test_recurse_pred (lfirst (item ),clause ))
917- return false;
950+ /* atom => OR-clause if A implies any of B's items */
951+ foreach (item , ((BoolExpr * )predicate )-> args )
952+ {
953+ if (pred_test_recurse (clause ,lfirst (item )))
954+ return true;
955+ }
956+ return false;
957+ }
958+ else
959+ {
960+ /* atom => atom is the base case */
961+ return pred_test_simple_clause ((Expr * )predicate ,clause );
918962}
919- return true;
920963}
921- else
922- return pred_test_simple_clause (predicate ,clause );
923964}
924965
925966