Header And Logo

PostgreSQL
| The world's most advanced open source database.

predtest.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * predtest.c
00004  *    Routines to attempt to prove logical implications between predicate
00005  *    expressions.
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  * Portions Copyright (c) 1994, Regents of the University of California
00009  *
00010  *
00011  * IDENTIFICATION
00012  *    src/backend/optimizer/util/predtest.c
00013  *
00014  *-------------------------------------------------------------------------
00015  */
00016 #include "postgres.h"
00017 
00018 #include "catalog/pg_proc.h"
00019 #include "catalog/pg_type.h"
00020 #include "executor/executor.h"
00021 #include "miscadmin.h"
00022 #include "optimizer/clauses.h"
00023 #include "optimizer/planmain.h"
00024 #include "optimizer/predtest.h"
00025 #include "utils/array.h"
00026 #include "utils/inval.h"
00027 #include "utils/lsyscache.h"
00028 #include "utils/syscache.h"
00029 
00030 
00031 /*
00032  * Proof attempts involving large arrays in ScalarArrayOpExpr nodes are
00033  * likely to require O(N^2) time, and more often than not fail anyway.
00034  * So we set an arbitrary limit on the number of array elements that
00035  * we will allow to be treated as an AND or OR clause.
00036  * XXX is it worth exposing this as a GUC knob?
00037  */
00038 #define MAX_SAOP_ARRAY_SIZE     100
00039 
00040 /*
00041  * To avoid redundant coding in predicate_implied_by_recurse and
00042  * predicate_refuted_by_recurse, we need to abstract out the notion of
00043  * iterating over the components of an expression that is logically an AND
00044  * or OR structure.  There are multiple sorts of expression nodes that can
00045  * be treated as ANDs or ORs, and we don't want to code each one separately.
00046  * Hence, these types and support routines.
00047  */
00048 typedef enum
00049 {
00050     CLASS_ATOM,                 /* expression that's not AND or OR */
00051     CLASS_AND,                  /* expression with AND semantics */
00052     CLASS_OR                    /* expression with OR semantics */
00053 } PredClass;
00054 
00055 typedef struct PredIterInfoData *PredIterInfo;
00056 
00057 typedef struct PredIterInfoData
00058 {
00059     /* node-type-specific iteration state */
00060     void       *state;
00061     /* initialize to do the iteration */
00062     void        (*startup_fn) (Node *clause, PredIterInfo info);
00063     /* next-component iteration function */
00064     Node       *(*next_fn) (PredIterInfo info);
00065     /* release resources when done with iteration */
00066     void        (*cleanup_fn) (PredIterInfo info);
00067 } PredIterInfoData;
00068 
00069 #define iterate_begin(item, clause, info)   \
00070     do { \
00071         Node   *item; \
00072         (info).startup_fn((clause), &(info)); \
00073         while ((item = (info).next_fn(&(info))) != NULL)
00074 
00075 #define iterate_end(info)   \
00076         (info).cleanup_fn(&(info)); \
00077     } while (0)
00078 
00079 
00080 static bool predicate_implied_by_recurse(Node *clause, Node *predicate);
00081 static bool predicate_refuted_by_recurse(Node *clause, Node *predicate);
00082 static PredClass predicate_classify(Node *clause, PredIterInfo info);
00083 static void list_startup_fn(Node *clause, PredIterInfo info);
00084 static Node *list_next_fn(PredIterInfo info);
00085 static void list_cleanup_fn(PredIterInfo info);
00086 static void boolexpr_startup_fn(Node *clause, PredIterInfo info);
00087 static void arrayconst_startup_fn(Node *clause, PredIterInfo info);
00088 static Node *arrayconst_next_fn(PredIterInfo info);
00089 static void arrayconst_cleanup_fn(PredIterInfo info);
00090 static void arrayexpr_startup_fn(Node *clause, PredIterInfo info);
00091 static Node *arrayexpr_next_fn(PredIterInfo info);
00092 static void arrayexpr_cleanup_fn(PredIterInfo info);
00093 static bool predicate_implied_by_simple_clause(Expr *predicate, Node *clause);
00094 static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause);
00095 static Node *extract_not_arg(Node *clause);
00096 static Node *extract_strong_not_arg(Node *clause);
00097 static bool list_member_strip(List *list, Expr *datum);
00098 static bool btree_predicate_proof(Expr *predicate, Node *clause,
00099                       bool refute_it);
00100 static Oid  get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it);
00101 static void InvalidateOprProofCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
00102 
00103 
00104 /*
00105  * predicate_implied_by
00106  *    Recursively checks whether the clauses in restrictinfo_list imply
00107  *    that the given predicate is true.
00108  *
00109  * The top-level List structure of each list corresponds to an AND list.
00110  * We assume that eval_const_expressions() has been applied and so there
00111  * are no un-flattened ANDs or ORs (e.g., no AND immediately within an AND,
00112  * including AND just below the top-level List structure).
00113  * If this is not true we might fail to prove an implication that is
00114  * valid, but no worse consequences will ensue.
00115  *
00116  * We assume the predicate has already been checked to contain only
00117  * immutable functions and operators.  (In most current uses this is true
00118  * because the predicate is part of an index predicate that has passed
00119  * CheckPredicate().)  We dare not make deductions based on non-immutable
00120  * functions, because they might change answers between the time we make
00121  * the plan and the time we execute the plan.
00122  */
00123 bool
00124 predicate_implied_by(List *predicate_list, List *restrictinfo_list)
00125 {
00126     Node       *p,
00127                *r;
00128 
00129     if (predicate_list == NIL)
00130         return true;            /* no predicate: implication is vacuous */
00131     if (restrictinfo_list == NIL)
00132         return false;           /* no restriction: implication must fail */
00133 
00134     /*
00135      * If either input is a single-element list, replace it with its lone
00136      * member; this avoids one useless level of AND-recursion.  We only need
00137      * to worry about this at top level, since eval_const_expressions should
00138      * have gotten rid of any trivial ANDs or ORs below that.
00139      */
00140     if (list_length(predicate_list) == 1)
00141         p = (Node *) linitial(predicate_list);
00142     else
00143         p = (Node *) predicate_list;
00144     if (list_length(restrictinfo_list) == 1)
00145         r = (Node *) linitial(restrictinfo_list);
00146     else
00147         r = (Node *) restrictinfo_list;
00148 
00149     /* And away we go ... */
00150     return predicate_implied_by_recurse(r, p);
00151 }
00152 
00153 /*
00154  * predicate_refuted_by
00155  *    Recursively checks whether the clauses in restrictinfo_list refute
00156  *    the given predicate (that is, prove it false).
00157  *
00158  * This is NOT the same as !(predicate_implied_by), though it is similar
00159  * in the technique and structure of the code.
00160  *
00161  * An important fine point is that truth of the clauses must imply that
00162  * the predicate returns FALSE, not that it does not return TRUE.  This
00163  * is normally used to try to refute CHECK constraints, and the only
00164  * thing we can assume about a CHECK constraint is that it didn't return
00165  * FALSE --- a NULL result isn't a violation per the SQL spec.  (Someday
00166  * perhaps this code should be extended to support both "strong" and
00167  * "weak" refutation, but for now we only need "strong".)
00168  *
00169  * The top-level List structure of each list corresponds to an AND list.
00170  * We assume that eval_const_expressions() has been applied and so there
00171  * are no un-flattened ANDs or ORs (e.g., no AND immediately within an AND,
00172  * including AND just below the top-level List structure).
00173  * If this is not true we might fail to prove an implication that is
00174  * valid, but no worse consequences will ensue.
00175  *
00176  * We assume the predicate has already been checked to contain only
00177  * immutable functions and operators.  We dare not make deductions based on
00178  * non-immutable functions, because they might change answers between the
00179  * time we make the plan and the time we execute the plan.
00180  */
00181 bool
00182 predicate_refuted_by(List *predicate_list, List *restrictinfo_list)
00183 {
00184     Node       *p,
00185                *r;
00186 
00187     if (predicate_list == NIL)
00188         return false;           /* no predicate: no refutation is possible */
00189     if (restrictinfo_list == NIL)
00190         return false;           /* no restriction: refutation must fail */
00191 
00192     /*
00193      * If either input is a single-element list, replace it with its lone
00194      * member; this avoids one useless level of AND-recursion.  We only need
00195      * to worry about this at top level, since eval_const_expressions should
00196      * have gotten rid of any trivial ANDs or ORs below that.
00197      */
00198     if (list_length(predicate_list) == 1)
00199         p = (Node *) linitial(predicate_list);
00200     else
00201         p = (Node *) predicate_list;
00202     if (list_length(restrictinfo_list) == 1)
00203         r = (Node *) linitial(restrictinfo_list);
00204     else
00205         r = (Node *) restrictinfo_list;
00206 
00207     /* And away we go ... */
00208     return predicate_refuted_by_recurse(r, p);
00209 }
00210 
00211 /*----------
00212  * predicate_implied_by_recurse
00213  *    Does the predicate implication test for non-NULL restriction and
00214  *    predicate clauses.
00215  *
00216  * The logic followed here is ("=>" means "implies"):
00217  *  atom A => atom B iff:           predicate_implied_by_simple_clause says so
00218  *  atom A => AND-expr B iff:       A => each of B's components
00219  *  atom A => OR-expr B iff:        A => any of B's components
00220  *  AND-expr A => atom B iff:       any of A's components => B
00221  *  AND-expr A => AND-expr B iff:   A => each of B's components
00222  *  AND-expr A => OR-expr B iff:    A => any of B's components,
00223  *                                  *or* any of A's components => B
00224  *  OR-expr A => atom B iff:        each of A's components => B
00225  *  OR-expr A => AND-expr B iff:    A => each of B's components
00226  *  OR-expr A => OR-expr B iff:     each of A's components => any of B's
00227  *
00228  * An "atom" is anything other than an AND or OR node.  Notice that we don't
00229  * have any special logic to handle NOT nodes; these should have been pushed
00230  * down or eliminated where feasible by prepqual.c.
00231  *
00232  * We can't recursively expand either side first, but have to interleave
00233  * the expansions per the above rules, to be sure we handle all of these
00234  * examples:
00235  *      (x OR y) => (x OR y OR z)
00236  *      (x AND y AND z) => (x AND y)
00237  *      (x AND y) => ((x AND y) OR z)
00238  *      ((x OR y) AND z) => (x OR y)
00239  * This is still not an exhaustive test, but it handles most normal cases
00240  * under the assumption that both inputs have been AND/OR flattened.
00241  *
00242  * We have to be prepared to handle RestrictInfo nodes in the restrictinfo
00243  * tree, though not in the predicate tree.
00244  *----------
00245  */
00246 static bool
00247 predicate_implied_by_recurse(Node *clause, Node *predicate)
00248 {
00249     PredIterInfoData clause_info;
00250     PredIterInfoData pred_info;
00251     PredClass   pclass;
00252     bool        result;
00253 
00254     /* skip through RestrictInfo */
00255     Assert(clause != NULL);
00256     if (IsA(clause, RestrictInfo))
00257         clause = (Node *) ((RestrictInfo *) clause)->clause;
00258 
00259     pclass = predicate_classify(predicate, &pred_info);
00260 
00261     switch (predicate_classify(clause, &clause_info))
00262     {
00263         case CLASS_AND:
00264             switch (pclass)
00265             {
00266                 case CLASS_AND:
00267 
00268                     /*
00269                      * AND-clause => AND-clause if A implies each of B's items
00270                      */
00271                     result = true;
00272                     iterate_begin(pitem, predicate, pred_info)
00273                     {
00274                         if (!predicate_implied_by_recurse(clause, pitem))
00275                         {
00276                             result = false;
00277                             break;
00278                         }
00279                     }
00280                     iterate_end(pred_info);
00281                     return result;
00282 
00283                 case CLASS_OR:
00284 
00285                     /*
00286                      * AND-clause => OR-clause if A implies any of B's items
00287                      *
00288                      * Needed to handle (x AND y) => ((x AND y) OR z)
00289                      */
00290                     result = false;
00291                     iterate_begin(pitem, predicate, pred_info)
00292                     {
00293                         if (predicate_implied_by_recurse(clause, pitem))
00294                         {
00295                             result = true;
00296                             break;
00297                         }
00298                     }
00299                     iterate_end(pred_info);
00300                     if (result)
00301                         return result;
00302 
00303                     /*
00304                      * Also check if any of A's items implies B
00305                      *
00306                      * Needed to handle ((x OR y) AND z) => (x OR y)
00307                      */
00308                     iterate_begin(citem, clause, clause_info)
00309                     {
00310                         if (predicate_implied_by_recurse(citem, predicate))
00311                         {
00312                             result = true;
00313                             break;
00314                         }
00315                     }
00316                     iterate_end(clause_info);
00317                     return result;
00318 
00319                 case CLASS_ATOM:
00320 
00321                     /*
00322                      * AND-clause => atom if any of A's items implies B
00323                      */
00324                     result = false;
00325                     iterate_begin(citem, clause, clause_info)
00326                     {
00327                         if (predicate_implied_by_recurse(citem, predicate))
00328                         {
00329                             result = true;
00330                             break;
00331                         }
00332                     }
00333                     iterate_end(clause_info);
00334                     return result;
00335             }
00336             break;
00337 
00338         case CLASS_OR:
00339             switch (pclass)
00340             {
00341                 case CLASS_OR:
00342 
00343                     /*
00344                      * OR-clause => OR-clause if each of A's items implies any
00345                      * of B's items.  Messy but can't do it any more simply.
00346                      */
00347                     result = true;
00348                     iterate_begin(citem, clause, clause_info)
00349                     {
00350                         bool        presult = false;
00351 
00352                         iterate_begin(pitem, predicate, pred_info)
00353                         {
00354                             if (predicate_implied_by_recurse(citem, pitem))
00355                             {
00356                                 presult = true;
00357                                 break;
00358                             }
00359                         }
00360                         iterate_end(pred_info);
00361                         if (!presult)
00362                         {
00363                             result = false;     /* doesn't imply any of B's */
00364                             break;
00365                         }
00366                     }
00367                     iterate_end(clause_info);
00368                     return result;
00369 
00370                 case CLASS_AND:
00371                 case CLASS_ATOM:
00372 
00373                     /*
00374                      * OR-clause => AND-clause if each of A's items implies B
00375                      *
00376                      * OR-clause => atom if each of A's items implies B
00377                      */
00378                     result = true;
00379                     iterate_begin(citem, clause, clause_info)
00380                     {
00381                         if (!predicate_implied_by_recurse(citem, predicate))
00382                         {
00383                             result = false;
00384                             break;
00385                         }
00386                     }
00387                     iterate_end(clause_info);
00388                     return result;
00389             }
00390             break;
00391 
00392         case CLASS_ATOM:
00393             switch (pclass)
00394             {
00395                 case CLASS_AND:
00396 
00397                     /*
00398                      * atom => AND-clause if A implies each of B's items
00399                      */
00400                     result = true;
00401                     iterate_begin(pitem, predicate, pred_info)
00402                     {
00403                         if (!predicate_implied_by_recurse(clause, pitem))
00404                         {
00405                             result = false;
00406                             break;
00407                         }
00408                     }
00409                     iterate_end(pred_info);
00410                     return result;
00411 
00412                 case CLASS_OR:
00413 
00414                     /*
00415                      * atom => OR-clause if A implies any of B's items
00416                      */
00417                     result = false;
00418                     iterate_begin(pitem, predicate, pred_info)
00419                     {
00420                         if (predicate_implied_by_recurse(clause, pitem))
00421                         {
00422                             result = true;
00423                             break;
00424                         }
00425                     }
00426                     iterate_end(pred_info);
00427                     return result;
00428 
00429                 case CLASS_ATOM:
00430 
00431                     /*
00432                      * atom => atom is the base case
00433                      */
00434                     return
00435                         predicate_implied_by_simple_clause((Expr *) predicate,
00436                                                            clause);
00437             }
00438             break;
00439     }
00440 
00441     /* can't get here */
00442     elog(ERROR, "predicate_classify returned a bogus value");
00443     return false;
00444 }
00445 
00446 /*----------
00447  * predicate_refuted_by_recurse
00448  *    Does the predicate refutation test for non-NULL restriction and
00449  *    predicate clauses.
00450  *
00451  * The logic followed here is ("R=>" means "refutes"):
00452  *  atom A R=> atom B iff:          predicate_refuted_by_simple_clause says so
00453  *  atom A R=> AND-expr B iff:      A R=> any of B's components
00454  *  atom A R=> OR-expr B iff:       A R=> each of B's components
00455  *  AND-expr A R=> atom B iff:      any of A's components R=> B
00456  *  AND-expr A R=> AND-expr B iff:  A R=> any of B's components,
00457  *                                  *or* any of A's components R=> B
00458  *  AND-expr A R=> OR-expr B iff:   A R=> each of B's components
00459  *  OR-expr A R=> atom B iff:       each of A's components R=> B
00460  *  OR-expr A R=> AND-expr B iff:   each of A's components R=> any of B's
00461  *  OR-expr A R=> OR-expr B iff:    A R=> each of B's components
00462  *
00463  * In addition, if the predicate is a NOT-clause then we can use
00464  *  A R=> NOT B if:                 A => B
00465  * This works for several different SQL constructs that assert the non-truth
00466  * of their argument, ie NOT, IS FALSE, IS NOT TRUE, IS UNKNOWN.
00467  * Unfortunately we *cannot* use
00468  *  NOT A R=> B if:                 B => A
00469  * because this type of reasoning fails to prove that B doesn't yield NULL.
00470  * We can however make the more limited deduction that
00471  *  NOT A R=> A
00472  *
00473  * Other comments are as for predicate_implied_by_recurse().
00474  *----------
00475  */
00476 static bool
00477 predicate_refuted_by_recurse(Node *clause, Node *predicate)
00478 {
00479     PredIterInfoData clause_info;
00480     PredIterInfoData pred_info;
00481     PredClass   pclass;
00482     Node       *not_arg;
00483     bool        result;
00484 
00485     /* skip through RestrictInfo */
00486     Assert(clause != NULL);
00487     if (IsA(clause, RestrictInfo))
00488         clause = (Node *) ((RestrictInfo *) clause)->clause;
00489 
00490     pclass = predicate_classify(predicate, &pred_info);
00491 
00492     switch (predicate_classify(clause, &clause_info))
00493     {
00494         case CLASS_AND:
00495             switch (pclass)
00496             {
00497                 case CLASS_AND:
00498 
00499                     /*
00500                      * AND-clause R=> AND-clause if A refutes any of B's items
00501                      *
00502                      * Needed to handle (x AND y) R=> ((!x OR !y) AND z)
00503                      */
00504                     result = false;
00505                     iterate_begin(pitem, predicate, pred_info)
00506                     {
00507                         if (predicate_refuted_by_recurse(clause, pitem))
00508                         {
00509                             result = true;
00510                             break;
00511                         }
00512                     }
00513                     iterate_end(pred_info);
00514                     if (result)
00515                         return result;
00516 
00517                     /*
00518                      * Also check if any of A's items refutes B
00519                      *
00520                      * Needed to handle ((x OR y) AND z) R=> (!x AND !y)
00521                      */
00522                     iterate_begin(citem, clause, clause_info)
00523                     {
00524                         if (predicate_refuted_by_recurse(citem, predicate))
00525                         {
00526                             result = true;
00527                             break;
00528                         }
00529                     }
00530                     iterate_end(clause_info);
00531                     return result;
00532 
00533                 case CLASS_OR:
00534 
00535                     /*
00536                      * AND-clause R=> OR-clause if A refutes each of B's items
00537                      */
00538                     result = true;
00539                     iterate_begin(pitem, predicate, pred_info)
00540                     {
00541                         if (!predicate_refuted_by_recurse(clause, pitem))
00542                         {
00543                             result = false;
00544                             break;
00545                         }
00546                     }
00547                     iterate_end(pred_info);
00548                     return result;
00549 
00550                 case CLASS_ATOM:
00551 
00552                     /*
00553                      * If B is a NOT-clause, A R=> B if A => B's arg
00554                      */
00555                     not_arg = extract_not_arg(predicate);
00556                     if (not_arg &&
00557                         predicate_implied_by_recurse(clause, not_arg))
00558                         return true;
00559 
00560                     /*
00561                      * AND-clause R=> atom if any of A's items refutes B
00562                      */
00563                     result = false;
00564                     iterate_begin(citem, clause, clause_info)
00565                     {
00566                         if (predicate_refuted_by_recurse(citem, predicate))
00567                         {
00568                             result = true;
00569                             break;
00570                         }
00571                     }
00572                     iterate_end(clause_info);
00573                     return result;
00574             }
00575             break;
00576 
00577         case CLASS_OR:
00578             switch (pclass)
00579             {
00580                 case CLASS_OR:
00581 
00582                     /*
00583                      * OR-clause R=> OR-clause if A refutes each of B's items
00584                      */
00585                     result = true;
00586                     iterate_begin(pitem, predicate, pred_info)
00587                     {
00588                         if (!predicate_refuted_by_recurse(clause, pitem))
00589                         {
00590                             result = false;
00591                             break;
00592                         }
00593                     }
00594                     iterate_end(pred_info);
00595                     return result;
00596 
00597                 case CLASS_AND:
00598 
00599                     /*
00600                      * OR-clause R=> AND-clause if each of A's items refutes
00601                      * any of B's items.
00602                      */
00603                     result = true;
00604                     iterate_begin(citem, clause, clause_info)
00605                     {
00606                         bool        presult = false;
00607 
00608                         iterate_begin(pitem, predicate, pred_info)
00609                         {
00610                             if (predicate_refuted_by_recurse(citem, pitem))
00611                             {
00612                                 presult = true;
00613                                 break;
00614                             }
00615                         }
00616                         iterate_end(pred_info);
00617                         if (!presult)
00618                         {
00619                             result = false;     /* citem refutes nothing */
00620                             break;
00621                         }
00622                     }
00623                     iterate_end(clause_info);
00624                     return result;
00625 
00626                 case CLASS_ATOM:
00627 
00628                     /*
00629                      * If B is a NOT-clause, A R=> B if A => B's arg
00630                      */
00631                     not_arg = extract_not_arg(predicate);
00632                     if (not_arg &&
00633                         predicate_implied_by_recurse(clause, not_arg))
00634                         return true;
00635 
00636                     /*
00637                      * OR-clause R=> atom if each of A's items refutes B
00638                      */
00639                     result = true;
00640                     iterate_begin(citem, clause, clause_info)
00641                     {
00642                         if (!predicate_refuted_by_recurse(citem, predicate))
00643                         {
00644                             result = false;
00645                             break;
00646                         }
00647                     }
00648                     iterate_end(clause_info);
00649                     return result;
00650             }
00651             break;
00652 
00653         case CLASS_ATOM:
00654 
00655             /*
00656              * If A is a strong NOT-clause, A R=> B if B equals A's arg
00657              *
00658              * We cannot make the stronger conclusion that B is refuted if B
00659              * implies A's arg; that would only prove that B is not-TRUE, not
00660              * that it's not NULL either.  Hence use equal() rather than
00661              * predicate_implied_by_recurse().  We could do the latter if we
00662              * ever had a need for the weak form of refutation.
00663              */
00664             not_arg = extract_strong_not_arg(clause);
00665             if (not_arg && equal(predicate, not_arg))
00666                 return true;
00667 
00668             switch (pclass)
00669             {
00670                 case CLASS_AND:
00671 
00672                     /*
00673                      * atom R=> AND-clause if A refutes any of B's items
00674                      */
00675                     result = false;
00676                     iterate_begin(pitem, predicate, pred_info)
00677                     {
00678                         if (predicate_refuted_by_recurse(clause, pitem))
00679                         {
00680                             result = true;
00681                             break;
00682                         }
00683                     }
00684                     iterate_end(pred_info);
00685                     return result;
00686 
00687                 case CLASS_OR:
00688 
00689                     /*
00690                      * atom R=> OR-clause if A refutes each of B's items
00691                      */
00692                     result = true;
00693                     iterate_begin(pitem, predicate, pred_info)
00694                     {
00695                         if (!predicate_refuted_by_recurse(clause, pitem))
00696                         {
00697                             result = false;
00698                             break;
00699                         }
00700                     }
00701                     iterate_end(pred_info);
00702                     return result;
00703 
00704                 case CLASS_ATOM:
00705 
00706                     /*
00707                      * If B is a NOT-clause, A R=> B if A => B's arg
00708                      */
00709                     not_arg = extract_not_arg(predicate);
00710                     if (not_arg &&
00711                         predicate_implied_by_recurse(clause, not_arg))
00712                         return true;
00713 
00714                     /*
00715                      * atom R=> atom is the base case
00716                      */
00717                     return
00718                         predicate_refuted_by_simple_clause((Expr *) predicate,
00719                                                            clause);
00720             }
00721             break;
00722     }
00723 
00724     /* can't get here */
00725     elog(ERROR, "predicate_classify returned a bogus value");
00726     return false;
00727 }
00728 
00729 
00730 /*
00731  * predicate_classify
00732  *    Classify an expression node as AND-type, OR-type, or neither (an atom).
00733  *
00734  * If the expression is classified as AND- or OR-type, then *info is filled
00735  * in with the functions needed to iterate over its components.
00736  *
00737  * This function also implements enforcement of MAX_SAOP_ARRAY_SIZE: if a
00738  * ScalarArrayOpExpr's array has too many elements, we just classify it as an
00739  * atom.  (This will result in its being passed as-is to the simple_clause
00740  * functions, which will fail to prove anything about it.)  Note that we
00741  * cannot just stop after considering MAX_SAOP_ARRAY_SIZE elements; in general
00742  * that would result in wrong proofs, rather than failing to prove anything.
00743  */
00744 static PredClass
00745 predicate_classify(Node *clause, PredIterInfo info)
00746 {
00747     /* Caller should not pass us NULL, nor a RestrictInfo clause */
00748     Assert(clause != NULL);
00749     Assert(!IsA(clause, RestrictInfo));
00750 
00751     /*
00752      * If we see a List, assume it's an implicit-AND list; this is the correct
00753      * semantics for lists of RestrictInfo nodes.
00754      */
00755     if (IsA(clause, List))
00756     {
00757         info->startup_fn = list_startup_fn;
00758         info->next_fn = list_next_fn;
00759         info->cleanup_fn = list_cleanup_fn;
00760         return CLASS_AND;
00761     }
00762 
00763     /* Handle normal AND and OR boolean clauses */
00764     if (and_clause(clause))
00765     {
00766         info->startup_fn = boolexpr_startup_fn;
00767         info->next_fn = list_next_fn;
00768         info->cleanup_fn = list_cleanup_fn;
00769         return CLASS_AND;
00770     }
00771     if (or_clause(clause))
00772     {
00773         info->startup_fn = boolexpr_startup_fn;
00774         info->next_fn = list_next_fn;
00775         info->cleanup_fn = list_cleanup_fn;
00776         return CLASS_OR;
00777     }
00778 
00779     /* Handle ScalarArrayOpExpr */
00780     if (IsA(clause, ScalarArrayOpExpr))
00781     {
00782         ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
00783         Node       *arraynode = (Node *) lsecond(saop->args);
00784 
00785         /*
00786          * We can break this down into an AND or OR structure, but only if we
00787          * know how to iterate through expressions for the array's elements.
00788          * We can do that if the array operand is a non-null constant or a
00789          * simple ArrayExpr.
00790          */
00791         if (arraynode && IsA(arraynode, Const) &&
00792             !((Const *) arraynode)->constisnull)
00793         {
00794             ArrayType  *arrayval;
00795             int         nelems;
00796 
00797             arrayval = DatumGetArrayTypeP(((Const *) arraynode)->constvalue);
00798             nelems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval));
00799             if (nelems <= MAX_SAOP_ARRAY_SIZE)
00800             {
00801                 info->startup_fn = arrayconst_startup_fn;
00802                 info->next_fn = arrayconst_next_fn;
00803                 info->cleanup_fn = arrayconst_cleanup_fn;
00804                 return saop->useOr ? CLASS_OR : CLASS_AND;
00805             }
00806         }
00807         else if (arraynode && IsA(arraynode, ArrayExpr) &&
00808                  !((ArrayExpr *) arraynode)->multidims &&
00809                  list_length(((ArrayExpr *) arraynode)->elements) <= MAX_SAOP_ARRAY_SIZE)
00810         {
00811             info->startup_fn = arrayexpr_startup_fn;
00812             info->next_fn = arrayexpr_next_fn;
00813             info->cleanup_fn = arrayexpr_cleanup_fn;
00814             return saop->useOr ? CLASS_OR : CLASS_AND;
00815         }
00816     }
00817 
00818     /* None of the above, so it's an atom */
00819     return CLASS_ATOM;
00820 }
00821 
00822 /*
00823  * PredIterInfo routines for iterating over regular Lists.  The iteration
00824  * state variable is the next ListCell to visit.
00825  */
00826 static void
00827 list_startup_fn(Node *clause, PredIterInfo info)
00828 {
00829     info->state = (void *) list_head((List *) clause);
00830 }
00831 
00832 static Node *
00833 list_next_fn(PredIterInfo info)
00834 {
00835     ListCell   *l = (ListCell *) info->state;
00836     Node       *n;
00837 
00838     if (l == NULL)
00839         return NULL;
00840     n = lfirst(l);
00841     info->state = (void *) lnext(l);
00842     return n;
00843 }
00844 
00845 static void
00846 list_cleanup_fn(PredIterInfo info)
00847 {
00848     /* Nothing to clean up */
00849 }
00850 
00851 /*
00852  * BoolExpr needs its own startup function, but can use list_next_fn and
00853  * list_cleanup_fn.
00854  */
00855 static void
00856 boolexpr_startup_fn(Node *clause, PredIterInfo info)
00857 {
00858     info->state = (void *) list_head(((BoolExpr *) clause)->args);
00859 }
00860 
00861 /*
00862  * PredIterInfo routines for iterating over a ScalarArrayOpExpr with a
00863  * constant array operand.
00864  */
00865 typedef struct
00866 {
00867     OpExpr      opexpr;
00868     Const       constexpr;
00869     int         next_elem;
00870     int         num_elems;
00871     Datum      *elem_values;
00872     bool       *elem_nulls;
00873 } ArrayConstIterState;
00874 
00875 static void
00876 arrayconst_startup_fn(Node *clause, PredIterInfo info)
00877 {
00878     ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
00879     ArrayConstIterState *state;
00880     Const      *arrayconst;
00881     ArrayType  *arrayval;
00882     int16       elmlen;
00883     bool        elmbyval;
00884     char        elmalign;
00885 
00886     /* Create working state struct */
00887     state = (ArrayConstIterState *) palloc(sizeof(ArrayConstIterState));
00888     info->state = (void *) state;
00889 
00890     /* Deconstruct the array literal */
00891     arrayconst = (Const *) lsecond(saop->args);
00892     arrayval = DatumGetArrayTypeP(arrayconst->constvalue);
00893     get_typlenbyvalalign(ARR_ELEMTYPE(arrayval),
00894                          &elmlen, &elmbyval, &elmalign);
00895     deconstruct_array(arrayval,
00896                       ARR_ELEMTYPE(arrayval),
00897                       elmlen, elmbyval, elmalign,
00898                       &state->elem_values, &state->elem_nulls,
00899                       &state->num_elems);
00900 
00901     /* Set up a dummy OpExpr to return as the per-item node */
00902     state->opexpr.xpr.type = T_OpExpr;
00903     state->opexpr.opno = saop->opno;
00904     state->opexpr.opfuncid = saop->opfuncid;
00905     state->opexpr.opresulttype = BOOLOID;
00906     state->opexpr.opretset = false;
00907     state->opexpr.opcollid = InvalidOid;
00908     state->opexpr.inputcollid = saop->inputcollid;
00909     state->opexpr.args = list_copy(saop->args);
00910 
00911     /* Set up a dummy Const node to hold the per-element values */
00912     state->constexpr.xpr.type = T_Const;
00913     state->constexpr.consttype = ARR_ELEMTYPE(arrayval);
00914     state->constexpr.consttypmod = -1;
00915     state->constexpr.constcollid = arrayconst->constcollid;
00916     state->constexpr.constlen = elmlen;
00917     state->constexpr.constbyval = elmbyval;
00918     lsecond(state->opexpr.args) = &state->constexpr;
00919 
00920     /* Initialize iteration state */
00921     state->next_elem = 0;
00922 }
00923 
00924 static Node *
00925 arrayconst_next_fn(PredIterInfo info)
00926 {
00927     ArrayConstIterState *state = (ArrayConstIterState *) info->state;
00928 
00929     if (state->next_elem >= state->num_elems)
00930         return NULL;
00931     state->constexpr.constvalue = state->elem_values[state->next_elem];
00932     state->constexpr.constisnull = state->elem_nulls[state->next_elem];
00933     state->next_elem++;
00934     return (Node *) &(state->opexpr);
00935 }
00936 
00937 static void
00938 arrayconst_cleanup_fn(PredIterInfo info)
00939 {
00940     ArrayConstIterState *state = (ArrayConstIterState *) info->state;
00941 
00942     pfree(state->elem_values);
00943     pfree(state->elem_nulls);
00944     list_free(state->opexpr.args);
00945     pfree(state);
00946 }
00947 
00948 /*
00949  * PredIterInfo routines for iterating over a ScalarArrayOpExpr with a
00950  * one-dimensional ArrayExpr array operand.
00951  */
00952 typedef struct
00953 {
00954     OpExpr      opexpr;
00955     ListCell   *next;
00956 } ArrayExprIterState;
00957 
00958 static void
00959 arrayexpr_startup_fn(Node *clause, PredIterInfo info)
00960 {
00961     ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
00962     ArrayExprIterState *state;
00963     ArrayExpr  *arrayexpr;
00964 
00965     /* Create working state struct */
00966     state = (ArrayExprIterState *) palloc(sizeof(ArrayExprIterState));
00967     info->state = (void *) state;
00968 
00969     /* Set up a dummy OpExpr to return as the per-item node */
00970     state->opexpr.xpr.type = T_OpExpr;
00971     state->opexpr.opno = saop->opno;
00972     state->opexpr.opfuncid = saop->opfuncid;
00973     state->opexpr.opresulttype = BOOLOID;
00974     state->opexpr.opretset = false;
00975     state->opexpr.opcollid = InvalidOid;
00976     state->opexpr.inputcollid = saop->inputcollid;
00977     state->opexpr.args = list_copy(saop->args);
00978 
00979     /* Initialize iteration variable to first member of ArrayExpr */
00980     arrayexpr = (ArrayExpr *) lsecond(saop->args);
00981     state->next = list_head(arrayexpr->elements);
00982 }
00983 
00984 static Node *
00985 arrayexpr_next_fn(PredIterInfo info)
00986 {
00987     ArrayExprIterState *state = (ArrayExprIterState *) info->state;
00988 
00989     if (state->next == NULL)
00990         return NULL;
00991     lsecond(state->opexpr.args) = lfirst(state->next);
00992     state->next = lnext(state->next);
00993     return (Node *) &(state->opexpr);
00994 }
00995 
00996 static void
00997 arrayexpr_cleanup_fn(PredIterInfo info)
00998 {
00999     ArrayExprIterState *state = (ArrayExprIterState *) info->state;
01000 
01001     list_free(state->opexpr.args);
01002     pfree(state);
01003 }
01004 
01005 
01006 /*----------
01007  * predicate_implied_by_simple_clause
01008  *    Does the predicate implication test for a "simple clause" predicate
01009  *    and a "simple clause" restriction.
01010  *
01011  * We return TRUE if able to prove the implication, FALSE if not.
01012  *
01013  * We have three strategies for determining whether one simple clause
01014  * implies another:
01015  *
01016  * A simple and general way is to see if they are equal(); this works for any
01017  * kind of expression.  (Actually, there is an implied assumption that the
01018  * functions in the expression are immutable, ie dependent only on their input
01019  * arguments --- but this was checked for the predicate by the caller.)
01020  *
01021  * When the predicate is of the form "foo IS NOT NULL", we can conclude that
01022  * the predicate is implied if the clause is a strict operator or function
01023  * that has "foo" as an input.  In this case the clause must yield NULL when
01024  * "foo" is NULL, which we can take as equivalent to FALSE because we know
01025  * we are within an AND/OR subtree of a WHERE clause.  (Again, "foo" is
01026  * already known immutable, so the clause will certainly always fail.)
01027  *
01028  * Finally, we may be able to deduce something using knowledge about btree
01029  * operator families; this is encapsulated in btree_predicate_proof().
01030  *----------
01031  */
01032 static bool
01033 predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
01034 {
01035     /* Allow interrupting long proof attempts */
01036     CHECK_FOR_INTERRUPTS();
01037 
01038     /* First try the equal() test */
01039     if (equal((Node *) predicate, clause))
01040         return true;
01041 
01042     /* Next try the IS NOT NULL case */
01043     if (predicate && IsA(predicate, NullTest) &&
01044         ((NullTest *) predicate)->nulltesttype == IS_NOT_NULL)
01045     {
01046         Expr       *nonnullarg = ((NullTest *) predicate)->arg;
01047 
01048         /* row IS NOT NULL does not act in the simple way we have in mind */
01049         if (!((NullTest *) predicate)->argisrow)
01050         {
01051             if (is_opclause(clause) &&
01052                 list_member_strip(((OpExpr *) clause)->args, nonnullarg) &&
01053                 op_strict(((OpExpr *) clause)->opno))
01054                 return true;
01055             if (is_funcclause(clause) &&
01056                 list_member_strip(((FuncExpr *) clause)->args, nonnullarg) &&
01057                 func_strict(((FuncExpr *) clause)->funcid))
01058                 return true;
01059         }
01060         return false;           /* we can't succeed below... */
01061     }
01062 
01063     /* Else try btree operator knowledge */
01064     return btree_predicate_proof(predicate, clause, false);
01065 }
01066 
01067 /*----------
01068  * predicate_refuted_by_simple_clause
01069  *    Does the predicate refutation test for a "simple clause" predicate
01070  *    and a "simple clause" restriction.
01071  *
01072  * We return TRUE if able to prove the refutation, FALSE if not.
01073  *
01074  * Unlike the implication case, checking for equal() clauses isn't
01075  * helpful.
01076  *
01077  * When the predicate is of the form "foo IS NULL", we can conclude that
01078  * the predicate is refuted if the clause is a strict operator or function
01079  * that has "foo" as an input (see notes for implication case), or if the
01080  * clause is "foo IS NOT NULL".  A clause "foo IS NULL" refutes a predicate
01081  * "foo IS NOT NULL", but unfortunately does not refute strict predicates,
01082  * because we are looking for strong refutation.  (The motivation for covering
01083  * these cases is to support using IS NULL/IS NOT NULL as partition-defining
01084  * constraints.)
01085  *
01086  * Finally, we may be able to deduce something using knowledge about btree
01087  * operator families; this is encapsulated in btree_predicate_proof().
01088  *----------
01089  */
01090 static bool
01091 predicate_refuted_by_simple_clause(Expr *predicate, Node *clause)
01092 {
01093     /* Allow interrupting long proof attempts */
01094     CHECK_FOR_INTERRUPTS();
01095 
01096     /* A simple clause can't refute itself */
01097     /* Worth checking because of relation_excluded_by_constraints() */
01098     if ((Node *) predicate == clause)
01099         return false;
01100 
01101     /* Try the predicate-IS-NULL case */
01102     if (predicate && IsA(predicate, NullTest) &&
01103         ((NullTest *) predicate)->nulltesttype == IS_NULL)
01104     {
01105         Expr       *isnullarg = ((NullTest *) predicate)->arg;
01106 
01107         /* row IS NULL does not act in the simple way we have in mind */
01108         if (((NullTest *) predicate)->argisrow)
01109             return false;
01110 
01111         /* Any strict op/func on foo refutes foo IS NULL */
01112         if (is_opclause(clause) &&
01113             list_member_strip(((OpExpr *) clause)->args, isnullarg) &&
01114             op_strict(((OpExpr *) clause)->opno))
01115             return true;
01116         if (is_funcclause(clause) &&
01117             list_member_strip(((FuncExpr *) clause)->args, isnullarg) &&
01118             func_strict(((FuncExpr *) clause)->funcid))
01119             return true;
01120 
01121         /* foo IS NOT NULL refutes foo IS NULL */
01122         if (clause && IsA(clause, NullTest) &&
01123             ((NullTest *) clause)->nulltesttype == IS_NOT_NULL &&
01124             !((NullTest *) clause)->argisrow &&
01125             equal(((NullTest *) clause)->arg, isnullarg))
01126             return true;
01127 
01128         return false;           /* we can't succeed below... */
01129     }
01130 
01131     /* Try the clause-IS-NULL case */
01132     if (clause && IsA(clause, NullTest) &&
01133         ((NullTest *) clause)->nulltesttype == IS_NULL)
01134     {
01135         Expr       *isnullarg = ((NullTest *) clause)->arg;
01136 
01137         /* row IS NULL does not act in the simple way we have in mind */
01138         if (((NullTest *) clause)->argisrow)
01139             return false;
01140 
01141         /* foo IS NULL refutes foo IS NOT NULL */
01142         if (predicate && IsA(predicate, NullTest) &&
01143             ((NullTest *) predicate)->nulltesttype == IS_NOT_NULL &&
01144             !((NullTest *) predicate)->argisrow &&
01145             equal(((NullTest *) predicate)->arg, isnullarg))
01146             return true;
01147 
01148         return false;           /* we can't succeed below... */
01149     }
01150 
01151     /* Else try btree operator knowledge */
01152     return btree_predicate_proof(predicate, clause, true);
01153 }
01154 
01155 
01156 /*
01157  * If clause asserts the non-truth of a subclause, return that subclause;
01158  * otherwise return NULL.
01159  */
01160 static Node *
01161 extract_not_arg(Node *clause)
01162 {
01163     if (clause == NULL)
01164         return NULL;
01165     if (IsA(clause, BoolExpr))
01166     {
01167         BoolExpr   *bexpr = (BoolExpr *) clause;
01168 
01169         if (bexpr->boolop == NOT_EXPR)
01170             return (Node *) linitial(bexpr->args);
01171     }
01172     else if (IsA(clause, BooleanTest))
01173     {
01174         BooleanTest *btest = (BooleanTest *) clause;
01175 
01176         if (btest->booltesttype == IS_NOT_TRUE ||
01177             btest->booltesttype == IS_FALSE ||
01178             btest->booltesttype == IS_UNKNOWN)
01179             return (Node *) btest->arg;
01180     }
01181     return NULL;
01182 }
01183 
01184 /*
01185  * If clause asserts the falsity of a subclause, return that subclause;
01186  * otherwise return NULL.
01187  */
01188 static Node *
01189 extract_strong_not_arg(Node *clause)
01190 {
01191     if (clause == NULL)
01192         return NULL;
01193     if (IsA(clause, BoolExpr))
01194     {
01195         BoolExpr   *bexpr = (BoolExpr *) clause;
01196 
01197         if (bexpr->boolop == NOT_EXPR)
01198             return (Node *) linitial(bexpr->args);
01199     }
01200     else if (IsA(clause, BooleanTest))
01201     {
01202         BooleanTest *btest = (BooleanTest *) clause;
01203 
01204         if (btest->booltesttype == IS_FALSE)
01205             return (Node *) btest->arg;
01206     }
01207     return NULL;
01208 }
01209 
01210 
01211 /*
01212  * Check whether an Expr is equal() to any member of a list, ignoring
01213  * any top-level RelabelType nodes.  This is legitimate for the purposes
01214  * we use it for (matching IS [NOT] NULL arguments to arguments of strict
01215  * functions) because RelabelType doesn't change null-ness.  It's helpful
01216  * for cases such as a varchar argument of a strict function on text.
01217  */
01218 static bool
01219 list_member_strip(List *list, Expr *datum)
01220 {
01221     ListCell   *cell;
01222 
01223     if (datum && IsA(datum, RelabelType))
01224         datum = ((RelabelType *) datum)->arg;
01225 
01226     foreach(cell, list)
01227     {
01228         Expr       *elem = (Expr *) lfirst(cell);
01229 
01230         if (elem && IsA(elem, RelabelType))
01231             elem = ((RelabelType *) elem)->arg;
01232 
01233         if (equal(elem, datum))
01234             return true;
01235     }
01236 
01237     return false;
01238 }
01239 
01240 
01241 /*
01242  * Define an "operator implication table" for btree operators ("strategies"),
01243  * and a similar table for refutation.
01244  *
01245  * The strategy numbers defined by btree indexes (see access/skey.h) are:
01246  *      (1) <   (2) <=   (3) =   (4) >=   (5) >
01247  * and in addition we use (6) to represent <>.  <> is not a btree-indexable
01248  * operator, but we assume here that if an equality operator of a btree
01249  * opfamily has a negator operator, the negator behaves as <> for the opfamily.
01250  * (This convention is also known to get_op_btree_interpretation().)
01251  *
01252  * The interpretation of:
01253  *
01254  *      test_op = BT_implic_table[given_op-1][target_op-1]
01255  *
01256  * where test_op, given_op and target_op are strategy numbers (from 1 to 6)
01257  * of btree operators, is as follows:
01258  *
01259  *   If you know, for some ATTR, that "ATTR given_op CONST1" is true, and you
01260  *   want to determine whether "ATTR target_op CONST2" must also be true, then
01261  *   you can use "CONST2 test_op CONST1" as a test.  If this test returns true,
01262  *   then the target expression must be true; if the test returns false, then
01263  *   the target expression may be false.
01264  *
01265  * For example, if clause is "Quantity > 10" and pred is "Quantity > 5"
01266  * then we test "5 <= 10" which evals to true, so clause implies pred.
01267  *
01268  * Similarly, the interpretation of a BT_refute_table entry is:
01269  *
01270  *   If you know, for some ATTR, that "ATTR given_op CONST1" is true, and you
01271  *   want to determine whether "ATTR target_op CONST2" must be false, then
01272  *   you can use "CONST2 test_op CONST1" as a test.  If this test returns true,
01273  *   then the target expression must be false; if the test returns false, then
01274  *   the target expression may be true.
01275  *
01276  * For example, if clause is "Quantity > 10" and pred is "Quantity < 5"
01277  * then we test "5 <= 10" which evals to true, so clause refutes pred.
01278  *
01279  * An entry where test_op == 0 means the implication cannot be determined.
01280  */
01281 
01282 #define BTLT BTLessStrategyNumber
01283 #define BTLE BTLessEqualStrategyNumber
01284 #define BTEQ BTEqualStrategyNumber
01285 #define BTGE BTGreaterEqualStrategyNumber
01286 #define BTGT BTGreaterStrategyNumber
01287 #define BTNE ROWCOMPARE_NE
01288 
01289 static const StrategyNumber BT_implic_table[6][6] = {
01290 /*
01291  *          The target operator:
01292  *
01293  *   LT    LE    EQ    GE    GT    NE
01294  */
01295     {BTGE, BTGE, 0, 0, 0, BTGE},    /* LT */
01296     {BTGT, BTGE, 0, 0, 0, BTGT},    /* LE */
01297     {BTGT, BTGE, BTEQ, BTLE, BTLT, BTNE},       /* EQ */
01298     {0, 0, 0, BTLE, BTLT, BTLT},    /* GE */
01299     {0, 0, 0, BTLE, BTLE, BTLE},    /* GT */
01300     {0, 0, 0, 0, 0, BTEQ}       /* NE */
01301 };
01302 
01303 static const StrategyNumber BT_refute_table[6][6] = {
01304 /*
01305  *          The target operator:
01306  *
01307  *   LT    LE    EQ    GE    GT    NE
01308  */
01309     {0, 0, BTGE, BTGE, BTGE, 0},    /* LT */
01310     {0, 0, BTGT, BTGT, BTGE, 0},    /* LE */
01311     {BTLE, BTLT, BTNE, BTGT, BTGE, BTEQ},       /* EQ */
01312     {BTLE, BTLT, BTLT, 0, 0, 0},    /* GE */
01313     {BTLE, BTLE, BTLE, 0, 0, 0},    /* GT */
01314     {0, 0, BTEQ, 0, 0, 0}       /* NE */
01315 };
01316 
01317 
01318 /*
01319  * btree_predicate_proof
01320  *    Does the predicate implication or refutation test for a "simple clause"
01321  *    predicate and a "simple clause" restriction, when both are simple
01322  *    operator clauses using related btree operators.
01323  *
01324  * When refute_it == false, we want to prove the predicate true;
01325  * when refute_it == true, we want to prove the predicate false.
01326  * (There is enough common code to justify handling these two cases
01327  * in one routine.)  We return TRUE if able to make the proof, FALSE
01328  * if not able to prove it.
01329  *
01330  * What we look for here is binary boolean opclauses of the form
01331  * "foo op constant", where "foo" is the same in both clauses.  The operators
01332  * and constants can be different but the operators must be in the same btree
01333  * operator family.  We use the above operator implication tables to
01334  * derive implications between nonidentical clauses.  (Note: "foo" is known
01335  * immutable, and constants are surely immutable, but we have to check that
01336  * the operators are too.  As of 8.0 it's possible for opfamilies to contain
01337  * operators that are merely stable, and we dare not make deductions with
01338  * these.)
01339  */
01340 static bool
01341 btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
01342 {
01343     Node       *leftop,
01344                *rightop;
01345     Node       *pred_var,
01346                *clause_var;
01347     Const      *pred_const,
01348                *clause_const;
01349     bool        pred_var_on_left,
01350                 clause_var_on_left;
01351     Oid         pred_collation,
01352                 clause_collation;
01353     Oid         pred_op,
01354                 clause_op,
01355                 test_op;
01356     Expr       *test_expr;
01357     ExprState  *test_exprstate;
01358     Datum       test_result;
01359     bool        isNull;
01360     EState     *estate;
01361     MemoryContext oldcontext;
01362 
01363     /*
01364      * Both expressions must be binary opclauses with a Const on one side, and
01365      * identical subexpressions on the other sides. Note we don't have to
01366      * think about binary relabeling of the Const node, since that would have
01367      * been folded right into the Const.
01368      *
01369      * If either Const is null, we also fail right away; this assumes that the
01370      * test operator will always be strict.
01371      */
01372     if (!is_opclause(predicate))
01373         return false;
01374     leftop = get_leftop(predicate);
01375     rightop = get_rightop(predicate);
01376     if (rightop == NULL)
01377         return false;           /* not a binary opclause */
01378     if (IsA(rightop, Const))
01379     {
01380         pred_var = leftop;
01381         pred_const = (Const *) rightop;
01382         pred_var_on_left = true;
01383     }
01384     else if (IsA(leftop, Const))
01385     {
01386         pred_var = rightop;
01387         pred_const = (Const *) leftop;
01388         pred_var_on_left = false;
01389     }
01390     else
01391         return false;           /* no Const to be found */
01392     if (pred_const->constisnull)
01393         return false;
01394 
01395     if (!is_opclause(clause))
01396         return false;
01397     leftop = get_leftop((Expr *) clause);
01398     rightop = get_rightop((Expr *) clause);
01399     if (rightop == NULL)
01400         return false;           /* not a binary opclause */
01401     if (IsA(rightop, Const))
01402     {
01403         clause_var = leftop;
01404         clause_const = (Const *) rightop;
01405         clause_var_on_left = true;
01406     }
01407     else if (IsA(leftop, Const))
01408     {
01409         clause_var = rightop;
01410         clause_const = (Const *) leftop;
01411         clause_var_on_left = false;
01412     }
01413     else
01414         return false;           /* no Const to be found */
01415     if (clause_const->constisnull)
01416         return false;
01417 
01418     /*
01419      * Check for matching subexpressions on the non-Const sides.  We used to
01420      * only allow a simple Var, but it's about as easy to allow any
01421      * expression.  Remember we already know that the pred expression does not
01422      * contain any non-immutable functions, so identical expressions should
01423      * yield identical results.
01424      */
01425     if (!equal(pred_var, clause_var))
01426         return false;
01427 
01428     /*
01429      * They'd better have the same collation, too.
01430      */
01431     pred_collation = ((OpExpr *) predicate)->inputcollid;
01432     clause_collation = ((OpExpr *) clause)->inputcollid;
01433     if (pred_collation != clause_collation)
01434         return false;
01435 
01436     /*
01437      * Okay, get the operators in the two clauses we're comparing. Commute
01438      * them if needed so that we can assume the variables are on the left.
01439      */
01440     pred_op = ((OpExpr *) predicate)->opno;
01441     if (!pred_var_on_left)
01442     {
01443         pred_op = get_commutator(pred_op);
01444         if (!OidIsValid(pred_op))
01445             return false;
01446     }
01447 
01448     clause_op = ((OpExpr *) clause)->opno;
01449     if (!clause_var_on_left)
01450     {
01451         clause_op = get_commutator(clause_op);
01452         if (!OidIsValid(clause_op))
01453             return false;
01454     }
01455 
01456     /*
01457      * Lookup the comparison operator using the system catalogs and the
01458      * operator implication tables.
01459      */
01460     test_op = get_btree_test_op(pred_op, clause_op, refute_it);
01461 
01462     if (!OidIsValid(test_op))
01463     {
01464         /* couldn't find a suitable comparison operator */
01465         return false;
01466     }
01467 
01468     /*
01469      * Evaluate the test.  For this we need an EState.
01470      */
01471     estate = CreateExecutorState();
01472 
01473     /* We can use the estate's working context to avoid memory leaks. */
01474     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
01475 
01476     /* Build expression tree */
01477     test_expr = make_opclause(test_op,
01478                               BOOLOID,
01479                               false,
01480                               (Expr *) pred_const,
01481                               (Expr *) clause_const,
01482                               InvalidOid,
01483                               pred_collation);
01484 
01485     /* Fill in opfuncids */
01486     fix_opfuncids((Node *) test_expr);
01487 
01488     /* Prepare it for execution */
01489     test_exprstate = ExecInitExpr(test_expr, NULL);
01490 
01491     /* And execute it. */
01492     test_result = ExecEvalExprSwitchContext(test_exprstate,
01493                                             GetPerTupleExprContext(estate),
01494                                             &isNull, NULL);
01495 
01496     /* Get back to outer memory context */
01497     MemoryContextSwitchTo(oldcontext);
01498 
01499     /* Release all the junk we just created */
01500     FreeExecutorState(estate);
01501 
01502     if (isNull)
01503     {
01504         /* Treat a null result as non-proof ... but it's a tad fishy ... */
01505         elog(DEBUG2, "null predicate test result");
01506         return false;
01507     }
01508     return DatumGetBool(test_result);
01509 }
01510 
01511 
01512 /*
01513  * We use a lookaside table to cache the result of btree proof operator
01514  * lookups, since the actual lookup is pretty expensive and doesn't change
01515  * for any given pair of operators (at least as long as pg_amop doesn't
01516  * change).  A single hash entry stores both positive and negative results
01517  * for a given pair of operators.
01518  */
01519 typedef struct OprProofCacheKey
01520 {
01521     Oid         pred_op;        /* predicate operator */
01522     Oid         clause_op;      /* clause operator */
01523 } OprProofCacheKey;
01524 
01525 typedef struct OprProofCacheEntry
01526 {
01527     /* the hash lookup key MUST BE FIRST */
01528     OprProofCacheKey key;
01529 
01530     bool        have_implic;    /* do we know the implication result? */
01531     bool        have_refute;    /* do we know the refutation result? */
01532     Oid         implic_test_op; /* OID of the operator, or 0 if none */
01533     Oid         refute_test_op; /* OID of the operator, or 0 if none */
01534 } OprProofCacheEntry;
01535 
01536 static HTAB *OprProofCacheHash = NULL;
01537 
01538 
01539 /*
01540  * get_btree_test_op
01541  *    Identify the comparison operator needed for a btree-operator
01542  *    proof or refutation.
01543  *
01544  * Given the truth of a predicate "var pred_op const1", we are attempting to
01545  * prove or refute a clause "var clause_op const2".  The identities of the two
01546  * operators are sufficient to determine the operator (if any) to compare
01547  * const2 to const1 with.
01548  *
01549  * Returns the OID of the operator to use, or InvalidOid if no proof is
01550  * possible.
01551  */
01552 static Oid
01553 get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
01554 {
01555     OprProofCacheKey key;
01556     OprProofCacheEntry *cache_entry;
01557     bool        cfound;
01558     Oid         test_op = InvalidOid;
01559     bool        found = false;
01560     List       *pred_op_infos,
01561                *clause_op_infos;
01562     ListCell   *lcp,
01563                *lcc;
01564 
01565     /*
01566      * Find or make a cache entry for this pair of operators.
01567      */
01568     if (OprProofCacheHash == NULL)
01569     {
01570         /* First time through: initialize the hash table */
01571         HASHCTL     ctl;
01572 
01573         MemSet(&ctl, 0, sizeof(ctl));
01574         ctl.keysize = sizeof(OprProofCacheKey);
01575         ctl.entrysize = sizeof(OprProofCacheEntry);
01576         ctl.hash = tag_hash;
01577         OprProofCacheHash = hash_create("Btree proof lookup cache", 256,
01578                                         &ctl, HASH_ELEM | HASH_FUNCTION);
01579 
01580         /* Arrange to flush cache on pg_amop changes */
01581         CacheRegisterSyscacheCallback(AMOPOPID,
01582                                       InvalidateOprProofCacheCallBack,
01583                                       (Datum) 0);
01584     }
01585 
01586     key.pred_op = pred_op;
01587     key.clause_op = clause_op;
01588     cache_entry = (OprProofCacheEntry *) hash_search(OprProofCacheHash,
01589                                                      (void *) &key,
01590                                                      HASH_ENTER, &cfound);
01591     if (!cfound)
01592     {
01593         /* new cache entry, set it invalid */
01594         cache_entry->have_implic = false;
01595         cache_entry->have_refute = false;
01596     }
01597     else
01598     {
01599         /* pre-existing cache entry, see if we know the answer */
01600         if (refute_it)
01601         {
01602             if (cache_entry->have_refute)
01603                 return cache_entry->refute_test_op;
01604         }
01605         else
01606         {
01607             if (cache_entry->have_implic)
01608                 return cache_entry->implic_test_op;
01609         }
01610     }
01611 
01612     /*
01613      * Try to find a btree opfamily containing the given operators.
01614      *
01615      * We must find a btree opfamily that contains both operators, else the
01616      * implication can't be determined.  Also, the opfamily must contain a
01617      * suitable test operator taking the operators' righthand datatypes.
01618      *
01619      * If there are multiple matching opfamilies, assume we can use any one to
01620      * determine the logical relationship of the two operators and the correct
01621      * corresponding test operator.  This should work for any logically
01622      * consistent opfamilies.
01623      */
01624     clause_op_infos = get_op_btree_interpretation(clause_op);
01625     if (clause_op_infos)
01626         pred_op_infos = get_op_btree_interpretation(pred_op);
01627     else    /* no point in looking */
01628         pred_op_infos = NIL;
01629 
01630     foreach(lcp, pred_op_infos)
01631     {
01632         OpBtreeInterpretation *pred_op_info = lfirst(lcp);
01633         Oid         opfamily_id = pred_op_info->opfamily_id;
01634 
01635         foreach(lcc, clause_op_infos)
01636         {
01637             OpBtreeInterpretation *clause_op_info = lfirst(lcc);
01638             StrategyNumber pred_strategy,
01639                         clause_strategy,
01640                         test_strategy;
01641 
01642             /* Must find them in same opfamily */
01643             if (opfamily_id != clause_op_info->opfamily_id)
01644                 continue;
01645             /* Lefttypes should match */
01646             Assert(clause_op_info->oplefttype == pred_op_info->oplefttype);
01647 
01648             pred_strategy = pred_op_info->strategy;
01649             clause_strategy = clause_op_info->strategy;
01650 
01651             /*
01652              * Look up the "test" strategy number in the implication table
01653              */
01654             if (refute_it)
01655                 test_strategy = BT_refute_table[clause_strategy - 1][pred_strategy - 1];
01656             else
01657                 test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
01658 
01659             if (test_strategy == 0)
01660             {
01661                 /* Can't determine implication using this interpretation */
01662                 continue;
01663             }
01664 
01665             /*
01666              * See if opfamily has an operator for the test strategy and the
01667              * datatypes.
01668              */
01669             if (test_strategy == BTNE)
01670             {
01671                 test_op = get_opfamily_member(opfamily_id,
01672                                               pred_op_info->oprighttype,
01673                                               clause_op_info->oprighttype,
01674                                               BTEqualStrategyNumber);
01675                 if (OidIsValid(test_op))
01676                     test_op = get_negator(test_op);
01677             }
01678             else
01679             {
01680                 test_op = get_opfamily_member(opfamily_id,
01681                                               pred_op_info->oprighttype,
01682                                               clause_op_info->oprighttype,
01683                                               test_strategy);
01684             }
01685 
01686             if (!OidIsValid(test_op))
01687                 continue;
01688 
01689             /*
01690              * Last check: test_op must be immutable.
01691              *
01692              * Note that we require only the test_op to be immutable, not the
01693              * original clause_op.  (pred_op is assumed to have been checked
01694              * immutable by the caller.)  Essentially we are assuming that the
01695              * opfamily is consistent even if it contains operators that are
01696              * merely stable.
01697              */
01698             if (op_volatile(test_op) == PROVOLATILE_IMMUTABLE)
01699             {
01700                 found = true;
01701                 break;
01702             }
01703         }
01704 
01705         if (found)
01706             break;
01707     }
01708 
01709     list_free_deep(pred_op_infos);
01710     list_free_deep(clause_op_infos);
01711 
01712     if (!found)
01713     {
01714         /* couldn't find a suitable comparison operator */
01715         test_op = InvalidOid;
01716     }
01717 
01718     /* Cache the result, whether positive or negative */
01719     if (refute_it)
01720     {
01721         cache_entry->refute_test_op = test_op;
01722         cache_entry->have_refute = true;
01723     }
01724     else
01725     {
01726         cache_entry->implic_test_op = test_op;
01727         cache_entry->have_implic = true;
01728     }
01729 
01730     return test_op;
01731 }
01732 
01733 
01734 /*
01735  * Callback for pg_amop inval events
01736  */
01737 static void
01738 InvalidateOprProofCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
01739 {
01740     HASH_SEQ_STATUS status;
01741     OprProofCacheEntry *hentry;
01742 
01743     Assert(OprProofCacheHash != NULL);
01744 
01745     /* Currently we just reset all entries; hard to be smarter ... */
01746     hash_seq_init(&status, OprProofCacheHash);
01747 
01748     while ((hentry = (OprProofCacheEntry *) hash_seq_search(&status)) != NULL)
01749     {
01750         hentry->have_implic = false;
01751         hentry->have_refute = false;
01752     }
01753 }