PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
predtest.c File Reference
#include "postgres.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/predtest.h"
#include "utils/array.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for predtest.c:

Go to the source code of this file.

Data Structures

struct  PredIterInfoData
 
struct  ArrayConstIterState
 
struct  ArrayExprIterState
 
struct  OprProofCacheKey
 
struct  OprProofCacheEntry
 

Macros

#define MAX_SAOP_ARRAY_SIZE   100
 
#define iterate_begin(item, clause, info)
 
#define iterate_end(info)
 
#define BTLT   BTLessStrategyNumber
 
#define BTLE   BTLessEqualStrategyNumber
 
#define BTEQ   BTEqualStrategyNumber
 
#define BTGE   BTGreaterEqualStrategyNumber
 
#define BTGT   BTGreaterStrategyNumber
 
#define BTNE   ROWCOMPARE_NE
 
#define none   0
 

Typedefs

typedef struct PredIterInfoDataPredIterInfo
 
typedef struct PredIterInfoData PredIterInfoData
 
typedef struct OprProofCacheKey OprProofCacheKey
 
typedef struct OprProofCacheEntry OprProofCacheEntry
 

Enumerations

enum  PredClass { CLASS_ATOM, CLASS_AND, CLASS_OR }
 

Functions

static bool predicate_implied_by_recurse (Node *clause, Node *predicate)
 
static bool predicate_refuted_by_recurse (Node *clause, Node *predicate)
 
static PredClass predicate_classify (Node *clause, PredIterInfo info)
 
static void list_startup_fn (Node *clause, PredIterInfo info)
 
static Nodelist_next_fn (PredIterInfo info)
 
static void list_cleanup_fn (PredIterInfo info)
 
static void boolexpr_startup_fn (Node *clause, PredIterInfo info)
 
static void arrayconst_startup_fn (Node *clause, PredIterInfo info)
 
static Nodearrayconst_next_fn (PredIterInfo info)
 
static void arrayconst_cleanup_fn (PredIterInfo info)
 
static void arrayexpr_startup_fn (Node *clause, PredIterInfo info)
 
static Nodearrayexpr_next_fn (PredIterInfo info)
 
static void arrayexpr_cleanup_fn (PredIterInfo info)
 
static bool predicate_implied_by_simple_clause (Expr *predicate, Node *clause)
 
static bool predicate_refuted_by_simple_clause (Expr *predicate, Node *clause)
 
static Nodeextract_not_arg (Node *clause)
 
static Nodeextract_strong_not_arg (Node *clause)
 
static bool list_member_strip (List *list, Expr *datum)
 
static bool operator_predicate_proof (Expr *predicate, Node *clause, bool refute_it)
 
static bool operator_same_subexprs_proof (Oid pred_op, Oid clause_op, bool refute_it)
 
static bool operator_same_subexprs_lookup (Oid pred_op, Oid clause_op, bool refute_it)
 
static Oid get_btree_test_op (Oid pred_op, Oid clause_op, bool refute_it)
 
static void InvalidateOprProofCacheCallBack (Datum arg, int cacheid, uint32 hashvalue)
 
bool predicate_implied_by (List *predicate_list, List *restrictinfo_list)
 
bool predicate_refuted_by (List *predicate_list, List *restrictinfo_list)
 
static OprProofCacheEntrylookup_proof_cache (Oid pred_op, Oid clause_op, bool refute_it)
 

Variables

static const bool BT_implies_table [6][6]
 
static const bool BT_refutes_table [6][6]
 
static const StrategyNumber BT_implic_table [6][6]
 
static const StrategyNumber BT_refute_table [6][6]
 
static HTABOprProofCacheHash = NULL
 

Macro Definition Documentation

#define BTEQ   BTEqualStrategyNumber

Definition at line 1308 of file predtest.c.

#define BTGE   BTGreaterEqualStrategyNumber

Definition at line 1309 of file predtest.c.

#define BTGT   BTGreaterStrategyNumber

Definition at line 1310 of file predtest.c.

#define BTLE   BTLessEqualStrategyNumber

Definition at line 1307 of file predtest.c.

#define BTLT   BTLessStrategyNumber

Definition at line 1306 of file predtest.c.

#define BTNE   ROWCOMPARE_NE

Definition at line 1311 of file predtest.c.

Referenced by lookup_proof_cache().

#define iterate_begin (   item,
  clause,
  info 
)
Value:
do { \
Node *item; \
(info).startup_fn((clause), &(info)); \
while ((item = (info).next_fn(&(info))) != NULL)
struct Node Node
#define NULL
Definition: c.h:226

Definition at line 69 of file predtest.c.

Referenced by predicate_implied_by_recurse(), and predicate_refuted_by_recurse().

#define iterate_end (   info)
Value:
(info).cleanup_fn(&(info)); \
} while (0)

Definition at line 75 of file predtest.c.

Referenced by predicate_implied_by_recurse(), and predicate_refuted_by_recurse().

#define MAX_SAOP_ARRAY_SIZE   100

Definition at line 38 of file predtest.c.

Referenced by predicate_classify().

#define none   0

Definition at line 1314 of file predtest.c.

Typedef Documentation

Definition at line 55 of file predtest.c.

Enumeration Type Documentation

enum PredClass
Enumerator
CLASS_ATOM 
CLASS_AND 
CLASS_OR 

Definition at line 48 of file predtest.c.

49 {
50  CLASS_ATOM, /* expression that's not AND or OR */
51  CLASS_AND, /* expression with AND semantics */
52  CLASS_OR /* expression with OR semantics */
53 } PredClass;
PredClass
Definition: predtest.c:48

Function Documentation

static void arrayconst_cleanup_fn ( PredIterInfo  info)
static

Definition at line 942 of file predtest.c.

References OpExpr::args, ArrayConstIterState::elem_nulls, ArrayConstIterState::elem_values, list_free(), ArrayConstIterState::opexpr, pfree(), and PredIterInfoData::state.

Referenced by predicate_classify().

943 {
945 
946  pfree(state->elem_values);
947  pfree(state->elem_nulls);
948  list_free(state->opexpr.args);
949  pfree(state);
950 }
Datum * elem_values
Definition: predtest.c:875
void * state
Definition: predtest.c:60
void pfree(void *pointer)
Definition: mcxt.c:992
Definition: regguts.h:298
void list_free(List *list)
Definition: list.c:1133
List * args
Definition: primnodes.h:479
static Node * arrayconst_next_fn ( PredIterInfo  info)
static

Definition at line 929 of file predtest.c.

References ArrayConstIterState::constexpr, Const::constisnull, Const::constvalue, ArrayConstIterState::elem_nulls, ArrayConstIterState::elem_values, ArrayConstIterState::next_elem, NULL, ArrayConstIterState::num_elems, ArrayConstIterState::opexpr, and PredIterInfoData::state.

Referenced by predicate_classify().

930 {
932 
933  if (state->next_elem >= state->num_elems)
934  return NULL;
935  state->constexpr.constvalue = state->elem_values[state->next_elem];
936  state->constexpr.constisnull = state->elem_nulls[state->next_elem];
937  state->next_elem++;
938  return (Node *) &(state->opexpr);
939 }
Datum constvalue
Definition: primnodes.h:174
Datum * elem_values
Definition: predtest.c:875
Definition: nodes.h:508
void * state
Definition: predtest.c:60
#define NULL
Definition: c.h:226
Definition: regguts.h:298
bool constisnull
Definition: primnodes.h:175
static void arrayconst_startup_fn ( Node clause,
PredIterInfo  info 
)
static

Definition at line 880 of file predtest.c.

References OpExpr::args, ScalarArrayOpExpr::args, ARR_ELEMTYPE, BOOLOID, Const::constbyval, Const::constcollid, ArrayConstIterState::constexpr, Const::constlen, Const::consttype, Const::consttypmod, Const::constvalue, DatumGetArrayTypeP, deconstruct_array(), ArrayConstIterState::elem_nulls, ArrayConstIterState::elem_values, get_typlenbyvalalign(), OpExpr::inputcollid, ScalarArrayOpExpr::inputcollid, InvalidOid, list_copy(), lsecond, ArrayConstIterState::next_elem, ArrayConstIterState::num_elems, OpExpr::opcollid, ArrayConstIterState::opexpr, OpExpr::opfuncid, ScalarArrayOpExpr::opfuncid, OpExpr::opno, ScalarArrayOpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, palloc(), PredIterInfoData::state, T_Const, T_OpExpr, Expr::type, Const::xpr, and OpExpr::xpr.

Referenced by predicate_classify().

