diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 5fac94f8631..a587ef5df5b 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.429 2009/04/05 19:59:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.430 2009/04/16 20:42:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1606,6 +1606,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 36f2bcc2d51..d4c8b7262c1 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.352 2009/04/05 19:59:40 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.353 2009/04/16 20:42:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -759,6 +759,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 67f051311fd..18e9a5792fa 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.358 2009/04/05 19:59:40 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.359 2009/04/16 20:42:16 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1613,6 +1613,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 2866689b9a7..db271e4f1ee 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.238 2009/03/11 03:32:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.239 2009/04/16 20:42:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2325,11 +2325,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; } } @@ -2360,11 +2356,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", @@ -2737,7 +2729,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 { @@ -2746,7 +2738,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); } } @@ -2832,7 +2824,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; } @@ -2847,7 +2839,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 @@ -2864,8 +2856,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; @@ -2928,7 +2919,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 )" */ @@ -2943,8 +2934,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 2f8a67394e2..c84591fe0ce 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.88 2009/02/15 20:16:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.89 2009/04/16 20:42:16 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 cf05f033b9a..952fd7649fd 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.149 2009/02/27 22:41:38 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.150 2009/04/16 20:42:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,7 +53,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 bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause); static void check_mergejoinable(RestrictInfo *restrictinfo); static void check_hashjoinable(RestrictInfo *restrictinfo); @@ -755,6 +755,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool pseudoconstant = false; bool maybe_equivalence; bool maybe_outer_join; + Relids nullable_relids; RestrictInfo *restrictinfo; /* @@ -861,6 +862,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; @@ -882,7 +884,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 @@ -907,7 +912,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) { @@ -957,7 +965,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 @@ -1064,7 +1073,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 - * SpecialJoinInfo structs. + * SpecialJoinInfo 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 @@ -1087,8 +1098,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 * join_info_list member and has to be evaluated above that OJ (because its @@ -1104,13 +1115,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 special joins */ + if (root->join_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 { @@ -1126,18 +1150,23 @@ check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, (sjinfo->jointype == JOIN_FULL && bms_overlap(relids, sjinfo->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(sjinfo->min_lefthand, relids) || !bms_is_subset(sjinfo->min_righthand, relids)) { /* no, so add them in */ relids = bms_add_members(relids, sjinfo->min_lefthand); relids = bms_add_members(relids, sjinfo->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, + sjinfo->min_righthand); + if (sjinfo->jointype == JOIN_FULL) + nullable_relids = bms_add_members(nullable_relids, + sjinfo->min_lefthand); /* set delay_upper_joins if needed */ if (is_pushed_down && sjinfo->jointype != JOIN_FULL && bms_overlap(relids, sjinfo->min_lefthand)) @@ -1146,7 +1175,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; } @@ -1352,7 +1387,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 22e2aeb493e..0fcfd0ed509 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.57 2009/02/06 23:43:23 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.58 2009/04/16 20:42:16 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 @@ -369,7 +378,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 @@ -380,7 +390,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)) { @@ -393,13 +404,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)) { @@ -412,7 +425,8 @@ make_sub_restrictinfos(Expr *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, - required_relids)); + required_relids, + nullable_relids)); return make_andclause(andlist); } else @@ -421,7 +435,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 cf567b99746..6a72504a2f7 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.171 2009/03/26 17:15:35 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.172 2009/04/16 20:42:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -920,8 +920,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, @@ -983,6 +989,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 7791afe947b..52d256ed284 100644 --- a/src/include/optimizer/restrictinfo.h +++ b/src/include/optimizer/restrictinfo.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.42 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.43 2009/04/16 20:42:16 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);