* ExecBuildProjectionInfo * * Build a ProjectionInfo node for evaluating the given tlist in the given * econtext, and storing the result into the tuple slot. (Caller must have * ensured that tuple slot has a descriptor matching the tlist!) * * inputDesc can be NULL, but if it is not, we check to see whether simple * Vars in the tlist match the descriptor. It is important to provide * in
| 362 | * should be the planner-created targetlist, since we do the compilation here. |
| 363 | */ |
| 364 | ProjectionInfo * |
| 365 | ExecBuildProjectionInfo(List *targetList, |
| 366 | ExprContext *econtext, |
| 367 | TupleTableSlot *slot, |
| 368 | PlanState *parent, |
| 369 | TupleDesc inputDesc) |
| 370 | { |
| 371 | ProjectionInfo *projInfo = makeNode(ProjectionInfo); |
| 372 | ExprState *state; |
| 373 | ExprEvalStep scratch = {0}; |
| 374 | ListCell *lc; |
| 375 | |
| 376 | projInfo->pi_exprContext = econtext; |
| 377 | /* We embed ExprState into ProjectionInfo instead of doing extra palloc */ |
| 378 | projInfo->pi_state.tag = T_ExprState; |
| 379 | state = &projInfo->pi_state; |
| 380 | state->expr = (Expr *) targetList; |
| 381 | state->parent = parent; |
| 382 | state->ext_params = NULL; |
| 383 | |
| 384 | state->resultslot = slot; |
| 385 | |
| 386 | /* Insert EEOP_*_FETCHSOME steps as needed */ |
| 387 | ExecInitExprSlots(state, (Node *) targetList); |
| 388 | |
| 389 | /* Now compile each tlist column */ |
| 390 | foreach(lc, targetList) |
| 391 | { |
| 392 | TargetEntry *tle = lfirst_node(TargetEntry, lc); |
| 393 | Var *variable = NULL; |
| 394 | AttrNumber attnum = 0; |
| 395 | bool isSafeVar = false; |
| 396 | |
| 397 | /* |
| 398 | * If tlist expression is a safe non-system Var, use the fast-path |
| 399 | * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply |
| 400 | * CheckVarSlotCompatibility() during plan startup. If a source slot |
| 401 | * was provided, we make the equivalent tests here; if a slot was not |
| 402 | * provided, we assume that no check is needed because we're dealing |
| 403 | * with a non-relation-scan-level expression. |
| 404 | */ |
| 405 | if (tle->expr != NULL && |
| 406 | IsA(tle->expr, Var) && |
| 407 | ((Var *) tle->expr)->varattno > 0) |
| 408 | { |
| 409 | /* Non-system Var, but how safe is it? */ |
| 410 | variable = (Var *) tle->expr; |
| 411 | attnum = variable->varattno; |
| 412 | |
| 413 | if (inputDesc == NULL) |
| 414 | isSafeVar = true; /* can't check, just assume OK */ |
| 415 | else if (attnum <= inputDesc->natts) |
| 416 | { |
| 417 | Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1); |
| 418 | |
| 419 | /* |
| 420 | * If user attribute is dropped or has a type mismatch, don't |
| 421 | * use ASSIGN_*_VAR. Instead let the normal expression |
no test coverage detected