| 663 | */ |
| 664 | |
| 665 | MotionState * |
| 666 | ExecInitMotion(Motion *node, EState *estate, int eflags) |
| 667 | { |
| 668 | MotionState *motionstate = NULL; |
| 669 | TupleDesc tupDesc; |
| 670 | ExecSlice *sendSlice; |
| 671 | ExecSlice *recvSlice; |
| 672 | SliceTable *sliceTable = estate->es_sliceTable; |
| 673 | PlanState *outerPlan; |
| 674 | int parentIndex; |
| 675 | |
| 676 | /* |
| 677 | * If GDD is enabled, the lock of table may downgrade to RowExclusiveLock, |
| 678 | * (see CdbTryOpenRelation function), then EPQ would be triggered, EPQ will |
| 679 | * execute the subplan in the executor, so it will create a new EState, |
| 680 | * but there are no slice tables in the new EState and we can not AssignGangs |
| 681 | * on the QE. In this case, we raise an error. |
| 682 | */ |
| 683 | if (estate->es_epq_active) |
| 684 | ereport(ERROR, |
| 685 | (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), |
| 686 | errmsg("EvalPlanQual can not handle subPlan with Motion node"))); |
| 687 | |
| 688 | Assert(node->motionID > 0); |
| 689 | AssertImply(node->senderSliceInfo && node->senderSliceInfo->parallel_workers <= 1, |
| 690 | node->motionID < sliceTable->numSlices); |
| 691 | AssertImply(node->motionType == MOTIONTYPE_HASH, node->numHashSegments > 0); |
| 692 | |
| 693 | parentIndex = estate->currentSliceId; |
| 694 | estate->currentSliceId = node->motionID; |
| 695 | |
| 696 | /* |
| 697 | * create state structure |
| 698 | */ |
| 699 | motionstate = makeNode(MotionState); |
| 700 | motionstate->ps.plan = (Plan *) node; |
| 701 | motionstate->ps.state = estate; |
| 702 | motionstate->ps.ExecProcNode = ExecMotion; |
| 703 | motionstate->mstype = MOTIONSTATE_NONE; |
| 704 | motionstate->stopRequested = false; |
| 705 | motionstate->hashExprs = NIL; |
| 706 | motionstate->cdbhash = NULL; |
| 707 | motionstate->cdbhashworkers = NULL; |
| 708 | |
| 709 | /* Look up the sending and receiving gang's slice table entries. */ |
| 710 | sendSlice = &sliceTable->slices[node->motionID]; |
| 711 | Assert(sendSlice->sliceIndex == node->motionID); |
| 712 | recvSlice = &sliceTable->slices[parentIndex]; |
| 713 | Assert(parentIndex == sendSlice->parentIndex); |
| 714 | |
| 715 | /* QD must fill in the global slice table. */ |
| 716 | if (Gp_role == GP_ROLE_DISPATCH) |
| 717 | { |
| 718 | MemoryContext oldcxt = MemoryContextSwitchTo(estate->es_query_cxt); |
| 719 | |
| 720 | if (node->motionType == MOTIONTYPE_GATHER || |
| 721 | node->motionType == MOTIONTYPE_GATHER_SINGLE) |
| 722 | { |
no test coverage detected