* ExecInitQual: prepare a qual for execution by ExecQual * * Prepares for the evaluation of a conjunctive boolean expression (qual list * with implicit AND semantics) that returns true if none of the * subexpressions are false. * * We must return true if the list is empty. Since that's a very common case, * we optimize it a bit further by translating to a NULL ExprState pointer * rather t
| 218 | * get selected. |
| 219 | */ |
| 220 | ExprState * |
| 221 | ExecInitQual(List *qual, PlanState *parent) |
| 222 | { |
| 223 | ExprState *state; |
| 224 | ExprEvalStep scratch = {0}; |
| 225 | List *adjust_jumps = NIL; |
| 226 | ListCell *lc; |
| 227 | |
| 228 | /* short-circuit (here and in ExecQual) for empty restriction list */ |
| 229 | if (qual == NIL) |
| 230 | return NULL; |
| 231 | |
| 232 | Assert(IsA(qual, List)); |
| 233 | |
| 234 | state = makeNode(ExprState); |
| 235 | state->expr = (Expr *) qual; |
| 236 | state->parent = parent; |
| 237 | state->ext_params = NULL; |
| 238 | |
| 239 | /* mark expression as to be used with ExecQual() */ |
| 240 | state->flags = EEO_FLAG_IS_QUAL; |
| 241 | |
| 242 | /* Insert EEOP_*_FETCHSOME steps as needed */ |
| 243 | ExecInitExprSlots(state, (Node *) qual); |
| 244 | |
| 245 | /* |
| 246 | * ExecQual() needs to return false for an expression returning NULL. That |
| 247 | * allows us to short-circuit the evaluation the first time a NULL is |
| 248 | * encountered. As qual evaluation is a hot-path this warrants using a |
| 249 | * special opcode for qual evaluation that's simpler than BOOL_AND (which |
| 250 | * has more complex NULL handling). |
| 251 | */ |
| 252 | scratch.opcode = EEOP_QUAL; |
| 253 | |
| 254 | /* |
| 255 | * We can use ExprState's resvalue/resnull as target for each qual expr. |
| 256 | */ |
| 257 | scratch.resvalue = &state->resvalue; |
| 258 | scratch.resnull = &state->resnull; |
| 259 | |
| 260 | foreach(lc, qual) |
| 261 | { |
| 262 | Expr *node = (Expr *) lfirst(lc); |
| 263 | |
| 264 | /* first evaluate expression */ |
| 265 | ExecInitExprRec(node, state, &state->resvalue, &state->resnull); |
| 266 | |
| 267 | /* then emit EEOP_QUAL to detect if it's false (or null) */ |
| 268 | scratch.d.qualexpr.jumpdone = -1; |
| 269 | ExprEvalPushStep(state, &scratch); |
| 270 | adjust_jumps = lappend_int(adjust_jumps, |
| 271 | state->steps_len - 1); |
| 272 | } |
| 273 | |
| 274 | /* adjust jump targets */ |
| 275 | foreach(lc, adjust_jumps) |
| 276 | { |
| 277 | ExprEvalStep *as = &state->steps[lfirst_int(lc)]; |
no test coverage detected