2020-11-11 16:51:59 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundFrontendQuery.h"
2021-12-07 16:32:38 -05:00
# include "Algo/AnyOf.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundFrontendDocument.h"
2021-12-07 16:32:38 -05:00
# include "MetasoundTrace.h"
# include "Misc/Guid.h"
2021-06-10 10:03:24 -04:00
# include "Templates/TypeHash.h"
2022-05-09 16:32:28 -04:00
# include "Traits/IsContiguousContainer.h"
2020-11-11 16:51:59 -04:00
namespace Metasound
{
namespace FrontendQueryPrivate
{
2022-04-27 13:19:55 -04:00
void CompactSelection ( FFrontendQuerySelection & InSelection )
{
2022-05-09 16:32:28 -04:00
InSelection . Shrink ( ) ;
}
// Not symmetric. Elements in LHS that are not in RHS. Modifies partition by resorting.
FFrontendQueryPartition Difference ( FFrontendQueryPartition & InLHS , FFrontendQueryPartition & InRHS )
{
static_assert ( TIsContiguousContainer < FFrontendQueryPartition > : : Value , " Partitions must be a contiguous container for Difference algorithm to no access invalid memory " ) ;
if ( ( InLHS . Num ( ) = = 0 ) | | ( InRHS . Num ( ) = = 0 ) )
2022-04-27 13:19:55 -04:00
{
2022-05-09 16:32:28 -04:00
return InLHS ;
2022-04-27 13:19:55 -04:00
}
2022-05-09 16:32:28 -04:00
auto IsIDLessThan = [ ] ( const FFrontendQueryEntry & InLHS , const FFrontendQueryEntry & InRHS ) { return InLHS . ID < InRHS . ID ; } ;
auto IsIDEqual = [ ] ( const FFrontendQueryEntry & InLHS , const FFrontendQueryEntry & InRHS ) { return InLHS . ID = = InRHS . ID ; } ;
InLHS . Sort ( IsIDLessThan ) ;
InRHS . Sort ( IsIDLessThan ) ;
FFrontendQueryPartition Result ;
const FFrontendQueryEntry * LHSPtr = InLHS . GetData ( ) ;
const FFrontendQueryEntry * LHSPtrEnd = LHSPtr + InLHS . Num ( ) ;
const FFrontendQueryEntry * RHSPtr = InRHS . GetData ( ) ;
const FFrontendQueryEntry * RHSPtrEnd = RHSPtr + InRHS . Num ( ) ;
while ( LHSPtr ! = LHSPtrEnd )
{
if ( ( RHSPtr = = RHSPtrEnd ) | | IsIDLessThan ( * LHSPtr , * RHSPtr ) )
{
Result . Add ( * LHSPtr ) ;
LHSPtr + + ;
}
else if ( IsIDLessThan ( * RHSPtr , * LHSPtr ) )
{
RHSPtr + + ;
}
else
{
// Values are equal
LHSPtr + + ;
RHSPtr + + ;
}
}
return Result ;
2022-04-27 13:19:55 -04:00
}
2021-05-27 14:45:41 -04:00
// Wrapper for step defined by function
struct FStreamFunctionFrontendQueryStep : IFrontendQueryStreamStep
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
using FStreamFunction = FFrontendQueryStep : : FStreamFunction ;
2020-11-11 16:51:59 -04:00
2021-05-27 14:45:41 -04:00
FStreamFunctionFrontendQueryStep ( FStreamFunction & & InFunc )
: Func ( MoveTemp ( InFunc ) )
2020-11-11 16:51:59 -04:00
{
}
2021-12-07 16:32:38 -05:00
void Stream ( TArray < FFrontendQueryValue > & OutValues ) override
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
Func ( OutValues ) ;
2020-11-11 16:51:59 -04:00
}
private :
2021-05-27 14:45:41 -04:00
FStreamFunction Func ;
2020-11-11 16:51:59 -04:00
} ;
2021-06-09 18:20:38 -04:00
// Wrapper for step defined by function
struct FTransformFunctionFrontendQueryStep : IFrontendQueryTransformStep
{
using FTransformFunction = FFrontendQueryStep : : FTransformFunction ;
FTransformFunctionFrontendQueryStep ( FTransformFunction InFunc )
: Func ( InFunc )
{
}
void Transform ( FFrontendQueryEntry : : FValue & InValue ) const override
{
Func ( InValue ) ;
}
FTransformFunction Func ;
} ;
2021-05-27 14:45:41 -04:00
// Wrapper for step defined by function
2020-11-11 16:51:59 -04:00
struct FMapFunctionFrontendQueryStep : IFrontendQueryMapStep
{
using FMapFunction = FFrontendQueryStep : : FMapFunction ;
FMapFunctionFrontendQueryStep ( FMapFunction InFunc )
: Func ( InFunc )
{
}
2021-12-07 16:32:38 -05:00
FFrontendQueryKey Map ( const FFrontendQueryEntry & InEntry ) const override
2020-11-11 16:51:59 -04:00
{
return Func ( InEntry ) ;
}
FMapFunction Func ;
} ;
2023-04-04 19:14:26 -04:00
// Wrapper for step defined by function
struct FMultiMapFunctionFrontendQueryStep : IFrontendQueryMultiMapStep
{
using FMultiMapFunction = FFrontendQueryStep : : FMultiMapFunction ;
FMultiMapFunctionFrontendQueryStep ( FMultiMapFunction InFunc )
: Func ( InFunc )
{
}
TArray < FFrontendQueryKey > Map ( const FFrontendQueryEntry & InEntry ) const override
{
return Func ( InEntry ) ;
}
FMultiMapFunction Func ;
} ;
2021-05-27 14:45:41 -04:00
// Wrapper for step defined by function
2020-11-11 16:51:59 -04:00
struct FReduceFunctionFrontendQueryStep : IFrontendQueryReduceStep
{
using FReduceFunction = FFrontendQueryStep : : FReduceFunction ;
FReduceFunctionFrontendQueryStep ( FReduceFunction InFunc )
: Func ( InFunc )
{
}
2021-12-07 16:32:38 -05:00
void Reduce ( const FFrontendQueryKey & InKey , FFrontendQueryPartition & InOutEntries ) const override
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
return Func ( InKey , InOutEntries ) ;
2020-11-11 16:51:59 -04:00
}
FReduceFunction Func ;
} ;
2021-05-27 14:45:41 -04:00
// Wrapper for step defined by function
2020-11-11 16:51:59 -04:00
struct FFilterFunctionFrontendQueryStep : IFrontendQueryFilterStep
{
using FFilterFunction = FFrontendQueryStep : : FFilterFunction ;
FFilterFunctionFrontendQueryStep ( FFilterFunction InFunc )
: Func ( InFunc )
{
}
bool Filter ( const FFrontendQueryEntry & InEntry ) const override
{
return Func ( InEntry ) ;
}
FFilterFunction Func ;
} ;
2021-05-27 14:45:41 -04:00
// Wrapper for step defined by function
2020-11-11 16:51:59 -04:00
struct FScoreFunctionFrontendQueryStep : IFrontendQueryScoreStep
{
using FScoreFunction = FFrontendQueryStep : : FScoreFunction ;
FScoreFunctionFrontendQueryStep ( FScoreFunction InFunc )
: Func ( InFunc )
{
}
float Score ( const FFrontendQueryEntry & InEntry ) const override
{
return Func ( InEntry ) ;
}
FScoreFunction Func ;
} ;
2021-05-27 14:45:41 -04:00
// Wrapper for step defined by function
2020-11-11 16:51:59 -04:00
struct FSortFunctionFrontendQueryStep : IFrontendQuerySortStep
{
using FSortFunction = FFrontendQueryStep : : FSortFunction ;
FSortFunctionFrontendQueryStep ( FSortFunction InFunc )
: Func ( InFunc )
{
}
bool Sort ( const FFrontendQueryEntry & InEntryLHS , const FFrontendQueryEntry & InEntryRHS ) const override
{
return Func ( InEntryLHS , InEntryRHS ) ;
}
FSortFunction Func ;
} ;
2021-05-27 14:45:41 -04:00
// Wrapper for step defined by function
2020-11-11 16:51:59 -04:00
struct FLimitFunctionFrontendQueryStep : IFrontendQueryLimitStep
{
using FLimitFunction = FFrontendQueryStep : : FLimitFunction ;
FLimitFunctionFrontendQueryStep ( FLimitFunction InFunc )
: Func ( InFunc )
{
}
int32 Limit ( ) const override
{
return Func ( ) ;
}
FLimitFunction Func ;
} ;
2021-12-07 16:32:38 -05:00
// Base step executer for all step types.
2020-11-11 16:51:59 -04:00
template < typename StepType >
2021-12-07 16:32:38 -05:00
struct TStepExecuterBase : public FFrontendQueryStep : : IStepExecuter
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
using FIncremental = FFrontendQueryStep : : FIncremental ;
TStepExecuterBase ( TUniquePtr < StepType > & & InStep )
2020-11-11 16:51:59 -04:00
: Step ( MoveTemp ( InStep ) )
{
}
2021-12-07 16:32:38 -05:00
virtual void Merge ( FIncremental & InOutIncremental , FFrontendQuerySelection & InOutSelection ) const override
{
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : BaseQueryStep : : Merge ) ;
MergePartitionCompositionIndependent ( InOutIncremental , InOutSelection ) ;
}
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
virtual bool IsDependentOnPartitionComposition ( ) const override { return false ; }
virtual bool CanProcessRemovals ( ) const override { return true ; }
virtual bool CanProduceEntries ( ) const override { return false ; }
2021-05-27 14:45:41 -04:00
protected :
2021-12-07 16:32:38 -05:00
void MergePartitionCompositionIndependent ( FIncremental & InOutIncremental , FFrontendQuerySelection & InOutSelection ) const
{
checkf ( ! IsDependentOnPartitionComposition ( ) , TEXT ( " Incorrect merge function called on step which is dependent upon merge composition " ) ) ;
Remove ( InOutIncremental . ActiveRemovalKeys , InOutIncremental . ActiveRemovalSelection , InOutSelection ) ;
Append ( InOutIncremental . ActiveKeys , InOutIncremental . ActiveSelection , InOutSelection ) ;
}
// Appends incremental results to the output results.
void Append ( const TSet < FFrontendQueryKey > & InActiveKeys , const FFrontendQuerySelection & InIncrementalSelection , FFrontendQuerySelection & InOutSelection ) const
{
for ( const FFrontendQueryKey & Key : InActiveKeys )
{
if ( const FFrontendQueryPartition * Partition = InIncrementalSelection . Find ( Key ) )
{
if ( Partition - > Num ( ) > 0 )
{
InOutSelection . FindOrAdd ( Key ) . Append ( * Partition ) ;
}
}
}
}
void Remove ( const TSet < FFrontendQueryKey > & InRemovalActiveKeys , const FFrontendQuerySelection & InRemovalSelection , FFrontendQuerySelection & InOutSelection ) const
{
for ( const FFrontendQueryKey & Key : InRemovalActiveKeys )
{
if ( FFrontendQueryPartition * Entries = InOutSelection . Find ( Key ) )
{
if ( const FFrontendQueryPartition * EntriesToRemove = InRemovalSelection . Find ( Key ) )
{
for ( const FFrontendQueryEntry & EntryToRemove : * EntriesToRemove )
{
Entries - > Remove ( EntryToRemove ) ;
}
}
if ( Entries - > Num ( ) = = 0 )
{
InOutSelection . Remove ( Key ) ;
}
}
}
}
2020-11-11 16:51:59 -04:00
TUniquePtr < StepType > Step ;
} ;
2021-12-07 16:32:38 -05:00
struct FStreamStepExecuter : TStepExecuterBase < IFrontendQueryStreamStep >
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
using TStepExecuterBase < IFrontendQueryStreamStep > : : TStepExecuterBase ;
2020-11-11 16:51:59 -04:00
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : StreamQueryStep : : Execute ) ;
InOutUpdatedKeys . Reset ( ) ;
2021-05-27 14:45:41 -04:00
2020-11-11 16:51:59 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
// Retrieve new values from step
TArray < FFrontendQueryValue > NewValues ;
Step - > Stream ( NewValues ) ;
2020-11-11 16:51:59 -04:00
2021-12-07 16:32:38 -05:00
const int32 Num = NewValues . Num ( ) ;
if ( NewValues . Num ( ) > 0 )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
FFrontendQueryKey NullKey ;
InOutUpdatedKeys . Add ( NullKey ) ;
FFrontendQueryPartition & NullPartition = InOutResult . FindOrAdd ( NullKey ) ;
for ( FFrontendQueryValue & Value : NewValues )
{
FFrontendQueryEntry Entry ;
Entry . ID = FGuid : : NewGuid ( ) ;
Entry . Value = MoveTemp ( Value ) ;
NullPartition . Add ( MoveTemp ( Entry ) ) ;
}
2021-05-27 14:45:41 -04:00
}
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
virtual bool CanProcessRemovals ( ) const override
{
// Cannot process removals since streams only add information.
return false ;
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
virtual bool CanProduceEntries ( ) const override
{
return true ;
2020-11-11 16:51:59 -04:00
}
} ;
2021-12-07 16:32:38 -05:00
struct FTransformStepExecuter : TStepExecuterBase < IFrontendQueryTransformStep >
2021-06-09 18:20:38 -04:00
{
2021-12-07 16:32:38 -05:00
using TStepExecuterBase < IFrontendQueryTransformStep > : : TStepExecuterBase ;
2021-06-09 18:20:38 -04:00
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2021-06-09 18:20:38 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : TransformQueryStep : : Execute ) ;
2021-06-09 18:20:38 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutUpdatedKeys )
2021-06-09 18:20:38 -04:00
{
2021-12-07 16:32:38 -05:00
if ( FFrontendQueryPartition * Partition = InOutResult . Find ( Key ) )
2021-06-09 18:20:38 -04:00
{
2021-12-07 16:32:38 -05:00
if ( Partition - > Num ( ) > 0 )
{
for ( FFrontendQueryEntry & Entry : * Partition )
{
Step - > Transform ( Entry . Value ) ;
}
}
2021-06-09 18:20:38 -04:00
}
}
}
}
} ;
2023-04-04 19:14:26 -04:00
template < typename MapQueryStep >
struct TMapStepExecuterBase : public TStepExecuterBase < MapQueryStep >
2020-11-11 16:51:59 -04:00
{
2023-04-04 19:14:26 -04:00
using TStepExecuterBase < MapQueryStep > : : TStepExecuterBase ;
using TStepExecuterBase < MapQueryStep > : : Step ;
virtual void ExecuteStep ( FFrontendQueryEntry & & Entry , FFrontendQuerySelection & OutResult ) const = 0 ;
2020-11-11 16:51:59 -04:00
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2020-11-11 16:51:59 -04:00
{
2023-04-04 19:14:26 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : MapStepQuery : : Execute ) ;
2020-11-11 16:51:59 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
if ( InOutUpdatedKeys . Num ( ) > 0 )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
FFrontendQuerySelection Result ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutUpdatedKeys )
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
if ( FFrontendQueryPartition * Partition = InOutResult . Find ( Key ) )
{
// Map all entries associated with the key to a new key.
if ( Partition - > Num ( ) > 0 )
{
for ( FFrontendQueryEntry & Entry : * Partition )
{
2023-04-04 19:14:26 -04:00
ExecuteStep ( MoveTemp ( Entry ) , Result ) ;
2021-12-07 16:32:38 -05:00
}
}
// Remove entries since they have been mapped to a new key
Partition - > Reset ( ) ;
}
2020-11-11 16:51:59 -04:00
}
2021-12-07 16:32:38 -05:00
// Get the updated set of keys in the output.
InOutUpdatedKeys . Reset ( ) ;
2022-05-09 16:32:28 -04:00
for ( const auto & Pair : Result )
{
InOutUpdatedKeys . Add ( Pair . Key ) ;
}
2021-12-07 16:32:38 -05:00
// Append the new values to the final result.
2023-04-04 19:14:26 -04:00
TStepExecuterBase < MapQueryStep > : : Append ( InOutUpdatedKeys , Result , InOutResult ) ;
2020-11-11 16:51:59 -04:00
}
}
}
} ;
2023-04-04 19:14:26 -04:00
struct FMapStepExecuter : TMapStepExecuterBase < IFrontendQueryMapStep >
{
using TMapStepExecuterBase < IFrontendQueryMapStep > : : TMapStepExecuterBase ;
virtual void ExecuteStep ( FFrontendQueryEntry & & Entry , FFrontendQuerySelection & OutResult ) const override
{
FFrontendQueryKey NewKey = Step - > Map ( Entry ) ;
OutResult . FindOrAdd ( MoveTemp ( NewKey ) ) . Add ( MoveTemp ( Entry ) ) ;
}
} ;
struct FMultiMapStepExecuter : TMapStepExecuterBase < IFrontendQueryMultiMapStep >
{
using TMapStepExecuterBase < IFrontendQueryMultiMapStep > : : TMapStepExecuterBase ;
virtual void ExecuteStep ( FFrontendQueryEntry & & Entry , FFrontendQuerySelection & OutResult ) const override
{
TArray < FFrontendQueryKey > NewKeys = Step - > Map ( Entry ) ;
for ( FFrontendQueryKey & NewKey : NewKeys )
{
OutResult . FindOrAdd ( MoveTemp ( NewKey ) ) . Add ( MoveTemp ( Entry ) ) ;
}
}
} ;
2021-12-07 16:32:38 -05:00
struct FReduceStepExecuter : TStepExecuterBase < IFrontendQueryReduceStep >
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
using FKey = FFrontendQueryKey ;
2021-05-27 14:45:41 -04:00
public :
2021-12-07 16:32:38 -05:00
using TStepExecuterBase < IFrontendQueryReduceStep > : : TStepExecuterBase ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
virtual void Merge ( FIncremental & InOutIncremental , FFrontendQuerySelection & InOutSelection ) const override
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : ReduceQueryStep : : Merge ) ;
Remove ( InOutIncremental . ActiveRemovalKeys , InOutIncremental . ActiveRemovalSelection , InOutSelection ) ;
2021-05-27 14:45:41 -04:00
if ( Step . IsValid ( ) )
2021-07-27 15:35:56 -04:00
{
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutIncremental . ActiveKeys )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
if ( const FFrontendQueryPartition * NewPartition = InOutIncremental . ActiveSelection . Find ( Key ) )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
if ( NewPartition - > Num ( ) > 0 )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
FFrontendQueryPartition & Partition = InOutSelection . FindOrAdd ( Key ) ;
FFrontendQueryPartition OriginalPartition = Partition ;
Partition . Append ( * NewPartition ) ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
Step - > Reduce ( Key , Partition ) ;
2022-05-09 16:32:28 -04:00
FFrontendQueryPartition Removed = FrontendQueryPrivate : : Difference ( OriginalPartition , Partition ) ;
2021-12-07 16:32:38 -05:00
if ( Removed . Num ( ) > 0 )
{
InOutIncremental . ActiveRemovalSelection . FindOrAdd ( Key ) . Append ( Removed ) ;
InOutIncremental . ActiveRemovalKeys . Add ( Key ) ;
}
}
}
2021-05-27 14:45:41 -04:00
}
}
}
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : ReduceQueryStep : : Execute ) ;
2021-05-27 14:45:41 -04:00
if ( Step . IsValid ( ) )
2021-07-27 15:35:56 -04:00
{
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutUpdatedKeys )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
if ( FFrontendQueryPartition * Partition = InOutResult . Find ( Key ) )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
if ( Partition - > Num ( ) > 0 )
{
Step - > Reduce ( Key , * Partition ) ;
}
}
2021-05-27 14:45:41 -04:00
}
}
}
2021-12-07 16:32:38 -05:00
virtual bool IsDependentOnPartitionComposition ( ) const override
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
// Results may change depending on what is in the partition.
2021-05-27 14:45:41 -04:00
return true ;
}
2020-11-11 16:51:59 -04:00
} ;
2021-12-07 16:32:38 -05:00
struct FFilterStepExecuter : TStepExecuterBase < IFrontendQueryFilterStep >
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
using TStepExecuterBase < IFrontendQueryFilterStep > : : TStepExecuterBase ;
2020-11-11 16:51:59 -04:00
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : FilterQueryStep : : Execute ) ;
2020-11-11 16:51:59 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutUpdatedKeys )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
if ( FFrontendQueryPartition * Partition = InOutResult . Find ( Key ) )
2021-08-18 14:34:27 -04:00
{
2021-12-07 16:32:38 -05:00
for ( FFrontendQueryPartition : : TIterator Iter = Partition - > CreateIterator ( ) ; Iter ; + + Iter )
{
const bool bKeepEntry = Step - > Filter ( * Iter ) ;
if ( ! bKeepEntry )
{
Iter . RemoveCurrent ( ) ;
}
}
2020-11-11 16:51:59 -04:00
}
}
}
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
} ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
struct FScoreStepExecuter : TStepExecuterBase < IFrontendQueryScoreStep >
{
using TStepExecuterBase < IFrontendQueryScoreStep > : : TStepExecuterBase ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : ScoreQueryStep : : Execute ) ;
if ( Step . IsValid ( ) )
{
for ( const FFrontendQueryKey & Key : InOutUpdatedKeys )
{
if ( FFrontendQueryPartition * Partition = InOutResult . Find ( Key ) )
{
for ( FFrontendQueryEntry & Entry : * Partition )
{
Entry . Score = Step - > Score ( Entry ) ;
}
}
}
}
2020-11-11 16:51:59 -04:00
}
} ;
2021-12-07 16:32:38 -05:00
struct FSortStepExecuter : TStepExecuterBase < IFrontendQuerySortStep >
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
using TStepExecuterBase < IFrontendQuerySortStep > : : TStepExecuterBase ;
2020-11-11 16:51:59 -04:00
2021-12-07 16:32:38 -05:00
virtual void Merge ( FIncremental & InOutIncremental , FFrontendQuerySelection & InOutSelection ) const override
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : SortQueryStep : : Merge ) ;
Remove ( InOutIncremental . ActiveRemovalKeys , InOutIncremental . ActiveRemovalSelection , InOutSelection ) ;
2021-05-27 14:45:41 -04:00
2020-11-11 16:51:59 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
auto SortFunc = [ & ] ( const FFrontendQueryEntry & InLHS , const FFrontendQueryEntry & InRHS )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
return Step - > Sort ( InLHS , InRHS ) ;
} ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutIncremental . ActiveKeys )
{
if ( const FFrontendQueryPartition * NewPartition = InOutIncremental . ActiveSelection . Find ( Key ) )
{
if ( FFrontendQueryPartition * OrigPartition = InOutSelection . Find ( Key ) )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
// Need to re-sort if merging two arrays
OrigPartition - > Append ( * NewPartition ) ;
OrigPartition - > Sort ( SortFunc ) ;
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
else
{
// New key entries are already sorted.
InOutSelection . Add ( Key , * NewPartition ) ;
}
}
2021-05-27 14:45:41 -04:00
}
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : SortQueryStep : : Execute ) ;
2021-05-27 14:45:41 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
auto SortFunc = [ & ] ( const FFrontendQueryEntry & InLHS , const FFrontendQueryEntry & InRHS )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
return Step - > Sort ( InLHS , InRHS ) ;
} ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutUpdatedKeys )
{
if ( FFrontendQueryPartition * OrigPartition = InOutResult . Find ( Key ) )
{
OrigPartition - > Sort ( SortFunc ) ;
}
2021-05-27 14:45:41 -04:00
}
}
}
2021-12-07 16:32:38 -05:00
virtual bool IsDependentOnPartitionComposition ( ) const
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
// Results may change depending on what is in the partition.
2021-05-27 14:45:41 -04:00
return true ;
2020-11-11 16:51:59 -04:00
}
} ;
2021-12-07 16:32:38 -05:00
struct FLimitStepExecuter : TStepExecuterBase < IFrontendQueryLimitStep >
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
using TStepExecuterBase < IFrontendQueryLimitStep > : : TStepExecuterBase ;
2020-11-11 16:51:59 -04:00
2021-12-07 16:32:38 -05:00
virtual void Merge ( FIncremental & InOutIncremental , FFrontendQuerySelection & InOutSelection ) const override
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : LimitQueryStep : : Merge ) ;
Remove ( InOutIncremental . ActiveRemovalKeys , InOutIncremental . ActiveRemovalSelection , InOutSelection ) ;
2021-05-27 14:45:41 -04:00
2020-11-11 16:51:59 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
TSet < FFrontendQueryKey > UpdatedKeys ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
const int32 Limit = Step - > Limit ( ) ;
for ( const FFrontendQueryKey & Key : InOutIncremental . ActiveKeys )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
if ( const FFrontendQueryPartition * NewPartition = InOutIncremental . ActiveSelection . Find ( Key ) )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
FFrontendQueryPartition & ExistingPartition = InOutSelection . FindOrAdd ( Key ) ;
const int32 NumToAdd = FMath : : Min ( Limit - ExistingPartition . Num ( ) , NewPartition - > Num ( ) ) ;
if ( NumToAdd > 0 )
{
UpdatedKeys . Add ( Key ) ;
for ( FFrontendQueryPartition : : TConstIterator Iter = NewPartition - > CreateConstIterator ( ) ; Iter ; + + Iter )
{
ExistingPartition . Add ( * Iter ) ;
}
}
2021-05-27 14:45:41 -04:00
}
}
}
}
2021-12-07 16:32:38 -05:00
virtual void Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const override
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSound : : LimitQueryStep : : Execute ) ;
2021-05-27 14:45:41 -04:00
if ( Step . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
const int32 Limit = Step - > Limit ( ) ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InOutUpdatedKeys )
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
if ( FFrontendQueryPartition * Partition = InOutResult . Find ( Key ) )
{
const int32 Num = Partition - > Num ( ) ;
if ( Num > Limit )
{
// Create a new partition and fill with desired number
// of objects.
FFrontendQueryPartition NewPartition ;
FFrontendQueryPartition : : TConstIterator Iter = Partition - > CreateConstIterator ( ) ;
for ( int32 i = 0 ; ( i < Limit ) & & Iter ; i + + )
{
NewPartition . Add ( * Iter ) ;
+ + Iter ;
}
// Replace the old partition with a new one.
InOutResult [ Key ] = NewPartition ;
}
}
2020-11-11 16:51:59 -04:00
}
}
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
virtual bool IsDependentOnPartitionComposition ( ) const
2021-05-27 14:45:41 -04:00
{
// Merge is required because values under limit may be different
// after merge.
return true ;
2020-11-11 16:51:59 -04:00
}
} ;
}
2021-06-09 18:20:38 -04:00
FFrontendQueryKey : : FFrontendQueryKey ( )
2021-12-07 16:32:38 -05:00
: Key ( TInPlaceType < FFrontendQueryKey : : FNull > ( ) )
2021-06-09 18:20:38 -04:00
, Hash ( INDEX_NONE )
{ }
FFrontendQueryKey : : FFrontendQueryKey ( int32 InKey )
: Key ( TInPlaceType < int32 > ( ) , InKey )
2021-06-11 12:24:02 -04:00
, Hash ( : : GetTypeHash ( InKey ) )
2021-06-09 18:20:38 -04:00
{
}
FFrontendQueryKey : : FFrontendQueryKey ( const FString & InKey )
: Key ( TInPlaceType < FString > ( ) , InKey )
2022-11-01 15:50:27 -04:00
, Hash ( GetTypeHash ( InKey ) )
2021-06-09 18:20:38 -04:00
{
}
FFrontendQueryKey : : FFrontendQueryKey ( const FName & InKey )
: Key ( TInPlaceType < FName > ( ) , InKey )
2022-11-01 15:50:27 -04:00
, Hash ( GetTypeHash ( InKey ) )
2021-06-09 18:20:38 -04:00
{
}
2021-12-07 16:32:38 -05:00
bool FFrontendQueryKey : : IsNull ( ) const
2021-06-09 18:20:38 -04:00
{
2021-12-07 16:32:38 -05:00
return Key . GetIndex ( ) ! = FKeyType : : IndexOfType < FFrontendQueryKey : : FNull > ( ) ;
2021-06-09 18:20:38 -04:00
}
bool operator = = ( const FFrontendQueryKey & InLHS , const FFrontendQueryKey & InRHS )
{
if ( InLHS . Hash = = InRHS . Hash )
{
2021-12-07 16:32:38 -05:00
if ( InLHS . Key . GetIndex ( ) = = InRHS . Key . GetIndex ( ) )
2021-06-09 18:20:38 -04:00
{
2021-12-07 16:32:38 -05:00
switch ( InLHS . Key . GetIndex ( ) )
2021-06-09 18:20:38 -04:00
{
2021-12-07 16:32:38 -05:00
case FFrontendQueryKey : : FKeyType : : IndexOfType < FFrontendQueryKey : : FNull > ( ) :
return true ;
2021-06-09 18:20:38 -04:00
2021-12-07 16:32:38 -05:00
case FFrontendQueryKey : : FKeyType : : IndexOfType < int32 > ( ) :
return InLHS . Key . Get < int32 > ( ) = = InRHS . Key . Get < int32 > ( ) ;
2021-06-09 18:20:38 -04:00
2021-12-07 16:32:38 -05:00
case FFrontendQueryKey : : FKeyType : : IndexOfType < FString > ( ) :
return InLHS . Key . Get < FString > ( ) = = InRHS . Key . Get < FString > ( ) ;
2021-06-09 18:20:38 -04:00
2021-12-07 16:32:38 -05:00
case FFrontendQueryKey : : FKeyType : : IndexOfType < FName > ( ) :
return InLHS . Key . Get < FName > ( ) = = InRHS . Key . Get < FName > ( ) ;
default :
// Unhandled case type.
checkNoEntry ( ) ;
2021-06-09 18:20:38 -04:00
}
}
}
return false ;
}
bool operator ! = ( const FFrontendQueryKey & InLHS , const FFrontendQueryKey & InRHS )
{
return ! ( InLHS = = InRHS ) ;
}
bool operator < ( const FFrontendQueryKey & InLHS , const FFrontendQueryKey & InRHS )
{
if ( InLHS . Hash ! = InRHS . Hash )
{
return InLHS . Hash < InRHS . Hash ;
}
if ( InLHS . Key . GetIndex ( ) ! = InRHS . Key . GetIndex ( ) )
{
return InLHS . Key . GetIndex ( ) < InRHS . Key . GetIndex ( ) ;
}
switch ( InLHS . Key . GetIndex ( ) )
{
2021-12-07 16:32:38 -05:00
case FFrontendQueryKey : : FKeyType : : IndexOfType < FFrontendQueryKey : : FNull > ( ) :
return false ;
2021-06-09 18:20:38 -04:00
case FFrontendQueryKey : : FKeyType : : IndexOfType < int32 > ( ) :
return InLHS . Key . Get < int32 > ( ) < InRHS . Key . Get < int32 > ( ) ;
case FFrontendQueryKey : : FKeyType : : IndexOfType < FString > ( ) :
return InLHS . Key . Get < FString > ( ) < InRHS . Key . Get < FString > ( ) ;
case FFrontendQueryKey : : FKeyType : : IndexOfType < FName > ( ) :
return InLHS . Key . Get < FName > ( ) . FastLess ( InRHS . Key . Get < FName > ( ) ) ;
default :
// Unhandled case type.
checkNoEntry ( ) ;
}
return false ;
}
uint32 GetTypeHash ( const FFrontendQueryKey & InKey )
{
return InKey . Hash ;
}
2021-12-07 16:32:38 -05:00
uint32 GetTypeHash ( const FFrontendQueryEntry & InEntry )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
return GetTypeHash ( InEntry . ID ) ;
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
bool operator = = ( const FFrontendQueryEntry & InLHS , const FFrontendQueryEntry & InRHS )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
return InLHS . ID = = InRHS . ID ;
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FStreamFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FStreamStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FStreamFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
2020-11-11 16:51:59 -04:00
{
}
2021-06-09 18:20:38 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FTransformFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FTransformStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FTransformFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
{
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FMapFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FMapStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FMapFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
2020-11-11 16:51:59 -04:00
{
}
2023-04-04 19:14:26 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FMultiMapFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FMultiMapStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FMultiMapFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
{
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FReduceFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FReduceStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FReduceFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
2020-11-11 16:51:59 -04:00
{
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FFilterFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FFilterStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FFilterFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
2020-11-11 16:51:59 -04:00
{
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FScoreFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FScoreStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FScoreFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
2020-11-11 16:51:59 -04:00
{
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FSortFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FSortStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FSortFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
2020-11-11 16:51:59 -04:00
{
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( FLimitFunction & & InFunc )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FLimitStepExecuter > ( MakeUnique < FrontendQueryPrivate : : FLimitFunctionFrontendQueryStep > ( MoveTemp ( InFunc ) ) ) )
2020-11-11 16:51:59 -04:00
{
}
2021-05-27 14:45:41 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryStreamStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FStreamStepExecuter > ( MoveTemp ( InStep ) ) )
2020-11-11 16:51:59 -04:00
{
}
2021-06-09 18:20:38 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryTransformStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FTransformStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
2020-11-11 16:51:59 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryMapStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FMapStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
2023-04-04 19:14:26 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryMultiMapStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FMultiMapStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
2020-11-11 16:51:59 -04:00
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryReduceStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FReduceStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryFilterStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FFilterStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryScoreStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FScoreStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQuerySortStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FSortStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
FFrontendQueryStep : : FFrontendQueryStep ( TUniquePtr < IFrontendQueryLimitStep > & & InStep )
: StepExecuter ( MakeUnique < FrontendQueryPrivate : : FLimitStepExecuter > ( MoveTemp ( InStep ) ) )
{
}
2021-12-07 16:32:38 -05:00
void FFrontendQueryStep : : Execute ( TSet < FFrontendQueryKey > & InOutUpdatedKeys , FFrontendQuerySelection & InOutResult ) const
2020-11-11 16:51:59 -04:00
{
if ( StepExecuter . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
StepExecuter - > Execute ( InOutUpdatedKeys , InOutResult ) ;
2021-05-27 14:45:41 -04:00
}
}
2021-12-07 16:32:38 -05:00
void FFrontendQueryStep : : Merge ( FIncremental & InOutIncremental , FFrontendQuerySelection & InOutSelection ) const
2021-05-27 14:45:41 -04:00
{
if ( StepExecuter . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
StepExecuter - > Merge ( InOutIncremental , InOutSelection ) ;
2021-05-27 14:45:41 -04:00
}
}
2021-12-07 16:32:38 -05:00
bool FFrontendQueryStep : : IsDependentOnPartitionComposition ( ) const
2021-05-27 14:45:41 -04:00
{
if ( StepExecuter . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
return StepExecuter - > IsDependentOnPartitionComposition ( ) ;
2021-05-27 14:45:41 -04:00
}
return false ;
}
2021-12-07 16:32:38 -05:00
bool FFrontendQueryStep : : CanProcessRemovals ( ) const
2021-05-27 14:45:41 -04:00
{
if ( StepExecuter . IsValid ( ) )
{
2021-12-07 16:32:38 -05:00
return StepExecuter - > CanProcessRemovals ( ) ;
2020-11-11 16:51:59 -04:00
}
2021-12-07 16:32:38 -05:00
return true ;
}
bool FFrontendQueryStep : : CanProduceEntries ( ) const
{
if ( StepExecuter . IsValid ( ) )
{
return StepExecuter - > CanProduceEntries ( ) ;
}
return true ;
}
2020-11-11 16:51:59 -04:00
2021-03-30 18:22:10 -04:00
FFrontendQuery : : FFrontendQuery ( )
: Result ( MakeShared < FFrontendQuerySelection , ESPMode : : ThreadSafe > ( ) )
{
}
2021-05-27 14:45:41 -04:00
FFrontendQuery & FFrontendQuery : : AddStreamLambdaStep ( FStreamFunction & & InFunc )
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
2020-11-11 16:51:59 -04:00
}
2021-06-09 18:20:38 -04:00
FFrontendQuery & FFrontendQuery : : AddTransformLambdaStep ( FTransformFunction & & InFunc )
{
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
}
2021-05-27 14:45:41 -04:00
FFrontendQuery & FFrontendQuery : : AddMapLambdaStep ( FMapFunction & & InFunc )
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
FFrontendQuery & FFrontendQuery : : AddReduceLambdaStep ( FReduceFunction & & InFunc )
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
FFrontendQuery & FFrontendQuery : : AddFilterLambdaStep ( FFilterFunction & & InFunc )
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
FFrontendQuery & FFrontendQuery : : AddScoreLambdaStep ( FScoreFunction & & InFunc )
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
FFrontendQuery & FFrontendQuery : : AddSortLambdaStep ( FSortFunction & & InFunc )
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
2020-11-11 16:51:59 -04:00
}
2021-05-27 14:45:41 -04:00
FFrontendQuery & FFrontendQuery : : AddLimitLambdaStep ( FLimitFunction & & InFunc )
2020-11-11 16:51:59 -04:00
{
2021-05-27 14:45:41 -04:00
return AddFunctionStep ( MoveTemp ( InFunc ) ) ;
2020-11-11 16:51:59 -04:00
}
FFrontendQuery & FFrontendQuery : : AddStep ( TUniquePtr < FFrontendQueryStep > & & InStep )
{
2021-05-27 14:45:41 -04:00
if ( ensure ( InStep . IsValid ( ) ) )
{
2021-12-07 16:32:38 -05:00
FStepInfo StepInfo ;
StepInfo . Step = MoveTemp ( InStep ) ;
StepInfo . bProcessRemovals = StepInfo . Step - > CanProcessRemovals ( ) ;
// Determine if this step is the last step which can produce entries.
if ( StepInfo . Step - > CanProduceEntries ( ) )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
FinalEntryProducingStepIndex = Steps . Num ( ) ;
}
// If any prior steps have the ability to remove a previously existing
// entry, and this step requires an incremental merge, then we need to
// cache the input to this step. If an entry is deleted from the input
// to this step, all inputs associated with a given key will be reevaluated.
//
// To cache the input to a step, we can equivalently cache the output
// of prior step.
const bool bCacheAncestorStepOutput = Algo : : AnyOf ( Steps , [ ] ( const FStepInfo & Info ) { return Info . Step - > IsDependentOnPartitionComposition ( ) ; } ) ;
if ( bCacheAncestorStepOutput & & StepInfo . Step - > IsDependentOnPartitionComposition ( ) )
{
Steps . Last ( ) . bMergeAndCacheOutput = true ;
}
else if ( StepInfo . Step - > IsDependentOnPartitionComposition ( ) )
{
// If the step is dependent upon the partition composition, and
// input is not a merged partition, then the incremental must be merged
// with the prior result for the step so that downstream steps are
// provided the correct input data.
StepInfo . bMergeAndCacheOutput = true ;
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
Steps . Add ( MoveTemp ( StepInfo ) ) ;
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
2020-11-11 16:51:59 -04:00
return * this ;
}
2021-12-07 16:32:38 -05:00
const FFrontendQuerySelection & FFrontendQuery : : Update ( )
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
TSet < FFrontendQueryKey > UpdatedKeys ;
return Update ( UpdatedKeys ) ;
2021-03-30 18:22:10 -04:00
}
2021-12-07 16:32:38 -05:00
const FFrontendQuerySelection & FFrontendQuery : : Update ( TSet < FFrontendQueryKey > & OutUpdatedKeys )
2021-03-30 18:22:10 -04:00
{
2021-12-07 16:32:38 -05:00
UpdateInternal ( OutUpdatedKeys ) ;
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
return * Result ;
2021-03-30 18:22:10 -04:00
}
2021-12-07 16:32:38 -05:00
const FFrontendQuerySelection & FFrontendQuery : : GetSelection ( ) const
2021-03-30 18:22:10 -04:00
{
2021-12-07 16:32:38 -05:00
return * Result ;
2021-03-30 18:22:10 -04:00
}
2021-12-07 16:32:38 -05:00
void FFrontendQuery : : MergeInternal ( FFrontendQueryStep & Step , FFrontendQuery : : FIncremental & InOutIncremental , FFrontendQuerySelection & InOutMergedSelection )
2021-03-30 18:22:10 -04:00
{
2021-12-07 16:32:38 -05:00
Step . Merge ( InOutIncremental , InOutMergedSelection ) ;
}
2021-05-27 14:45:41 -04:00
2021-12-07 16:32:38 -05:00
void FFrontendQuery : : UpdateInternal ( TSet < FFrontendQueryKey > & OutUpdatedKeys )
{
2022-04-27 13:19:55 -04:00
using namespace FrontendQueryPrivate ;
2021-12-07 16:32:38 -05:00
FIncremental Incremental ;
const int32 LastStepIndex = Steps . Num ( ) - 1 ;
2021-05-27 14:45:41 -04:00
// Perform incremental update sequentially
2020-11-11 16:51:59 -04:00
for ( int32 StepIndex = 0 ; StepIndex < Steps . Num ( ) ; StepIndex + + )
{
2021-12-07 16:32:38 -05:00
FStepInfo & StepInfo = Steps [ StepIndex ] ;
StepInfo . Step - > Execute ( Incremental . ActiveKeys , Incremental . ActiveSelection ) ;
if ( StepInfo . bProcessRemovals )
2020-11-11 16:51:59 -04:00
{
2021-12-07 16:32:38 -05:00
StepInfo . Step - > Execute ( Incremental . ActiveRemovalKeys , Incremental . ActiveRemovalSelection ) ;
}
2020-11-11 16:51:59 -04:00
2021-12-07 16:32:38 -05:00
const bool bIsLastProducingStep = StepIndex = = FinalEntryProducingStepIndex ;
if ( bIsLastProducingStep )
{
const bool bIsIncrementalEmpty = ( Incremental . ActiveKeys . Num ( ) = = 0 ) & & ( Incremental . ActiveRemovalKeys . Num ( ) = = 0 ) ;
if ( bIsIncrementalEmpty )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
// Early out if following steps will not produce any new outputs.
return ;
2021-07-27 15:35:56 -04:00
}
2021-05-27 14:45:41 -04:00
}
2021-12-07 16:32:38 -05:00
// Determine if incremental results need to be merged because it's
// the last step, or because the step requires merging.
const bool bIsLastStep = StepIndex = = LastStepIndex ;
if ( bIsLastStep )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
StepInfo . Step - > Merge ( Incremental , * Result ) ;
2022-04-27 13:19:55 -04:00
CompactSelection ( * Result ) ;
2021-12-07 16:32:38 -05:00
OutUpdatedKeys = Incremental . ActiveKeys . Union ( Incremental . ActiveRemovalKeys ) ;
}
else if ( StepInfo . bMergeAndCacheOutput )
{
StepInfo . Step - > Merge ( Incremental , StepInfo . OutputCache ) ;
2022-04-27 13:19:55 -04:00
2021-12-07 16:32:38 -05:00
// If entries were removed during a merge, the subsequent step
// needs to re-evaluate the entire partition. The entire partition
// is added to the active set for each removed key.
AppendPartitions ( Incremental . ActiveRemovalKeys , StepInfo . OutputCache , Incremental . ActiveKeys , Incremental . ActiveSelection ) ;
2022-04-27 13:19:55 -04:00
CompactSelection ( StepInfo . OutputCache ) ;
2021-05-27 14:45:41 -04:00
}
}
}
2021-12-07 16:32:38 -05:00
void FFrontendQuery : : AppendPartitions ( const TSet < FFrontendQueryKey > & InKeysToAppend , const FFrontendQuerySelection & InSelection , TSet < FFrontendQueryKey > & OutKeysModified , FFrontendQuerySelection & OutSelection ) const
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
for ( const FFrontendQueryKey & Key : InKeysToAppend )
2021-05-27 14:45:41 -04:00
{
2021-12-07 16:32:38 -05:00
if ( const FFrontendQueryPartition * Partition = InSelection . Find ( Key ) )
2021-05-27 14:45:41 -04:00
{
2023-08-01 15:00:17 -04:00
OutKeysModified . Add ( Key ) ;
OutSelection . FindOrAdd ( Key ) = * Partition ;
2021-05-27 14:45:41 -04:00
}
2020-11-11 16:51:59 -04:00
}
}
}