Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "postgres.h"
00023
00024 #include "executor/execdebug.h"
00025 #include "executor/nodeNestloop.h"
00026 #include "utils/memutils.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 TupleTableSlot *
00060 ExecNestLoop(NestLoopState *node)
00061 {
00062 NestLoop *nl;
00063 PlanState *innerPlan;
00064 PlanState *outerPlan;
00065 TupleTableSlot *outerTupleSlot;
00066 TupleTableSlot *innerTupleSlot;
00067 List *joinqual;
00068 List *otherqual;
00069 ExprContext *econtext;
00070 ListCell *lc;
00071
00072
00073
00074
00075 ENL1_printf("getting info from node");
00076
00077 nl = (NestLoop *) node->js.ps.plan;
00078 joinqual = node->js.joinqual;
00079 otherqual = node->js.ps.qual;
00080 outerPlan = outerPlanState(node);
00081 innerPlan = innerPlanState(node);
00082 econtext = node->js.ps.ps_ExprContext;
00083
00084
00085
00086
00087
00088
00089 if (node->js.ps.ps_TupFromTlist)
00090 {
00091 TupleTableSlot *result;
00092 ExprDoneCond isDone;
00093
00094 result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
00095 if (isDone == ExprMultipleResult)
00096 return result;
00097
00098 node->js.ps.ps_TupFromTlist = false;
00099 }
00100
00101
00102
00103
00104
00105
00106 ResetExprContext(econtext);
00107
00108
00109
00110
00111
00112 ENL1_printf("entering main loop");
00113
00114 for (;;)
00115 {
00116
00117
00118
00119
00120 if (node->nl_NeedNewOuter)
00121 {
00122 ENL1_printf("getting new outer tuple");
00123 outerTupleSlot = ExecProcNode(outerPlan);
00124
00125
00126
00127
00128 if (TupIsNull(outerTupleSlot))
00129 {
00130 ENL1_printf("no outer tuple, ending join");
00131 return NULL;
00132 }
00133
00134 ENL1_printf("saving new outer tuple information");
00135 econtext->ecxt_outertuple = outerTupleSlot;
00136 node->nl_NeedNewOuter = false;
00137 node->nl_MatchedOuter = false;
00138
00139
00140
00141
00142
00143 foreach(lc, nl->nestParams)
00144 {
00145 NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
00146 int paramno = nlp->paramno;
00147 ParamExecData *prm;
00148
00149 prm = &(econtext->ecxt_param_exec_vals[paramno]);
00150
00151 Assert(IsA(nlp->paramval, Var));
00152 Assert(nlp->paramval->varno == OUTER_VAR);
00153 Assert(nlp->paramval->varattno > 0);
00154 prm->value = slot_getattr(outerTupleSlot,
00155 nlp->paramval->varattno,
00156 &(prm->isnull));
00157
00158 innerPlan->chgParam = bms_add_member(innerPlan->chgParam,
00159 paramno);
00160 }
00161
00162
00163
00164
00165 ENL1_printf("rescanning inner plan");
00166 ExecReScan(innerPlan);
00167 }
00168
00169
00170
00171
00172 ENL1_printf("getting new inner tuple");
00173
00174 innerTupleSlot = ExecProcNode(innerPlan);
00175 econtext->ecxt_innertuple = innerTupleSlot;
00176
00177 if (TupIsNull(innerTupleSlot))
00178 {
00179 ENL1_printf("no inner tuple, need new outer tuple");
00180
00181 node->nl_NeedNewOuter = true;
00182
00183 if (!node->nl_MatchedOuter &&
00184 (node->js.jointype == JOIN_LEFT ||
00185 node->js.jointype == JOIN_ANTI))
00186 {
00187
00188
00189
00190
00191
00192
00193 econtext->ecxt_innertuple = node->nl_NullInnerTupleSlot;
00194
00195 ENL1_printf("testing qualification for outer-join tuple");
00196
00197 if (otherqual == NIL || ExecQual(otherqual, econtext, false))
00198 {
00199
00200
00201
00202
00203
00204 TupleTableSlot *result;
00205 ExprDoneCond isDone;
00206
00207 ENL1_printf("qualification succeeded, projecting tuple");
00208
00209 result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
00210
00211 if (isDone != ExprEndResult)
00212 {
00213 node->js.ps.ps_TupFromTlist =
00214 (isDone == ExprMultipleResult);
00215 return result;
00216 }
00217 }
00218 else
00219 InstrCountFiltered2(node, 1);
00220 }
00221
00222
00223
00224
00225 continue;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 ENL1_printf("testing qualification");
00237
00238 if (ExecQual(joinqual, econtext, false))
00239 {
00240 node->nl_MatchedOuter = true;
00241
00242
00243 if (node->js.jointype == JOIN_ANTI)
00244 {
00245 node->nl_NeedNewOuter = true;
00246 continue;
00247 }
00248
00249
00250
00251
00252
00253 if (node->js.jointype == JOIN_SEMI)
00254 node->nl_NeedNewOuter = true;
00255
00256 if (otherqual == NIL || ExecQual(otherqual, econtext, false))
00257 {
00258
00259
00260
00261
00262 TupleTableSlot *result;
00263 ExprDoneCond isDone;
00264
00265 ENL1_printf("qualification succeeded, projecting tuple");
00266
00267 result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
00268
00269 if (isDone != ExprEndResult)
00270 {
00271 node->js.ps.ps_TupFromTlist =
00272 (isDone == ExprMultipleResult);
00273 return result;
00274 }
00275 }
00276 else
00277 InstrCountFiltered2(node, 1);
00278 }
00279 else
00280 InstrCountFiltered1(node, 1);
00281
00282
00283
00284
00285 ResetExprContext(econtext);
00286
00287 ENL1_printf("qualification failed, looping");
00288 }
00289 }
00290
00291
00292
00293
00294
00295 NestLoopState *
00296 ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
00297 {
00298 NestLoopState *nlstate;
00299
00300
00301 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
00302
00303 NL1_printf("ExecInitNestLoop: %s\n",
00304 "initializing node");
00305
00306
00307
00308
00309 nlstate = makeNode(NestLoopState);
00310 nlstate->js.ps.plan = (Plan *) node;
00311 nlstate->js.ps.state = estate;
00312
00313
00314
00315
00316
00317
00318 ExecAssignExprContext(estate, &nlstate->js.ps);
00319
00320
00321
00322
00323 nlstate->js.ps.targetlist = (List *)
00324 ExecInitExpr((Expr *) node->join.plan.targetlist,
00325 (PlanState *) nlstate);
00326 nlstate->js.ps.qual = (List *)
00327 ExecInitExpr((Expr *) node->join.plan.qual,
00328 (PlanState *) nlstate);
00329 nlstate->js.jointype = node->join.jointype;
00330 nlstate->js.joinqual = (List *)
00331 ExecInitExpr((Expr *) node->join.joinqual,
00332 (PlanState *) nlstate);
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate, eflags);
00344 if (node->nestParams == NIL)
00345 eflags |= EXEC_FLAG_REWIND;
00346 else
00347 eflags &= ~EXEC_FLAG_REWIND;
00348 innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate, eflags);
00349
00350
00351
00352
00353 ExecInitResultTupleSlot(estate, &nlstate->js.ps);
00354
00355 switch (node->join.jointype)
00356 {
00357 case JOIN_INNER:
00358 case JOIN_SEMI:
00359 break;
00360 case JOIN_LEFT:
00361 case JOIN_ANTI:
00362 nlstate->nl_NullInnerTupleSlot =
00363 ExecInitNullTupleSlot(estate,
00364 ExecGetResultType(innerPlanState(nlstate)));
00365 break;
00366 default:
00367 elog(ERROR, "unrecognized join type: %d",
00368 (int) node->join.jointype);
00369 }
00370
00371
00372
00373
00374 ExecAssignResultTypeFromTL(&nlstate->js.ps);
00375 ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
00376
00377
00378
00379
00380 nlstate->js.ps.ps_TupFromTlist = false;
00381 nlstate->nl_NeedNewOuter = true;
00382 nlstate->nl_MatchedOuter = false;
00383
00384 NL1_printf("ExecInitNestLoop: %s\n",
00385 "node initialized");
00386
00387 return nlstate;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 void
00397 ExecEndNestLoop(NestLoopState *node)
00398 {
00399 NL1_printf("ExecEndNestLoop: %s\n",
00400 "ending node processing");
00401
00402
00403
00404
00405 ExecFreeExprContext(&node->js.ps);
00406
00407
00408
00409
00410 ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
00411
00412
00413
00414
00415 ExecEndNode(outerPlanState(node));
00416 ExecEndNode(innerPlanState(node));
00417
00418 NL1_printf("ExecEndNestLoop: %s\n",
00419 "node processing ended");
00420 }
00421
00422
00423
00424
00425
00426 void
00427 ExecReScanNestLoop(NestLoopState *node)
00428 {
00429 PlanState *outerPlan = outerPlanState(node);
00430
00431
00432
00433
00434
00435 if (outerPlan->chgParam == NULL)
00436 ExecReScan(outerPlan);
00437
00438
00439
00440
00441
00442
00443
00444 node->js.ps.ps_TupFromTlist = false;
00445 node->nl_NeedNewOuter = true;
00446 node->nl_MatchedOuter = false;
00447 }