881 {
882  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
884  Const *arrayconst;
885  ArrayType *arrayval;
886  int16 elmlen;
887  bool elmbyval;
888  char elmalign;
889 
890  /* Create working state struct */
891  state = (ArrayConstIterState *) palloc(sizeof(ArrayConstIterState));
892  info->state = (void *) state;
893 
894  /* Deconstruct the array literal */
895  arrayconst = (Const *) lsecond(saop->args);
896  arrayval = DatumGetArrayTypeP(arrayconst->constvalue);
898  &elmlen, &elmbyval, &elmalign);
899  deconstruct_array(arrayval,
900  ARR_ELEMTYPE(arrayval),
901  elmlen, elmbyval, elmalign,
902  &state->elem_values, &state->elem_nulls,
903  &state->num_elems);
904 
905  /* Set up a dummy OpExpr to return as the per-item node */
906  state->opexpr.xpr.type = T_OpExpr;
907  state->opexpr.opno = saop->opno;
908  state->opexpr.opfuncid = saop->opfuncid;
909  state->opexpr.opresulttype = BOOLOID;
910  state->opexpr.opretset = false;
911  state->opexpr.opcollid = InvalidOid;
912  state->opexpr.inputcollid = saop->inputcollid;
913  state->opexpr.args = list_copy(saop->args);
914 
915  /* Set up a dummy Const node to hold the per-element values */
916  state->constexpr.xpr.type = T_Const;
917  state->constexpr.consttype = ARR_ELEMTYPE(arrayval);
918  state->constexpr.consttypmod = -1;
919  state->constexpr.constcollid = arrayconst->constcollid;
920  state->constexpr.constlen = elmlen;
921  state->constexpr.constbyval = elmbyval;
922  lsecond(state->opexpr.args) = &state->constexpr;
923 
924  /* Initialize iteration state */
925  state->next_elem = 0;
926 }
Datum constvalue
Definition: primnodes.h:174
signed short int16
Definition: c.h:252
bool constbyval
Definition: primnodes.h:177
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
Datum * elem_values
Definition: predtest.c:875
List * list_copy(const List *oldlist)
Definition: list.c:1160
void * state
Definition: predtest.c:60
#define lsecond(l)
Definition: pg_list.h:114
int constlen
Definition: primnodes.h:173
Expr xpr
Definition: primnodes.h:472
Oid consttype
Definition: primnodes.h:170
Oid opresulttype
Definition: primnodes.h:475
Oid constcollid
Definition: primnodes.h:172
Expr xpr
Definition: primnodes.h:169
Oid opcollid
Definition: primnodes.h:477
Definition: nodes.h:140
Oid opfuncid
Definition: primnodes.h:474
#define InvalidOid
Definition: postgres_ext.h:36
Definition: regguts.h:298
Oid inputcollid
Definition: primnodes.h:478
#define BOOLOID
Definition: pg_type.h:288
int32 consttypmod
Definition: primnodes.h:171
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
void * palloc(Size size)
Definition: mcxt.c:891
NodeTag type
Definition: primnodes.h:112
Oid opno
Definition: primnodes.h:473
List * args
Definition: primnodes.h:479
#define ARR_ELEMTYPE(a)
Definition: array.h:273
bool opretset
Definition: primnodes.h:476
#define DatumGetArrayTypeP(X)
Definition: array.h:242
static void arrayexpr_cleanup_fn ( PredIterInfo  info)
static

Definition at line 1001 of file predtest.c.

References OpExpr::args, list_free(), ArrayExprIterState::opexpr, pfree(), and PredIterInfoData::state.

Referenced by predicate_classify().

1002 {
1004 
1005  list_free(state->opexpr.args);
1006  pfree(state);
1007 }
void * state
Definition: predtest.c:60
void pfree(void *pointer)
Definition: mcxt.c:992
Definition: regguts.h:298
void list_free(List *list)
Definition: list.c:1133
List * args
Definition: primnodes.h:479
static Node * arrayexpr_next_fn ( PredIterInfo  info)
static

Definition at line 989 of file predtest.c.

References OpExpr::args, lfirst, lnext, lsecond, ArrayExprIterState::next, NULL, ArrayExprIterState::opexpr, and PredIterInfoData::state.

Referenced by predicate_classify().

990 {
992 
993  if (state->next == NULL)
994  return NULL;
995  lsecond(state->opexpr.args) = lfirst(state->next);
996  state->next = lnext(state->next);
997  return (Node *) &(state->opexpr);
998 }
Definition: nodes.h:508
void * state
Definition: predtest.c:60
#define lsecond(l)
Definition: pg_list.h:114
#define lnext(lc)
Definition: pg_list.h:105
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:298
ListCell * next
Definition: predtest.c:959
List * args
Definition: primnodes.h:479
static void arrayexpr_startup_fn ( Node clause,
PredIterInfo  info 
)
static

Definition at line 963 of file predtest.c.

References OpExpr::args, ScalarArrayOpExpr::args, BOOLOID, ArrayExpr::elements, OpExpr::inputcollid, ScalarArrayOpExpr::inputcollid, InvalidOid, list_copy(), list_head(), lsecond, ArrayExprIterState::next, OpExpr::opcollid, ArrayExprIterState::opexpr, OpExpr::opfuncid, ScalarArrayOpExpr::opfuncid, OpExpr::opno, ScalarArrayOpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, palloc(), PredIterInfoData::state, T_OpExpr, Expr::type, and OpExpr::xpr.

Referenced by predicate_classify().

964 {
965  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
967  ArrayExpr *arrayexpr;
968 
969  /* Create working state struct */
970  state = (ArrayExprIterState *) palloc(sizeof(ArrayExprIterState));
971  info->state = (void *) state;
972 
973  /* Set up a dummy OpExpr to return as the per-item node */
974  state->opexpr.xpr.type = T_OpExpr;
975  state->opexpr.opno = saop->opno;
976  state->opexpr.opfuncid = saop->opfuncid;
977  state->opexpr.opresulttype = BOOLOID;
978  state->opexpr.opretset = false;
979  state->opexpr.opcollid = InvalidOid;
980  state->opexpr.inputcollid = saop->inputcollid;
981  state->opexpr.args = list_copy(saop->args);
982 
983  /* Initialize iteration variable to first member of ArrayExpr */
984  arrayexpr = (ArrayExpr *) lsecond(saop->args);
985  state->next = list_head(arrayexpr->elements);
986 }
List * list_copy(const List *oldlist)
Definition: list.c:1160
void * state
Definition: predtest.c:60
#define lsecond(l)
Definition: pg_list.h:114
Expr xpr
Definition: primnodes.h:472
Oid opresulttype
Definition: primnodes.h:475
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
List * elements
Definition: primnodes.h:931
Oid opcollid
Definition: primnodes.h:477
Oid opfuncid
Definition: primnodes.h:474
#define InvalidOid
Definition: postgres_ext.h:36
Definition: regguts.h:298
ListCell * next
Definition: predtest.c:959
Oid inputcollid
Definition: primnodes.h:478
#define BOOLOID
Definition: pg_type.h:288
void * palloc(Size size)
Definition: mcxt.c:891
NodeTag type
Definition: primnodes.h:112
Oid opno
Definition: primnodes.h:473
List * args
Definition: primnodes.h:479
bool opretset
Definition: primnodes.h:476
static void boolexpr_startup_fn ( Node clause,
PredIterInfo  info 
)
static

Definition at line 860 of file predtest.c.

References list_head(), and PredIterInfoData::state.

Referenced by predicate_classify().

861 {
862  info->state = (void *) list_head(((BoolExpr *) clause)->args);
863 }
void * state
Definition: predtest.c:60
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
static Node * extract_not_arg ( Node clause)
static

Definition at line 1171 of file predtest.c.

References BooleanTest::arg, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, IS_FALSE, IS_NOT_TRUE, IS_UNKNOWN, IsA, linitial, NOT_EXPR, and NULL.

Referenced by predicate_refuted_by_recurse().

