00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "optimizer/clauses.h"
00018 #include "optimizer/predtest.h"
00019 #include "optimizer/restrictinfo.h"
00020 #include "optimizer/var.h"
00021
00022
00023 static RestrictInfo *make_restrictinfo_internal(Expr *clause,
00024 Expr *orclause,
00025 bool is_pushed_down,
00026 bool outerjoin_delayed,
00027 bool pseudoconstant,
00028 Relids required_relids,
00029 Relids outer_relids,
00030 Relids nullable_relids);
00031 static Expr *make_sub_restrictinfos(Expr *clause,
00032 bool is_pushed_down,
00033 bool outerjoin_delayed,
00034 bool pseudoconstant,
00035 Relids required_relids,
00036 Relids outer_relids,
00037 Relids nullable_relids);
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 RestrictInfo *
00056 make_restrictinfo(Expr *clause,
00057 bool is_pushed_down,
00058 bool outerjoin_delayed,
00059 bool pseudoconstant,
00060 Relids required_relids,
00061 Relids outer_relids,
00062 Relids nullable_relids)
00063 {
00064
00065
00066
00067
00068 if (or_clause((Node *) clause))
00069 return (RestrictInfo *) make_sub_restrictinfos(clause,
00070 is_pushed_down,
00071 outerjoin_delayed,
00072 pseudoconstant,
00073 required_relids,
00074 outer_relids,
00075 nullable_relids);
00076
00077
00078 Assert(!and_clause((Node *) clause));
00079
00080 return make_restrictinfo_internal(clause,
00081 NULL,
00082 is_pushed_down,
00083 outerjoin_delayed,
00084 pseudoconstant,
00085 required_relids,
00086 outer_relids,
00087 nullable_relids);
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 List *
00117 make_restrictinfo_from_bitmapqual(Path *bitmapqual,
00118 bool is_pushed_down,
00119 bool include_predicates)
00120 {
00121 List *result;
00122 ListCell *l;
00123
00124 if (IsA(bitmapqual, BitmapAndPath))
00125 {
00126 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
00127
00128
00129
00130
00131
00132
00133
00134
00135 result = NIL;
00136 foreach(l, apath->bitmapquals)
00137 {
00138 List *sublist;
00139
00140 sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
00141 is_pushed_down,
00142 include_predicates);
00143 result = list_concat_unique(result, sublist);
00144 }
00145 }
00146 else if (IsA(bitmapqual, BitmapOrPath))
00147 {
00148 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
00149 List *withris = NIL;
00150 List *withoutris = NIL;
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 foreach(l, opath->bitmapquals)
00162 {
00163 List *sublist;
00164
00165 sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
00166 is_pushed_down,
00167 include_predicates);
00168 if (sublist == NIL)
00169 {
00170
00171
00172
00173
00174
00175 return NIL;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 if (list_length(sublist) > 1)
00188 {
00189 withris = lappend(withris, make_andclause(sublist));
00190 sublist = get_actual_clauses(sublist);
00191 withoutris = lappend(withoutris, make_andclause(sublist));
00192 }
00193 else
00194 {
00195 RestrictInfo *subri = (RestrictInfo *) linitial(sublist);
00196
00197 Assert(IsA(subri, RestrictInfo));
00198 if (restriction_is_or_clause(subri))
00199 {
00200 BoolExpr *subor = (BoolExpr *) subri->orclause;
00201
00202 Assert(or_clause((Node *) subor));
00203 withris = list_concat(withris,
00204 list_copy(subor->args));
00205 subor = (BoolExpr *) subri->clause;
00206 Assert(or_clause((Node *) subor));
00207 withoutris = list_concat(withoutris,
00208 list_copy(subor->args));
00209 }
00210 else
00211 {
00212 withris = lappend(withris, subri);
00213 withoutris = lappend(withoutris, subri->clause);
00214 }
00215 }
00216 }
00217
00218
00219
00220
00221
00222 if (list_length(withris) <= 1)
00223 result = withris;
00224 else
00225 {
00226
00227 result =
00228 list_make1(make_restrictinfo_internal(make_orclause(withoutris),
00229 make_orclause(withris),
00230 is_pushed_down,
00231 false,
00232 false,
00233 NULL,
00234 NULL,
00235 NULL));
00236 }
00237 }
00238 else if (IsA(bitmapqual, IndexPath))
00239 {
00240 IndexPath *ipath = (IndexPath *) bitmapqual;
00241
00242 result = list_copy(ipath->indexclauses);
00243 if (include_predicates && ipath->indexinfo->indpred != NIL)
00244 {
00245 foreach(l, ipath->indexinfo->indpred)
00246 {
00247 Expr *pred = (Expr *) lfirst(l);
00248
00249
00250
00251
00252
00253
00254
00255 if (!predicate_implied_by(list_make1(pred), result))
00256 result = lappend(result,
00257 make_restrictinfo(pred,
00258 is_pushed_down,
00259 false,
00260 false,
00261 NULL,
00262 NULL,
00263 NULL));
00264 }
00265 }
00266 }
00267 else
00268 {
00269 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
00270 result = NIL;
00271 }
00272
00273 return result;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 List *
00290 make_restrictinfos_from_actual_clauses(PlannerInfo *root,
00291 List *clause_list)
00292 {
00293 List *result = NIL;
00294 ListCell *l;
00295
00296 foreach(l, clause_list)
00297 {
00298 Expr *clause = (Expr *) lfirst(l);
00299 bool pseudoconstant;
00300 RestrictInfo *rinfo;
00301
00302
00303
00304
00305
00306
00307
00308 pseudoconstant =
00309 !contain_vars_of_level((Node *) clause, 0) &&
00310 !contain_volatile_functions((Node *) clause);
00311 if (pseudoconstant)
00312 {
00313
00314 root->hasPseudoConstantQuals = true;
00315 }
00316
00317 rinfo = make_restrictinfo(clause,
00318 true,
00319 false,
00320 pseudoconstant,
00321 NULL,
00322 NULL,
00323 NULL);
00324 result = lappend(result, rinfo);
00325 }
00326 return result;
00327 }
00328
00329
00330
00331
00332
00333
00334 static RestrictInfo *
00335 make_restrictinfo_internal(Expr *clause,
00336 Expr *orclause,
00337 bool is_pushed_down,
00338 bool outerjoin_delayed,
00339 bool pseudoconstant,
00340 Relids required_relids,
00341 Relids outer_relids,
00342 Relids nullable_relids)
00343 {
00344 RestrictInfo *restrictinfo = makeNode(RestrictInfo);
00345
00346 restrictinfo->clause = clause;
00347 restrictinfo->orclause = orclause;
00348 restrictinfo->is_pushed_down = is_pushed_down;
00349 restrictinfo->outerjoin_delayed = outerjoin_delayed;
00350 restrictinfo->pseudoconstant = pseudoconstant;
00351 restrictinfo->can_join = false;
00352 restrictinfo->outer_relids = outer_relids;
00353 restrictinfo->nullable_relids = nullable_relids;
00354
00355
00356
00357
00358
00359 if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
00360 {
00361 restrictinfo->left_relids = pull_varnos(get_leftop(clause));
00362 restrictinfo->right_relids = pull_varnos(get_rightop(clause));
00363
00364 restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
00365 restrictinfo->right_relids);
00366
00367
00368
00369
00370
00371
00372
00373 if (!bms_is_empty(restrictinfo->left_relids) &&
00374 !bms_is_empty(restrictinfo->right_relids) &&
00375 !bms_overlap(restrictinfo->left_relids,
00376 restrictinfo->right_relids))
00377 {
00378 restrictinfo->can_join = true;
00379
00380 Assert(!restrictinfo->pseudoconstant);
00381 }
00382 }
00383 else
00384 {
00385
00386 restrictinfo->left_relids = NULL;
00387 restrictinfo->right_relids = NULL;
00388
00389 restrictinfo->clause_relids = pull_varnos((Node *) clause);
00390 }
00391
00392
00393 if (required_relids != NULL)
00394 restrictinfo->required_relids = required_relids;
00395 else
00396 restrictinfo->required_relids = restrictinfo->clause_relids;
00397
00398
00399
00400
00401
00402
00403
00404
00405 restrictinfo->parent_ec = NULL;
00406
00407 restrictinfo->eval_cost.startup = -1;
00408 restrictinfo->norm_selec = -1;
00409 restrictinfo->outer_selec = -1;
00410
00411 restrictinfo->mergeopfamilies = NIL;
00412
00413 restrictinfo->left_ec = NULL;
00414 restrictinfo->right_ec = NULL;
00415 restrictinfo->left_em = NULL;
00416 restrictinfo->right_em = NULL;
00417 restrictinfo->scansel_cache = NIL;
00418
00419 restrictinfo->outer_is_left = false;
00420
00421 restrictinfo->hashjoinoperator = InvalidOid;
00422
00423 restrictinfo->left_bucketsize = -1;
00424 restrictinfo->right_bucketsize = -1;
00425
00426 return restrictinfo;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 static Expr *
00447 make_sub_restrictinfos(Expr *clause,
00448 bool is_pushed_down,
00449 bool outerjoin_delayed,
00450 bool pseudoconstant,
00451 Relids required_relids,
00452 Relids outer_relids,
00453 Relids nullable_relids)
00454 {
00455 if (or_clause((Node *) clause))
00456 {
00457 List *orlist = NIL;
00458 ListCell *temp;
00459
00460 foreach(temp, ((BoolExpr *) clause)->args)
00461 orlist = lappend(orlist,
00462 make_sub_restrictinfos(lfirst(temp),
00463 is_pushed_down,
00464 outerjoin_delayed,
00465 pseudoconstant,
00466 NULL,
00467 outer_relids,
00468 nullable_relids));
00469 return (Expr *) make_restrictinfo_internal(clause,
00470 make_orclause(orlist),
00471 is_pushed_down,
00472 outerjoin_delayed,
00473 pseudoconstant,
00474 required_relids,
00475 outer_relids,
00476 nullable_relids);
00477 }
00478 else if (and_clause((Node *) clause))
00479 {
00480 List *andlist = NIL;
00481 ListCell *temp;
00482
00483 foreach(temp, ((BoolExpr *) clause)->args)
00484 andlist = lappend(andlist,
00485 make_sub_restrictinfos(lfirst(temp),
00486 is_pushed_down,
00487 outerjoin_delayed,
00488 pseudoconstant,
00489 required_relids,
00490 outer_relids,
00491 nullable_relids));
00492 return make_andclause(andlist);
00493 }
00494 else
00495 return (Expr *) make_restrictinfo_internal(clause,
00496 NULL,
00497 is_pushed_down,
00498 outerjoin_delayed,
00499 pseudoconstant,
00500 required_relids,
00501 outer_relids,
00502 nullable_relids);
00503 }
00504
00505
00506
00507
00508
00509
00510 bool
00511 restriction_is_or_clause(RestrictInfo *restrictinfo)
00512 {
00513 if (restrictinfo->orclause != NULL)
00514 return true;
00515 else
00516 return false;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 List *
00528 get_actual_clauses(List *restrictinfo_list)
00529 {
00530 List *result = NIL;
00531 ListCell *l;
00532
00533 foreach(l, restrictinfo_list)
00534 {
00535 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00536
00537 Assert(IsA(rinfo, RestrictInfo));
00538
00539 Assert(!rinfo->pseudoconstant);
00540
00541 result = lappend(result, rinfo->clause);
00542 }
00543 return result;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 List *
00555 get_all_actual_clauses(List *restrictinfo_list)
00556 {
00557 List *result = NIL;
00558 ListCell *l;
00559
00560 foreach(l, restrictinfo_list)
00561 {
00562 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00563
00564 Assert(IsA(rinfo, RestrictInfo));
00565
00566 result = lappend(result, rinfo->clause);
00567 }
00568 return result;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577 List *
00578 extract_actual_clauses(List *restrictinfo_list,
00579 bool pseudoconstant)
00580 {
00581 List *result = NIL;
00582 ListCell *l;
00583
00584 foreach(l, restrictinfo_list)
00585 {
00586 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00587
00588 Assert(IsA(rinfo, RestrictInfo));
00589
00590 if (rinfo->pseudoconstant == pseudoconstant)
00591 result = lappend(result, rinfo->clause);
00592 }
00593 return result;
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 void
00607 extract_actual_join_clauses(List *restrictinfo_list,
00608 List **joinquals,
00609 List **otherquals)
00610 {
00611 ListCell *l;
00612
00613 *joinquals = NIL;
00614 *otherquals = NIL;
00615
00616 foreach(l, restrictinfo_list)
00617 {
00618 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00619
00620 Assert(IsA(rinfo, RestrictInfo));
00621
00622 if (rinfo->is_pushed_down)
00623 {
00624 if (!rinfo->pseudoconstant)
00625 *otherquals = lappend(*otherquals, rinfo->clause);
00626 }
00627 else
00628 {
00629
00630 Assert(!rinfo->pseudoconstant);
00631 *joinquals = lappend(*joinquals, rinfo->clause);
00632 }
00633 }
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 bool
00660 join_clause_is_movable_to(RestrictInfo *rinfo, Index baserelid)
00661 {
00662
00663 if (!bms_is_member(baserelid, rinfo->clause_relids))
00664 return false;
00665
00666
00667 if (bms_is_member(baserelid, rinfo->outer_relids))
00668 return false;
00669
00670
00671 if (bms_is_member(baserelid, rinfo->nullable_relids))
00672 return false;
00673
00674 return true;
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 bool
00703 join_clause_is_movable_into(RestrictInfo *rinfo,
00704 Relids currentrelids,
00705 Relids current_and_outer)
00706 {
00707
00708 if (!bms_is_subset(rinfo->clause_relids, current_and_outer))
00709 return false;
00710
00711
00712 if (!bms_overlap(currentrelids, rinfo->clause_relids))
00713 return false;
00714
00715
00716 if (bms_overlap(currentrelids, rinfo->outer_relids))
00717 return false;
00718
00719
00720 if (bms_overlap(currentrelids, rinfo->nullable_relids))
00721 return false;
00722
00723 return true;
00724 }