/* ---------------------------------------------------------------- * ExternalNext * * This is a workhorse for ExecExtScan * ---------------------------------------------------------------- */ static TupleTableSlot * ExternalNext(ExternalScanState *node) { HeapTuple tuple; FileScanDesc scandesc; Index scanrelid; EState *estate; ScanDirection direction; TupleTableSlot *slot; /* * get information from the estate and scan state */ estate = node->ss.ps.state; scandesc = node->ess_ScanDesc; scanrelid = ((ExternalScan *) node->ss.ps.plan)->scan.scanrelid; direction = estate->es_direction; slot = node->ss.ss_ScanTupleSlot; /* * get the next tuple from the file access methods */ tuple = external_getnext(scandesc, direction); /* * save the tuple and the buffer returned to us by the access methods in * our scan tuple slot and return the slot. Note: we pass 'false' because * tuples returned by heap_getnext() are pointers onto disk pages and were * not created with palloc() and so should not be pfree()'d. Note also * that ExecStoreTuple will increment the refcount of the buffer; the * refcount will not be dropped until the tuple table slot is cleared. */ if (tuple) { Gpmon_M_Incr_Rows_Out(GpmonPktFromExtScanState(node)); CheckSendPlanStateGpmonPkt(&node->ss.ps); ExecStoreGenericTuple(tuple, slot, true); /* * CDB: Label each row with a synthetic ctid if needed for subquery dedup. */ if (node->cdb_want_ctid && !TupIsNull(slot)) { slot_set_ctid_from_fake(slot, &node->cdb_fake_ctid); } } else { ExecClearTuple(slot); if (!node->ss.ps.delayEagerFree) { ExecEagerFreeExternalScan(node); } } return slot; }
/* ---------------------------------------------------------------- * SubqueryNext * * This is a workhorse for ExecSubqueryScan * ---------------------------------------------------------------- */ static TupleTableSlot * SubqueryNext(SubqueryScanState *node) { TupleTableSlot *slot; /* * We need not support EvalPlanQual here, since we are not scanning a real * relation. */ /* * Get the next tuple from the sub-query. */ slot = ExecProcNode(node->subplan); /* * We just overwrite our ScanTupleSlot with the subplan's result slot, * rather than expending the cycles for ExecCopySlot(). */ node->ss.ss_ScanTupleSlot = slot; /* * CDB: Label each row with a synthetic ctid if needed for subquery dedup. */ if (node->cdb_want_ctid && !TupIsNull(slot)) { slot_set_ctid_from_fake(slot, &node->cdb_fake_ctid); } if (!TupIsNull(slot)) { Gpmon_M_Incr_Rows_Out(GpmonPktFromSubqueryScanState(node)); CheckSendPlanStateGpmonPkt(&node->ss.ps); } return slot; }