1172 {
1173  if (clause == NULL)
1174  return NULL;
1175  if (IsA(clause, BoolExpr))
1176  {
1177  BoolExpr *bexpr = (BoolExpr *) clause;
1178 
1179  if (bexpr->boolop == NOT_EXPR)
1180  return (Node *) linitial(bexpr->args);
1181  }
1182  else if (IsA(clause, BooleanTest))
1183  {
1184  BooleanTest *btest = (BooleanTest *) clause;
1185 
1186  if (btest->booltesttype == IS_NOT_TRUE ||
1187  btest->booltesttype == IS_FALSE ||
1188  btest->booltesttype == IS_UNKNOWN)
1189  return (Node *) btest->arg;
1190  }
1191  return NULL;
1192 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Definition: nodes.h:508
#define linitial(l)
Definition: pg_list.h:110
BoolExprType boolop
Definition: primnodes.h:539
Expr * arg
Definition: primnodes.h:1179
BoolTestType booltesttype
Definition: primnodes.h:1180
#define NULL
Definition: c.h:226
List * args
Definition: primnodes.h:540
static Node * extract_strong_not_arg ( Node clause)
static

Definition at line 1199 of file predtest.c.

References BooleanTest::arg, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, IS_FALSE, IsA, linitial, NOT_EXPR, and NULL.

Referenced by predicate_refuted_by_recurse().

1200 {
1201  if (clause == NULL)
1202  return NULL;
1203  if (IsA(clause, BoolExpr))
1204  {
1205  BoolExpr *bexpr = (BoolExpr *) clause;
1206 
1207  if (bexpr->boolop == NOT_EXPR)
1208  return (Node *) linitial(bexpr->args);
1209  }
1210  else if (IsA(clause, BooleanTest))
1211  {
1212  BooleanTest *btest = (BooleanTest *) clause;
1213 
1214  if (btest->booltesttype == IS_FALSE)
1215  return (Node *) btest->arg;
1216  }
1217  return NULL;
1218 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Definition: nodes.h:508
#define linitial(l)
Definition: pg_list.h:110
BoolExprType boolop
Definition: primnodes.h:539
Expr * arg
Definition: primnodes.h:1179
BoolTestType booltesttype
Definition: primnodes.h:1180
#define NULL
Definition: c.h:226
List * args
Definition: primnodes.h:540
static Oid get_btree_test_op ( Oid  pred_op,
Oid  clause_op,
bool  refute_it 
)
static

Definition at line 1924 of file predtest.c.

References OprProofCacheEntry::implic_test_op, lookup_proof_cache(), and OprProofCacheEntry::refute_test_op.

Referenced by operator_predicate_proof().

1925 {
1926  OprProofCacheEntry *cache_entry;
1927 
1928  cache_entry = lookup_proof_cache(pred_op, clause_op, refute_it);
1929  if (refute_it)
1930  return cache_entry->refute_test_op;
1931  else
1932  return cache_entry->implic_test_op;
1933 }
static OprProofCacheEntry * lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
Definition: predtest.c:1694
static void InvalidateOprProofCacheCallBack ( Datum  arg,
int  cacheid,
uint32  hashvalue 
)
static

Definition at line 1940 of file predtest.c.

References Assert, hash_seq_init(), hash_seq_search(), OprProofCacheEntry::have_implic, OprProofCacheEntry::have_refute, NULL, and status().

Referenced by lookup_proof_cache().

1941 {
1943  OprProofCacheEntry *hentry;
1944 
1946 
1947  /* Currently we just reset all entries; hard to be smarter ... */
1948  hash_seq_init(&status, OprProofCacheHash);
1949 
1950  while ((hentry = (OprProofCacheEntry *) hash_seq_search(&status)) != NULL)
1951  {
1952  hentry->have_implic = false;
1953  hentry->have_refute = false;
1954  }
1955 }
static HTAB * OprProofCacheHash
Definition: predtest.c:1686
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
static void list_cleanup_fn ( PredIterInfo  info)
static

Definition at line 850 of file predtest.c.

Referenced by predicate_classify().

851 {
852  /* Nothing to clean up */
853 }
static bool list_member_strip ( List list,
Expr datum 
)
static

Definition at line 1229 of file predtest.c.

References arg, equal(), IsA, and lfirst.

Referenced by predicate_implied_by_simple_clause(), and predicate_refuted_by_simple_clause().

1230 {
1231  ListCell *cell;
1232 
1233  if (datum && IsA(datum, RelabelType))
1234  datum = ((RelabelType *) datum)->arg;
1235 
1236  foreach(cell, list)
1237  {
1238  Expr *elem = (Expr *) lfirst(cell);
1239 
1240  if (elem && IsA(elem, RelabelType))
1241  elem = ((RelabelType *) elem)->arg;
1242 
1243  if (equal(elem, datum))
1244  return true;
1245  }
1246 
1247  return false;
1248 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
#define lfirst(lc)
Definition: pg_list.h:106
void * arg
static Node * list_next_fn ( PredIterInfo  info)
static

Definition at line 837 of file predtest.c.

References lfirst, lnext, NULL, and PredIterInfoData::state.

Referenced by predicate_classify().

838 {
839  ListCell *l = (ListCell *) info->state;
840  Node *n;
841 
842  if (l == NULL)
843  return NULL;
844  n = lfirst(l);
845  info->state = (void *) lnext(l);
846  return n;
847 }
Definition: nodes.h:508
void * state
Definition: predtest.c:60
#define lnext(lc)
Definition: pg_list.h:105
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
static void list_startup_fn ( Node clause,
PredIterInfo  info 
)
static

Definition at line 831 of file predtest.c.

References list_head(), and PredIterInfoData::state.

Referenced by predicate_classify().

832 {
833  info->state = (void *) list_head((List *) clause);
834 }
void * state
Definition: predtest.c:60
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
Definition: pg_list.h:45
static OprProofCacheEntry* lookup_proof_cache ( Oid  pred_op,
Oid  clause_op,
bool  refute_it 
)
static

Definition at line 1694 of file predtest.c.

References AMOPOPID, Assert, BT_implic_table, BT_implies_table, BT_refute_table, BT_refutes_table, BTEqualStrategyNumber, BTNE, CacheRegisterSyscacheCallback(), OprProofCacheKey::clause_op, HASHCTL::entrysize, get_negator(), get_op_btree_interpretation(), get_opfamily_member(), HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), OprProofCacheEntry::have_implic, OprProofCacheEntry::have_refute, OprProofCacheEntry::implic_test_op, InvalidateOprProofCacheCallBack(), InvalidOid, HASHCTL::keysize, lfirst, list_free_deep(), MemSet, NIL, NULL, OidIsValid, op_volatile(), OpBtreeInterpretation::opfamily_id, OpBtreeInterpretation::oplefttype, OpBtreeInterpretation::oprighttype, OprProofCacheKey::pred_op, PROVOLATILE_IMMUTABLE, OprProofCacheEntry::refute_test_op, OprProofCacheEntry::same_subexprs_implies, OprProofCacheEntry::same_subexprs_refutes, and OpBtreeInterpretation::strategy.

Referenced by get_btree_test_op(), and operator_same_subexprs_lookup().

1695 {
1696  OprProofCacheKey key;
1697  OprProofCacheEntry *cache_entry;
1698  bool cfound;
1699  bool same_subexprs = false;
1700  Oid test_op = InvalidOid;
1701  bool found = false;
1702  List *pred_op_infos,
1703  *clause_op_infos;
1704  ListCell *lcp,
1705  *lcc;
1706 
1707  /*
1708  * Find or make a cache entry for this pair of operators.
1709  */
1710  if (OprProofCacheHash == NULL)
1711  {
1712  /* First time through: initialize the hash table */
1713  HASHCTL ctl;
1714 
1715  MemSet(&ctl, 0, sizeof(ctl));
1716  ctl.keysize = sizeof(OprProofCacheKey);
1717  ctl.entrysize = sizeof(OprProofCacheEntry);
1718  OprProofCacheHash = hash_create("Btree proof lookup cache", 256,
1719  &ctl, HASH_ELEM | HASH_BLOBS);
1720 
1721  /* Arrange to flush cache on pg_amop changes */
1724  (Datum) 0);
1725  }
1726 
1727  key.pred_op = pred_op;
1728  key.clause_op = clause_op;
1730  (void *) &key,
1731  HASH_ENTER, &cfound);
1732  if (!cfound)
1733  {
1734  /* new cache entry, set it invalid */
1735  cache_entry->have_implic = false;
1736  cache_entry->have_refute = false;
1737  }
1738  else
1739  {
1740  /* pre-existing cache entry, see if we know the answer yet */
1741  if (refute_it ? cache_entry->have_refute : cache_entry->have_implic)
1742  return cache_entry;
1743  }
1744 
1745  /*
1746  * Try to find a btree opfamily containing the given operators.
1747  *
1748  * We must find a btree opfamily that contains both operators, else the
1749  * implication can't be determined. Also, the opfamily must contain a
1750  * suitable test operator taking the operators' righthand datatypes.
1751  *
1752  * If there are multiple matching opfamilies, assume we can use any one to
1753  * determine the logical relationship of the two operators and the correct
1754  * corresponding test operator. This should work for any logically
1755  * consistent opfamilies.
1756  *
1757  * Note that we can determine the operators' relationship for
1758  * same-subexprs cases even from an opfamily that lacks a usable test
1759  * operator. This can happen in cases with incomplete sets of cross-type
1760  * comparison operators.
1761  */
1762  clause_op_infos = get_op_btree_interpretation(clause_op);
1763  if (clause_op_infos)
1764  pred_op_infos = get_op_btree_interpretation(pred_op);
1765  else /* no point in looking */
1766  pred_op_infos = NIL;
1767 
1768  foreach(lcp, pred_op_infos)
1769  {
1770  OpBtreeInterpretation *pred_op_info = lfirst(lcp);
1771  Oid opfamily_id = pred_op_info->opfamily_id;
1772 
1773  foreach(lcc, clause_op_infos)
1774  {
1775  OpBtreeInterpretation *clause_op_info = lfirst(lcc);
1776  StrategyNumber pred_strategy,
1777  clause_strategy,
1778  test_strategy;
1779 
1780  /* Must find them in same opfamily */
1781  if (opfamily_id != clause_op_info->opfamily_id)
1782  continue;
1783  /* Lefttypes should match */
1784  Assert(clause_op_info->oplefttype == pred_op_info->oplefttype);
1785 
1786  pred_strategy = pred_op_info->strategy;
1787  clause_strategy = clause_op_info->strategy;
1788 
1789  /*
1790  * Check to see if we can make a proof for same-subexpressions
1791  * cases based on the operators' relationship in this opfamily.
1792  */
1793  if (refute_it)
1794  same_subexprs |= BT_refutes_table[clause_strategy - 1][pred_strategy - 1];
1795  else
1796  same_subexprs |= BT_implies_table[clause_strategy - 1][pred_strategy - 1];
1797 
1798  /*
1799  * Look up the "test" strategy number in the implication table
1800  */
1801  if (refute_it)
1802  test_strategy = BT_refute_table[clause_strategy - 1][pred_strategy - 1];
1803  else
1804  test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
1805 
1806  if (test_strategy == 0)
1807  {
1808  /* Can't determine implication using this interpretation */
1809  continue;
1810  }
1811 
1812  /*
1813  * See if opfamily has an operator for the test strategy and the
1814  * datatypes.
1815  */
1816  if (test_strategy == BTNE)
1817  {
1818  test_op = get_opfamily_member(opfamily_id,
1819  pred_op_info->oprighttype,
1820  clause_op_info->oprighttype,
1822  if (OidIsValid(test_op))
1823  test_op = get_negator(test_op);
1824  }
1825  else
1826  {
1827  test_op = get_opfamily_member(opfamily_id,
1828  pred_op_info->oprighttype,
1829  clause_op_info->oprighttype,
1830  test_strategy);
1831  }
1832 
1833  if (!OidIsValid(test_op))
1834  continue;
1835 
1836  /*
1837  * Last check: test_op must be immutable.
1838  *
1839  * Note that we require only the test_op to be immutable, not the
1840  * original clause_op. (pred_op is assumed to have been checked
1841  * immutable by the caller.) Essentially we are assuming that the
1842  * opfamily is consistent even if it contains operators that are
1843  * merely stable.
1844  */
1845  if (op_volatile(test_op) == PROVOLATILE_IMMUTABLE)
1846  {
1847  found = true;
1848  break;
1849  }
1850  }
1851 
1852  if (found)
1853  break;
1854  }
1855 
1856  list_free_deep(pred_op_infos);
1857  list_free_deep(clause_op_infos);
1858 
1859  if (!found)
1860  {
1861  /* couldn't find a suitable comparison operator */
1862  test_op = InvalidOid;
1863  }
1864 
1865  /*
1866  * If we think we were able to prove something about same-subexpressions
1867  * cases, check to make sure the clause_op is immutable before believing
1868  * it completely. (Usually, the clause_op would be immutable if the
1869  * pred_op is, but it's not entirely clear that this must be true in all
1870  * cases, so let's check.)
1871  */
1872  if (same_subexprs &&
1873  op_volatile(clause_op) != PROVOLATILE_IMMUTABLE)
1874  same_subexprs = false;
1875 
1876  /* Cache the results, whether positive or negative */
1877  if (refute_it)
1878  {
1879  cache_entry->refute_test_op = test_op;
1880  cache_entry->same_subexprs_refutes = same_subexprs;
1881  cache_entry->have_refute = true;
1882  }
1883  else
1884  {
1885  cache_entry->implic_test_op = test_op;
1886  cache_entry->same_subexprs_implies = same_subexprs;
1887  cache_entry->have_implic = true;
1888  }
1889 
1890  return cache_entry;
1891 }
#define NIL
Definition: pg_list.h:69
bool same_subexprs_implies
Definition: predtest.c:1680
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5372
#define HASH_ELEM
Definition: hsearch.h:87
static void InvalidateOprProofCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: predtest.c:1940
Size entrysize
Definition: hsearch.h:73
struct OprProofCacheEntry OprProofCacheEntry
uint16 StrategyNumber
Definition: stratnum.h:22
#define MemSet(start, val, len)
Definition: c.h:853
static const bool BT_refutes_table[6][6]
Definition: predtest.c:1329
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
void list_free_deep(List *list)
Definition: list.c:1147
bool same_subexprs_refutes
Definition: predtest.c:1681
static HTAB * OprProofCacheHash
Definition: predtest.c:1686
static const StrategyNumber BT_refute_table[6][6]
Definition: predtest.c:1355
static const StrategyNumber BT_implic_table[6][6]
Definition: predtest.c:1342
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
#define BTNE
Definition: predtest.c:1311
struct OprProofCacheKey OprProofCacheKey
#define HASH_BLOBS
Definition: hsearch.h:88
char op_volatile(Oid opno)
Definition: lsyscache.c:1265
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1381
List * get_op_btree_interpretation(Oid opno)
Definition: lsyscache.c:598
uintptr_t Datum
Definition: postgres.h:374
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
Oid get_negator(Oid opno)
Definition: lsyscache.c:1305
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static const bool BT_implies_table[6][6]
Definition: predtest.c:1316
static bool operator_predicate_proof ( Expr predicate,
Node clause,
bool  refute_it 
)
static

Definition at line 1407 of file predtest.c.

References OpExpr::args, BOOLOID, Const::constisnull, CreateExecutorState(), DatumGetBool, DEBUG2, elog, equal(), EState::es_query_cxt, ExecEvalExprSwitchContext(), ExecInitExpr(), fix_opfuncids(), FreeExecutorState(), get_btree_test_op(), get_commutator(), GetPerTupleExprContext, OpExpr::inputcollid, InvalidOid, is_opclause, IsA, linitial, list_length(), lsecond, make_opclause(), MemoryContextSwitchTo(), NULL, OidIsValid, operator_same_subexprs_proof(), and OpExpr::opno.

Referenced by predicate_implied_by_simple_clause(), and predicate_refuted_by_simple_clause().

1408 {
1409  OpExpr *pred_opexpr,
1410  *clause_opexpr;
1411  Oid pred_collation,
1412  clause_collation;
1413  Oid pred_op,
1414  clause_op,
1415  test_op;
1416  Node *pred_leftop,
1417  *pred_rightop,
1418  *clause_leftop,
1419  *clause_rightop;
1420  Const *pred_const,
1421  *clause_const;
1422  Expr *test_expr;
1423  ExprState *test_exprstate;
1424  Datum test_result;
1425  bool isNull;
1426  EState *estate;
1427  MemoryContext oldcontext;
1428 
1429  /*
1430  * Both expressions must be binary opclauses, else we can't do anything.
1431  *
1432  * Note: in future we might extend this logic to other operator-based
1433  * constructs such as DistinctExpr. But the planner isn't very smart
1434  * about DistinctExpr in general, and this probably isn't the first place
1435  * to fix if you want to improve that.
1436  */
1437  if (!is_opclause(predicate))
1438  return false;
1439  pred_opexpr = (OpExpr *) predicate;
1440  if (list_length(pred_opexpr->args) != 2)
1441  return false;
1442  if (!is_opclause(clause))
1443  return false;
1444  clause_opexpr = (OpExpr *) clause;
1445  if (list_length(clause_opexpr->args) != 2)
1446  return false;
1447 
1448  /*
1449  * If they're marked with different collations then we can't do anything.
1450  * This is a cheap test so let's get it out of the way early.
1451  */
1452  pred_collation = pred_opexpr->inputcollid;
1453  clause_collation = clause_opexpr->inputcollid;
1454  if (pred_collation != clause_collation)
1455  return false;
1456 
1457  /* Grab the operator OIDs now too. We may commute these below. */
1458  pred_op = pred_opexpr->opno;
1459  clause_op = clause_opexpr->opno;
1460 
1461  /*
1462  * We have to match up at least one pair of input expressions.
1463  */
1464  pred_leftop = (Node *) linitial(pred_opexpr->args);
1465  pred_rightop = (Node *) lsecond(pred_opexpr->args);
1466  clause_leftop = (Node *) linitial(clause_opexpr->args);
1467  clause_rightop = (Node *) lsecond(clause_opexpr->args);
1468 
1469  if (equal(pred_leftop, clause_leftop))
1470  {
1471  if (equal(pred_rightop, clause_rightop))
1472  {
1473  /* We have x op1 y and x op2 y */
1474  return operator_same_subexprs_proof(pred_op, clause_op, refute_it);
1475  }
1476  else
1477  {
1478  /* Fail unless rightops are both Consts */
1479  if (pred_rightop == NULL || !IsA(pred_rightop, Const))
1480  return false;
1481  pred_const = (Const *) pred_rightop;
1482  if (clause_rightop == NULL || !IsA(clause_rightop, Const))
1483  return false;
1484  clause_const = (Const *) clause_rightop;
1485  }
1486  }
1487  else if (equal(pred_rightop, clause_rightop))
1488  {
1489  /* Fail unless leftops are both Consts */
1490  if (pred_leftop == NULL || !IsA(pred_leftop, Const))
1491  return false;
1492  pred_const = (Const *) pred_leftop;
1493  if (clause_leftop == NULL || !IsA(clause_leftop, Const))
1494  return false;
1495  clause_const = (Const *) clause_leftop;
1496  /* Commute both operators so we can assume Consts are on the right */
1497  pred_op = get_commutator(pred_op);
1498  if (!OidIsValid(pred_op))
1499  return false;
1500  clause_op = get_commutator(clause_op);
1501  if (!OidIsValid(clause_op))
1502  return false;
1503  }
1504  else if (equal(pred_leftop, clause_rightop))
1505  {
1506  if (equal(pred_rightop, clause_leftop))
1507  {
1508  /* We have x op1 y and y op2 x */
1509  /* Commute pred_op that we can treat this like a straight match */
1510  pred_op = get_commutator(pred_op);
1511  if (!OidIsValid(pred_op))
1512  return false;
1513  return operator_same_subexprs_proof(pred_op, clause_op, refute_it);
1514  }
1515  else
1516  {
1517  /* Fail unless pred_rightop/clause_leftop are both Consts */
1518  if (pred_rightop == NULL || !IsA(pred_rightop, Const))
1519  return false;
1520  pred_const = (Const *) pred_rightop;
1521  if (clause_leftop == NULL || !IsA(clause_leftop, Const))
1522  return false;
1523  clause_const = (Const *) clause_leftop;
1524  /* Commute clause_op so we can assume Consts are on the right */
1525  clause_op = get_commutator(clause_op);
1526  if (!OidIsValid(clause_op))
1527  return false;
1528  }
1529  }
1530  else if (equal(pred_rightop, clause_leftop))
1531  {
1532  /* Fail unless pred_leftop/clause_rightop are both Consts */
1533  if (pred_leftop == NULL || !IsA(pred_leftop, Const))
1534  return false;
1535  pred_const = (Const *) pred_leftop;
1536  if (clause_rightop == NULL || !IsA(clause_rightop, Const))
1537  return false;
1538  clause_const = (Const *) clause_rightop;
1539  /* Commute pred_op so we can assume Consts are on the right */
1540  pred_op = get_commutator(pred_op);
1541  if (!OidIsValid(pred_op))
1542  return false;
1543  }
1544  else
1545  {
1546  /* Failed to match up any of the subexpressions, so we lose */
1547  return false;
1548  }
1549 
1550  /*
1551  * We have two identical subexpressions, and two other subexpressions that
1552  * are not identical but are both Consts; and we have commuted the
1553  * operators if necessary so that the Consts are on the right. We'll need
1554  * to compare the Consts' values. If either is NULL, fail.
1555  */
1556  if (pred_const->constisnull)
1557  return false;
1558  if (clause_const->constisnull)
1559  return false;
1560 
1561  /*
1562  * Lookup the constant-comparison operator using the system catalogs and
1563  * the operator implication tables.
1564  */
1565  test_op = get_btree_test_op(pred_op, clause_op, refute_it);
1566 
1567  if (!OidIsValid(test_op))
1568  {
1569  /* couldn't find a suitable comparison operator */
1570  return false;
1571  }
1572 
1573  /*
1574  * Evaluate the test. For this we need an EState.
1575  */
1576  estate = CreateExecutorState();
1577 
1578  /* We can use the estate's working context to avoid memory leaks. */
1579  oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1580 
1581  /* Build expression tree */
1582  test_expr = make_opclause(test_op,
1583  BOOLOID,
1584  false,
1585  (Expr *) pred_const,
1586  (Expr *) clause_const,
1587  InvalidOid,
1588  pred_collation);
1589 
1590  /* Fill in opfuncids */
1591  fix_opfuncids((Node *) test_expr);
1592 
1593  /* Prepare it for execution */
1594  test_exprstate = ExecInitExpr(test_expr, NULL);
1595 
1596  /* And execute it. */
1597  test_result = ExecEvalExprSwitchContext(test_exprstate,
1598  GetPerTupleExprContext(estate),
1599  &isNull);
1600 
1601  /* Get back to outer memory context */
1602  MemoryContextSwitchTo(oldcontext);
1603 
1604  /* Release all the junk we just created */
1605  FreeExecutorState(estate);
1606 
1607  if (isNull)
1608  {
1609  /* Treat a null result as non-proof ... but it's a tad fishy ... */
1610  elog(DEBUG2, "null predicate test result");
1611  return false;
1612  }
1613  return DatumGetBool(test_result);
1614 }
static Oid get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
Definition: predtest.c:1924
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1281
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1591
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:508
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: clauses.c:171
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
#define lsecond(l)
Definition: pg_list.h:114
Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execQual.c:4219
void FreeExecutorState(EState *estate)
Definition: execUtils.c:168
#define GetPerTupleExprContext(estate)
Definition: executor.h:338
static bool operator_same_subexprs_proof(Oid pred_op, Oid clause_op, bool refute_it)
Definition: predtest.c:1625
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
MemoryContext es_query_cxt
Definition: execnodes.h:397
#define linitial(l)
Definition: pg_list.h:110
#define is_opclause(clause)
Definition: clauses.h:20
#define DEBUG2
Definition: elog.h:24
#define DatumGetBool(X)
Definition: postgres.h:401
EState * CreateExecutorState(void)
Definition: execUtils.c:72
uintptr_t Datum
Definition: postgres.h:374
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
static int list_length(const List *l)
Definition: pg_list.h:89
Oid inputcollid
Definition: primnodes.h:478
#define BOOLOID
Definition: pg_type.h:288
Oid opno
Definition: primnodes.h:473
#define elog
Definition: elog.h:219
List * args
Definition: primnodes.h:479
bool constisnull
Definition: primnodes.h:175
static bool operator_same_subexprs_lookup ( Oid  pred_op,
Oid  clause_op,
bool  refute_it 
)
static

Definition at line 1899 of file predtest.c.

References lookup_proof_cache(), OprProofCacheEntry::same_subexprs_implies, and OprProofCacheEntry::same_subexprs_refutes.

Referenced by operator_same_subexprs_proof().

1900 {
1901  OprProofCacheEntry *cache_entry;
1902 
1903  cache_entry = lookup_proof_cache(pred_op, clause_op, refute_it);
1904  if (refute_it)
1905  return cache_entry->same_subexprs_refutes;
1906  else
1907  return cache_entry->same_subexprs_implies;
1908 }
bool same_subexprs_implies
Definition: predtest.c:1680
static OprProofCacheEntry * lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
Definition: predtest.c:1694
bool same_subexprs_refutes
Definition: predtest.c:1681
static bool operator_same_subexprs_proof ( Oid  pred_op,
Oid  clause_op,
bool  refute_it 
)
static

Definition at line 1625 of file predtest.c.

References get_negator(), and operator_same_subexprs_lookup().

Referenced by operator_predicate_proof().

1626 {
1627  /*
1628  * A simple and general rule is that the predicate is proven if clause_op
1629  * and pred_op are the same, or refuted if they are each other's negators.
1630  * We need not check immutability since the pred_op is already known
1631  * immutable. (Actually, by this point we may have the commutator of a
1632  * known-immutable pred_op, but that should certainly be immutable too.
1633  * Likewise we don't worry whether the pred_op's negator is immutable.)
1634  *
1635  * Note: the "same" case won't get here if we actually had EXPR1 clause_op
1636  * EXPR2 and EXPR1 pred_op EXPR2, because the overall-expression-equality
1637  * test in predicate_implied_by_simple_clause would have caught it. But
1638  * we can see the same operator after having commuted the pred_op.
1639  */
1640  if (refute_it)
1641  {
1642  if (get_negator(pred_op) == clause_op)
1643  return true;
1644  }
1645  else
1646  {
1647  if (pred_op == clause_op)
1648  return true;
1649  }
1650 
1651  /*
1652  * Otherwise, see if we can determine the implication by finding the
1653  * operators' relationship via some btree opfamily.
1654  */
1655  return operator_same_subexprs_lookup(pred_op, clause_op, refute_it);
1656 }
static bool operator_same_subexprs_lookup(Oid pred_op, Oid clause_op, bool refute_it)
Definition: predtest.c:1899
Oid get_negator(Oid opno)
Definition: lsyscache.c:1305
static PredClass predicate_classify ( Node clause,
PredIterInfo  info 
)
static

Definition at line 749 of file predtest.c.

References and_clause(), ScalarArrayOpExpr::args, ARR_DIMS, ARR_NDIM, arrayconst_cleanup_fn(), arrayconst_next_fn(), arrayconst_startup_fn(), arrayexpr_cleanup_fn(), arrayexpr_next_fn(), arrayexpr_startup_fn(), ArrayGetNItems(), Assert, boolexpr_startup_fn(), CLASS_AND, CLASS_ATOM, CLASS_OR, PredIterInfoData::cleanup_fn, DatumGetArrayTypeP, IsA, list_cleanup_fn(), list_length(), list_next_fn(), list_startup_fn(), lsecond, MAX_SAOP_ARRAY_SIZE, PredIterInfoData::next_fn, NULL, or_clause(), PredIterInfoData::startup_fn, and ScalarArrayOpExpr::useOr.

Referenced by predicate_implied_by_recurse(), and predicate_refuted_by_recurse().

750 {
751  /* Caller should not pass us NULL, nor a RestrictInfo clause */
752  Assert(clause != NULL);
753  Assert(!IsA(clause, RestrictInfo));
754 
755  /*
756  * If we see a List, assume it's an implicit-AND list; this is the correct
757  * semantics for lists of RestrictInfo nodes.
758  */
759  if (IsA(clause, List))
760  {
761  info->startup_fn = list_startup_fn;
762  info->next_fn = list_next_fn;
763  info->cleanup_fn = list_cleanup_fn;
764  return CLASS_AND;
765  }
766 
767  /* Handle normal AND and OR boolean clauses */
768  if (and_clause(clause))
769  {
771  info->next_fn = list_next_fn;
772  info->cleanup_fn = list_cleanup_fn;
773  return CLASS_AND;
774  }
775  if (or_clause(clause))
776  {
778  info->next_fn = list_next_fn;
779  info->cleanup_fn = list_cleanup_fn;
780  return CLASS_OR;
781  }
782 
783  /* Handle ScalarArrayOpExpr */
784  if (IsA(clause, ScalarArrayOpExpr))
785  {
786  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
787  Node *arraynode = (Node *) lsecond(saop->args);
788 
789  /*
790  * We can break this down into an AND or OR structure, but only if we
791  * know how to iterate through expressions for the array's elements.
792  * We can do that if the array operand is a non-null constant or a
793  * simple ArrayExpr.
794  */
795  if (arraynode && IsA(arraynode, Const) &&
796  !((Const *) arraynode)->constisnull)
797  {
798  ArrayType *arrayval;
799  int nelems;
800 
801  arrayval = DatumGetArrayTypeP(((Const *) arraynode)->constvalue);
802  nelems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval));
803  if (nelems <= MAX_SAOP_ARRAY_SIZE)
804  {
806  info->next_fn = arrayconst_next_fn;
808  return saop->useOr ? CLASS_OR : CLASS_AND;
809  }
810  }
811  else if (arraynode && IsA(arraynode, ArrayExpr) &&
812  !((ArrayExpr *) arraynode)->multidims &&
813  list_length(((ArrayExpr *) arraynode)->elements) <= MAX_SAOP_ARRAY_SIZE)
814  {
816  info->next_fn = arrayexpr_next_fn;
818  return saop->useOr ? CLASS_OR : CLASS_AND;
819  }
820  }
821 
822  /* None of the above, so it's an atom */
823  return CLASS_ATOM;
824 }
static Node * arrayexpr_next_fn(PredIterInfo info)
Definition: predtest.c:989
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static void arrayexpr_cleanup_fn(PredIterInfo info)
Definition: predtest.c:1001
#define MAX_SAOP_ARRAY_SIZE
Definition: predtest.c:38
Node *(* next_fn)(PredIterInfo info)
Definition: predtest.c:64
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
Definition: nodes.h:508
static void arrayconst_startup_fn(Node *clause, PredIterInfo info)
Definition: predtest.c:880
static void arrayexpr_startup_fn(Node *clause, PredIterInfo info)
Definition: predtest.c:963
#define lsecond(l)
Definition: pg_list.h:114
#define ARR_DIMS(a)
Definition: array.h:275
bool and_clause(Node *clause)
Definition: clauses.c:313
static Node * arrayconst_next_fn(PredIterInfo info)
Definition: predtest.c:929
static void list_cleanup_fn(PredIterInfo info)
Definition: predtest.c:850
bool or_clause(Node *clause)
Definition: clauses.c:279
static void list_startup_fn(Node *clause, PredIterInfo info)
Definition: predtest.c:831
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void(* startup_fn)(Node *clause, PredIterInfo info)
Definition: predtest.c:62
static Node * list_next_fn(PredIterInfo info)
Definition: predtest.c:837
static int list_length(const List *l)
Definition: pg_list.h:89
#define ARR_NDIM(a)
Definition: array.h:271
static void boolexpr_startup_fn(Node *clause, PredIterInfo info)
Definition: predtest.c:860
Definition: pg_list.h:45
static void arrayconst_cleanup_fn(PredIterInfo info)
Definition: predtest.c:942
void(* cleanup_fn)(PredIterInfo info)
Definition: predtest.c:66
#define DatumGetArrayTypeP(X)
Definition: array.h:242
bool predicate_implied_by ( List predicate_list,
List restrictinfo_list 
)

