1 /*------------------------------------------------------------------------- 2 * 3 * execExpr.c 4 * Expression evaluation infrastructure. 5 * 6 * During executor startup, we compile each expression tree (which has 7 * previously been processed by the parser and planner) into an ExprState, 8 * using ExecInitExpr() et al. This converts the tree into a flat array 9 * of ExprEvalSteps, which may be thought of as instructions in a program. 10 * At runtime, we'll execute steps, starting with the first, until we reach 11 * an EEOP_DONE opcode. 12 * 13 * This file contains the "compilation" logic. It is independent of the 14 * specific execution technology we use (switch statement, computed goto, 15 * JIT compilation, etc). 16 * 17 * See src/backend/executor/README for some background, specifically the 18 * "Expression Trees and ExprState nodes", "Expression Initialization", 19 * and "Expression Evaluation" sections. 20 * 21 * 22 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group 23 * Portions Copyright (c) 1994, Regents of the University of California 24 * 25 * 26 * IDENTIFICATION 27 * src/backend/executor/execExpr.c 28 * 29 *------------------------------------------------------------------------- 30 */ 31 #include "postgres.h" 32 33 #include "access/nbtree.h" 34 #include "catalog/objectaccess.h" 35 #include "catalog/pg_type.h" 36 #include "executor/execExpr.h" 37 #include "executor/nodeSubplan.h" 38 #include "funcapi.h" 39 #include "jit/jit.h" 40 #include "miscadmin.h" 41 #include "nodes/makefuncs.h" 42 #include "nodes/nodeFuncs.h" 43 #include "optimizer/clauses.h" 44 #include "optimizer/planner.h" 45 #include "pgstat.h" 46 #include "utils/builtins.h" 47 #include "utils/datum.h" 48 #include "utils/lsyscache.h" 49 #include "utils/typcache.h" 50 51 52 typedef struct LastAttnumInfo 53 { 54 AttrNumber last_inner; 55 AttrNumber last_outer; 56 AttrNumber last_scan; 57 } LastAttnumInfo; 58 59 static void ExecReadyExpr(ExprState *state); 60 static void ExecInitExprRec(Expr *node, ExprState *state, 61 Datum *resv, bool *resnull); 62 static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, 63 Oid funcid, Oid inputcollid, 64 ExprState *state); 65 static void ExecInitExprSlots(ExprState *state, Node *node); 66 static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info); 67 static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info); 68 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, 69 ExprState *state); 70 static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, 71 ExprState *state, 72 Datum *resv, bool *resnull); 73 static bool isAssignmentIndirectionExpr(Expr *expr); 74 static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, 75 ExprState *state, 76 Datum *resv, bool *resnull); 77 static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate, 78 ExprEvalStep *scratch, 79 FunctionCallInfo fcinfo, AggStatePerTrans pertrans, 80 int transno, int setno, int setoff, bool ishash); 81 82 83 /* 84 * ExecInitExpr: prepare an expression tree for execution 85 * 86 * This function builds and returns an ExprState implementing the given 87 * Expr node tree. The return ExprState can then be handed to ExecEvalExpr 88 * for execution. Because the Expr tree itself is read-only as far as 89 * ExecInitExpr and ExecEvalExpr are concerned, several different executions 90 * of the same plan tree can occur concurrently. (But note that an ExprState 91 * does mutate at runtime, so it can't be re-used concurrently.) 92 * 93 * This must be called in a memory context that will last as long as repeated 94 * executions of the expression are needed. Typically the context will be 95 * the same as the per-query context of the associated ExprContext. 96 * 97 * Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to 98 * the lists of such nodes held by the parent PlanState (or more accurately, 99 * the AggrefExprState etc. nodes created for them are added). 100 * 101 * Note: there is no ExecEndExpr function; we assume that any resource 102 * cleanup needed will be handled by just releasing the memory context 103 * in which the state tree is built. Functions that require additional 104 * cleanup work can register a shutdown callback in the ExprContext. 105 * 106 * 'node' is the root of the expression tree to compile. 107 * 'parent' is the PlanState node that owns the expression. 108 * 109 * 'parent' may be NULL if we are preparing an expression that is not 110 * associated with a plan tree. (If so, it can't have aggs or subplans.) 111 * Such cases should usually come through ExecPrepareExpr, not directly here. 112 * 113 * Also, if 'node' is NULL, we just return NULL. This is convenient for some 114 * callers that may or may not have an expression that needs to be compiled. 115 * Note that a NULL ExprState pointer *cannot* be handed to ExecEvalExpr, 116 * although ExecQual and ExecCheck will accept one (and treat it as "true"). 117 */ 118 ExprState * 119 ExecInitExpr(Expr *node, PlanState *parent) 120 { 121 ExprState *state; 122 ExprEvalStep scratch = {0}; 123 124 /* Special case: NULL expression produces a NULL ExprState pointer */ 125 if (node == NULL) 126 return NULL; 127 128 /* Initialize ExprState with empty step list */ 129 state = makeNode(ExprState); 130 state->expr = node; 131 state->parent = parent; 132 state->ext_params = NULL; 133 134 /* Insert EEOP_*_FETCHSOME steps as needed */ 135 ExecInitExprSlots(state, (Node *) node); 136 137 /* Compile the expression proper */ 138 ExecInitExprRec(node, state, &state->resvalue, &state->resnull); 139 140 /* Finally, append a DONE step */ 141 scratch.opcode = EEOP_DONE; 142 ExprEvalPushStep(state, &scratch); 143 144 ExecReadyExpr(state); 145 146 return state; 147 } 148 149 /* 150 * ExecInitExprWithParams: prepare a standalone expression tree for execution 151 * 152 * This is the same as ExecInitExpr, except that there is no parent PlanState, 153 * and instead we may have a ParamListInfo describing PARAM_EXTERN Params. 154 */ 155 ExprState * 156 ExecInitExprWithParams(Expr *node, ParamListInfo ext_params) 157 { 158 ExprState *state; 159 ExprEvalStep scratch = {0}; 160 161 /* Special case: NULL expression produces a NULL ExprState pointer */ 162 if (node == NULL) 163 return NULL; 164 165 /* Initialize ExprState with empty step list */ 166 state = makeNode(ExprState); 167 state->expr = node; 168 state->parent = NULL; 169 state->ext_params = ext_params; 170 171 /* Insert EEOP_*_FETCHSOME steps as needed */ 172 ExecInitExprSlots(state, (Node *) node); 173 174 /* Compile the expression proper */ 175 ExecInitExprRec(node, state, &state->resvalue, &state->resnull); 176 177 /* Finally, append a DONE step */ 178 scratch.opcode = EEOP_DONE; 179 ExprEvalPushStep(state, &scratch); 180 181 ExecReadyExpr(state); 182 183 return state; 184 } 185 186 /* 187 * ExecInitQual: prepare a qual for execution by ExecQual 188 * 189 * Prepares for the evaluation of a conjunctive boolean expression (qual list 190 * with implicit AND semantics) that returns true if none of the 191 * subexpressions are false. 192 * 193 * We must return true if the list is empty. Since that's a very common case, 194 * we optimize it a bit further by translating to a NULL ExprState pointer 195 * rather than setting up an ExprState that computes constant TRUE. (Some 196 * especially hot-spot callers of ExecQual detect this and avoid calling 197 * ExecQual at all.) 198 * 199 * If any of the subexpressions yield NULL, then the result of the conjunction 200 * is false. This makes ExecQual primarily useful for evaluating WHERE 201 * clauses, since SQL specifies that tuples with null WHERE results do not 202 * get selected. 203 */ 204 ExprState * 205 ExecInitQual(List *qual, PlanState *parent) 206 { 207 ExprState *state; 208 ExprEvalStep scratch = {0}; 209 List *adjust_jumps = NIL; 210 ListCell *lc; 211 212 /* short-circuit (here and in ExecQual) for empty restriction list */ 213 if (qual == NIL) 214 return NULL; 215 216 Assert(IsA(qual, List)); 217 218 state = makeNode(ExprState); 219 state->expr = (Expr *) qual; 220 state->parent = parent; 221 state->ext_params = NULL; 222 223 /* mark expression as to be used with ExecQual() */ 224 state->flags = EEO_FLAG_IS_QUAL; 225 226 /* Insert EEOP_*_FETCHSOME steps as needed */ 227 ExecInitExprSlots(state, (Node *) qual); 228 229 /* 230 * ExecQual() needs to return false for an expression returning NULL. That 231 * allows us to short-circuit the evaluation the first time a NULL is 232 * encountered. As qual evaluation is a hot-path this warrants using a 233 * special opcode for qual evaluation that's simpler than BOOL_AND (which 234 * has more complex NULL handling). 235 */ 236 scratch.opcode = EEOP_QUAL; 237 238 /* 239 * We can use ExprState's resvalue/resnull as target for each qual expr. 240 */ 241 scratch.resvalue = &state->resvalue; 242 scratch.resnull = &state->resnull; 243 244 foreach(lc, qual) 245 { 246 Expr *node = (Expr *) lfirst(lc); 247 248 /* first evaluate expression */ 249 ExecInitExprRec(node, state, &state->resvalue, &state->resnull); 250 251 /* then emit EEOP_QUAL to detect if it's false (or null) */ 252 scratch.d.qualexpr.jumpdone = -1; 253 ExprEvalPushStep(state, &scratch); 254 adjust_jumps = lappend_int(adjust_jumps, 255 state->steps_len - 1); 256 } 257 258 /* adjust jump targets */ 259 foreach(lc, adjust_jumps) 260 { 261 ExprEvalStep *as = &state->steps[lfirst_int(lc)]; 262 263 Assert(as->opcode == EEOP_QUAL); 264 Assert(as->d.qualexpr.jumpdone == -1); 265 as->d.qualexpr.jumpdone = state->steps_len; 266 } 267 268 /* 269 * At the end, we don't need to do anything more. The last qual expr must 270 * have yielded TRUE, and since its result is stored in the desired output 271 * location, we're done. 272 */ 273 scratch.opcode = EEOP_DONE; 274 ExprEvalPushStep(state, &scratch); 275 276 ExecReadyExpr(state); 277 278 return state; 279 } 280 281 /* 282 * ExecInitCheck: prepare a check constraint for execution by ExecCheck 283 * 284 * This is much like ExecInitQual/ExecQual, except that a null result from 285 * the conjunction is treated as TRUE. This behavior is appropriate for 286 * evaluating CHECK constraints, since SQL specifies that NULL constraint 287 * conditions are not failures. 288 * 289 * Note that like ExecInitQual, this expects input in implicit-AND format. 290 * Users of ExecCheck that have expressions in normal explicit-AND format 291 * can just apply ExecInitExpr to produce suitable input for ExecCheck. 292 */ 293 ExprState * 294 ExecInitCheck(List *qual, PlanState *parent) 295 { 296 /* short-circuit (here and in ExecCheck) for empty restriction list */ 297 if (qual == NIL) 298 return NULL; 299 300 Assert(IsA(qual, List)); 301 302 /* 303 * Just convert the implicit-AND list to an explicit AND (if there's more 304 * than one entry), and compile normally. Unlike ExecQual, we can't 305 * short-circuit on NULL results, so the regular AND behavior is needed. 306 */ 307 return ExecInitExpr(make_ands_explicit(qual), parent); 308 } 309 310 /* 311 * Call ExecInitExpr() on a list of expressions, return a list of ExprStates. 312 */ 313 List * 314 ExecInitExprList(List *nodes, PlanState *parent) 315 { 316 List *result = NIL; 317 ListCell *lc; 318 319 foreach(lc, nodes) 320 { 321 Expr *e = lfirst(lc); 322 323 result = lappend(result, ExecInitExpr(e, parent)); 324 } 325 326 return result; 327 } 328 329 /* 330 * ExecBuildProjectionInfo 331 * 332 * Build a ProjectionInfo node for evaluating the given tlist in the given 333 * econtext, and storing the result into the tuple slot. (Caller must have 334 * ensured that tuple slot has a descriptor matching the tlist!) 335 * 336 * inputDesc can be NULL, but if it is not, we check to see whether simple 337 * Vars in the tlist match the descriptor. It is important to provide 338 * inputDesc for relation-scan plan nodes, as a cross check that the relation 339 * hasn't been changed since the plan was made. At higher levels of a plan, 340 * there is no need to recheck. 341 * 342 * This is implemented by internally building an ExprState that performs the 343 * whole projection in one go. 344 * 345 * Caution: before PG v10, the targetList was a list of ExprStates; now it 346 * should be the planner-created targetlist, since we do the compilation here. 347 */ 348 ProjectionInfo * 349 ExecBuildProjectionInfo(List *targetList, 350 ExprContext *econtext, 351 TupleTableSlot *slot, 352 PlanState *parent, 353 TupleDesc inputDesc) 354 { 355 return ExecBuildProjectionInfoExt(targetList, 356 econtext, 357 slot, 358 true, 359 parent, 360 inputDesc); 361 } 362 363 /* 364 * ExecBuildProjectionInfoExt 365 * 366 * As above, with one additional option. 367 * 368 * If assignJunkEntries is true (the usual case), resjunk entries in the tlist 369 * are not handled specially: they are evaluated and assigned to the proper 370 * column of the result slot. If assignJunkEntries is false, resjunk entries 371 * are evaluated, but their result is discarded without assignment. 372 */ 373 ProjectionInfo * 374 ExecBuildProjectionInfoExt(List *targetList, 375 ExprContext *econtext, 376 TupleTableSlot *slot, 377 bool assignJunkEntries, 378 PlanState *parent, 379 TupleDesc inputDesc) 380 { 381 ProjectionInfo *projInfo = makeNode(ProjectionInfo); 382 ExprState *state; 383 ExprEvalStep scratch = {0}; 384 ListCell *lc; 385 386 projInfo->pi_exprContext = econtext; 387 /* We embed ExprState into ProjectionInfo instead of doing extra palloc */ 388 projInfo->pi_state.tag.type = T_ExprState; 389 state = &projInfo->pi_state; 390 state->expr = (Expr *) targetList; 391 state->parent = parent; 392 state->ext_params = NULL; 393 394 state->resultslot = slot; 395 396 /* Insert EEOP_*_FETCHSOME steps as needed */ 397 ExecInitExprSlots(state, (Node *) targetList); 398 399 /* Now compile each tlist column */ 400 foreach(lc, targetList) 401 { 402 TargetEntry *tle = lfirst_node(TargetEntry, lc); 403 Var *variable = NULL; 404 AttrNumber attnum = 0; 405 bool isSafeVar = false; 406 407 /* 408 * If tlist expression is a safe non-system Var, use the fast-path 409 * ASSIGN_*_VAR opcodes. "Safe" means that we don't need to apply 410 * CheckVarSlotCompatibility() during plan startup. If a source slot 411 * was provided, we make the equivalent tests here; if a slot was not 412 * provided, we assume that no check is needed because we're dealing 413 * with a non-relation-scan-level expression. 414 */ 415 if (tle->expr != NULL && 416 IsA(tle->expr, Var) && 417 ((Var *) tle->expr)->varattno > 0 && 418 (assignJunkEntries || !tle->resjunk)) 419 { 420 /* Non-system Var, but how safe is it? */ 421 variable = (Var *) tle->expr; 422 attnum = variable->varattno; 423 424 if (inputDesc == NULL) 425 isSafeVar = true; /* can't check, just assume OK */ 426 else if (attnum <= inputDesc->natts) 427 { 428 Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1); 429 430 /* 431 * If user attribute is dropped or has a type mismatch, don't 432 * use ASSIGN_*_VAR. Instead let the normal expression 433 * machinery handle it (which'll possibly error out). 434 */ 435 if (!attr->attisdropped && variable->vartype == attr->atttypid) 436 { 437 isSafeVar = true; 438 } 439 } 440 } 441 442 if (isSafeVar) 443 { 444 /* Fast-path: just generate an EEOP_ASSIGN_*_VAR step */ 445 switch (variable->varno) 446 { 447 case INNER_VAR: 448 /* get the tuple from the inner node */ 449 scratch.opcode = EEOP_ASSIGN_INNER_VAR; 450 break; 451 452 case OUTER_VAR: 453 /* get the tuple from the outer node */ 454 scratch.opcode = EEOP_ASSIGN_OUTER_VAR; 455 break; 456 457 /* INDEX_VAR is handled by default case */ 458 459 default: 460 /* get the tuple from the relation being scanned */ 461 scratch.opcode = EEOP_ASSIGN_SCAN_VAR; 462 break; 463 } 464 465 scratch.d.assign_var.attnum = attnum - 1; 466 scratch.d.assign_var.resultnum = tle->resno - 1; 467 ExprEvalPushStep(state, &scratch); 468 } 469 else 470 { 471 /* 472 * Otherwise, compile the column expression normally. 473 * 474 * We can't tell the expression to evaluate directly into the 475 * result slot, as the result slot (and the exprstate for that 476 * matter) can change between executions. We instead evaluate 477 * into the ExprState's resvalue/resnull and then move. 478 */ 479 ExecInitExprRec(tle->expr, state, 480 &state->resvalue, &state->resnull); 481 482 /* This makes it easy to discard resjunk results when told to. */ 483 if (!assignJunkEntries && tle->resjunk) 484 continue; 485 486 /* 487 * Column might be referenced multiple times in upper nodes, so 488 * force value to R/O - but only if it could be an expanded datum. 489 */ 490 if (get_typlen(exprType((Node *) tle->expr)) == -1) 491 scratch.opcode = EEOP_ASSIGN_TMP_MAKE_RO; 492 else 493 scratch.opcode = EEOP_ASSIGN_TMP; 494 scratch.d.assign_tmp.resultnum = tle->resno - 1; 495 ExprEvalPushStep(state, &scratch); 496 } 497 } 498 499 scratch.opcode = EEOP_DONE; 500 ExprEvalPushStep(state, &scratch); 501 502 ExecReadyExpr(state); 503 504 return projInfo; 505 } 506 507 /* 508 * ExecPrepareExpr --- initialize for expression execution outside a normal 509 * Plan tree context. 510 * 511 * This differs from ExecInitExpr in that we don't assume the caller is 512 * already running in the EState's per-query context. Also, we run the 513 * passed expression tree through expression_planner() to prepare it for 514 * execution. (In ordinary Plan trees the regular planning process will have 515 * made the appropriate transformations on expressions, but for standalone 516 * expressions this won't have happened.) 517 */ 518 ExprState * 519 ExecPrepareExpr(Expr *node, EState *estate) 520 { 521 ExprState *result; 522 MemoryContext oldcontext; 523 524 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); 525 526 node = expression_planner(node); 527 528 result = ExecInitExpr(node, NULL); 529 530 MemoryContextSwitchTo(oldcontext); 531 532 return result; 533 } 534 535 /* 536 * ExecPrepareQual --- initialize for qual execution outside a normal 537 * Plan tree context. 538 * 539 * This differs from ExecInitQual in that we don't assume the caller is 540 * already running in the EState's per-query context. Also, we run the 541 * passed expression tree through expression_planner() to prepare it for 542 * execution. (In ordinary Plan trees the regular planning process will have 543 * made the appropriate transformations on expressions, but for standalone 544 * expressions this won't have happened.) 545 */ 546 ExprState * 547 ExecPrepareQual(List *qual, EState *estate) 548 { 549 ExprState *result; 550 MemoryContext oldcontext; 551 552 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); 553 554 qual = (List *) expression_planner((Expr *) qual); 555 556 result = ExecInitQual(qual, NULL); 557 558 MemoryContextSwitchTo(oldcontext); 559 560 return result; 561 } 562 563 /* 564 * ExecPrepareCheck -- initialize check constraint for execution outside a 565 * normal Plan tree context. 566 * 567 * See ExecPrepareExpr() and ExecInitCheck() for details. 568 */ 569 ExprState * 570 ExecPrepareCheck(List *qual, EState *estate) 571 { 572 ExprState *result; 573 MemoryContext oldcontext; 574 575 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); 576 577 qual = (List *) expression_planner((Expr *) qual); 578 579 result = ExecInitCheck(qual, NULL); 580 581 MemoryContextSwitchTo(oldcontext); 582 583 return result; 584 } 585 586 /* 587 * Call ExecPrepareExpr() on each member of a list of Exprs, and return 588 * a list of ExprStates. 589 * 590 * See ExecPrepareExpr() for details. 591 */ 592 List * 593 ExecPrepareExprList(List *nodes, EState *estate) 594 { 595 List *result = NIL; 596 MemoryContext oldcontext; 597 ListCell *lc; 598 599 /* Ensure that the list cell nodes are in the right context too */ 600 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); 601 602 foreach(lc, nodes) 603 { 604 Expr *e = (Expr *) lfirst(lc); 605 606 result = lappend(result, ExecPrepareExpr(e, estate)); 607 } 608 609 MemoryContextSwitchTo(oldcontext); 610 611 return result; 612 } 613 614 /* 615 * ExecCheck - evaluate a check constraint 616 * 617 * For check constraints, a null result is taken as TRUE, ie the constraint 618 * passes. 619 * 620 * The check constraint may have been prepared with ExecInitCheck 621 * (possibly via ExecPrepareCheck) if the caller had it in implicit-AND 622 * format, but a regular boolean expression prepared with ExecInitExpr or 623 * ExecPrepareExpr works too. 624 */ 625 bool 626 ExecCheck(ExprState *state, ExprContext *econtext) 627 { 628 Datum ret; 629 bool isnull; 630 631 /* short-circuit (here and in ExecInitCheck) for empty restriction list */ 632 if (state == NULL) 633 return true; 634 635 /* verify that expression was not compiled using ExecInitQual */ 636 Assert(!(state->flags & EEO_FLAG_IS_QUAL)); 637 638 ret = ExecEvalExprSwitchContext(state, econtext, &isnull); 639 640 if (isnull) 641 return true; 642 643 return DatumGetBool(ret); 644 } 645 646 /* 647 * Prepare a compiled expression for execution. This has to be called for 648 * every ExprState before it can be executed. 649 * 650 * NB: While this currently only calls ExecReadyInterpretedExpr(), 651 * this will likely get extended to further expression evaluation methods. 652 * Therefore this should be used instead of directly calling 653 * ExecReadyInterpretedExpr(). 654 */ 655 static void 656 ExecReadyExpr(ExprState *state) 657 { 658 if (jit_compile_expr(state)) 659 return; 660 661 ExecReadyInterpretedExpr(state); 662 } 663 664 /* 665 * Append the steps necessary for the evaluation of node to ExprState->steps, 666 * possibly recursing into sub-expressions of node. 667 * 668 * node - expression to evaluate 669 * state - ExprState to whose ->steps to append the necessary operations 670 * resv / resnull - where to store the result of the node into 671 */ 672 static void 673 ExecInitExprRec(Expr *node, ExprState *state, 674 Datum *resv, bool *resnull) 675 { 676 ExprEvalStep scratch = {0}; 677 678 /* Guard against stack overflow due to overly complex expressions */ 679 check_stack_depth(); 680 681 /* Step's output location is always what the caller gave us */ 682 Assert(resv != NULL && resnull != NULL); 683 scratch.resvalue = resv; 684 scratch.resnull = resnull; 685 686 /* cases should be ordered as they are in enum NodeTag */ 687 switch (nodeTag(node)) 688 { 689 case T_Var: 690 { 691 Var *variable = (Var *) node; 692 693 if (variable->varattno == InvalidAttrNumber) 694 { 695 /* whole-row Var */ 696 ExecInitWholeRowVar(&scratch, variable, state); 697 } 698 else if (variable->varattno <= 0) 699 { 700 /* system column */ 701 scratch.d.var.attnum = variable->varattno; 702 scratch.d.var.vartype = variable->vartype; 703 switch (variable->varno) 704 { 705 case INNER_VAR: 706 scratch.opcode = EEOP_INNER_SYSVAR; 707 break; 708 case OUTER_VAR: 709 scratch.opcode = EEOP_OUTER_SYSVAR; 710 break; 711 712 /* INDEX_VAR is handled by default case */ 713 714 default: 715 scratch.opcode = EEOP_SCAN_SYSVAR; 716 break; 717 } 718 } 719 else 720 { 721 /* regular user column */ 722 scratch.d.var.attnum = variable->varattno - 1; 723 scratch.d.var.vartype = variable->vartype; 724 switch (variable->varno) 725 { 726 case INNER_VAR: 727 scratch.opcode = EEOP_INNER_VAR; 728 break; 729 case OUTER_VAR: 730 scratch.opcode = EEOP_OUTER_VAR; 731 break; 732 733 /* INDEX_VAR is handled by default case */ 734 735 default: 736 scratch.opcode = EEOP_SCAN_VAR; 737 break; 738 } 739 } 740 741 ExprEvalPushStep(state, &scratch); 742 break; 743 } 744 745 case T_Const: 746 { 747 Const *con = (Const *) node; 748 749 scratch.opcode = EEOP_CONST; 750 scratch.d.constval.value = con->constvalue; 751 scratch.d.constval.isnull = con->constisnull; 752 753 ExprEvalPushStep(state, &scratch); 754 break; 755 } 756 757 case T_Param: 758 { 759 Param *param = (Param *) node; 760 ParamListInfo params; 761 762 switch (param->paramkind) 763 { 764 case PARAM_EXEC: 765 scratch.opcode = EEOP_PARAM_EXEC; 766 scratch.d.param.paramid = param->paramid; 767 scratch.d.param.paramtype = param->paramtype; 768 ExprEvalPushStep(state, &scratch); 769 break; 770 case PARAM_EXTERN: 771 772 /* 773 * If we have a relevant ParamCompileHook, use it; 774 * otherwise compile a standard EEOP_PARAM_EXTERN 775 * step. ext_params, if supplied, takes precedence 776 * over info from the parent node's EState (if any). 777 */ 778 if (state->ext_params) 779 params = state->ext_params; 780 else if (state->parent && 781 state->parent->state) 782 params = state->parent->state->es_param_list_info; 783 else 784 params = NULL; 785 if (params && params->paramCompile) 786 { 787 params->paramCompile(params, param, state, 788 resv, resnull); 789 } 790 else 791 { 792 scratch.opcode = EEOP_PARAM_EXTERN; 793 scratch.d.param.paramid = param->paramid; 794 scratch.d.param.paramtype = param->paramtype; 795 ExprEvalPushStep(state, &scratch); 796 } 797 break; 798 default: 799 elog(ERROR, "unrecognized paramkind: %d", 800 (int) param->paramkind); 801 break; 802 } 803 break; 804 } 805 806 case T_Aggref: 807 { 808 Aggref *aggref = (Aggref *) node; 809 AggrefExprState *astate = makeNode(AggrefExprState); 810 811 scratch.opcode = EEOP_AGGREF; 812 scratch.d.aggref.astate = astate; 813 astate->aggref = aggref; 814 815 if (state->parent && IsA(state->parent, AggState)) 816 { 817 AggState *aggstate = (AggState *) state->parent; 818 819 aggstate->aggs = lcons(astate, aggstate->aggs); 820 aggstate->numaggs++; 821 } 822 else 823 { 824 /* planner messed up */ 825 elog(ERROR, "Aggref found in non-Agg plan node"); 826 } 827 828 ExprEvalPushStep(state, &scratch); 829 break; 830 } 831 832 case T_GroupingFunc: 833 { 834 GroupingFunc *grp_node = (GroupingFunc *) node; 835 Agg *agg; 836 837 if (!state->parent || !IsA(state->parent, AggState) || 838 !IsA(state->parent->plan, Agg)) 839 elog(ERROR, "GroupingFunc found in non-Agg plan node"); 840 841 scratch.opcode = EEOP_GROUPING_FUNC; 842 scratch.d.grouping_func.parent = (AggState *) state->parent; 843 844 agg = (Agg *) (state->parent->plan); 845 846 if (agg->groupingSets) 847 scratch.d.grouping_func.clauses = grp_node->cols; 848 else 849 scratch.d.grouping_func.clauses = NIL; 850 851 ExprEvalPushStep(state, &scratch); 852 break; 853 } 854 855 case T_WindowFunc: 856 { 857 WindowFunc *wfunc = (WindowFunc *) node; 858 WindowFuncExprState *wfstate = makeNode(WindowFuncExprState); 859 860 wfstate->wfunc = wfunc; 861 862 if (state->parent && IsA(state->parent, WindowAggState)) 863 { 864 WindowAggState *winstate = (WindowAggState *) state->parent; 865 int nfuncs; 866 867 winstate->funcs = lcons(wfstate, winstate->funcs); 868 nfuncs = ++winstate->numfuncs; 869 if (wfunc->winagg) 870 winstate->numaggs++; 871 872 /* for now initialize agg using old style expressions */ 873 wfstate->args = ExecInitExprList(wfunc->args, 874 state->parent); 875 wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter, 876 state->parent); 877 878 /* 879 * Complain if the windowfunc's arguments contain any 880 * windowfuncs; nested window functions are semantically 881 * nonsensical. (This should have been caught earlier, 882 * but we defend against it here anyway.) 883 */ 884 if (nfuncs != winstate->numfuncs) 885 ereport(ERROR, 886 (errcode(ERRCODE_WINDOWING_ERROR), 887 errmsg("window function calls cannot be nested"))); 888 } 889 else 890 { 891 /* planner messed up */ 892 elog(ERROR, "WindowFunc found in non-WindowAgg plan node"); 893 } 894 895 scratch.opcode = EEOP_WINDOW_FUNC; 896 scratch.d.window_func.wfstate = wfstate; 897 ExprEvalPushStep(state, &scratch); 898 break; 899 } 900 901 case T_ArrayRef: 902 { 903 ArrayRef *aref = (ArrayRef *) node; 904 905 ExecInitArrayRef(&scratch, aref, state, resv, resnull); 906 break; 907 } 908 909 case T_FuncExpr: 910 { 911 FuncExpr *func = (FuncExpr *) node; 912 913 ExecInitFunc(&scratch, node, 914 func->args, func->funcid, func->inputcollid, 915 state); 916 ExprEvalPushStep(state, &scratch); 917 break; 918 } 919 920 case T_OpExpr: 921 { 922 OpExpr *op = (OpExpr *) node; 923 924 ExecInitFunc(&scratch, node, 925 op->args, op->opfuncid, op->inputcollid, 926 state); 927 ExprEvalPushStep(state, &scratch); 928 break; 929 } 930 931 case T_DistinctExpr: 932 { 933 DistinctExpr *op = (DistinctExpr *) node; 934 935 ExecInitFunc(&scratch, node, 936 op->args, op->opfuncid, op->inputcollid, 937 state); 938 939 /* 940 * Change opcode of call instruction to EEOP_DISTINCT. 941 * 942 * XXX: historically we've not called the function usage 943 * pgstat infrastructure - that seems inconsistent given that 944 * we do so for normal function *and* operator evaluation. If 945 * we decided to do that here, we'd probably want separate 946 * opcodes for FUSAGE or not. 947 */ 948 scratch.opcode = EEOP_DISTINCT; 949 ExprEvalPushStep(state, &scratch); 950 break; 951 } 952 953 case T_NullIfExpr: 954 { 955 NullIfExpr *op = (NullIfExpr *) node; 956 957 ExecInitFunc(&scratch, node, 958 op->args, op->opfuncid, op->inputcollid, 959 state); 960 961 /* 962 * Change opcode of call instruction to EEOP_NULLIF. 963 * 964 * XXX: historically we've not called the function usage 965 * pgstat infrastructure - that seems inconsistent given that 966 * we do so for normal function *and* operator evaluation. If 967 * we decided to do that here, we'd probably want separate 968 * opcodes for FUSAGE or not. 969 */ 970 scratch.opcode = EEOP_NULLIF; 971 ExprEvalPushStep(state, &scratch); 972 break; 973 } 974 975 case T_ScalarArrayOpExpr: 976 { 977 ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node; 978 Expr *scalararg; 979 Expr *arrayarg; 980 FmgrInfo *finfo; 981 FunctionCallInfo fcinfo; 982 AclResult aclresult; 983 984 Assert(list_length(opexpr->args) == 2); 985 scalararg = (Expr *) linitial(opexpr->args); 986 arrayarg = (Expr *) lsecond(opexpr->args); 987 988 /* Check permission to call function */ 989 aclresult = pg_proc_aclcheck(opexpr->opfuncid, 990 GetUserId(), 991 ACL_EXECUTE); 992 if (aclresult != ACLCHECK_OK) 993 aclcheck_error(aclresult, OBJECT_FUNCTION, 994 get_func_name(opexpr->opfuncid)); 995 InvokeFunctionExecuteHook(opexpr->opfuncid); 996 997 /* Set up the primary fmgr lookup information */ 998 finfo = palloc0(sizeof(FmgrInfo)); 999 fcinfo = palloc0(sizeof(FunctionCallInfoData)); 1000 fmgr_info(opexpr->opfuncid, finfo); 1001 fmgr_info_set_expr((Node *) node, finfo); 1002 InitFunctionCallInfoData(*fcinfo, finfo, 2, 1003 opexpr->inputcollid, NULL, NULL); 1004 1005 /* Evaluate scalar directly into left function argument */ 1006 ExecInitExprRec(scalararg, state, 1007 &fcinfo->arg[0], &fcinfo->argnull[0]); 1008 1009 /* 1010 * Evaluate array argument into our return value. There's no 1011 * danger in that, because the return value is guaranteed to 1012 * be overwritten by EEOP_SCALARARRAYOP, and will not be 1013 * passed to any other expression. 1014 */ 1015 ExecInitExprRec(arrayarg, state, resv, resnull); 1016 1017 /* And perform the operation */ 1018 scratch.opcode = EEOP_SCALARARRAYOP; 1019 scratch.d.scalararrayop.element_type = InvalidOid; 1020 scratch.d.scalararrayop.useOr = opexpr->useOr; 1021 scratch.d.scalararrayop.finfo = finfo; 1022 scratch.d.scalararrayop.fcinfo_data = fcinfo; 1023 scratch.d.scalararrayop.fn_addr = finfo->fn_addr; 1024 ExprEvalPushStep(state, &scratch); 1025 break; 1026 } 1027 1028 case T_BoolExpr: 1029 { 1030 BoolExpr *boolexpr = (BoolExpr *) node; 1031 int nargs = list_length(boolexpr->args); 1032 List *adjust_jumps = NIL; 1033 int off; 1034 ListCell *lc; 1035 1036 /* allocate scratch memory used by all steps of AND/OR */ 1037 if (boolexpr->boolop != NOT_EXPR) 1038 scratch.d.boolexpr.anynull = (bool *) palloc(sizeof(bool)); 1039 1040 /* 1041 * For each argument evaluate the argument itself, then 1042 * perform the bool operation's appropriate handling. 1043 * 1044 * We can evaluate each argument into our result area, since 1045 * the short-circuiting logic means we only need to remember 1046 * previous NULL values. 1047 * 1048 * AND/OR is split into separate STEP_FIRST (one) / STEP (zero 1049 * or more) / STEP_LAST (one) steps, as each of those has to 1050 * perform different work. The FIRST/LAST split is valid 1051 * because AND/OR have at least two arguments. 1052 */ 1053 off = 0; 1054 foreach(lc, boolexpr->args) 1055 { 1056 Expr *arg = (Expr *) lfirst(lc); 1057 1058 /* Evaluate argument into our output variable */ 1059 ExecInitExprRec(arg, state, resv, resnull); 1060 1061 /* Perform the appropriate step type */ 1062 switch (boolexpr->boolop) 1063 { 1064 case AND_EXPR: 1065 Assert(nargs >= 2); 1066 1067 if (off == 0) 1068 scratch.opcode = EEOP_BOOL_AND_STEP_FIRST; 1069 else if (off + 1 == nargs) 1070 scratch.opcode = EEOP_BOOL_AND_STEP_LAST; 1071 else 1072 scratch.opcode = EEOP_BOOL_AND_STEP; 1073 break; 1074 case OR_EXPR: 1075 Assert(nargs >= 2); 1076 1077 if (off == 0) 1078 scratch.opcode = EEOP_BOOL_OR_STEP_FIRST; 1079 else if (off + 1 == nargs) 1080 scratch.opcode = EEOP_BOOL_OR_STEP_LAST; 1081 else 1082 scratch.opcode = EEOP_BOOL_OR_STEP; 1083 break; 1084 case NOT_EXPR: 1085 Assert(nargs == 1); 1086 1087 scratch.opcode = EEOP_BOOL_NOT_STEP; 1088 break; 1089 default: 1090 elog(ERROR, "unrecognized boolop: %d", 1091 (int) boolexpr->boolop); 1092 break; 1093 } 1094 1095 scratch.d.boolexpr.jumpdone = -1; 1096 ExprEvalPushStep(state, &scratch); 1097 adjust_jumps = lappend_int(adjust_jumps, 1098 state->steps_len - 1); 1099 off++; 1100 } 1101 1102 /* adjust jump targets */ 1103 foreach(lc, adjust_jumps) 1104 { 1105 ExprEvalStep *as = &state->steps[lfirst_int(lc)]; 1106 1107 Assert(as->d.boolexpr.jumpdone == -1); 1108 as->d.boolexpr.jumpdone = state->steps_len; 1109 } 1110 1111 break; 1112 } 1113 1114 case T_SubPlan: 1115 { 1116 SubPlan *subplan = (SubPlan *) node; 1117 SubPlanState *sstate; 1118 1119 if (!state->parent) 1120 elog(ERROR, "SubPlan found with no parent plan"); 1121 1122 sstate = ExecInitSubPlan(subplan, state->parent); 1123 1124 /* add SubPlanState nodes to state->parent->subPlan */ 1125 state->parent->subPlan = lappend(state->parent->subPlan, 1126 sstate); 1127 1128 scratch.opcode = EEOP_SUBPLAN; 1129 scratch.d.subplan.sstate = sstate; 1130 1131 ExprEvalPushStep(state, &scratch); 1132 break; 1133 } 1134 1135 case T_AlternativeSubPlan: 1136 { 1137 AlternativeSubPlan *asplan = (AlternativeSubPlan *) node; 1138 AlternativeSubPlanState *asstate; 1139 1140 if (!state->parent) 1141 elog(ERROR, "AlternativeSubPlan found with no parent plan"); 1142 1143 asstate = ExecInitAlternativeSubPlan(asplan, state->parent); 1144 1145 scratch.opcode = EEOP_ALTERNATIVE_SUBPLAN; 1146 scratch.d.alternative_subplan.asstate = asstate; 1147 1148 ExprEvalPushStep(state, &scratch); 1149 break; 1150 } 1151 1152 case T_FieldSelect: 1153 { 1154 FieldSelect *fselect = (FieldSelect *) node; 1155 1156 /* evaluate row/record argument into result area */ 1157 ExecInitExprRec(fselect->arg, state, resv, resnull); 1158 1159 /* and extract field */ 1160 scratch.opcode = EEOP_FIELDSELECT; 1161 scratch.d.fieldselect.fieldnum = fselect->fieldnum; 1162 scratch.d.fieldselect.resulttype = fselect->resulttype; 1163 scratch.d.fieldselect.rowcache.cacheptr = NULL; 1164 1165 ExprEvalPushStep(state, &scratch); 1166 break; 1167 } 1168 1169 case T_FieldStore: 1170 { 1171 FieldStore *fstore = (FieldStore *) node; 1172 TupleDesc tupDesc; 1173 ExprEvalRowtypeCache *rowcachep; 1174 Datum *values; 1175 bool *nulls; 1176 int ncolumns; 1177 ListCell *l1, 1178 *l2; 1179 1180 /* find out the number of columns in the composite type */ 1181 tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1); 1182 ncolumns = tupDesc->natts; 1183 DecrTupleDescRefCount(tupDesc); 1184 1185 /* create workspace for column values */ 1186 values = (Datum *) palloc(sizeof(Datum) * ncolumns); 1187 nulls = (bool *) palloc(sizeof(bool) * ncolumns); 1188 1189 /* create shared composite-type-lookup cache struct */ 1190 rowcachep = palloc(sizeof(ExprEvalRowtypeCache)); 1191 rowcachep->cacheptr = NULL; 1192 1193 /* emit code to evaluate the composite input value */ 1194 ExecInitExprRec(fstore->arg, state, resv, resnull); 1195 1196 /* next, deform the input tuple into our workspace */ 1197 scratch.opcode = EEOP_FIELDSTORE_DEFORM; 1198 scratch.d.fieldstore.fstore = fstore; 1199 scratch.d.fieldstore.rowcache = rowcachep; 1200 scratch.d.fieldstore.values = values; 1201 scratch.d.fieldstore.nulls = nulls; 1202 scratch.d.fieldstore.ncolumns = ncolumns; 1203 ExprEvalPushStep(state, &scratch); 1204 1205 /* evaluate new field values, store in workspace columns */ 1206 forboth(l1, fstore->newvals, l2, fstore->fieldnums) 1207 { 1208 Expr *e = (Expr *) lfirst(l1); 1209 AttrNumber fieldnum = lfirst_int(l2); 1210 Datum *save_innermost_caseval; 1211 bool *save_innermost_casenull; 1212 1213 if (fieldnum <= 0 || fieldnum > ncolumns) 1214 elog(ERROR, "field number %d is out of range in FieldStore", 1215 fieldnum); 1216 1217 /* 1218 * Use the CaseTestExpr mechanism to pass down the old 1219 * value of the field being replaced; this is needed in 1220 * case the newval is itself a FieldStore or ArrayRef that 1221 * has to obtain and modify the old value. It's safe to 1222 * reuse the CASE mechanism because there cannot be a CASE 1223 * between here and where the value would be needed, and a 1224 * field assignment can't be within a CASE either. (So 1225 * saving and restoring innermost_caseval is just 1226 * paranoia, but let's do it anyway.) 1227 * 1228 * Another non-obvious point is that it's safe to use the 1229 * field's values[]/nulls[] entries as both the caseval 1230 * source and the result address for this subexpression. 1231 * That's okay only because (1) both FieldStore and 1232 * ArrayRef evaluate their arg or refexpr inputs first, 1233 * and (2) any such CaseTestExpr is directly the arg or 1234 * refexpr input. So any read of the caseval will occur 1235 * before there's a chance to overwrite it. Also, if 1236 * multiple entries in the newvals/fieldnums lists target 1237 * the same field, they'll effectively be applied 1238 * left-to-right which is what we want. 1239 */ 1240 save_innermost_caseval = state->innermost_caseval; 1241 save_innermost_casenull = state->innermost_casenull; 1242 state->innermost_caseval = &values[fieldnum - 1]; 1243 state->innermost_casenull = &nulls[fieldnum - 1]; 1244 1245 ExecInitExprRec(e, state, 1246 &values[fieldnum - 1], 1247 &nulls[fieldnum - 1]); 1248 1249 state->innermost_caseval = save_innermost_caseval; 1250 state->innermost_casenull = save_innermost_casenull; 1251 } 1252 1253 /* finally, form result tuple */ 1254 scratch.opcode = EEOP_FIELDSTORE_FORM; 1255 scratch.d.fieldstore.fstore = fstore; 1256 scratch.d.fieldstore.rowcache = rowcachep; 1257 scratch.d.fieldstore.values = values; 1258 scratch.d.fieldstore.nulls = nulls; 1259 scratch.d.fieldstore.ncolumns = ncolumns; 1260 ExprEvalPushStep(state, &scratch); 1261 break; 1262 } 1263 1264 case T_RelabelType: 1265 { 1266 /* relabel doesn't need to do anything at runtime */ 1267 RelabelType *relabel = (RelabelType *) node; 1268 1269 ExecInitExprRec(relabel->arg, state, resv, resnull); 1270 break; 1271 } 1272 1273 case T_CoerceViaIO: 1274 { 1275 CoerceViaIO *iocoerce = (CoerceViaIO *) node; 1276 Oid iofunc; 1277 bool typisvarlena; 1278 Oid typioparam; 1279 FunctionCallInfo fcinfo_in; 1280 1281 /* evaluate argument into step's result area */ 1282 ExecInitExprRec(iocoerce->arg, state, resv, resnull); 1283 1284 /* 1285 * Prepare both output and input function calls, to be 1286 * evaluated inside a single evaluation step for speed - this 1287 * can be a very common operation. 1288 * 1289 * We don't check permissions here as a type's input/output 1290 * function are assumed to be executable by everyone. 1291 */ 1292 scratch.opcode = EEOP_IOCOERCE; 1293 1294 /* lookup the source type's output function */ 1295 scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo)); 1296 scratch.d.iocoerce.fcinfo_data_out = palloc0(sizeof(FunctionCallInfoData)); 1297 1298 getTypeOutputInfo(exprType((Node *) iocoerce->arg), 1299 &iofunc, &typisvarlena); 1300 fmgr_info(iofunc, scratch.d.iocoerce.finfo_out); 1301 fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out); 1302 InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out, 1303 scratch.d.iocoerce.finfo_out, 1304 1, InvalidOid, NULL, NULL); 1305 1306 /* lookup the result type's input function */ 1307 scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo)); 1308 scratch.d.iocoerce.fcinfo_data_in = palloc0(sizeof(FunctionCallInfoData)); 1309 1310 getTypeInputInfo(iocoerce->resulttype, 1311 &iofunc, &typioparam); 1312 fmgr_info(iofunc, scratch.d.iocoerce.finfo_in); 1313 fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in); 1314 InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in, 1315 scratch.d.iocoerce.finfo_in, 1316 3, InvalidOid, NULL, NULL); 1317 1318 /* 1319 * We can preload the second and third arguments for the input 1320 * function, since they're constants. 1321 */ 1322 fcinfo_in = scratch.d.iocoerce.fcinfo_data_in; 1323 fcinfo_in->arg[1] = ObjectIdGetDatum(typioparam); 1324 fcinfo_in->argnull[1] = false; 1325 fcinfo_in->arg[2] = Int32GetDatum(-1); 1326 fcinfo_in->argnull[2] = false; 1327 1328 ExprEvalPushStep(state, &scratch); 1329 break; 1330 } 1331 1332 case T_ArrayCoerceExpr: 1333 { 1334 ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; 1335 Oid resultelemtype; 1336 ExprState *elemstate; 1337 1338 /* evaluate argument into step's result area */ 1339 ExecInitExprRec(acoerce->arg, state, resv, resnull); 1340 1341 resultelemtype = get_element_type(acoerce->resulttype); 1342 if (!OidIsValid(resultelemtype)) 1343 ereport(ERROR, 1344 (errcode(ERRCODE_INVALID_PARAMETER_VALUE), 1345 errmsg("target type is not an array"))); 1346 1347 /* 1348 * Construct a sub-expression for the per-element expression; 1349 * but don't ready it until after we check it for triviality. 1350 * We assume it hasn't any Var references, but does have a 1351 * CaseTestExpr representing the source array element values. 1352 */ 1353 elemstate = makeNode(ExprState); 1354 elemstate->expr = acoerce->elemexpr; 1355 elemstate->parent = state->parent; 1356 elemstate->ext_params = state->ext_params; 1357 1358 elemstate->innermost_caseval = (Datum *) palloc(sizeof(Datum)); 1359 elemstate->innermost_casenull = (bool *) palloc(sizeof(bool)); 1360 1361 ExecInitExprRec(acoerce->elemexpr, elemstate, 1362 &elemstate->resvalue, &elemstate->resnull); 1363 1364 if (elemstate->steps_len == 1 && 1365 elemstate->steps[0].opcode == EEOP_CASE_TESTVAL) 1366 { 1367 /* Trivial, so we need no per-element work at runtime */ 1368 elemstate = NULL; 1369 } 1370 else 1371 { 1372 /* Not trivial, so append a DONE step */ 1373 scratch.opcode = EEOP_DONE; 1374 ExprEvalPushStep(elemstate, &scratch); 1375 /* and ready the subexpression */ 1376 ExecReadyExpr(elemstate); 1377 } 1378 1379 scratch.opcode = EEOP_ARRAYCOERCE; 1380 scratch.d.arraycoerce.elemexprstate = elemstate; 1381 scratch.d.arraycoerce.resultelemtype = resultelemtype; 1382 1383 if (elemstate) 1384 { 1385 /* Set up workspace for array_map */ 1386 scratch.d.arraycoerce.amstate = 1387 (ArrayMapState *) palloc0(sizeof(ArrayMapState)); 1388 } 1389 else 1390 { 1391 /* Don't need workspace if there's no subexpression */ 1392 scratch.d.arraycoerce.amstate = NULL; 1393 } 1394 1395 ExprEvalPushStep(state, &scratch); 1396 break; 1397 } 1398 1399 case T_ConvertRowtypeExpr: 1400 { 1401 ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node; 1402 ExprEvalRowtypeCache *rowcachep; 1403 1404 /* cache structs must be out-of-line for space reasons */ 1405 rowcachep = palloc(2 * sizeof(ExprEvalRowtypeCache)); 1406 rowcachep[0].cacheptr = NULL; 1407 rowcachep[1].cacheptr = NULL; 1408 1409 /* evaluate argument into step's result area */ 1410 ExecInitExprRec(convert->arg, state, resv, resnull); 1411 1412 /* and push conversion step */ 1413 scratch.opcode = EEOP_CONVERT_ROWTYPE; 1414 scratch.d.convert_rowtype.inputtype = 1415 exprType((Node *) convert->arg); 1416 scratch.d.convert_rowtype.outputtype = convert->resulttype; 1417 scratch.d.convert_rowtype.incache = &rowcachep[0]; 1418 scratch.d.convert_rowtype.outcache = &rowcachep[1]; 1419 scratch.d.convert_rowtype.map = NULL; 1420 1421 ExprEvalPushStep(state, &scratch); 1422 break; 1423 } 1424 1425 /* note that CaseWhen expressions are handled within this block */ 1426 case T_CaseExpr: 1427 { 1428 CaseExpr *caseExpr = (CaseExpr *) node; 1429 List *adjust_jumps = NIL; 1430 Datum *caseval = NULL; 1431 bool *casenull = NULL; 1432 ListCell *lc; 1433 1434 /* 1435 * If there's a test expression, we have to evaluate it and 1436 * save the value where the CaseTestExpr placeholders can find 1437 * it. 1438 */ 1439 if (caseExpr->arg != NULL) 1440 { 1441 /* Evaluate testexpr into caseval/casenull workspace */ 1442 caseval = palloc(sizeof(Datum)); 1443 casenull = palloc(sizeof(bool)); 1444 1445 ExecInitExprRec(caseExpr->arg, state, 1446 caseval, casenull); 1447 1448 /* 1449 * Since value might be read multiple times, force to R/O 1450 * - but only if it could be an expanded datum. 1451 */ 1452 if (get_typlen(exprType((Node *) caseExpr->arg)) == -1) 1453 { 1454 /* change caseval in-place */ 1455 scratch.opcode = EEOP_MAKE_READONLY; 1456 scratch.resvalue = caseval; 1457 scratch.resnull = casenull; 1458 scratch.d.make_readonly.value = caseval; 1459 scratch.d.make_readonly.isnull = casenull; 1460 ExprEvalPushStep(state, &scratch); 1461 /* restore normal settings of scratch fields */ 1462 scratch.resvalue = resv; 1463 scratch.resnull = resnull; 1464 } 1465 } 1466 1467 /* 1468 * Prepare to evaluate each of the WHEN clauses in turn; as 1469 * soon as one is true we return the value of the 1470 * corresponding THEN clause. If none are true then we return 1471 * the value of the ELSE clause, or NULL if there is none. 1472 */ 1473 foreach(lc, caseExpr->args) 1474 { 1475 CaseWhen *when = (CaseWhen *) lfirst(lc); 1476 Datum *save_innermost_caseval; 1477 bool *save_innermost_casenull; 1478 int whenstep; 1479 1480 /* 1481 * Make testexpr result available to CaseTestExpr nodes 1482 * within the condition. We must save and restore prior 1483 * setting of innermost_caseval fields, in case this node 1484 * is itself within a larger CASE. 1485 * 1486 * If there's no test expression, we don't actually need 1487 * to save and restore these fields; but it's less code to 1488 * just do so unconditionally. 1489 */ 1490 save_innermost_caseval = state->innermost_caseval; 1491 save_innermost_casenull = state->innermost_casenull; 1492 state->innermost_caseval = caseval; 1493 state->innermost_casenull = casenull; 1494 1495 /* evaluate condition into CASE's result variables */ 1496 ExecInitExprRec(when->expr, state, resv, resnull); 1497 1498 state->innermost_caseval = save_innermost_caseval; 1499 state->innermost_casenull = save_innermost_casenull; 1500 1501 /* If WHEN result isn't true, jump to next CASE arm */ 1502 scratch.opcode = EEOP_JUMP_IF_NOT_TRUE; 1503 scratch.d.jump.jumpdone = -1; /* computed later */ 1504 ExprEvalPushStep(state, &scratch); 1505 whenstep = state->steps_len - 1; 1506 1507 /* 1508 * If WHEN result is true, evaluate THEN result, storing 1509 * it into the CASE's result variables. 1510 */ 1511 ExecInitExprRec(when->result, state, resv, resnull); 1512 1513 /* Emit JUMP step to jump to end of CASE's code */ 1514 scratch.opcode = EEOP_JUMP; 1515 scratch.d.jump.jumpdone = -1; /* computed later */ 1516 ExprEvalPushStep(state, &scratch); 1517 1518 /* 1519 * Don't know address for that jump yet, compute once the 1520 * whole CASE expression is built. 1521 */ 1522 adjust_jumps = lappend_int(adjust_jumps, 1523 state->steps_len - 1); 1524 1525 /* 1526 * But we can set WHEN test's jump target now, to make it 1527 * jump to the next WHEN subexpression or the ELSE. 1528 */ 1529 state->steps[whenstep].d.jump.jumpdone = state->steps_len; 1530 } 1531 1532 /* transformCaseExpr always adds a default */ 1533 Assert(caseExpr->defresult); 1534 1535 /* evaluate ELSE expr into CASE's result variables */ 1536 ExecInitExprRec(caseExpr->defresult, state, 1537 resv, resnull); 1538 1539 /* adjust jump targets */ 1540 foreach(lc, adjust_jumps) 1541 { 1542 ExprEvalStep *as = &state->steps[lfirst_int(lc)]; 1543 1544 Assert(as->opcode == EEOP_JUMP); 1545 Assert(as->d.jump.jumpdone == -1); 1546 as->d.jump.jumpdone = state->steps_len; 1547 } 1548 1549 break; 1550 } 1551 1552 case T_CaseTestExpr: 1553 { 1554 /* 1555 * Read from location identified by innermost_caseval. Note 1556 * that innermost_caseval could be NULL, if this node isn't 1557 * actually within a CaseExpr, ArrayCoerceExpr, etc structure. 1558 * That can happen because some parts of the system abuse 1559 * CaseTestExpr to cause a read of a value externally supplied 1560 * in econtext->caseValue_datum. We'll take care of that 1561 * scenario at runtime. 1562 */ 1563 scratch.opcode = EEOP_CASE_TESTVAL; 1564 scratch.d.casetest.value = state->innermost_caseval; 1565 scratch.d.casetest.isnull = state->innermost_casenull; 1566 1567 ExprEvalPushStep(state, &scratch); 1568 break; 1569 } 1570 1571 case T_ArrayExpr: 1572 { 1573 ArrayExpr *arrayexpr = (ArrayExpr *) node; 1574 int nelems = list_length(arrayexpr->elements); 1575 ListCell *lc; 1576 int elemoff; 1577 1578 /* 1579 * Evaluate by computing each element, and then forming the 1580 * array. Elements are computed into scratch arrays 1581 * associated with the ARRAYEXPR step. 1582 */ 1583 scratch.opcode = EEOP_ARRAYEXPR; 1584 scratch.d.arrayexpr.elemvalues = 1585 (Datum *) palloc(sizeof(Datum) * nelems); 1586 scratch.d.arrayexpr.elemnulls = 1587 (bool *) palloc(sizeof(bool) * nelems); 1588 scratch.d.arrayexpr.nelems = nelems; 1589 1590 /* fill remaining fields of step */ 1591 scratch.d.arrayexpr.multidims = arrayexpr->multidims; 1592 scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid; 1593 1594 /* do one-time catalog lookup for type info */ 1595 get_typlenbyvalalign(arrayexpr->element_typeid, 1596 &scratch.d.arrayexpr.elemlength, 1597 &scratch.d.arrayexpr.elembyval, 1598 &scratch.d.arrayexpr.elemalign); 1599 1600 /* prepare to evaluate all arguments */ 1601 elemoff = 0; 1602 foreach(lc, arrayexpr->elements) 1603 { 1604 Expr *e = (Expr *) lfirst(lc); 1605 1606 ExecInitExprRec(e, state, 1607 &scratch.d.arrayexpr.elemvalues[elemoff], 1608 &scratch.d.arrayexpr.elemnulls[elemoff]); 1609 elemoff++; 1610 } 1611 1612 /* and then collect all into an array */ 1613 ExprEvalPushStep(state, &scratch); 1614 break; 1615 } 1616 1617 case T_RowExpr: 1618 { 1619 RowExpr *rowexpr = (RowExpr *) node; 1620 int nelems = list_length(rowexpr->args); 1621 TupleDesc tupdesc; 1622 int i; 1623 ListCell *l; 1624 1625 /* Build tupdesc to describe result tuples */ 1626 if (rowexpr->row_typeid == RECORDOID) 1627 { 1628 /* generic record, use types of given expressions */ 1629 tupdesc = ExecTypeFromExprList(rowexpr->args); 1630 } 1631 else 1632 { 1633 /* it's been cast to a named type, use that */ 1634 tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1); 1635 } 1636 /* In either case, adopt RowExpr's column aliases */ 1637 ExecTypeSetColNames(tupdesc, rowexpr->colnames); 1638 /* Bless the tupdesc in case it's now of type RECORD */ 1639 BlessTupleDesc(tupdesc); 1640 1641 /* 1642 * In the named-type case, the tupdesc could have more columns 1643 * than are in the args list, since the type might have had 1644 * columns added since the ROW() was parsed. We want those 1645 * extra columns to go to nulls, so we make sure that the 1646 * workspace arrays are large enough and then initialize any 1647 * extra columns to read as NULLs. 1648 */ 1649 Assert(nelems <= tupdesc->natts); 1650 nelems = Max(nelems, tupdesc->natts); 1651 1652 /* 1653 * Evaluate by first building datums for each field, and then 1654 * a final step forming the composite datum. 1655 */ 1656 scratch.opcode = EEOP_ROW; 1657 scratch.d.row.tupdesc = tupdesc; 1658 1659 /* space for the individual field datums */ 1660 scratch.d.row.elemvalues = 1661 (Datum *) palloc(sizeof(Datum) * nelems); 1662 scratch.d.row.elemnulls = 1663 (bool *) palloc(sizeof(bool) * nelems); 1664 /* as explained above, make sure any extra columns are null */ 1665 memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems); 1666 1667 /* Set up evaluation, skipping any deleted columns */ 1668 i = 0; 1669 foreach(l, rowexpr->args) 1670 { 1671 Form_pg_attribute att = TupleDescAttr(tupdesc, i); 1672 Expr *e = (Expr *) lfirst(l); 1673 1674 if (!att->attisdropped) 1675 { 1676 /* 1677 * Guard against ALTER COLUMN TYPE on rowtype since 1678 * the RowExpr was created. XXX should we check 1679 * typmod too? Not sure we can be sure it'll be the 1680 * same. 1681 */ 1682 if (exprType((Node *) e) != att->atttypid) 1683 ereport(ERROR, 1684 (errcode(ERRCODE_DATATYPE_MISMATCH), 1685 errmsg("ROW() column has type %s instead of type %s", 1686 format_type_be(exprType((Node *) e)), 1687 format_type_be(att->atttypid)))); 1688 } 1689 else 1690 { 1691 /* 1692 * Ignore original expression and insert a NULL. We 1693 * don't really care what type of NULL it is, so 1694 * always make an int4 NULL. 1695 */ 1696 e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid); 1697 } 1698 1699 /* Evaluate column expr into appropriate workspace slot */ 1700 ExecInitExprRec(e, state, 1701 &scratch.d.row.elemvalues[i], 1702 &scratch.d.row.elemnulls[i]); 1703 i++; 1704 } 1705 1706 /* And finally build the row value */ 1707 ExprEvalPushStep(state, &scratch); 1708 break; 1709 } 1710 1711 case T_RowCompareExpr: 1712 { 1713 RowCompareExpr *rcexpr = (RowCompareExpr *) node; 1714 int nopers = list_length(rcexpr->opnos); 1715 List *adjust_jumps = NIL; 1716 ListCell *l_left_expr, 1717 *l_right_expr, 1718 *l_opno, 1719 *l_opfamily, 1720 *l_inputcollid; 1721 ListCell *lc; 1722 int off; 1723 1724 /* 1725 * Iterate over each field, prepare comparisons. To handle 1726 * NULL results, prepare jumps to after the expression. If a 1727 * comparison yields a != 0 result, jump to the final step. 1728 */ 1729 Assert(list_length(rcexpr->largs) == nopers); 1730 Assert(list_length(rcexpr->rargs) == nopers); 1731 Assert(list_length(rcexpr->opfamilies) == nopers); 1732 Assert(list_length(rcexpr->inputcollids) == nopers); 1733 1734 off = 0; 1735 for (off = 0, 1736 l_left_expr = list_head(rcexpr->largs), 1737 l_right_expr = list_head(rcexpr->rargs), 1738 l_opno = list_head(rcexpr->opnos), 1739 l_opfamily = list_head(rcexpr->opfamilies), 1740 l_inputcollid = list_head(rcexpr->inputcollids); 1741 off < nopers; 1742 off++, 1743 l_left_expr = lnext(l_left_expr), 1744 l_right_expr = lnext(l_right_expr), 1745 l_opno = lnext(l_opno), 1746 l_opfamily = lnext(l_opfamily), 1747 l_inputcollid = lnext(l_inputcollid)) 1748 { 1749 Expr *left_expr = (Expr *) lfirst(l_left_expr); 1750 Expr *right_expr = (Expr *) lfirst(l_right_expr); 1751 Oid opno = lfirst_oid(l_opno); 1752 Oid opfamily = lfirst_oid(l_opfamily); 1753 Oid inputcollid = lfirst_oid(l_inputcollid); 1754 int strategy; 1755 Oid lefttype; 1756 Oid righttype; 1757 Oid proc; 1758 FmgrInfo *finfo; 1759 FunctionCallInfo fcinfo; 1760 1761 get_op_opfamily_properties(opno, opfamily, false, 1762 &strategy, 1763 &lefttype, 1764 &righttype); 1765 proc = get_opfamily_proc(opfamily, 1766 lefttype, 1767 righttype, 1768 BTORDER_PROC); 1769 if (!OidIsValid(proc)) 1770 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u", 1771 BTORDER_PROC, lefttype, righttype, opfamily); 1772 1773 /* Set up the primary fmgr lookup information */ 1774 finfo = palloc0(sizeof(FmgrInfo)); 1775 fcinfo = palloc0(sizeof(FunctionCallInfoData)); 1776 fmgr_info(proc, finfo); 1777 fmgr_info_set_expr((Node *) node, finfo); 1778 InitFunctionCallInfoData(*fcinfo, finfo, 2, 1779 inputcollid, NULL, NULL); 1780 1781 /* 1782 * If we enforced permissions checks on index support 1783 * functions, we'd need to make a check here. But the 1784 * index support machinery doesn't do that, and thus 1785 * neither does this code. 1786 */ 1787 1788 /* evaluate left and right args directly into fcinfo */ 1789 ExecInitExprRec(left_expr, state, 1790 &fcinfo->arg[0], &fcinfo->argnull[0]); 1791 ExecInitExprRec(right_expr, state, 1792 &fcinfo->arg[1], &fcinfo->argnull[1]); 1793 1794 scratch.opcode = EEOP_ROWCOMPARE_STEP; 1795 scratch.d.rowcompare_step.finfo = finfo; 1796 scratch.d.rowcompare_step.fcinfo_data = fcinfo; 1797 scratch.d.rowcompare_step.fn_addr = finfo->fn_addr; 1798 /* jump targets filled below */ 1799 scratch.d.rowcompare_step.jumpnull = -1; 1800 scratch.d.rowcompare_step.jumpdone = -1; 1801 1802 ExprEvalPushStep(state, &scratch); 1803 adjust_jumps = lappend_int(adjust_jumps, 1804 state->steps_len - 1); 1805 } 1806 1807 /* 1808 * We could have a zero-column rowtype, in which case the rows 1809 * necessarily compare equal. 1810 */ 1811 if (nopers == 0) 1812 { 1813 scratch.opcode = EEOP_CONST; 1814 scratch.d.constval.value = Int32GetDatum(0); 1815 scratch.d.constval.isnull = false; 1816 ExprEvalPushStep(state, &scratch); 1817 } 1818 1819 /* Finally, examine the last comparison result */ 1820 scratch.opcode = EEOP_ROWCOMPARE_FINAL; 1821 scratch.d.rowcompare_final.rctype = rcexpr->rctype; 1822 ExprEvalPushStep(state, &scratch); 1823 1824 /* adjust jump targetss */ 1825 foreach(lc, adjust_jumps) 1826 { 1827 ExprEvalStep *as = &state->steps[lfirst_int(lc)]; 1828 1829 Assert(as->opcode == EEOP_ROWCOMPARE_STEP); 1830 Assert(as->d.rowcompare_step.jumpdone == -1); 1831 Assert(as->d.rowcompare_step.jumpnull == -1); 1832 1833 /* jump to comparison evaluation */ 1834 as->d.rowcompare_step.jumpdone = state->steps_len - 1; 1835 /* jump to the following expression */ 1836 as->d.rowcompare_step.jumpnull = state->steps_len; 1837 } 1838 1839 break; 1840 } 1841 1842 case T_CoalesceExpr: 1843 { 1844 CoalesceExpr *coalesce = (CoalesceExpr *) node; 1845 List *adjust_jumps = NIL; 1846 ListCell *lc; 1847 1848 /* We assume there's at least one arg */ 1849 Assert(coalesce->args != NIL); 1850 1851 /* 1852 * Prepare evaluation of all coalesced arguments, after each 1853 * one push a step that short-circuits if not null. 1854 */ 1855 foreach(lc, coalesce->args) 1856 { 1857 Expr *e = (Expr *) lfirst(lc); 1858 1859 /* evaluate argument, directly into result datum */ 1860 ExecInitExprRec(e, state, resv, resnull); 1861 1862 /* if it's not null, skip to end of COALESCE expr */ 1863 scratch.opcode = EEOP_JUMP_IF_NOT_NULL; 1864 scratch.d.jump.jumpdone = -1; /* adjust later */ 1865 ExprEvalPushStep(state, &scratch); 1866 1867 adjust_jumps = lappend_int(adjust_jumps, 1868 state->steps_len - 1); 1869 } 1870 1871 /* 1872 * No need to add a constant NULL return - we only can get to 1873 * the end of the expression if a NULL already is being 1874 * returned. 1875 */ 1876 1877 /* adjust jump targets */ 1878 foreach(lc, adjust_jumps) 1879 { 1880 ExprEvalStep *as = &state->steps[lfirst_int(lc)]; 1881 1882 Assert(as->opcode == EEOP_JUMP_IF_NOT_NULL); 1883 Assert(as->d.jump.jumpdone == -1); 1884 as->d.jump.jumpdone = state->steps_len; 1885 } 1886 1887 break; 1888 } 1889 1890 case T_MinMaxExpr: 1891 { 1892 MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; 1893 int nelems = list_length(minmaxexpr->args); 1894 TypeCacheEntry *typentry; 1895 FmgrInfo *finfo; 1896 FunctionCallInfo fcinfo; 1897 ListCell *lc; 1898 int off; 1899 1900 /* Look up the btree comparison function for the datatype */ 1901 typentry = lookup_type_cache(minmaxexpr->minmaxtype, 1902 TYPECACHE_CMP_PROC); 1903 if (!OidIsValid(typentry->cmp_proc)) 1904 ereport(ERROR, 1905 (errcode(ERRCODE_UNDEFINED_FUNCTION), 1906 errmsg("could not identify a comparison function for type %s", 1907 format_type_be(minmaxexpr->minmaxtype)))); 1908 1909 /* 1910 * If we enforced permissions checks on index support 1911 * functions, we'd need to make a check here. But the index 1912 * support machinery doesn't do that, and thus neither does 1913 * this code. 1914 */ 1915 1916 /* Perform function lookup */ 1917 finfo = palloc0(sizeof(FmgrInfo)); 1918 fcinfo = palloc0(sizeof(FunctionCallInfoData)); 1919 fmgr_info(typentry->cmp_proc, finfo); 1920 fmgr_info_set_expr((Node *) node, finfo); 1921 InitFunctionCallInfoData(*fcinfo, finfo, 2, 1922 minmaxexpr->inputcollid, NULL, NULL); 1923 1924 scratch.opcode = EEOP_MINMAX; 1925 /* allocate space to store arguments */ 1926 scratch.d.minmax.values = 1927 (Datum *) palloc(sizeof(Datum) * nelems); 1928 scratch.d.minmax.nulls = 1929 (bool *) palloc(sizeof(bool) * nelems); 1930 scratch.d.minmax.nelems = nelems; 1931 1932 scratch.d.minmax.op = minmaxexpr->op; 1933 scratch.d.minmax.finfo = finfo; 1934 scratch.d.minmax.fcinfo_data = fcinfo; 1935 1936 /* evaluate expressions into minmax->values/nulls */ 1937 off = 0; 1938 foreach(lc, minmaxexpr->args) 1939 { 1940 Expr *e = (Expr *) lfirst(lc); 1941 1942 ExecInitExprRec(e, state, 1943 &scratch.d.minmax.values[off], 1944 &scratch.d.minmax.nulls[off]); 1945 off++; 1946 } 1947 1948 /* and push the final comparison */ 1949 ExprEvalPushStep(state, &scratch); 1950 break; 1951 } 1952 1953 case T_SQLValueFunction: 1954 { 1955 SQLValueFunction *svf = (SQLValueFunction *) node; 1956 1957 scratch.opcode = EEOP_SQLVALUEFUNCTION; 1958 scratch.d.sqlvaluefunction.svf = svf; 1959 1960 ExprEvalPushStep(state, &scratch); 1961 break; 1962 } 1963 1964 case T_XmlExpr: 1965 { 1966 XmlExpr *xexpr = (XmlExpr *) node; 1967 int nnamed = list_length(xexpr->named_args); 1968 int nargs = list_length(xexpr->args); 1969 int off; 1970 ListCell *arg; 1971 1972 scratch.opcode = EEOP_XMLEXPR; 1973 scratch.d.xmlexpr.xexpr = xexpr; 1974 1975 /* allocate space for storing all the arguments */ 1976 if (nnamed) 1977 { 1978 scratch.d.xmlexpr.named_argvalue = 1979 (Datum *) palloc(sizeof(Datum) * nnamed); 1980 scratch.d.xmlexpr.named_argnull = 1981 (bool *) palloc(sizeof(bool) * nnamed); 1982 } 1983 else 1984 { 1985 scratch.d.xmlexpr.named_argvalue = NULL; 1986 scratch.d.xmlexpr.named_argnull = NULL; 1987 } 1988 1989 if (nargs) 1990 { 1991 scratch.d.xmlexpr.argvalue = 1992 (Datum *) palloc(sizeof(Datum) * nargs); 1993 scratch.d.xmlexpr.argnull = 1994 (bool *) palloc(sizeof(bool) * nargs); 1995 } 1996 else 1997 { 1998 scratch.d.xmlexpr.argvalue = NULL; 1999 scratch.d.xmlexpr.argnull = NULL; 2000 } 2001 2002 /* prepare argument execution */ 2003 off = 0; 2004 foreach(arg, xexpr->named_args) 2005 { 2006 Expr *e = (Expr *) lfirst(arg); 2007 2008 ExecInitExprRec(e, state, 2009 &scratch.d.xmlexpr.named_argvalue[off], 2010 &scratch.d.xmlexpr.named_argnull[off]); 2011 off++; 2012 } 2013 2014 off = 0; 2015 foreach(arg, xexpr->args) 2016 { 2017 Expr *e = (Expr *) lfirst(arg); 2018 2019 ExecInitExprRec(e, state, 2020 &scratch.d.xmlexpr.argvalue[off], 2021 &scratch.d.xmlexpr.argnull[off]); 2022 off++; 2023 } 2024 2025 /* and evaluate the actual XML expression */ 2026 ExprEvalPushStep(state, &scratch); 2027 break; 2028 } 2029 2030 case T_NullTest: 2031 { 2032 NullTest *ntest = (NullTest *) node; 2033 2034 if (ntest->nulltesttype == IS_NULL) 2035 { 2036 if (ntest->argisrow) 2037 scratch.opcode = EEOP_NULLTEST_ROWISNULL; 2038 else 2039 scratch.opcode = EEOP_NULLTEST_ISNULL; 2040 } 2041 else if (ntest->nulltesttype == IS_NOT_NULL) 2042 { 2043 if (ntest->argisrow) 2044 scratch.opcode = EEOP_NULLTEST_ROWISNOTNULL; 2045 else 2046 scratch.opcode = EEOP_NULLTEST_ISNOTNULL; 2047 } 2048 else 2049 { 2050 elog(ERROR, "unrecognized nulltesttype: %d", 2051 (int) ntest->nulltesttype); 2052 } 2053 /* initialize cache in case it's a row test */ 2054 scratch.d.nulltest_row.rowcache.cacheptr = NULL; 2055 2056 /* first evaluate argument into result variable */ 2057 ExecInitExprRec(ntest->arg, state, 2058 resv, resnull); 2059 2060 /* then push the test of that argument */ 2061 ExprEvalPushStep(state, &scratch); 2062 break; 2063 } 2064 2065 case T_BooleanTest: 2066 { 2067 BooleanTest *btest = (BooleanTest *) node; 2068 2069 /* 2070 * Evaluate argument, directly into result datum. That's ok, 2071 * because resv/resnull is definitely not used anywhere else, 2072 * and will get overwritten by the below EEOP_BOOLTEST_IS_* 2073 * step. 2074 */ 2075 ExecInitExprRec(btest->arg, state, resv, resnull); 2076 2077 switch (btest->booltesttype) 2078 { 2079 case IS_TRUE: 2080 scratch.opcode = EEOP_BOOLTEST_IS_TRUE; 2081 break; 2082 case IS_NOT_TRUE: 2083 scratch.opcode = EEOP_BOOLTEST_IS_NOT_TRUE; 2084 break; 2085 case IS_FALSE: 2086 scratch.opcode = EEOP_BOOLTEST_IS_FALSE; 2087 break; 2088 case IS_NOT_FALSE: 2089 scratch.opcode = EEOP_BOOLTEST_IS_NOT_FALSE; 2090 break; 2091 case IS_UNKNOWN: 2092 /* Same as scalar IS NULL test */ 2093 scratch.opcode = EEOP_NULLTEST_ISNULL; 2094 break; 2095 case IS_NOT_UNKNOWN: 2096 /* Same as scalar IS NOT NULL test */ 2097 scratch.opcode = EEOP_NULLTEST_ISNOTNULL; 2098 break; 2099 default: 2100 elog(ERROR, "unrecognized booltesttype: %d", 2101 (int) btest->booltesttype); 2102 } 2103 2104 ExprEvalPushStep(state, &scratch); 2105 break; 2106 } 2107 2108 case T_CoerceToDomain: 2109 { 2110 CoerceToDomain *ctest = (CoerceToDomain *) node; 2111 2112 ExecInitCoerceToDomain(&scratch, ctest, state, 2113 resv, resnull); 2114 break; 2115 } 2116 2117 case T_CoerceToDomainValue: 2118 { 2119 /* 2120 * Read from location identified by innermost_domainval. Note 2121 * that innermost_domainval could be NULL, if we're compiling 2122 * a standalone domain check rather than one embedded in a 2123 * larger expression. In that case we must read from 2124 * econtext->domainValue_datum. We'll take care of that 2125 * scenario at runtime. 2126 */ 2127 scratch.opcode = EEOP_DOMAIN_TESTVAL; 2128 /* we share instruction union variant with case testval */ 2129 scratch.d.casetest.value = state->innermost_domainval; 2130 scratch.d.casetest.isnull = state->innermost_domainnull; 2131 2132 ExprEvalPushStep(state, &scratch); 2133 break; 2134 } 2135 2136 case T_CurrentOfExpr: 2137 { 2138 scratch.opcode = EEOP_CURRENTOFEXPR; 2139 ExprEvalPushStep(state, &scratch); 2140 break; 2141 } 2142 2143 case T_NextValueExpr: 2144 { 2145 NextValueExpr *nve = (NextValueExpr *) node; 2146 2147 scratch.opcode = EEOP_NEXTVALUEEXPR; 2148 scratch.d.nextvalueexpr.seqid = nve->seqid; 2149 scratch.d.nextvalueexpr.seqtypid = nve->typeId; 2150 2151 ExprEvalPushStep(state, &scratch); 2152 break; 2153 } 2154 2155 default: 2156 elog(ERROR, "unrecognized node type: %d", 2157 (int) nodeTag(node)); 2158 break; 2159 } 2160 } 2161 2162 /* 2163 * Add another expression evaluation step to ExprState->steps. 2164 * 2165 * Note that this potentially re-allocates es->steps, therefore no pointer 2166 * into that array may be used while the expression is still being built. 2167 */ 2168 void 2169 ExprEvalPushStep(ExprState *es, const ExprEvalStep *s) 2170 { 2171 if (es->steps_alloc == 0) 2172 { 2173 es->steps_alloc = 16; 2174 es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc); 2175 } 2176 else if (es->steps_alloc == es->steps_len) 2177 { 2178 es->steps_alloc *= 2; 2179 es->steps = repalloc(es->steps, 2180 sizeof(ExprEvalStep) * es->steps_alloc); 2181 } 2182 2183 memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep)); 2184 } 2185 2186 /* 2187 * Perform setup necessary for the evaluation of a function-like expression, 2188 * appending argument evaluation steps to the steps list in *state, and 2189 * setting up *scratch so it is ready to be pushed. 2190 * 2191 * *scratch is not pushed here, so that callers may override the opcode, 2192 * which is useful for function-like cases like DISTINCT. 2193 */ 2194 static void 2195 ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, 2196 Oid inputcollid, ExprState *state) 2197 { 2198 int nargs = list_length(args); 2199 AclResult aclresult; 2200 FmgrInfo *flinfo; 2201 FunctionCallInfo fcinfo; 2202 int argno; 2203 ListCell *lc; 2204 2205 /* Check permission to call function */ 2206 aclresult = pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE); 2207 if (aclresult != ACLCHECK_OK) 2208 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(funcid)); 2209 InvokeFunctionExecuteHook(funcid); 2210 2211 /* 2212 * Safety check on nargs. Under normal circumstances this should never 2213 * fail, as parser should check sooner. But possibly it might fail if 2214 * server has been compiled with FUNC_MAX_ARGS smaller than some functions 2215 * declared in pg_proc? 2216 */ 2217 if (nargs > FUNC_MAX_ARGS) 2218 ereport(ERROR, 2219 (errcode(ERRCODE_TOO_MANY_ARGUMENTS), 2220 errmsg_plural("cannot pass more than %d argument to a function", 2221 "cannot pass more than %d arguments to a function", 2222 FUNC_MAX_ARGS, 2223 FUNC_MAX_ARGS))); 2224 2225 /* Allocate function lookup data and parameter workspace for this call */ 2226 scratch->d.func.finfo = palloc0(sizeof(FmgrInfo)); 2227 scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData)); 2228 flinfo = scratch->d.func.finfo; 2229 fcinfo = scratch->d.func.fcinfo_data; 2230 2231 /* Set up the primary fmgr lookup information */ 2232 fmgr_info(funcid, flinfo); 2233 fmgr_info_set_expr((Node *) node, flinfo); 2234 2235 /* Initialize function call parameter structure too */ 2236 InitFunctionCallInfoData(*fcinfo, flinfo, 2237 nargs, inputcollid, NULL, NULL); 2238 2239 /* Keep extra copies of this info to save an indirection at runtime */ 2240 scratch->d.func.fn_addr = flinfo->fn_addr; 2241 scratch->d.func.nargs = nargs; 2242 2243 /* We only support non-set functions here */ 2244 if (flinfo->fn_retset) 2245 ereport(ERROR, 2246 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 2247 errmsg("set-valued function called in context that cannot accept a set"), 2248 state->parent ? 2249 executor_errposition(state->parent->state, 2250 exprLocation((Node *) node)) : 0)); 2251 2252 /* Build code to evaluate arguments directly into the fcinfo struct */ 2253 argno = 0; 2254 foreach(lc, args) 2255 { 2256 Expr *arg = (Expr *) lfirst(lc); 2257 2258 if (IsA(arg, Const)) 2259 { 2260 /* 2261 * Don't evaluate const arguments every round; especially 2262 * interesting for constants in comparisons. 2263 */ 2264 Const *con = (Const *) arg; 2265 2266 fcinfo->arg[argno] = con->constvalue; 2267 fcinfo->argnull[argno] = con->constisnull; 2268 } 2269 else 2270 { 2271 ExecInitExprRec(arg, state, 2272 &fcinfo->arg[argno], &fcinfo->argnull[argno]); 2273 } 2274 argno++; 2275 } 2276 2277 /* Insert appropriate opcode depending on strictness and stats level */ 2278 if (pgstat_track_functions <= flinfo->fn_stats) 2279 { 2280 if (flinfo->fn_strict && nargs > 0) 2281 scratch->opcode = EEOP_FUNCEXPR_STRICT; 2282 else 2283 scratch->opcode = EEOP_FUNCEXPR; 2284 } 2285 else 2286 { 2287 if (flinfo->fn_strict && nargs > 0) 2288 scratch->opcode = EEOP_FUNCEXPR_STRICT_FUSAGE; 2289 else 2290 scratch->opcode = EEOP_FUNCEXPR_FUSAGE; 2291 } 2292 } 2293 2294 /* 2295 * Add expression steps deforming the ExprState's inner/outer/scan slots 2296 * as much as required by the expression. 2297 */ 2298 static void 2299 ExecInitExprSlots(ExprState *state, Node *node) 2300 { 2301 LastAttnumInfo info = {0, 0, 0}; 2302 2303 /* 2304 * Figure out which attributes we're going to need. 2305 */ 2306 get_last_attnums_walker(node, &info); 2307 2308 ExecPushExprSlots(state, &info); 2309 } 2310 2311 /* 2312 * Add steps deforming the ExprState's inner/out/scan slots as much as 2313 * indicated by info. This is useful when building an ExprState covering more 2314 * than one expression. 2315 */ 2316 static void 2317 ExecPushExprSlots(ExprState *state, LastAttnumInfo *info) 2318 { 2319 ExprEvalStep scratch = {0}; 2320 2321 scratch.resvalue = NULL; 2322 scratch.resnull = NULL; 2323 2324 /* Emit steps as needed */ 2325 if (info->last_inner > 0) 2326 { 2327 scratch.opcode = EEOP_INNER_FETCHSOME; 2328 scratch.d.fetch.last_var = info->last_inner; 2329 scratch.d.fetch.known_desc = NULL; 2330 ExprEvalPushStep(state, &scratch); 2331 } 2332 if (info->last_outer > 0) 2333 { 2334 scratch.opcode = EEOP_OUTER_FETCHSOME; 2335 scratch.d.fetch.last_var = info->last_outer; 2336 scratch.d.fetch.known_desc = NULL; 2337 ExprEvalPushStep(state, &scratch); 2338 } 2339 if (info->last_scan > 0) 2340 { 2341 scratch.opcode = EEOP_SCAN_FETCHSOME; 2342 scratch.d.fetch.last_var = info->last_scan; 2343 scratch.d.fetch.known_desc = NULL; 2344 ExprEvalPushStep(state, &scratch); 2345 } 2346 } 2347 2348 /* 2349 * get_last_attnums_walker: expression walker for ExecInitExprSlots 2350 */ 2351 static bool 2352 get_last_attnums_walker(Node *node, LastAttnumInfo *info) 2353 { 2354 if (node == NULL) 2355 return false; 2356 if (IsA(node, Var)) 2357 { 2358 Var *variable = (Var *) node; 2359 AttrNumber attnum = variable->varattno; 2360 2361 switch (variable->varno) 2362 { 2363 case INNER_VAR: 2364 info->last_inner = Max(info->last_inner, attnum); 2365 break; 2366 2367 case OUTER_VAR: 2368 info->last_outer = Max(info->last_outer, attnum); 2369 break; 2370 2371 /* INDEX_VAR is handled by default case */ 2372 2373 default: 2374 info->last_scan = Max(info->last_scan, attnum); 2375 break; 2376 } 2377 return false; 2378 } 2379 2380 /* 2381 * Don't examine the arguments or filters of Aggrefs or WindowFuncs, 2382 * because those do not represent expressions to be evaluated within the 2383 * calling expression's econtext. GroupingFunc arguments are never 2384 * evaluated at all. 2385 */ 2386 if (IsA(node, Aggref)) 2387 return false; 2388 if (IsA(node, WindowFunc)) 2389 return false; 2390 if (IsA(node, GroupingFunc)) 2391 return false; 2392 return expression_tree_walker(node, get_last_attnums_walker, 2393 (void *) info); 2394 } 2395 2396 /* 2397 * Prepare step for the evaluation of a whole-row variable. 2398 * The caller still has to push the step. 2399 */ 2400 static void 2401 ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state) 2402 { 2403 PlanState *parent = state->parent; 2404 2405 /* fill in all but the target */ 2406 scratch->opcode = EEOP_WHOLEROW; 2407 scratch->d.wholerow.var = variable; 2408 scratch->d.wholerow.first = true; 2409 scratch->d.wholerow.slow = false; 2410 scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */ 2411 scratch->d.wholerow.junkFilter = NULL; 2412 2413 /* 2414 * If the input tuple came from a subquery, it might contain "resjunk" 2415 * columns (such as GROUP BY or ORDER BY columns), which we don't want to 2416 * keep in the whole-row result. We can get rid of such columns by 2417 * passing the tuple through a JunkFilter --- but to make one, we have to 2418 * lay our hands on the subquery's targetlist. Fortunately, there are not 2419 * very many cases where this can happen, and we can identify all of them 2420 * by examining our parent PlanState. We assume this is not an issue in 2421 * standalone expressions that don't have parent plans. (Whole-row Vars 2422 * can occur in such expressions, but they will always be referencing 2423 * table rows.) 2424 */ 2425 if (parent) 2426 { 2427 PlanState *subplan = NULL; 2428 2429 switch (nodeTag(parent)) 2430 { 2431 case T_SubqueryScanState: 2432 subplan = ((SubqueryScanState *) parent)->subplan; 2433 break; 2434 case T_CteScanState: 2435 subplan = ((CteScanState *) parent)->cteplanstate; 2436 break; 2437 default: 2438 break; 2439 } 2440 2441 if (subplan) 2442 { 2443 bool junk_filter_needed = false; 2444 ListCell *tlist; 2445 2446 /* Detect whether subplan tlist actually has any junk columns */ 2447 foreach(tlist, subplan->plan->targetlist) 2448 { 2449 TargetEntry *tle = (TargetEntry *) lfirst(tlist); 2450 2451 if (tle->resjunk) 2452 { 2453 junk_filter_needed = true; 2454 break; 2455 } 2456 } 2457 2458 /* If so, build the junkfilter now */ 2459 if (junk_filter_needed) 2460 { 2461 scratch->d.wholerow.junkFilter = 2462 ExecInitJunkFilter(subplan->plan->targetlist, 2463 ExecGetResultType(subplan)->tdhasoid, 2464 ExecInitExtraTupleSlot(parent->state, NULL)); 2465 } 2466 } 2467 } 2468 } 2469 2470 /* 2471 * Prepare evaluation of an ArrayRef expression. 2472 */ 2473 static void 2474 ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, 2475 ExprState *state, Datum *resv, bool *resnull) 2476 { 2477 bool isAssignment = (aref->refassgnexpr != NULL); 2478 ArrayRefState *arefstate = palloc0(sizeof(ArrayRefState)); 2479 List *adjust_jumps = NIL; 2480 ListCell *lc; 2481 int i; 2482 2483 /* Fill constant fields of ArrayRefState */ 2484 arefstate->isassignment = isAssignment; 2485 arefstate->refelemtype = aref->refelemtype; 2486 arefstate->refattrlength = get_typlen(aref->refarraytype); 2487 get_typlenbyvalalign(aref->refelemtype, 2488 &arefstate->refelemlength, 2489 &arefstate->refelembyval, 2490 &arefstate->refelemalign); 2491 2492 /* 2493 * Evaluate array input. It's safe to do so into resv/resnull, because we 2494 * won't use that as target for any of the other subexpressions, and it'll 2495 * be overwritten by the final EEOP_ARRAYREF_FETCH/ASSIGN step, which is 2496 * pushed last. 2497 */ 2498 ExecInitExprRec(aref->refexpr, state, resv, resnull); 2499 2500 /* 2501 * If refexpr yields NULL, and it's a fetch, then result is NULL. We can 2502 * implement this with just JUMP_IF_NULL, since we evaluated the array 2503 * into the desired target location. 2504 */ 2505 if (!isAssignment) 2506 { 2507 scratch->opcode = EEOP_JUMP_IF_NULL; 2508 scratch->d.jump.jumpdone = -1; /* adjust later */ 2509 ExprEvalPushStep(state, scratch); 2510 adjust_jumps = lappend_int(adjust_jumps, 2511 state->steps_len - 1); 2512 } 2513 2514 /* Verify subscript list lengths are within limit */ 2515 if (list_length(aref->refupperindexpr) > MAXDIM) 2516 ereport(ERROR, 2517 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), 2518 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", 2519 list_length(aref->refupperindexpr), MAXDIM))); 2520 2521 if (list_length(aref->reflowerindexpr) > MAXDIM) 2522 ereport(ERROR, 2523 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), 2524 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", 2525 list_length(aref->reflowerindexpr), MAXDIM))); 2526 2527 /* Evaluate upper subscripts */ 2528 i = 0; 2529 foreach(lc, aref->refupperindexpr) 2530 { 2531 Expr *e = (Expr *) lfirst(lc); 2532 2533 /* When slicing, individual subscript bounds can be omitted */ 2534 if (!e) 2535 { 2536 arefstate->upperprovided[i] = false; 2537 i++; 2538 continue; 2539 } 2540 2541 arefstate->upperprovided[i] = true; 2542 2543 /* Each subscript is evaluated into subscriptvalue/subscriptnull */ 2544 ExecInitExprRec(e, state, 2545 &arefstate->subscriptvalue, &arefstate->subscriptnull); 2546 2547 /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */ 2548 scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT; 2549 scratch->d.arrayref_subscript.state = arefstate; 2550 scratch->d.arrayref_subscript.off = i; 2551 scratch->d.arrayref_subscript.isupper = true; 2552 scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */ 2553 ExprEvalPushStep(state, scratch); 2554 adjust_jumps = lappend_int(adjust_jumps, 2555 state->steps_len - 1); 2556 i++; 2557 } 2558 arefstate->numupper = i; 2559 2560 /* Evaluate lower subscripts similarly */ 2561 i = 0; 2562 foreach(lc, aref->reflowerindexpr) 2563 { 2564 Expr *e = (Expr *) lfirst(lc); 2565 2566 /* When slicing, individual subscript bounds can be omitted */ 2567 if (!e) 2568 { 2569 arefstate->lowerprovided[i] = false; 2570 i++; 2571 continue; 2572 } 2573 2574 arefstate->lowerprovided[i] = true; 2575 2576 /* Each subscript is evaluated into subscriptvalue/subscriptnull */ 2577 ExecInitExprRec(e, state, 2578 &arefstate->subscriptvalue, &arefstate->subscriptnull); 2579 2580 /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */ 2581 scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT; 2582 scratch->d.arrayref_subscript.state = arefstate; 2583 scratch->d.arrayref_subscript.off = i; 2584 scratch->d.arrayref_subscript.isupper = false; 2585 scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */ 2586 ExprEvalPushStep(state, scratch); 2587 adjust_jumps = lappend_int(adjust_jumps, 2588 state->steps_len - 1); 2589 i++; 2590 } 2591 arefstate->numlower = i; 2592 2593 /* Should be impossible if parser is sane, but check anyway: */ 2594 if (arefstate->numlower != 0 && 2595 arefstate->numupper != arefstate->numlower) 2596 elog(ERROR, "upper and lower index lists are not same length"); 2597 2598 if (isAssignment) 2599 { 2600 Datum *save_innermost_caseval; 2601 bool *save_innermost_casenull; 2602 2603 /* 2604 * We might have a nested-assignment situation, in which the 2605 * refassgnexpr is itself a FieldStore or ArrayRef that needs to 2606 * obtain and modify the previous value of the array element or slice 2607 * being replaced. If so, we have to extract that value from the 2608 * array and pass it down via the CaseTestExpr mechanism. It's safe 2609 * to reuse the CASE mechanism because there cannot be a CASE between 2610 * here and where the value would be needed, and an array assignment 2611 * can't be within a CASE either. (So saving and restoring 2612 * innermost_caseval is just paranoia, but let's do it anyway.) 2613 * 2614 * Since fetching the old element might be a nontrivial expense, do it 2615 * only if the argument actually needs it. 2616 */ 2617 if (isAssignmentIndirectionExpr(aref->refassgnexpr)) 2618 { 2619 scratch->opcode = EEOP_ARRAYREF_OLD; 2620 scratch->d.arrayref.state = arefstate; 2621 ExprEvalPushStep(state, scratch); 2622 } 2623 2624 /* ARRAYREF_OLD puts extracted value into prevvalue/prevnull */ 2625 save_innermost_caseval = state->innermost_caseval; 2626 save_innermost_casenull = state->innermost_casenull; 2627 state->innermost_caseval = &arefstate->prevvalue; 2628 state->innermost_casenull = &arefstate->prevnull; 2629 2630 /* evaluate replacement value into replacevalue/replacenull */ 2631 ExecInitExprRec(aref->refassgnexpr, state, 2632 &arefstate->replacevalue, &arefstate->replacenull); 2633 2634 state->innermost_caseval = save_innermost_caseval; 2635 state->innermost_casenull = save_innermost_casenull; 2636 2637 /* and perform the assignment */ 2638 scratch->opcode = EEOP_ARRAYREF_ASSIGN; 2639 scratch->d.arrayref.state = arefstate; 2640 ExprEvalPushStep(state, scratch); 2641 } 2642 else 2643 { 2644 /* array fetch is much simpler */ 2645 scratch->opcode = EEOP_ARRAYREF_FETCH; 2646 scratch->d.arrayref.state = arefstate; 2647 ExprEvalPushStep(state, scratch); 2648 } 2649 2650 /* adjust jump targets */ 2651 foreach(lc, adjust_jumps) 2652 { 2653 ExprEvalStep *as = &state->steps[lfirst_int(lc)]; 2654 2655 if (as->opcode == EEOP_ARRAYREF_SUBSCRIPT) 2656 { 2657 Assert(as->d.arrayref_subscript.jumpdone == -1); 2658 as->d.arrayref_subscript.jumpdone = state->steps_len; 2659 } 2660 else 2661 { 2662 Assert(as->opcode == EEOP_JUMP_IF_NULL); 2663 Assert(as->d.jump.jumpdone == -1); 2664 as->d.jump.jumpdone = state->steps_len; 2665 } 2666 } 2667 } 2668 2669 /* 2670 * Helper for preparing ArrayRef expressions for evaluation: is expr a nested 2671 * FieldStore or ArrayRef that needs the old element value passed down? 2672 * 2673 * (We could use this in FieldStore too, but in that case passing the old 2674 * value is so cheap there's no need.) 2675 * 2676 * Note: it might seem that this needs to recurse, but in most cases it does 2677 * not; the CaseTestExpr, if any, will be directly the arg or refexpr of the 2678 * top-level node. Nested-assignment situations give rise to expression 2679 * trees in which each level of assignment has its own CaseTestExpr, and the 2680 * recursive structure appears within the newvals or refassgnexpr field. 2681 * There is an exception, though: if the array is an array-of-domain, we will 2682 * have a CoerceToDomain as the refassgnexpr, and we need to be able to look 2683 * through that. 2684 */ 2685 static bool 2686 isAssignmentIndirectionExpr(Expr *expr) 2687 { 2688 if (expr == NULL) 2689 return false; /* just paranoia */ 2690 if (IsA(expr, FieldStore)) 2691 { 2692 FieldStore *fstore = (FieldStore *) expr; 2693 2694 if (fstore->arg && IsA(fstore->arg, CaseTestExpr)) 2695 return true; 2696 } 2697 else if (IsA(expr, ArrayRef)) 2698 { 2699 ArrayRef *arrayRef = (ArrayRef *) expr; 2700 2701 if (arrayRef->refexpr && IsA(arrayRef->refexpr, CaseTestExpr)) 2702 return true; 2703 } 2704 else if (IsA(expr, CoerceToDomain)) 2705 { 2706 CoerceToDomain *cd = (CoerceToDomain *) expr; 2707 2708 return isAssignmentIndirectionExpr(cd->arg); 2709 } 2710 return false; 2711 } 2712 2713 /* 2714 * Prepare evaluation of a CoerceToDomain expression. 2715 */ 2716 static void 2717 ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, 2718 ExprState *state, Datum *resv, bool *resnull) 2719 { 2720 ExprEvalStep scratch2 = {0}; 2721 DomainConstraintRef *constraint_ref; 2722 Datum *domainval = NULL; 2723 bool *domainnull = NULL; 2724 Datum *save_innermost_domainval; 2725 bool *save_innermost_domainnull; 2726 ListCell *l; 2727 2728 scratch->d.domaincheck.resulttype = ctest->resulttype; 2729 /* we'll allocate workspace only if needed */ 2730 scratch->d.domaincheck.checkvalue = NULL; 2731 scratch->d.domaincheck.checknull = NULL; 2732 2733 /* 2734 * Evaluate argument - it's fine to directly store it into resv/resnull, 2735 * if there's constraint failures there'll be errors, otherwise it's what 2736 * needs to be returned. 2737 */ 2738 ExecInitExprRec(ctest->arg, state, resv, resnull); 2739 2740 /* 2741 * Note: if the argument is of varlena type, it could be a R/W expanded 2742 * object. We want to return the R/W pointer as the final result, but we 2743 * have to pass a R/O pointer as the value to be tested by any functions 2744 * in check expressions. We don't bother to emit a MAKE_READONLY step 2745 * unless there's actually at least one check expression, though. Until 2746 * we've tested that, domainval/domainnull are NULL. 2747 */ 2748 2749 /* 2750 * Collect the constraints associated with the domain. 2751 * 2752 * Note: before PG v10 we'd recheck the set of constraints during each 2753 * evaluation of the expression. Now we bake them into the ExprState 2754 * during executor initialization. That means we don't need typcache.c to 2755 * provide compiled exprs. 2756 */ 2757 constraint_ref = (DomainConstraintRef *) 2758 palloc(sizeof(DomainConstraintRef)); 2759 InitDomainConstraintRef(ctest->resulttype, 2760 constraint_ref, 2761 CurrentMemoryContext, 2762 false); 2763 2764 /* 2765 * Compile code to check each domain constraint. NOTNULL constraints can 2766 * just be applied on the resv/resnull value, but for CHECK constraints we 2767 * need more pushups. 2768 */ 2769 foreach(l, constraint_ref->constraints) 2770 { 2771 DomainConstraintState *con = (DomainConstraintState *) lfirst(l); 2772 2773 scratch->d.domaincheck.constraintname = con->name; 2774 2775 switch (con->constrainttype) 2776 { 2777 case DOM_CONSTRAINT_NOTNULL: 2778 scratch->opcode = EEOP_DOMAIN_NOTNULL; 2779 ExprEvalPushStep(state, scratch); 2780 break; 2781 case DOM_CONSTRAINT_CHECK: 2782 /* Allocate workspace for CHECK output if we didn't yet */ 2783 if (scratch->d.domaincheck.checkvalue == NULL) 2784 { 2785 scratch->d.domaincheck.checkvalue = 2786 (Datum *) palloc(sizeof(Datum)); 2787 scratch->d.domaincheck.checknull = 2788 (bool *) palloc(sizeof(bool)); 2789 } 2790 2791 /* 2792 * If first time through, determine where CoerceToDomainValue 2793 * nodes should read from. 2794 */ 2795 if (domainval == NULL) 2796 { 2797 /* 2798 * Since value might be read multiple times, force to R/O 2799 * - but only if it could be an expanded datum. 2800 */ 2801 if (get_typlen(ctest->resulttype) == -1) 2802 { 2803 /* Yes, so make output workspace for MAKE_READONLY */ 2804 domainval = (Datum *) palloc(sizeof(Datum)); 2805 domainnull = (bool *) palloc(sizeof(bool)); 2806 2807 /* Emit MAKE_READONLY */ 2808 scratch2.opcode = EEOP_MAKE_READONLY; 2809 scratch2.resvalue = domainval; 2810 scratch2.resnull = domainnull; 2811 scratch2.d.make_readonly.value = resv; 2812 scratch2.d.make_readonly.isnull = resnull; 2813 ExprEvalPushStep(state, &scratch2); 2814 } 2815 else 2816 { 2817 /* No, so it's fine to read from resv/resnull */ 2818 domainval = resv; 2819 domainnull = resnull; 2820 } 2821 } 2822 2823 /* 2824 * Set up value to be returned by CoerceToDomainValue nodes. 2825 * We must save and restore innermost_domainval/null fields, 2826 * in case this node is itself within a check expression for 2827 * another domain. 2828 */ 2829 save_innermost_domainval = state->innermost_domainval; 2830 save_innermost_domainnull = state->innermost_domainnull; 2831 state->innermost_domainval = domainval; 2832 state->innermost_domainnull = domainnull; 2833 2834 /* evaluate check expression value */ 2835 ExecInitExprRec(con->check_expr, state, 2836 scratch->d.domaincheck.checkvalue, 2837 scratch->d.domaincheck.checknull); 2838 2839 state->innermost_domainval = save_innermost_domainval; 2840 state->innermost_domainnull = save_innermost_domainnull; 2841 2842 /* now test result */ 2843 scratch->opcode = EEOP_DOMAIN_CHECK; 2844 ExprEvalPushStep(state, scratch); 2845 2846 break; 2847 default: 2848 elog(ERROR, "unrecognized constraint type: %d", 2849 (int) con->constrainttype); 2850 break; 2851 } 2852 } 2853 } 2854 2855 /* 2856 * Build transition/combine function invocations for all aggregate transition 2857 * / combination function invocations in a grouping sets phase. This has to 2858 * invoke all sort based transitions in a phase (if doSort is true), all hash 2859 * based transitions (if doHash is true), or both (both true). 2860 * 2861 * The resulting expression will, for each set of transition values, first 2862 * check for filters, evaluate aggregate input, check that that input is not 2863 * NULL for a strict transition function, and then finally invoke the 2864 * transition for each of the concurrently computed grouping sets. 2865 */ 2866 ExprState * 2867 ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, 2868 bool doSort, bool doHash) 2869 { 2870 ExprState *state = makeNode(ExprState); 2871 PlanState *parent = &aggstate->ss.ps; 2872 ExprEvalStep scratch = {0}; 2873 int transno = 0; 2874 int setoff = 0; 2875 bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit); 2876 LastAttnumInfo deform = {0, 0, 0}; 2877 2878 state->expr = (Expr *) aggstate; 2879 state->parent = parent; 2880 2881 scratch.resvalue = &state->resvalue; 2882 scratch.resnull = &state->resnull; 2883 2884 /* 2885 * First figure out which slots, and how many columns from each, we're 2886 * going to need. 2887 */ 2888 for (transno = 0; transno < aggstate->numtrans; transno++) 2889 { 2890 AggStatePerTrans pertrans = &aggstate->pertrans[transno]; 2891 2892 get_last_attnums_walker((Node *) pertrans->aggref->aggdirectargs, 2893 &deform); 2894 get_last_attnums_walker((Node *) pertrans->aggref->args, 2895 &deform); 2896 get_last_attnums_walker((Node *) pertrans->aggref->aggorder, 2897 &deform); 2898 get_last_attnums_walker((Node *) pertrans->aggref->aggdistinct, 2899 &deform); 2900 get_last_attnums_walker((Node *) pertrans->aggref->aggfilter, 2901 &deform); 2902 } 2903 ExecPushExprSlots(state, &deform); 2904 2905 /* 2906 * Emit instructions for each transition value / grouping set combination. 2907 */ 2908 for (transno = 0; transno < aggstate->numtrans; transno++) 2909 { 2910 AggStatePerTrans pertrans = &aggstate->pertrans[transno]; 2911 int argno; 2912 int setno; 2913 FunctionCallInfo trans_fcinfo = &pertrans->transfn_fcinfo; 2914 ListCell *arg; 2915 ListCell *bail; 2916 List *adjust_bailout = NIL; 2917 bool *strictnulls = NULL; 2918 2919 /* 2920 * If filter present, emit. Do so before evaluating the input, to 2921 * avoid potentially unneeded computations, or even worse, unintended 2922 * side-effects. When combining, all the necessary filtering has 2923 * already been done. 2924 */ 2925 if (pertrans->aggref->aggfilter && !isCombine) 2926 { 2927 /* evaluate filter expression */ 2928 ExecInitExprRec(pertrans->aggref->aggfilter, state, 2929 &state->resvalue, &state->resnull); 2930 /* and jump out if false */ 2931 scratch.opcode = EEOP_JUMP_IF_NOT_TRUE; 2932 scratch.d.jump.jumpdone = -1; /* adjust later */ 2933 ExprEvalPushStep(state, &scratch); 2934 adjust_bailout = lappend_int(adjust_bailout, 2935 state->steps_len - 1); 2936 } 2937 2938 /* 2939 * Evaluate arguments to aggregate/combine function. 2940 */ 2941 argno = 0; 2942 if (isCombine) 2943 { 2944 /* 2945 * Combining two aggregate transition values. Instead of directly 2946 * coming from a tuple the input is a, potentially deserialized, 2947 * transition value. 2948 */ 2949 TargetEntry *source_tle; 2950 2951 Assert(pertrans->numSortCols == 0); 2952 Assert(list_length(pertrans->aggref->args) == 1); 2953 2954 strictnulls = trans_fcinfo->argnull + 1; 2955 source_tle = (TargetEntry *) linitial(pertrans->aggref->args); 2956 2957 /* 2958 * deserialfn_oid will be set if we must deserialize the input 2959 * state before calling the combine function. 2960 */ 2961 if (!OidIsValid(pertrans->deserialfn_oid)) 2962 { 2963 /* 2964 * Start from 1, since the 0th arg will be the transition 2965 * value 2966 */ 2967 ExecInitExprRec(source_tle->expr, state, 2968 &trans_fcinfo->arg[argno + 1], 2969 &trans_fcinfo->argnull[argno + 1]); 2970 } 2971 else 2972 { 2973 FunctionCallInfo ds_fcinfo = &pertrans->deserialfn_fcinfo; 2974 2975 /* evaluate argument */ 2976 ExecInitExprRec(source_tle->expr, state, 2977 &ds_fcinfo->arg[0], 2978 &ds_fcinfo->argnull[0]); 2979 2980 /* Dummy second argument for type-safety reasons */ 2981 ds_fcinfo->arg[1] = PointerGetDatum(NULL); 2982 ds_fcinfo->argnull[1] = false; 2983 2984 /* 2985 * Don't call a strict deserialization function with NULL 2986 * input 2987 */ 2988 if (pertrans->deserialfn.fn_strict) 2989 scratch.opcode = EEOP_AGG_STRICT_DESERIALIZE; 2990 else 2991 scratch.opcode = EEOP_AGG_DESERIALIZE; 2992 2993 scratch.d.agg_deserialize.aggstate = aggstate; 2994 scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo; 2995 scratch.d.agg_deserialize.jumpnull = -1; /* adjust later */ 2996 scratch.resvalue = &trans_fcinfo->arg[argno + 1]; 2997 scratch.resnull = &trans_fcinfo->argnull[argno + 1]; 2998 2999 ExprEvalPushStep(state, &scratch); 3000 /* don't add an adjustment unless the function is strict */ 3001 if (pertrans->deserialfn.fn_strict) 3002 adjust_bailout = lappend_int(adjust_bailout, 3003 state->steps_len - 1); 3004 3005 /* restore normal settings of scratch fields */ 3006 scratch.resvalue = &state->resvalue; 3007 scratch.resnull = &state->resnull; 3008 } 3009 argno++; 3010 } 3011 else if (pertrans->numSortCols == 0) 3012 { 3013 /* 3014 * Normal transition function without ORDER BY / DISTINCT. 3015 */ 3016 strictnulls = trans_fcinfo->argnull + 1; 3017 3018 foreach(arg, pertrans->aggref->args) 3019 { 3020 TargetEntry *source_tle = (TargetEntry *) lfirst(arg); 3021 3022 /* 3023 * Start from 1, since the 0th arg will be the transition 3024 * value 3025 */ 3026 ExecInitExprRec(source_tle->expr, state, 3027 &trans_fcinfo->arg[argno + 1], 3028 &trans_fcinfo->argnull[argno + 1]); 3029 argno++; 3030 } 3031 } 3032 else if (pertrans->numInputs == 1) 3033 { 3034 /* 3035 * DISTINCT and/or ORDER BY case, with a single column sorted on. 3036 */ 3037 TargetEntry *source_tle = 3038 (TargetEntry *) linitial(pertrans->aggref->args); 3039 3040 Assert(list_length(pertrans->aggref->args) == 1); 3041 3042 ExecInitExprRec(source_tle->expr, state, 3043 &state->resvalue, 3044 &state->resnull); 3045 strictnulls = &state->resnull; 3046 argno++; 3047 } 3048 else 3049 { 3050 /* 3051 * DISTINCT and/or ORDER BY case, with multiple columns sorted on. 3052 */ 3053 Datum *values = pertrans->sortslot->tts_values; 3054 bool *nulls = pertrans->sortslot->tts_isnull; 3055 3056 strictnulls = nulls; 3057 3058 foreach(arg, pertrans->aggref->args) 3059 { 3060 TargetEntry *source_tle = (TargetEntry *) lfirst(arg); 3061 3062 ExecInitExprRec(source_tle->expr, state, 3063 &values[argno], &nulls[argno]); 3064 argno++; 3065 } 3066 } 3067 Assert(pertrans->numInputs == argno); 3068 3069 /* 3070 * For a strict transfn, nothing happens when there's a NULL input; we 3071 * just keep the prior transValue. This is true for both plain and 3072 * sorted/distinct aggregates. 3073 */ 3074 if (trans_fcinfo->flinfo->fn_strict && pertrans->numTransInputs > 0) 3075 { 3076 scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK; 3077 scratch.d.agg_strict_input_check.nulls = strictnulls; 3078 scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */ 3079 scratch.d.agg_strict_input_check.nargs = pertrans->numTransInputs; 3080 ExprEvalPushStep(state, &scratch); 3081 adjust_bailout = lappend_int(adjust_bailout, 3082 state->steps_len - 1); 3083 } 3084 3085 /* 3086 * Call transition function (once for each concurrently evaluated 3087 * grouping set). Do so for both sort and hash based computations, as 3088 * applicable. 3089 */ 3090 setoff = 0; 3091 if (doSort) 3092 { 3093 int processGroupingSets = Max(phase->numsets, 1); 3094 3095 for (setno = 0; setno < processGroupingSets; setno++) 3096 { 3097 ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo, 3098 pertrans, transno, setno, setoff, false); 3099 setoff++; 3100 } 3101 } 3102 3103 if (doHash) 3104 { 3105 int numHashes = aggstate->num_hashes; 3106 3107 /* in MIXED mode, there'll be preceding transition values */ 3108 if (aggstate->aggstrategy != AGG_HASHED) 3109 setoff = aggstate->maxsets; 3110 else 3111 setoff = 0; 3112 3113 for (setno = 0; setno < numHashes; setno++) 3114 { 3115 ExecBuildAggTransCall(state, aggstate, &scratch, trans_fcinfo, 3116 pertrans, transno, setno, setoff, true); 3117 setoff++; 3118 } 3119 } 3120 3121 /* adjust early bail out jump target(s) */ 3122 foreach(bail, adjust_bailout) 3123 { 3124 ExprEvalStep *as = &state->steps[lfirst_int(bail)]; 3125 3126 if (as->opcode == EEOP_JUMP_IF_NOT_TRUE) 3127 { 3128 Assert(as->d.jump.jumpdone == -1); 3129 as->d.jump.jumpdone = state->steps_len; 3130 } 3131 else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK) 3132 { 3133 Assert(as->d.agg_strict_input_check.jumpnull == -1); 3134 as->d.agg_strict_input_check.jumpnull = state->steps_len; 3135 } 3136 else if (as->opcode == EEOP_AGG_STRICT_DESERIALIZE) 3137 { 3138 Assert(as->d.agg_deserialize.jumpnull == -1); 3139 as->d.agg_deserialize.jumpnull = state->steps_len; 3140 } 3141 } 3142 } 3143 3144 scratch.resvalue = NULL; 3145 scratch.resnull = NULL; 3146 scratch.opcode = EEOP_DONE; 3147 ExprEvalPushStep(state, &scratch); 3148 3149 ExecReadyExpr(state); 3150 3151 return state; 3152 } 3153 3154 /* 3155 * Build transition/combine function invocation for a single transition 3156 * value. This is separated from ExecBuildAggTrans() because there are 3157 * multiple callsites (hash and sort in some grouping set cases). 3158 */ 3159 static void 3160 ExecBuildAggTransCall(ExprState *state, AggState *aggstate, 3161 ExprEvalStep *scratch, 3162 FunctionCallInfo fcinfo, AggStatePerTrans pertrans, 3163 int transno, int setno, int setoff, bool ishash) 3164 { 3165 int adjust_init_jumpnull = -1; 3166 int adjust_strict_jumpnull = -1; 3167 ExprContext *aggcontext; 3168 3169 if (ishash) 3170 aggcontext = aggstate->hashcontext; 3171 else 3172 aggcontext = aggstate->aggcontexts[setno]; 3173 3174 /* 3175 * If the initial value for the transition state doesn't exist in the 3176 * pg_aggregate table then we will let the first non-NULL value returned 3177 * from the outer procNode become the initial value. (This is useful for 3178 * aggregates like max() and min().) The noTransValue flag signals that we 3179 * still need to do this. 3180 */ 3181 if (pertrans->numSortCols == 0 && 3182 fcinfo->flinfo->fn_strict && 3183 pertrans->initValueIsNull) 3184 { 3185 scratch->opcode = EEOP_AGG_INIT_TRANS; 3186 scratch->d.agg_init_trans.aggstate = aggstate; 3187 scratch->d.agg_init_trans.pertrans = pertrans; 3188 scratch->d.agg_init_trans.setno = setno; 3189 scratch->d.agg_init_trans.setoff = setoff; 3190 scratch->d.agg_init_trans.transno = transno; 3191 scratch->d.agg_init_trans.aggcontext = aggcontext; 3192 scratch->d.agg_init_trans.jumpnull = -1; /* adjust later */ 3193 ExprEvalPushStep(state, scratch); 3194 3195 /* see comment about jumping out below */ 3196 adjust_init_jumpnull = state->steps_len - 1; 3197 } 3198 3199 if (pertrans->numSortCols == 0 && 3200 fcinfo->flinfo->fn_strict) 3201 { 3202 scratch->opcode = EEOP_AGG_STRICT_TRANS_CHECK; 3203 scratch->d.agg_strict_trans_check.aggstate = aggstate; 3204 scratch->d.agg_strict_trans_check.setno = setno; 3205 scratch->d.agg_strict_trans_check.setoff = setoff; 3206 scratch->d.agg_strict_trans_check.transno = transno; 3207 scratch->d.agg_strict_trans_check.jumpnull = -1; /* adjust later */ 3208 ExprEvalPushStep(state, scratch); 3209 3210 /* 3211 * Note, we don't push into adjust_bailout here - those jump to the 3212 * end of all transition value computations. Here a single transition 3213 * value is NULL, so just skip processing the individual value. 3214 */ 3215 adjust_strict_jumpnull = state->steps_len - 1; 3216 } 3217 3218 /* invoke appropriate transition implementation */ 3219 if (pertrans->numSortCols == 0 && pertrans->transtypeByVal) 3220 scratch->opcode = EEOP_AGG_PLAIN_TRANS_BYVAL; 3221 else if (pertrans->numSortCols == 0) 3222 scratch->opcode = EEOP_AGG_PLAIN_TRANS; 3223 else if (pertrans->numInputs == 1) 3224 scratch->opcode = EEOP_AGG_ORDERED_TRANS_DATUM; 3225 else 3226 scratch->opcode = EEOP_AGG_ORDERED_TRANS_TUPLE; 3227 3228 scratch->d.agg_trans.aggstate = aggstate; 3229 scratch->d.agg_trans.pertrans = pertrans; 3230 scratch->d.agg_trans.setno = setno; 3231 scratch->d.agg_trans.setoff = setoff; 3232 scratch->d.agg_trans.transno = transno; 3233 scratch->d.agg_trans.aggcontext = aggcontext; 3234 ExprEvalPushStep(state, scratch); 3235 3236 /* adjust jumps so they jump till after transition invocation */ 3237 if (adjust_init_jumpnull != -1) 3238 { 3239 ExprEvalStep *as = &state->steps[adjust_init_jumpnull]; 3240 3241 Assert(as->d.agg_init_trans.jumpnull == -1); 3242 as->d.agg_init_trans.jumpnull = state->steps_len; 3243 } 3244 if (adjust_strict_jumpnull != -1) 3245 { 3246 ExprEvalStep *as = &state->steps[adjust_strict_jumpnull]; 3247 3248 Assert(as->d.agg_strict_trans_check.jumpnull == -1); 3249 as->d.agg_strict_trans_check.jumpnull = state->steps_len; 3250 } 3251 } 3252 3253 /* 3254 * Build equality expression that can be evaluated using ExecQual(), returning 3255 * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e 3256 * two nulls match, a null and a not-null don't match. 3257 * 3258 * desc: tuple descriptor of the to-be-compared tuples 3259 * numCols: the number of attributes to be examined 3260 * keyColIdx: array of attribute column numbers 3261 * eqFunctions: array of function oids of the equality functions to use 3262 * parent: parent executor node 3263 */ 3264 ExprState * 3265 ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, 3266 int numCols, 3267 AttrNumber *keyColIdx, 3268 Oid *eqfunctions, 3269 PlanState *parent) 3270 { 3271 ExprState *state = makeNode(ExprState); 3272 ExprEvalStep scratch = {0}; 3273 int natt; 3274 int maxatt = -1; 3275 List *adjust_jumps = NIL; 3276 ListCell *lc; 3277 3278 /* 3279 * When no columns are actually compared, the result's always true. See 3280 * special case in ExecQual(). 3281 */ 3282 if (numCols == 0) 3283 return NULL; 3284 3285 state->expr = NULL; 3286 state->flags = EEO_FLAG_IS_QUAL; 3287 state->parent = parent; 3288 3289 scratch.resvalue = &state->resvalue; 3290 scratch.resnull = &state->resnull; 3291 3292 /* compute max needed attribute */ 3293 for (natt = 0; natt < numCols; natt++) 3294 { 3295 int attno = keyColIdx[natt]; 3296 3297 if (attno > maxatt) 3298 maxatt = attno; 3299 } 3300 Assert(maxatt >= 0); 3301 3302 /* push deform steps */ 3303 scratch.opcode = EEOP_INNER_FETCHSOME; 3304 scratch.d.fetch.last_var = maxatt; 3305 scratch.d.fetch.known_desc = ldesc; 3306 ExprEvalPushStep(state, &scratch); 3307 3308 scratch.opcode = EEOP_OUTER_FETCHSOME; 3309 scratch.d.fetch.last_var = maxatt; 3310 scratch.d.fetch.known_desc = rdesc; 3311 ExprEvalPushStep(state, &scratch); 3312 3313 /* 3314 * Start comparing at the last field (least significant sort key). That's 3315 * the most likely to be different if we are dealing with sorted input. 3316 */ 3317 for (natt = numCols; --natt >= 0;) 3318 { 3319 int attno = keyColIdx[natt]; 3320 Form_pg_attribute latt = TupleDescAttr(ldesc, attno - 1); 3321 Form_pg_attribute ratt = TupleDescAttr(rdesc, attno - 1); 3322 Oid foid = eqfunctions[natt]; 3323 FmgrInfo *finfo; 3324 FunctionCallInfo fcinfo; 3325 AclResult aclresult; 3326 3327 /* Check permission to call function */ 3328 aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE); 3329 if (aclresult != ACLCHECK_OK) 3330 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(foid)); 3331 3332 InvokeFunctionExecuteHook(foid); 3333 3334 /* Set up the primary fmgr lookup information */ 3335 finfo = palloc0(sizeof(FmgrInfo)); 3336 fcinfo = palloc0(sizeof(FunctionCallInfoData)); 3337 fmgr_info(foid, finfo); 3338 fmgr_info_set_expr(NULL, finfo); 3339 InitFunctionCallInfoData(*fcinfo, finfo, 2, 3340 InvalidOid, NULL, NULL); 3341 3342 /* left arg */ 3343 scratch.opcode = EEOP_INNER_VAR; 3344 scratch.d.var.attnum = attno - 1; 3345 scratch.d.var.vartype = latt->atttypid; 3346 scratch.resvalue = &fcinfo->arg[0]; 3347 scratch.resnull = &fcinfo->argnull[0]; 3348 ExprEvalPushStep(state, &scratch); 3349 3350 /* right arg */ 3351 scratch.opcode = EEOP_OUTER_VAR; 3352 scratch.d.var.attnum = attno - 1; 3353 scratch.d.var.vartype = ratt->atttypid; 3354 scratch.resvalue = &fcinfo->arg[1]; 3355 scratch.resnull = &fcinfo->argnull[1]; 3356 ExprEvalPushStep(state, &scratch); 3357 3358 /* evaluate distinctness */ 3359 scratch.opcode = EEOP_NOT_DISTINCT; 3360 scratch.d.func.finfo = finfo; 3361 scratch.d.func.fcinfo_data = fcinfo; 3362 scratch.d.func.fn_addr = finfo->fn_addr; 3363 scratch.d.func.nargs = 2; 3364 scratch.resvalue = &state->resvalue; 3365 scratch.resnull = &state->resnull; 3366 ExprEvalPushStep(state, &scratch); 3367 3368 /* then emit EEOP_QUAL to detect if result is false (or null) */ 3369 scratch.opcode = EEOP_QUAL; 3370 scratch.d.qualexpr.jumpdone = -1; 3371 scratch.resvalue = &state->resvalue; 3372 scratch.resnull = &state->resnull; 3373 ExprEvalPushStep(state, &scratch); 3374 adjust_jumps = lappend_int(adjust_jumps, 3375 state->steps_len - 1); 3376 } 3377 3378 /* adjust jump targets */ 3379 foreach(lc, adjust_jumps) 3380 { 3381 ExprEvalStep *as = &state->steps[lfirst_int(lc)]; 3382 3383 Assert(as->opcode == EEOP_QUAL); 3384 Assert(as->d.qualexpr.jumpdone == -1); 3385 as->d.qualexpr.jumpdone = state->steps_len; 3386 } 3387 3388 scratch.resvalue = NULL; 3389 scratch.resnull = NULL; 3390 scratch.opcode = EEOP_DONE; 3391 ExprEvalPushStep(state, &scratch); 3392 3393 ExecReadyExpr(state); 3394 3395 return state; 3396 } 3397