/* *SetOpStatePerGroupData-per-groupworkingstate * *InSETOP_SORTEDmode,weneedonlyoneofthesestructs,andit'sjusta *localinsetop_retrieve_sorted.InSETOP_HASHEDmode,thehashtable *containsoneoftheseforeachtuplegroup.
*/ typedefstruct SetOpStatePerGroupData
{
int64 numLeft; /* number of left-input dups in group */
int64 numRight; /* number of right-input dups in group */
} SetOpStatePerGroupData;
/* Otherwise, we're done if we are out of groups */ if (node->setop_done) return NULL;
/* Fetch the next tuple group according to the correct strategy */ if (plannode->strategy == SETOP_HASHED)
{ if (!node->table_filled)
setop_fill_hash_table(node); return setop_retrieve_hash_table(node);
} else return setop_retrieve_sorted(node);
}
/* *Fetchtherestofthecurrentinnergroup,ifwedidn'talready.
*/ if (setopstate->rightInput.needGroup)
setop_load_group(&setopstate->rightInput, innerPlan, setopstate);
/* *Determinewhetherwehavematchinggroupsonbothsides(thisis *basicallylikethecorelogicofamergejoin).
*/ if (setopstate->rightInput.numTuples == 0)
cmpresult = -1; /* as though left input is lesser */ else
cmpresult = setop_compare_slots(setopstate->leftInput.firstTupleSlot,
setopstate->rightInput.firstTupleSlot,
setopstate);
if (cmpresult < 0)
{ /* Left group is first, and has no right matches */
pergroup.numLeft = setopstate->leftInput.numTuples;
pergroup.numRight = 0; /* We'll need another left group next time */
setopstate->leftInput.needGroup = true;
} elseif (cmpresult == 0)
{ /* We have matching groups */
pergroup.numLeft = setopstate->leftInput.numTuples;
pergroup.numRight = setopstate->rightInput.numTuples; /* We'll need to read from both sides next time */
setopstate->leftInput.needGroup = true;
setopstate->rightInput.needGroup = true;
} else
{ /* Right group has no left matches, so we can ignore it */
setopstate->rightInput.needGroup = true; continue;
}
/* If we've exhausted this child plan, report an empty group */ if (TupIsNull(input->nextTupleSlot))
{
ExecClearTuple(input->firstTupleSlot);
input->numTuples = 0; return;
}
/* Make a local copy of the first tuple for comparisons */
ExecStoreMinimalTuple(ExecCopySlotMinimalTuple(input->nextTupleSlot),
input->firstTupleSlot, true); /* and count it */
input->numTuples = 1;
/* Scan till we find the end-of-group */ for (;;)
{ int cmpresult;
/* Get next input tuple, if there is one */
input->nextTupleSlot = ExecProcNode(inputPlan); if (TupIsNull(input->nextTupleSlot)) break;
/* There is; does it belong to same group as firstTuple? */
cmpresult = setop_compare_slots(input->firstTupleSlot,
input->nextTupleSlot,
setopstate);
Assert(cmpresult <= 0); /* else input is mis-sorted */ if (cmpresult != 0) break;
/* Still in same group, so count this tuple */
input->numTuples++;
}
}
/* *Comparethetuplesinthetwogivenslots.
*/ staticint
setop_compare_slots(TupleTableSlot *s1, TupleTableSlot *s2,
SetOpState *setopstate)
{ /* We'll often need to fetch all the columns, so just do it */
slot_getallattrs(s1);
slot_getallattrs(s2); for (int nkey = 0; nkey < setopstate->numCols; nkey++)
{
SortSupport sortKey = setopstate->sortKeys + nkey;
AttrNumber attno = sortKey->ssup_attno;
Datum datum1 = s1->tts_values[attno - 1],
datum2 = s2->tts_values[attno - 1]; bool isNull1 = s1->tts_isnull[attno - 1],
isNull2 = s2->tts_isnull[attno - 1]; int compare;
outerslot = ExecProcNode(outerPlan); if (TupIsNull(outerslot)) break;
have_tuples = true;
/* Find or build hashtable entry for this tuple's group */
entry = LookupTupleHashEntry(hashtable,
outerslot,
&isnew, NULL);
pergroup = TupleHashEntryGetAdditional(hashtable, entry); /* If new tuple group, initialize counts to zero */ if (isnew)
{
pergroup->numLeft = 0;
pergroup->numRight = 0;
}
/* Advance the counts */
pergroup->numLeft++;
/* Must reset expression context after each hashtable lookup */
ResetExprContext(econtext);
}
/* Release any hashtable storage */ if (node->tableContext)
MemoryContextReset(node->tableContext);
/* And rebuild an empty hashtable */
ResetTupleHashTable(node->hashtable);
node->table_filled = false;
} else
{ /* Need to re-read first input from each side */
node->need_init = true;
}
/* *ifchgParamofsubnodeisnotnullthenplanwillbere-scannedby *firstExecProcNode.
*/ if (outerPlan->chgParam == NULL)
ExecReScan(outerPlan); if (innerPlan->chgParam == NULL)
ExecReScan(innerPlan);
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.16Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.