Definition at line 128 of file predtest.c.

References linitial, list_length(), NIL, and predicate_implied_by_recurse().

Referenced by add_predicate_to_quals(), ATExecAttachPartition(), build_paths_for_OR(), check_index_predicates(), choose_bitmap_and(), create_bitmap_scan_plan(), create_bitmap_subplan(), create_indexscan_plan(), gincostestimate(), and infer_arbiter_indexes().

129 {
130  Node *p,
131  *r;
132 
133  if (predicate_list == NIL)
134  return true; /* no predicate: implication is vacuous */
135  if (restrictinfo_list == NIL)
136  return false; /* no restriction: implication must fail */
137 
138  /*
139  * If either input is a single-element list, replace it with its lone
140  * member; this avoids one useless level of AND-recursion. We only need
141  * to worry about this at top level, since eval_const_expressions should
142  * have gotten rid of any trivial ANDs or ORs below that.
143  */
144  if (list_length(predicate_list) == 1)
145  p = (Node *) linitial(predicate_list);
146  else
147  p = (Node *) predicate_list;
148  if (list_length(restrictinfo_list) == 1)
149  r = (Node *) linitial(restrictinfo_list);
150  else
151  r = (Node *) restrictinfo_list;
152 
153  /* And away we go ... */
154  return predicate_implied_by_recurse(r, p);
155 }
#define NIL
Definition: pg_list.h:69
static bool predicate_implied_by_recurse(Node *clause, Node *predicate)
Definition: predtest.c:251
Definition: nodes.h:508
#define linitial(l)
Definition: pg_list.h:110
static int list_length(const List *l)
Definition: pg_list.h:89
static bool predicate_implied_by_recurse ( Node clause,
Node predicate 
)
static

