in Arriba/Arriba/Model/Query/DistinctQuery.cs [179:306]
public override Array GetUniqueValuesFromColumn(IColumn column, ShortSet whereSet, int count, out bool allValuesReturned)
{
if (count <= 0)
{
allValuesReturned = false;
return new T[0];
}
IColumn<T> typedColumn = (IColumn<T>)column;
// Boolean columns aren't sorted - just check true and false
if (typedColumn is BooleanColumn)
{
int countBefore = whereSet.Count();
if (countBefore == 0)
{
allValuesReturned = true;
return new bool[0];
}
// Filter to the set of values with the column 'true'
BooleanColumn bc = (BooleanColumn)typedColumn;
ShortSet trueSet = new ShortSet(bc.Count);
bc.TryWhere(Operator.Equals, true, trueSet, null);
whereSet.And(trueSet);
// Determine the count which were true and false matching the query
int countWhichAreTrue = whereSet.Count();
int countWhichAreFalse = countBefore - countWhichAreTrue;
allValuesReturned = true;
if (countWhichAreTrue > 0 && countWhichAreFalse > 0)
{
// If both existed and only one value was requested, return the value which more items had
if (count == 1)
{
allValuesReturned = false;
return new bool[] { (countWhichAreTrue > countWhichAreFalse) };
}
return new bool[] { true, false };
}
else if (countWhichAreTrue > 0)
{
return new bool[] { true };
}
else
{
return new bool[] { false };
}
}
// Get all LIDs in sorted order
IList<ushort> sortedIndexes;
int sortedIndexesCount;
if (!column.TryGetSortedIndexes(out sortedIndexes, out sortedIndexesCount)) throw new ArribaException(String.Format("Unable to sort by non-sorted column {0}", column.Name));
int uniqueValuesCount = 0;
T prevValue = default(T);
// Count the # of unique items
for (int lastSortedIndex = 0; lastSortedIndex < sortedIndexesCount; ++lastSortedIndex)
{
ushort itemLID = sortedIndexes[lastSortedIndex];
// Find the next LID which is still in our match set
if (whereSet.Contains(itemLID))
{
T currentValue = typedColumn[itemLID];
bool sameValue = prevValue.Equals(currentValue);
if (uniqueValuesCount != 0 && sameValue == true)
{
continue;
}
uniqueValuesCount++;
prevValue = currentValue;
// If we have enough matches, stop
// (*after computing remaining items to tell if we got all of them*)
if (uniqueValuesCount == count)
{
break;
}
}
}
T[] uniqueValues = new T[uniqueValuesCount];
ushort uniqueValuesIndex = 0;
allValuesReturned = true; // until proven false
// Retrieve all of the unique items
for (int lastSortedIndex = 0; lastSortedIndex < sortedIndexesCount; ++lastSortedIndex)
{
ushort itemLID = sortedIndexes[lastSortedIndex];
// Find the next LID which is still in our match set
if (whereSet.Contains(itemLID))
{
T currentValue = typedColumn[itemLID];
bool sameValue = prevValue.Equals(currentValue);
if (uniqueValuesIndex != 0 && sameValue == true)
{
continue;
}
uniqueValues[uniqueValuesIndex++] = currentValue;
prevValue = currentValue;
// If we have enough matches, stop
// (*after computing remaining items to tell if we got all of them*)
if (uniqueValuesIndex == count)
{
ushort lastItemLID = sortedIndexes[sortedIndexesCount - 1];
T lastValue = typedColumn[lastItemLID];
allValuesReturned = currentValue.Equals(lastValue);
break;
}
}
}
return uniqueValues;
}