bool compareDatum(Datum value1, Datum value2, Oid typeOid){ bool res = false; switch(typeOid){ case 20: case 21: case 23: { res = datumIsEqual(value1, value2, true, (typeOid==20)? 8 : ((typeOid==21)? 2 : 4)); return res; } case 700: case 701: { res = datumIsEqual(value1, value2, false, (typeOid==700)? 4 : 8 ); return res; } case 1042: { res = DirectFunctionCall2(bpchareq, value1, value2); return res; } case 1043: { res = DirectFunctionCall2(texteq, value1, value2); return res; } default: return false; } }
/* * Compare the tuple and slot and check if they have equal values. * * We use binary datum comparison which might return false negatives but * that's the best we can do here as there may be multiple notions of * equality for the data types and table columns don't specify which one * to use. */ static bool tuple_equals_slot(TupleDesc desc, HeapTuple tup, TupleTableSlot *slot) { Datum values[MaxTupleAttributeNumber]; bool isnull[MaxTupleAttributeNumber]; int attrnum; Form_pg_attribute att; heap_deform_tuple(tup, desc, values, isnull); /* Check equality of the attributes. */ for (attrnum = 0; attrnum < desc->natts; attrnum++) { /* * If one value is NULL and other is not, then they are certainly not * equal */ if (isnull[attrnum] != slot->tts_isnull[attrnum]) return false; /* * If both are NULL, they can be considered equal. */ if (isnull[attrnum]) continue; att = desc->attrs[attrnum]; if (!datumIsEqual(values[attrnum], slot->tts_values[attrnum], att->attbyval, att->attlen)) return false; } return true; }
/* * UpdateTopnArray is a helper function for the unions and inserts. It takes * given item and its frequency. If the item is not in the top-n array, it tries * to insert new item. If there is place in the top-n array, it insert directly. * Otherwise, it compares its frequency with the minimum of current items in the * array and updates top-n array if new frequency is bigger. */ static ArrayType * UpdateTopnArray(CmsTopn *cmsTopn, Datum candidateItem, TypeCacheEntry *itemTypeCacheEntry, Frequency itemFrequency, bool *topnArrayUpdated) { ArrayType *currentTopnArray = TopnArray(cmsTopn); ArrayType *updatedTopnArray = NULL; int16 itemTypeLength = itemTypeCacheEntry->typlen; bool itemTypeByValue = itemTypeCacheEntry->typbyval; char itemTypeAlignment = itemTypeCacheEntry->typalign; Frequency minOfNewTopnItems = MAX_FREQUENCY; bool candidateAlreadyInArray = false; int candidateIndex = -1; int currentArrayLength = ARR_DIMS(currentTopnArray)[0]; if (currentArrayLength == 0) { Oid itemType = itemTypeCacheEntry->type_id; if (itemTypeCacheEntry->typtype == TYPTYPE_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("composite types are not supported"))); } currentTopnArray = construct_empty_array(itemType); } /* * If item frequency is smaller than min frequency of old top-n items, * it cannot be in the top-n items and we insert it only if there is place. * Otherwise, we need to check new minimum and whether it is in the top-n. */ if (itemFrequency <= cmsTopn->minFrequencyOfTopnItems) { if (currentArrayLength < cmsTopn->topnItemCount) { candidateIndex = currentArrayLength + 1; minOfNewTopnItems = itemFrequency; } } else { ArrayIterator iterator = array_create_iterator(currentTopnArray, 0); Datum topnItem = 0; int topnItemIndex = 1; int minItemIndex = 1; bool hasMoreItem = false; bool isNull = false; /* * Find the top-n item with minimum frequency to replace it with candidate * item. */ hasMoreItem = array_iterate(iterator, &topnItem, &isNull); while (hasMoreItem) { Frequency topnItemFrequency = 0; /* check if we already have this item in top-n array */ candidateAlreadyInArray = datumIsEqual(topnItem, candidateItem, itemTypeByValue, itemTypeLength); if (candidateAlreadyInArray) { minItemIndex = -1; break; } /* keep track of minumum frequency item in the top-n array */ topnItemFrequency = CmsTopnEstimateItemFrequency(cmsTopn, topnItem, itemTypeCacheEntry); if (topnItemFrequency < minOfNewTopnItems) { minOfNewTopnItems = topnItemFrequency; minItemIndex = topnItemIndex; } hasMoreItem = array_iterate(iterator, &topnItem, &isNull); topnItemIndex++; } /* if new item is not in the top-n and there is place, insert the item */ if (!candidateAlreadyInArray && currentArrayLength < cmsTopn->topnItemCount) { minItemIndex = currentArrayLength + 1; minOfNewTopnItems = Min(minOfNewTopnItems, itemFrequency); } candidateIndex = minItemIndex; } /* * If it is not in the top-n structure and its frequency bigger than minimum * put into top-n instead of the item which has minimum frequency. If it is * in top-n or not frequent items, do not change anything. */ if (!candidateAlreadyInArray && minOfNewTopnItems <= itemFrequency) { updatedTopnArray = array_set(currentTopnArray, 1, &candidateIndex, candidateItem, false, -1, itemTypeLength, itemTypeByValue, itemTypeAlignment); cmsTopn->minFrequencyOfTopnItems = minOfNewTopnItems; *topnArrayUpdated = true; } else { updatedTopnArray = currentTopnArray; *topnArrayUpdated = false; } return updatedTopnArray; }