Definition at line 251 of file predtest.c.

References Assert, CLASS_AND, CLASS_ATOM, CLASS_OR, elog, ERROR, IsA, iterate_begin, iterate_end, NULL, predicate_classify(), and predicate_implied_by_simple_clause().

Referenced by predicate_implied_by(), and predicate_refuted_by_recurse().

252 {
253  PredIterInfoData clause_info;
254  PredIterInfoData pred_info;
255  PredClass pclass;
256  bool result;
257 
258  /* skip through RestrictInfo */
259  Assert(clause != NULL);
260  if (IsA(clause, RestrictInfo))
261  clause = (Node *) ((RestrictInfo *) clause)->clause;
262 
263  pclass = predicate_classify(predicate, &pred_info);
264 
265  switch (predicate_classify(clause, &clause_info))
266  {
267  case CLASS_AND:
268  switch (pclass)
269  {
270  case CLASS_AND:
271 
272  /*
273  * AND-clause => AND-clause if A implies each of B's items
274  */
275  result = true;
276  iterate_begin(pitem, predicate, pred_info)
277  {
278  if (!predicate_implied_by_recurse(clause, pitem))
279  {
280  result = false;
281  break;
282  }
283  }
284  iterate_end(pred_info);
285  return result;
286 
287  case CLASS_OR:
288 
289  /*
290  * AND-clause => OR-clause if A implies any of B's items
291  *
292  * Needed to handle (x AND y) => ((x AND y) OR z)
293  */
294  result = false;
295  iterate_begin(pitem, predicate, pred_info)
296  {
297  if (predicate_implied_by_recurse(clause, pitem))
298  {
299  result = true;
300  break;
301  }
302  }
303  iterate_end(pred_info);
304  if (result)
305  return result;
306 
307  /*
308  * Also check if any of A's items implies B
309  *
310  * Needed to handle ((x OR y) AND z) => (x OR y)
311  */
312  iterate_begin(citem, clause, clause_info)
313  {
314  if (predicate_implied_by_recurse(citem, predicate))
315  {
316  result = true;
317  break;
318  }
319  }
320  iterate_end(clause_info);
321  return result;
322 
323  case CLASS_ATOM:
324 
325  /*
326  * AND-clause => atom if any of A's items implies B
327  */
328  result = false;
329  iterate_begin(citem, clause, clause_info)
330  {
331  if (predicate_implied_by_recurse(citem, predicate))
332  {
333  result = true;
334  break;
335  }
336  }
337  iterate_end(clause_info);
338  return result;
339  }
340  break;
341 
342  case CLASS_OR:
343  switch (pclass)
344  {
345  case CLASS_OR:
346 
347  /*
348  * OR-clause => OR-clause if each of A's items implies any
349  * of B's items. Messy but can't do it any more simply.
350  */
351  result = true;
352  iterate_begin(citem, clause, clause_info)
353  {
354  bool presult = false;
355 
356  iterate_begin(pitem, predicate, pred_info)
357  {
358  if (predicate_implied_by_recurse(citem, pitem))
359  {
360  presult = true;
361  break;
362  }
363  }
364  iterate_end(pred_info);
365  if (!presult)
366  {
367  result = false; /* doesn't imply any of B's */
368  break;
369  }
370  }
371  iterate_end(clause_info);
372  return result;
373 
374  case CLASS_AND:
375  case CLASS_ATOM:
376 
377  /*
378  * OR-clause => AND-clause if each of A's items implies B
379  *
380  * OR-clause => atom if each of A's items implies B
381  */
382  result = true;
383  iterate_begin(citem, clause, clause_info)
384  {
385  if (!predicate_implied_by_recurse(citem, predicate))
386  {
387  result = false;
388  break;
389  }
390  }
391  iterate_end(clause_info);
392  return result;
393  }
394  break;
395 
396  case CLASS_ATOM:
397  switch (pclass)
398  {
399  case CLASS_AND:
400 
401  /*
402  * atom => AND-clause if A implies each of B's items
403  */
404  result = true;
405  iterate_begin(pitem, predicate, pred_info)
406  {
407  if (!predicate_implied_by_recurse(clause, pitem))
408  {
409  result = false;
410  break;
411  }
412  }
413  iterate_end(pred_info);
414  return result;
415 
416  case CLASS_OR:
417 
418  /*
419  * atom => OR-clause if A implies any of B's items
420  */
421  result = false;
422  iterate_begin(pitem, predicate, pred_info)
423  {
424  if (predicate_implied_by_recurse(clause, pitem))
425  {
426  result = true;
427  break;
428  }
429  }
430  iterate_end(pred_info);
431  return result;
432 
433  case CLASS_ATOM:
434 
435  /*
436  * atom => atom is the base case
437  */
438  return
440  clause);
441  }
442  break;
443  }
444 
445  /* can't get here */
446  elog(ERROR, "predicate_classify returned a bogus value");
447  return false;
448 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define iterate_begin(item, clause, info)
Definition: predtest.c:69
static bool predicate_implied_by_recurse(Node *clause, Node *predicate)
Definition: predtest.c:251
Definition: nodes.h:508
static PredClass predicate_classify(Node *clause, PredIterInfo info)
Definition: predtest.c:749
PredClass
Definition: predtest.c:48
#define ERROR
Definition: elog.h:43
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static bool predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
Definition: predtest.c:1040
#define elog
Definition: elog.h:219
#define iterate_end(info)
Definition: predtest.c:75
static bool predicate_implied_by_simple_clause ( Expr predicate,
Node clause 
)
static

