diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index e9df49bab9c..f6581bbe44f 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.388 2008/02/07 20:19:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.388.2.1 2009/04/16 20:42:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1421,6 +1421,7 @@ _copyRestrictInfo(RestrictInfo *from) COPY_SCALAR_FIELD(pseudoconstant); COPY_BITMAPSET_FIELD(clause_relids); COPY_BITMAPSET_FIELD(required_relids); + COPY_BITMAPSET_FIELD(nullable_relids); COPY_BITMAPSET_FIELD(left_relids); COPY_BITMAPSET_FIELD(right_relids); COPY_NODE_FIELD(orclause); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 57c51b2c73f..9506d2c43e5 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.318 2008/02/07 20:19:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.318.2.1 2009/04/16 20:42:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -692,6 +692,7 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b) COMPARE_SCALAR_FIELD(is_pushed_down); COMPARE_SCALAR_FIELD(outerjoin_delayed); COMPARE_BITMAPSET_FIELD(required_relids); + COMPARE_BITMAPSET_FIELD(nullable_relids); /* * We ignore all the remaining fields, since they may not be set yet, and diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 6bc2595eafc..da069b8877c 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.322.2.1 2008/12/01 21:06:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.322.2.2 2009/04/16 20:42:28 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1455,6 +1455,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node) WRITE_BOOL_FIELD(pseudoconstant); WRITE_BITMAPSET_FIELD(clause_relids); WRITE_BITMAPSET_FIELD(required_relids); + WRITE_BITMAPSET_FIELD(nullable_relids); WRITE_BITMAPSET_FIELD(left_relids); WRITE_BITMAPSET_FIELD(right_relids); WRITE_NODE_FIELD(orclause); diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 3100c92d3d8..856e399fa2e 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.227.2.1 2008/09/12 14:56:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.227.2.2 2009/04/16 20:42:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2254,11 +2254,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) if (boolqual) { resultquals = lappend(resultquals, - make_restrictinfo(boolqual, - true, - false, - false, - NULL)); + make_simple_restrictinfo(boolqual)); continue; } } @@ -2289,11 +2285,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) { Assert(index->amsearchnulls); resultquals = lappend(resultquals, - make_restrictinfo(clause, - true, - false, - false, - NULL)); + make_simple_restrictinfo(clause)); } else elog(ERROR, "unsupported indexqual type: %d", @@ -2652,7 +2644,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, matching_cols); rc->rargs = list_truncate((List *) copyObject(clause->rargs), matching_cols); - return make_restrictinfo((Expr *) rc, true, false, false, NULL); + return make_simple_restrictinfo((Expr *) rc); } else { @@ -2661,7 +2653,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, opexpr = make_opclause(linitial_oid(new_ops), BOOLOID, false, copyObject(linitial(clause->largs)), copyObject(linitial(clause->rargs))); - return make_restrictinfo(opexpr, true, false, false, NULL); + return make_simple_restrictinfo(opexpr); } } @@ -2749,7 +2741,7 @@ prefix_quals(Node *leftop, Oid opfamily, elog(ERROR, "no = operator for opfamily %u", opfamily); expr = make_opclause(oproid, BOOLOID, false, (Expr *) leftop, (Expr *) prefix_const); - result = list_make1(make_restrictinfo(expr, true, false, false, NULL)); + result = list_make1(make_simple_restrictinfo(expr)); return result; } @@ -2764,7 +2756,7 @@ prefix_quals(Node *leftop, Oid opfamily, elog(ERROR, "no >= operator for opfamily %u", opfamily); expr = make_opclause(oproid, BOOLOID, false, (Expr *) leftop, (Expr *) prefix_const); - result = list_make1(make_restrictinfo(expr, true, false, false, NULL)); + result = list_make1(make_simple_restrictinfo(expr)); /*------- * If we can create a string larger than the prefix, we can say @@ -2781,8 +2773,7 @@ prefix_quals(Node *leftop, Oid opfamily, { expr = make_opclause(oproid, BOOLOID, false, (Expr *) leftop, (Expr *) greaterstr); - result = lappend(result, - make_restrictinfo(expr, true, false, false, NULL)); + result = lappend(result, make_simple_restrictinfo(expr)); } return result; @@ -2845,7 +2836,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop) (Expr *) leftop, (Expr *) makeConst(datatype, -1, -1, opr1right, false, false)); - result = list_make1(make_restrictinfo(expr, true, false, false, NULL)); + result = list_make1(make_simple_restrictinfo(expr)); /* create clause "key <= network_scan_last( rightop )" */ @@ -2860,8 +2851,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop) (Expr *) leftop, (Expr *) makeConst(datatype, -1, -1, opr2right, false, false)); - result = lappend(result, - make_restrictinfo(expr, true, false, false, NULL)); + result = lappend(result, make_simple_restrictinfo(expr)); return result; } diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c index 1556bf74df6..c13a48d46b6 100644 --- a/src/backend/optimizer/path/orindxpath.c +++ b/src/backend/optimizer/path/orindxpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.84 2008/01/09 20:42:27 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.84.2.1 2009/04/16 20:42:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -89,12 +89,18 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel) ListCell *i; /* - * Find potentially interesting OR joinclauses. Note we must ignore any - * joinclauses that are marked outerjoin_delayed or !is_pushed_down, - * because they cannot be pushed down to the per-relation level due to - * outer-join rules. (XXX in some cases it might be possible to allow - * this, but it would require substantially more bookkeeping about where - * the clause came from.) + * Find potentially interesting OR joinclauses. + * + * We must ignore clauses for which the target rel is in nullable_relids; + * that means there's an outer join below the clause and so it can't be + * enforced at the relation scan level. + * + * We must also ignore clauses that are marked !is_pushed_down (ie they + * are themselves outer-join clauses). It would be safe to extract an + * index condition from such a clause if we are within the nullable rather + * than the non-nullable side of its join, but we haven't got enough + * context here to tell which applies. OR clauses in outer-join quals + * aren't exactly common, so we'll let that case go unoptimized for now. */ foreach(i, rel->joininfo) { @@ -102,7 +108,7 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel) if (restriction_is_or_clause(rinfo) && rinfo->is_pushed_down && - !rinfo->outerjoin_delayed) + !bms_is_member(rel->relid, rinfo->nullable_relids)) { /* * Use the generate_bitmap_or_paths() machinery to estimate the diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 0294b9a3915..17dc3d0da14 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.138.2.2 2008/06/27 20:54:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.138.2.3 2009/04/16 20:42:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,7 +51,7 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, Relids ojscope, Relids outerjoin_nonnullable); static bool check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, - bool is_pushed_down); + Relids *nullable_relids_p, bool is_pushed_down); static void check_mergejoinable(RestrictInfo *restrictinfo); static void check_hashjoinable(RestrictInfo *restrictinfo); @@ -732,6 +732,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool pseudoconstant = false; bool maybe_equivalence; bool maybe_outer_join; + Relids nullable_relids; RestrictInfo *restrictinfo; /* @@ -836,6 +837,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, Assert(!ojscope); is_pushed_down = true; outerjoin_delayed = false; + nullable_relids = NULL; /* Don't feed it back for more deductions */ maybe_equivalence = false; maybe_outer_join = false; @@ -857,7 +859,10 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, maybe_outer_join = true; /* Check to see if must be delayed by lower outer join */ - outerjoin_delayed = check_outerjoin_delay(root, &relids, false); + outerjoin_delayed = check_outerjoin_delay(root, + &relids, + &nullable_relids, + false); /* * Now force the qual to be evaluated exactly at the level of joining @@ -882,7 +887,10 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, is_pushed_down = true; /* Check to see if must be delayed by lower outer join */ - outerjoin_delayed = check_outerjoin_delay(root, &relids, true); + outerjoin_delayed = check_outerjoin_delay(root, + &relids, + &nullable_relids, + true); if (outerjoin_delayed) { @@ -923,7 +931,8 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, - relids); + relids, + nullable_relids); /* * If it's a join clause (either naturally, or because delayed by @@ -1030,7 +1039,9 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, * If the qual must be delayed, add relids to *relids_p to reflect the lowest * safe level for evaluating the qual, and return TRUE. Any extra delay for * higher-level joins is reflected by setting delay_upper_joins to TRUE in - * OuterJoinInfo structs. + * OuterJoinInfo structs. We also compute nullable_relids, the set of + * referenced relids that are nullable by lower outer joins (note that this + * can be nonempty even for a non-delayed qual). * * For an is_pushed_down qual, we can evaluate the qual as soon as (1) we have * all the rels it mentions, and (2) we are at or above any outer joins that @@ -1053,8 +1064,8 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, * mentioning only C cannot be applied below the join to A. * * For a non-pushed-down qual, this isn't going to determine where we place the - * qual, but we need to determine outerjoin_delayed anyway for possible use - * in reconsider_outer_join_clauses(). + * qual, but we need to determine outerjoin_delayed and nullable_relids anyway + * for use later in the planning process. * * Lastly, a pushed-down qual that references the nullable side of any current * oj_info_list member and has to be evaluated above that OJ (because its @@ -1070,13 +1081,26 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, * two OJs to commute.) */ static bool -check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, +check_outerjoin_delay(PlannerInfo *root, + Relids *relids_p, /* in/out parameter */ + Relids *nullable_relids_p, /* output parameter */ bool is_pushed_down) { - Relids relids = *relids_p; + Relids relids; + Relids nullable_relids; bool outerjoin_delayed; bool found_some; + /* fast path if no outer joins */ + if (root->oj_info_list == NIL) + { + *nullable_relids_p = NULL; + return false; + } + + /* must copy relids because we need the original value at the end */ + relids = bms_copy(*relids_p); + nullable_relids = NULL; outerjoin_delayed = false; do { @@ -1092,18 +1116,23 @@ check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, (ojinfo->is_full_join && bms_overlap(relids, ojinfo->min_lefthand))) { - /* yes, so set the result flag */ - outerjoin_delayed = true; - /* have we included all its rels in relids? */ + /* yes; have we included all its rels in relids? */ if (!bms_is_subset(ojinfo->min_lefthand, relids) || !bms_is_subset(ojinfo->min_righthand, relids)) { /* no, so add them in */ relids = bms_add_members(relids, ojinfo->min_lefthand); relids = bms_add_members(relids, ojinfo->min_righthand); + outerjoin_delayed = true; /* we'll need another iteration */ found_some = true; } + /* track all the nullable rels of relevant OJs */ + nullable_relids = bms_add_members(nullable_relids, + ojinfo->min_righthand); + if (ojinfo->is_full_join) + nullable_relids = bms_add_members(nullable_relids, + ojinfo->min_lefthand); /* set delay_upper_joins if needed */ if (is_pushed_down && !ojinfo->is_full_join && bms_overlap(relids, ojinfo->min_lefthand)) @@ -1112,7 +1141,13 @@ check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, } } while (found_some); + /* identify just the actually-referenced nullable rels */ + nullable_relids = bms_int_members(nullable_relids, *relids_p); + + /* replace *relids_p, and return nullable_relids */ + bms_free(*relids_p); *relids_p = relids; + *nullable_relids_p = nullable_relids; return outerjoin_delayed; } @@ -1279,7 +1314,8 @@ build_implied_join_equality(Oid opno, true, /* is_pushed_down */ false, /* outerjoin_delayed */ false, /* pseudoconstant */ - qualscope); + qualscope, /* required_relids */ + NULL); /* nullable_relids */ /* Set mergejoinability info always, and hashjoinability if enabled */ check_mergejoinable(restrictinfo); diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index 09aa7f46873..ecb1087d851 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.55 2008/01/01 19:45:50 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.55.2.1 2009/04/16 20:42:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,12 +27,14 @@ static RestrictInfo *make_restrictinfo_internal(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, - Relids required_relids); + Relids required_relids, + Relids nullable_relids); static Expr *make_sub_restrictinfos(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, - Relids required_relids); + Relids required_relids, + Relids nullable_relids); static bool join_clause_is_redundant(PlannerInfo *root, RestrictInfo *rinfo, List *reference_list); @@ -44,9 +46,9 @@ static bool join_clause_is_redundant(PlannerInfo *root, * Build a RestrictInfo node containing the given subexpression. * * The is_pushed_down, outerjoin_delayed, and pseudoconstant flags for the - * RestrictInfo must be supplied by the caller. required_relids can be NULL, - * in which case it defaults to the actual clause contents (i.e., - * clause_relids). + * RestrictInfo must be supplied by the caller, as well as the correct value + * for nullable_relids. required_relids can be NULL, in which case it + * defaults to the actual clause contents (i.e., clause_relids). * * We initialize fields that depend only on the given subexpression, leaving * others that depend on context (or may never be needed at all) to be filled @@ -57,7 +59,8 @@ make_restrictinfo(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, - Relids required_relids) + Relids required_relids, + Relids nullable_relids) { /* * If it's an OR clause, build a modified copy with RestrictInfos inserted @@ -68,7 +71,8 @@ make_restrictinfo(Expr *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, - required_relids); + required_relids, + nullable_relids); /* Shouldn't be an AND clause, else AND/OR flattening messed up */ Assert(!and_clause((Node *) clause)); @@ -78,7 +82,8 @@ make_restrictinfo(Expr *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, - required_relids); + required_relids, + nullable_relids); } /* @@ -92,8 +97,8 @@ make_restrictinfo(Expr *clause, * RestrictInfos. * * The caller must pass is_pushed_down, but we assume outerjoin_delayed - * and pseudoconstant are false (no such qual should ever get into a - * bitmapqual). + * and pseudoconstant are false and nullable_relids is NULL (no other + * kind of qual should ever get into a bitmapqual). * * If include_predicates is true, we add any partial index predicates to * the explicit index quals. When this is not true, we return a condition @@ -224,6 +229,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual, is_pushed_down, false, false, + NULL, NULL)); } } @@ -250,6 +256,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual, is_pushed_down, false, false, + NULL, NULL)); } } @@ -274,7 +281,8 @@ make_restrictinfo_internal(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, - Relids required_relids) + Relids required_relids, + Relids nullable_relids) { RestrictInfo *restrictinfo = makeNode(RestrictInfo); @@ -284,6 +292,7 @@ make_restrictinfo_internal(Expr *clause, restrictinfo->outerjoin_delayed = outerjoin_delayed; restrictinfo->pseudoconstant = pseudoconstant; restrictinfo->can_join = false; /* may get set below */ + restrictinfo->nullable_relids = nullable_relids; /* * If it's a binary opclause, set up left/right relids info. In any case @@ -368,7 +377,8 @@ make_restrictinfo_internal(Expr *clause, * simple clauses are valid RestrictInfos. * * The same is_pushed_down, outerjoin_delayed, and pseudoconstant flag - * values can be applied to all RestrictInfo nodes in the result. + * values can be applied to all RestrictInfo nodes in the result. Likewise + * for nullable_relids. * * The given required_relids are attached to our top-level output, * but any OR-clause constituents are allowed to default to just the @@ -379,7 +389,8 @@ make_sub_restrictinfos(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, - Relids required_relids) + Relids required_relids, + Relids nullable_relids) { if (or_clause((Node *) clause)) { @@ -392,13 +403,15 @@ make_sub_restrictinfos(Expr *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, - NULL)); + NULL, + nullable_relids)); return (Expr *) make_restrictinfo_internal(clause, make_orclause(orlist), is_pushed_down, outerjoin_delayed, pseudoconstant, - required_relids); + required_relids, + nullable_relids); } else if (and_clause((Node *) clause)) { @@ -411,7 +424,8 @@ make_sub_restrictinfos(Expr *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, - required_relids)); + required_relids, + nullable_relids)); return make_andclause(andlist); } else @@ -420,7 +434,8 @@ make_sub_restrictinfos(Expr *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, - required_relids); + required_relids, + nullable_relids); } /* diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 3d4b9ddcf8c..b5cde02b8c9 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.154.2.3 2008/12/01 21:06:20 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.154.2.4 2009/04/16 20:42:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -897,8 +897,14 @@ typedef struct HashPath * * RestrictInfo nodes also contain an outerjoin_delayed flag, which is true * if the clause's applicability must be delayed due to any outer joins - * appearing below its own syntactic level (ie, it references any Vars from - * the nullable side of any lower outer join). + * appearing below it (ie, it has to be postponed to some join level higher + * than the set of relations it actually references). There is also a + * nullable_relids field, which is the set of rels it references that can be + * forced null by some outer join below the clause. outerjoin_delayed = true + * is subtly different from nullable_relids != NULL: a clause might reference + * some nullable rels and yet not be outerjoin_delayed because it also + * references all the other rels of the outer join(s). A clause that is not + * outerjoin_delayed can be enforced anywhere it is computable. * * In general, the referenced clause might be arbitrarily complex. The * kinds of clauses we can handle as indexscan quals, mergejoin clauses, @@ -960,6 +966,9 @@ typedef struct RestrictInfo /* The set of relids required to evaluate the clause: */ Relids required_relids; + /* The relids used in the clause that are nullable by lower outer joins: */ + Relids nullable_relids; + /* These fields are set for any binary opclause: */ Relids left_relids; /* relids in left side of clause */ Relids right_relids; /* relids in right side of clause */ diff --git a/src/include/optimizer/restrictinfo.h b/src/include/optimizer/restrictinfo.h index fe26489353f..06bb8fe8868 100644 --- a/src/include/optimizer/restrictinfo.h +++ b/src/include/optimizer/restrictinfo.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.41 2008/01/01 19:45:58 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.41.2.1 2009/04/16 20:42:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,11 +17,16 @@ #include "nodes/relation.h" +/* Convenience macro for the common case of a valid-everywhere qual */ +#define make_simple_restrictinfo(clause) \ + make_restrictinfo(clause, true, false, false, NULL, NULL) + extern RestrictInfo *make_restrictinfo(Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, - Relids required_relids); + Relids required_relids, + Relids nullable_relids); extern List *make_restrictinfo_from_bitmapqual(Path *bitmapqual, bool is_pushed_down, bool include_predicates);