Definition at line 1040 of file predtest.c.

References generate_unaccent_rules::args, CHECK_FOR_INTERRUPTS, equal(), func_strict(), is_funcclause, IS_NOT_NULL, is_opclause, IsA, list_member_strip(), op_strict(), and operator_predicate_proof().

Referenced by predicate_implied_by_recurse().

1041 {
1042  /* Allow interrupting long proof attempts */
1044 
1045  /* First try the equal() test */
1046  if (equal((Node *) predicate, clause))
1047  return true;
1048 
1049  /* Next try the IS NOT NULL case */
1050  if (predicate && IsA(predicate, NullTest) &&
1051  ((NullTest *) predicate)->nulltesttype == IS_NOT_NULL)
1052  {
1053  Expr *nonnullarg = ((NullTest *) predicate)->arg;
1054 
1055  /* row IS NOT NULL does not act in the simple way we have in mind */
1056  if (!((NullTest *) predicate)->argisrow)
1057  {
1058  if (is_opclause(clause) &&
1059  list_member_strip(((OpExpr *) clause)->args, nonnullarg) &&
1060  op_strict(((OpExpr *) clause)->opno))
1061  return true;
1062  if (is_funcclause(clause) &&
1063  list_member_strip(((FuncExpr *) clause)->args, nonnullarg) &&
1064  func_strict(((FuncExpr *) clause)->funcid))
1065  return true;
1066  if (equal(clause, nonnullarg))
1067  return true;
1068  }
1069  return false; /* we can't succeed below... */
1070  }
1071 
1072  /* Else try operator-related knowledge */
1073  return operator_predicate_proof(predicate, clause, false);
1074 }
static bool list_member_strip(List *list, Expr *datum)
Definition: predtest.c:1229
bool op_strict(Oid opno)
Definition: lsyscache.c:1249
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static bool operator_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
Definition: predtest.c:1407
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
#define is_funcclause(clause)
Definition: clauses.h:21
Definition: nodes.h:508
#define is_opclause(clause)
Definition: clauses.h:20
bool func_strict(Oid funcid)
Definition: lsyscache.c:1533
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
bool predicate_refuted_by ( List predicate_list,
List restrictinfo_list 
)

Definition at line 186 of file predtest.c.

References linitial, list_length(), NIL, and predicate_refuted_by_recurse().

Referenced by relation_excluded_by_constraints().

187 {
188  Node *p,
189  *r;
190 
191  if (predicate_list == NIL)
192  return false; /* no predicate: no refutation is possible */
193  if (restrictinfo_list == NIL)
194  return false; /* no restriction: refutation must fail */
195 
196  /*
197  * If either input is a single-element list, replace it with its lone
198  * member; this avoids one useless level of AND-recursion. We only need
199  * to worry about this at top level, since eval_const_expressions should
200  * have gotten rid of any trivial ANDs or ORs below that.
201  */
202  if (list_length(predicate_list) == 1)
203  p = (Node *) linitial(predicate_list);
204  else
205  p = (Node *) predicate_list;
206  if (list_length(restrictinfo_list) == 1)
207  r = (Node *) linitial(restrictinfo_list);
208  else
209  r = (Node *) restrictinfo_list;
210 
211  /* And away we go ... */
212  return predicate_refuted_by_recurse(r, p);
213 }
#define NIL
Definition: pg_list.h:69
Definition: nodes.h:508
#define linitial(l)
Definition: pg_list.h:110
static bool predicate_refuted_by_recurse(Node *clause, Node *predicate)
Definition: predtest.c:481
static int list_length(const List *l)
Definition: pg_list.h:89
static bool predicate_refuted_by_recurse ( Node clause,
Node predicate 
)
static

Definition at line 481 of file predtest.c.

References Assert, CLASS_AND, CLASS_ATOM, CLASS_OR, elog, equal(), ERROR, extract_not_arg(), extract_strong_not_arg(), IsA, iterate_begin, iterate_end, NULL, predicate_classify(), predicate_implied_by_recurse(), and predicate_refuted_by_simple_clause().

Referenced by predicate_refuted_by().

482 {
483  PredIterInfoData clause_info;
484  PredIterInfoData pred_info;
485  PredClass pclass;
486  Node *not_arg;
487  bool result;
488 
489  /* skip through RestrictInfo */
490  Assert(clause != NULL);
491  if (IsA(clause, RestrictInfo))
492  clause = (Node *) ((RestrictInfo *) clause)->clause;
493 
494  pclass = predicate_classify(predicate, &pred_info);
495 
496  switch (predicate_classify(clause, &clause_info))
497  {
498  case CLASS_AND:
499  switch (pclass)
500  {
501  case CLASS_AND:
502 
503  /*
504  * AND-clause R=> AND-clause if A refutes any of B's items
505  *
506  * Needed to handle (x AND y) R=> ((!x OR !y) AND z)
507  */
508  result = false;
509  iterate_begin(pitem, predicate, pred_info)
510  {
511  if (predicate_refuted_by_recurse(clause, pitem))
512  {
513  result = true;
514  break;
515  }
516  }
517  iterate_end(pred_info);
518  if (result)
519  return result;
520 
521  /*
522  * Also check if any of A's items refutes B
523  *
524  * Needed to handle ((x OR y) AND z) R=> (!x AND !y)
525  */
526  iterate_begin(citem, clause, clause_info)
527  {
528  if (predicate_refuted_by_recurse(citem, predicate))
529  {
530  result = true;
531  break;
532  }
533  }
534  iterate_end(clause_info);
535  return result;
536 
537  case CLASS_OR:
538 
539  /*
540  * AND-clause R=> OR-clause if A refutes each of B's items
541  */
542  result = true;
543  iterate_begin(pitem, predicate, pred_info)
544  {
545  if (!predicate_refuted_by_recurse(clause, pitem))
546  {
547  result = false;
548  break;
549  }
550  }
551  iterate_end(pred_info);
552  return result;
553 
554  case CLASS_ATOM:
555 
556  /*
557  * If B is a NOT-clause, A R=> B if A => B's arg
558  */
559  not_arg = extract_not_arg(predicate);
560  if (not_arg &&
561  predicate_implied_by_recurse(clause, not_arg))
562  return true;
563 
564  /*
565  * AND-clause R=> atom if any of A's items refutes B
566  */
567  result = false;
568  iterate_begin(citem, clause, clause_info)
569  {
570  if (predicate_refuted_by_recurse(citem, predicate))
571  {
572  result = true;
573  break;
574  }
575  }
576  iterate_end(clause_info);
577  return result;
578  }
579  break;
580 
581  case CLASS_OR:
582  switch (pclass)
583  {
584  case CLASS_OR:
585 
586  /*
587  * OR-clause R=> OR-clause if A refutes each of B's items
588  */
589  result = true;
590  iterate_begin(pitem, predicate, pred_info)
591  {
592  if (!predicate_refuted_by_recurse(clause, pitem))
593  {
594  result = false;
595  break;
596  }
597  }
598  iterate_end(pred_info);
599  return result;
600 
601  case CLASS_AND:
602 
603  /*
604  * OR-clause R=> AND-clause if each of A's items refutes
605  * any of B's items.
606  */
607  result = true;
608  iterate_begin(citem, clause, clause_info)
609  {
610  bool presult = false;
611 
612  iterate_begin(pitem, predicate, pred_info)
613  {
614  if (predicate_refuted_by_recurse(citem, pitem))
615  {
616  presult = true;
617  break;
618  }
619  }
620  iterate_end(pred_info);
621  if (!presult)
622  {
623  result = false; /* citem refutes nothing */
624  break;
625  }
626  }
627  iterate_end(clause_info);
628  return result;
629 
630  case CLASS_ATOM:
631 
632  /*
633  * If B is a NOT-clause, A R=> B if A => B's arg
634  */
635  not_arg = extract_not_arg(predicate);
636  if (not_arg &&
637  predicate_implied_by_recurse(clause, not_arg))
638  return true;
639 
640  /*
641  * OR-clause R=> atom if each of A's items refutes B
642  */
643  result = true;
644  iterate_begin(citem, clause, clause_info)
645  {
646  if (!predicate_refuted_by_recurse(citem, predicate))
647  {
648  result = false;
649  break;
650  }
651  }
652  iterate_end(clause_info);
653  return result;
654  }
655  break;
656 
657  case CLASS_ATOM:
658 
659  /*
660  * If A is a strong NOT-clause, A R=> B if B equals A's arg
661  *
662  * We cannot make the stronger conclusion that B is refuted if B
663  * implies A's arg; that would only prove that B is not-TRUE, not
664  * that it's not NULL either. Hence use equal() rather than
665  * predicate_implied_by_recurse(). We could do the latter if we
666  * ever had a need for the weak form of refutation.
667  */
668  not_arg = extract_strong_not_arg(clause);
669  if (not_arg && equal(predicate, not_arg))
670  return true;
671 
672  switch (pclass)
673  {
674  case CLASS_AND:
675 
676  /*
677  * atom R=> AND-clause if A refutes any of B's items
678  */
679  result = false;
680  iterate_begin(pitem, predicate, pred_info)
681  {
682  if (predicate_refuted_by_recurse(clause, pitem))
683  {
684  result = true;
685  break;
686  }
687  }
688  iterate_end(pred_info);
689  return result;
690 
691  case CLASS_OR:
692 
693  /*
694  * atom R=> OR-clause if A refutes each of B's items
695  */
696  result = true;
697  iterate_begin(pitem, predicate, pred_info)
698  {
699  if (!predicate_refuted_by_recurse(clause, pitem))
700  {
701  result = false;
702  break;
703  }
704  }
705  iterate_end(pred_info);
706  return result;
707 
708  case CLASS_ATOM:
709 
710  /*
711  * If B is a NOT-clause, A R=> B if A => B's arg
712  */
713  not_arg = extract_not_arg(predicate);
714  if (not_arg &&
715  predicate_implied_by_recurse(clause, not_arg))
716  return true;
717 
718  /*
719  * atom R=> atom is the base case
720  */
721  return
723  clause);
724  }
725  break;
726  }
727 
728  /* can't get here */
729  elog(ERROR, "predicate_classify returned a bogus value");
730  return false;
731 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define iterate_begin(item, clause, info)
Definition: predtest.c:69
static bool predicate_implied_by_recurse(Node *clause, Node *predicate)
Definition: predtest.c:251
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
Definition: nodes.h:508
static PredClass predicate_classify(Node *clause, PredIterInfo info)
Definition: predtest.c:749
PredClass
Definition: predtest.c:48
#define ERROR
Definition: elog.h:43
static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause)
Definition: predtest.c:1101
static Node * extract_strong_not_arg(Node *clause)
Definition: predtest.c:1199
static Node * extract_not_arg(Node *clause)
Definition: predtest.c:1171
static bool predicate_refuted_by_recurse(Node *clause, Node *predicate)
Definition: predtest.c:481
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define elog
Definition: elog.h:219
#define iterate_end(info)
Definition: predtest.c:75
static bool predicate_refuted_by_simple_clause ( Expr predicate,
Node clause 
)
static

Definition at line 1101 of file predtest.c.

References arg, generate_unaccent_rules::args, CHECK_FOR_INTERRUPTS, equal(), func_strict(), is_funcclause, IS_NOT_NULL, IS_NULL, is_opclause, IsA, list_member_strip(), op_strict(), and operator_predicate_proof().

Referenced by predicate_refuted_by_recurse().

1102 {
1103  /* Allow interrupting long proof attempts */
1105 
1106  /* A simple clause can't refute itself */
1107  /* Worth checking because of relation_excluded_by_constraints() */
1108  if ((Node *) predicate == clause)
1109  return false;
1110 
1111  /* Try the predicate-IS-NULL case */
1112  if (predicate && IsA(predicate, NullTest) &&
1113  ((NullTest *) predicate)->nulltesttype == IS_NULL)
1114  {
1115  Expr *isnullarg = ((NullTest *) predicate)->arg;
1116 
1117  /* row IS NULL does not act in the simple way we have in mind */
1118  if (((NullTest *) predicate)->argisrow)
1119  return false;
1120 
1121  /* Any strict op/func on foo refutes foo IS NULL */
1122  if (is_opclause(clause) &&
1123  list_member_strip(((OpExpr *) clause)->args, isnullarg) &&
1124  op_strict(((OpExpr *) clause)->opno))
1125  return true;
1126  if (is_funcclause(clause) &&
1127  list_member_strip(((FuncExpr *) clause)->args, isnullarg) &&
1128  func_strict(((FuncExpr *) clause)->funcid))
1129  return true;
1130 
1131  /* foo IS NOT NULL refutes foo IS NULL */
1132  if (clause && IsA(clause, NullTest) &&
1133  ((NullTest *) clause)->nulltesttype == IS_NOT_NULL &&
1134  !((NullTest *) clause)->argisrow &&
1135  equal(((NullTest *) clause)->arg, isnullarg))
1136  return true;
1137 
1138  return false; /* we can't succeed below... */
1139  }
1140 
1141  /* Try the clause-IS-NULL case */
1142  if (clause && IsA(clause, NullTest) &&
1143  ((NullTest *) clause)->nulltesttype == IS_NULL)
1144  {
1145  Expr *isnullarg = ((NullTest *) clause)->arg;
1146 
1147  /* row IS NULL does not act in the simple way we have in mind */
1148  if (((NullTest *) clause)->argisrow)
1149  return false;
1150 
1151  /* foo IS NULL refutes foo IS NOT NULL */
1152  if (predicate && IsA(predicate, NullTest) &&
1153  ((NullTest *) predicate)->nulltesttype == IS_NOT_NULL &&
1154  !((NullTest *) predicate)->argisrow &&
1155  equal(((NullTest *) predicate)->arg, isnullarg))
1156  return true;
1157 
1158  return false; /* we can't succeed below... */
1159  }
1160 
1161  /* Else try operator-related knowledge */
1162  return operator_predicate_proof(predicate, clause, true);
1163 }
static bool list_member_strip(List *list, Expr *datum)
Definition: predtest.c:1229
bool op_strict(Oid opno)
Definition: lsyscache.c:1249
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static bool operator_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
Definition: predtest.c:1407
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
#define is_funcclause(clause)
Definition: clauses.h:21
Definition: nodes.h:508
#define is_opclause(clause)
Definition: clauses.h:20
bool func_strict(Oid funcid)
Definition: lsyscache.c:1533
void * arg
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97

Variable Documentation

const StrategyNumber BT_implic_table[6][6]
static
Initial value:
= {
{BTGE, BTGE, none, none, none, BTGE},
{none, none, none, BTLE, BTLT, BTLT},
{none, none, none, BTLE, BTLE, BTLE},
}
#define none
Definition: predtest.c:1314
#define BTGT
Definition: predtest.c:1310
#define BTLT
Definition: predtest.c:1306
#define BTGE
Definition: predtest.c:1309
#define BTEQ
Definition: predtest.c:1308
#define BTNE
Definition: predtest.c:1311
#define BTLE
Definition: predtest.c:1307

Definition at line 1342 of file predtest.c.

Referenced by lookup_proof_cache().

const bool BT_implies_table[6][6]
static
Initial value:
= {
{TRUE, TRUE, none, none, none, TRUE},
{none, TRUE, none, none, none, none},
{none, TRUE, TRUE, TRUE, none, none},
{none, none, none, TRUE, none, none},
{none, none, none, TRUE, TRUE, TRUE},
}
#define none
Definition: predtest.c:1314
#define TRUE
Definition: c.h:214

Definition at line 1316 of file predtest.c.

Referenced by lookup_proof_cache().

const StrategyNumber BT_refute_table[6][6]
static
Initial value:
= {
{none, none, BTGE, BTGE, BTGE, none},
{none, none, BTGT, BTGT, BTGE, none},
{BTLE, BTLT, BTLT, none, none, none},
{BTLE, BTLE, BTLE, none, none, none},
{none, none, BTEQ, none, none, none}
}
#define none
Definition: predtest.c:1314
#define BTGT
Definition: predtest.c:1310
#define BTLT
Definition: predtest.c:1306
#define BTGE
Definition: predtest.c:1309
#define BTEQ
Definition: predtest.c:1308
#define BTNE
Definition: predtest.c:1311
#define BTLE
Definition: predtest.c:1307

Definition at line 1355 of file predtest.c.

Referenced by lookup_proof_cache().

const bool BT_refutes_table[6][6]
static
Initial value:
= {
{none, none, TRUE, TRUE, TRUE, none},
{none, none, none, none, TRUE, none},
{TRUE, none, none, none, TRUE, TRUE},
{TRUE, none, none, none, none, none},
{TRUE, TRUE, TRUE, none, none, none},
{none, none, TRUE, none, none, none}
}
#define none
Definition: predtest.c:1314
#define TRUE
Definition: c.h:214

Definition at line 1329 of file predtest.c.

Referenced by lookup_proof_cache().

HTAB* OprProofCacheHash = NULL
static

Definition at line 1686 of file predtest.c.