11package org .hypertrace .gateway .service .entity .query ;
22
33import static java .util .Collections .emptyList ;
4- import static java .util .Collections .emptyMap ;
54import static java .util .Collections .unmodifiableList ;
65import static org .hypertrace .core .attribute .service .v1 .AttributeSource .EDS ;
76import static org .hypertrace .core .attribute .service .v1 .AttributeSource .QS ;
87
98import com .google .common .annotations .VisibleForTesting ;
109import java .util .ArrayList ;
1110import java .util .Collection ;
12- import java .util .Collections ;
1311import java .util .HashMap ;
1412import java .util .List ;
1513import java .util .Map ;
16- import java .util .Map .Entry ;
1714import java .util .Optional ;
1815import java .util .Set ;
1916import java .util .stream .Collectors ;
2017import java .util .stream .Stream ;
21- import org .hypertrace .core .attribute .service .v1 .AttributeMetadata ;
2218import org .hypertrace .core .attribute .service .v1 .AttributeSource ;
2319import org .hypertrace .gateway .service .common .ExpressionContext ;
24- import org .hypertrace .gateway .service .common .util .ExpressionReader ;
2520import org .hypertrace .gateway .service .common .util .TimeRangeFilterUtil ;
2621import org .hypertrace .gateway .service .entity .query .visitor .ExecutionContextBuilderVisitor ;
2722import org .hypertrace .gateway .service .entity .query .visitor .FilterOptimizingVisitor ;
2823import org .hypertrace .gateway .service .entity .query .visitor .PrintVisitor ;
29- import org .hypertrace .gateway .service .v1 .common .Expression ;
3024import org .hypertrace .gateway .service .v1 .common .Filter ;
3125import org .hypertrace .gateway .service .v1 .common .Operator ;
3226import org .hypertrace .gateway .service .v1 .common .OrderByExpression ;
@@ -39,18 +33,11 @@ public class ExecutionTreeBuilder {
3933
4034 private static final Logger LOG = LoggerFactory .getLogger (ExecutionTreeBuilder .class );
4135
42- private final Map <String , AttributeMetadata > attributeMetadataMap ;
4336 private final EntityExecutionContext executionContext ;
4437 private final Set <String > sourceSetsIfFilterAndOrderByAreFromSameSourceSets ;
4538
4639 public ExecutionTreeBuilder (EntityExecutionContext executionContext ) {
4740 this .executionContext = executionContext ;
48- this .attributeMetadataMap =
49- executionContext
50- .getAttributeMetadataProvider ()
51- .getAttributesMetadata (
52- executionContext .getEntitiesRequestContext (),
53- executionContext .getEntitiesRequest ().getEntityType ());
5441
5542 this .sourceSetsIfFilterAndOrderByAreFromSameSourceSets =
5643 ExpressionContext .getSourceSetsIfFilterAndOrderByAreFromSameSourceSets (
@@ -132,7 +119,7 @@ public QueryNode build() {
132119
133120 ExecutionTreeUtils .removeDuplicateSelectionAttributes (executionContext , QS .name ());
134121
135- QueryNode filterTree = buildFilterTree (executionContext , entitiesRequest .getFilter ());
122+ QueryNode filterTree = buildFilterTreeNode (executionContext , entitiesRequest .getFilter ());
136123 if (LOG .isDebugEnabled ()) {
137124 LOG .debug ("Filter Tree:{}" , filterTree .acceptVisitor (new PrintVisitor ()));
138125 }
@@ -268,8 +255,7 @@ QueryNode buildExecutionTree(EntityExecutionContext executionContext, QueryNode
268255 return rootNode ;
269256 }
270257
271- @ VisibleForTesting
272- QueryNode buildFilterTree (EntityExecutionContext context , Filter filter ) {
258+ QueryNode buildFilterTreeNode (EntityExecutionContext context , Filter filter ) {
273259 EntitiesRequest entitiesRequest = executionContext .getEntitiesRequest ();
274260 // Convert the time range into a filter and set it on the request so that all downstream
275261 // components needn't treat it specially
@@ -281,29 +267,29 @@ QueryNode buildFilterTree(EntityExecutionContext context, Filter filter) {
281267 entitiesRequest .getEndTimeMillis ());
282268
283269 boolean isAndFilter = executionContext .getExpressionContext ().isAndFilter ();
284- return isAndFilter
285- ? buildAndFilterTree (entitiesRequest )
286- : buildFilterTree (entitiesRequest , timeRangeFilter );
270+ return isAndFilter ? buildAndFilterTree (context ) : buildFilterTree (context , timeRangeFilter );
287271 }
288272
289273 @ VisibleForTesting
290- QueryNode buildFilterTree (EntitiesRequest entitiesRequest , Filter filter ) {
274+ QueryNode buildFilterTree (EntityExecutionContext context , Filter filter ) {
275+ EntitiesRequest entitiesRequest = context .getEntitiesRequest ();
291276 if (filter .equals (Filter .getDefaultInstance ())) {
292277 return new NoOpNode ();
293278 }
294279 Operator operator = filter .getOperator ();
295280 if (operator == Operator .AND ) {
296281 return new AndNode (
297282 filter .getChildFilterList ().stream ()
298- .map (childFilter -> buildFilterTree (entitiesRequest , childFilter ))
283+ .map (childFilter -> buildFilterTree (context , childFilter ))
299284 .collect (Collectors .toList ()));
300285 } else if (operator == Operator .OR ) {
301286 return new OrNode (
302287 filter .getChildFilterList ().stream ()
303- .map (childFilter -> buildFilterTree (entitiesRequest , childFilter ))
288+ .map (childFilter -> buildFilterTree (context , childFilter ))
304289 .collect (Collectors .toList ()));
305290 } else {
306- List <AttributeSource > sources = getAttributeSources (filter .getLhs ());
291+ List <AttributeSource > sources =
292+ context .getExpressionContext ().getAttributeSources (filter .getLhs ());
307293 // if the filter by and order by are from QS, pagination can be pushed down to QS
308294
309295 // There will always be a DataFetcherNode for QS, because the results are always fetched
@@ -319,7 +305,8 @@ QueryNode buildFilterTree(EntitiesRequest entitiesRequest, Filter filter) {
319305 }
320306
321307 // filters and order by on QS, but you can still have selection on EDS
322- QueryNode buildAndFilterTree (EntitiesRequest entitiesRequest ) {
308+ QueryNode buildAndFilterTree (EntityExecutionContext context ) {
309+ EntitiesRequest entitiesRequest = context .getEntitiesRequest ();
323310 // If the filter by and order by are from QS (and selections are on other sources), pagination
324311 // can be pushed down to QS
325312 // Since the filter and order by are from QS, there won't be any filter on other
@@ -330,7 +317,7 @@ QueryNode buildAndFilterTree(EntitiesRequest entitiesRequest) {
330317 }
331318
332319 Map <AttributeSource , Filter > sourceToAndFilterMap =
333- new HashMap <>(buildSourceToAndFilterMap ( entitiesRequest . getFilter () ));
320+ new HashMap <>(context . getExpressionContext (). getSourceToFilterMap ( ));
334321
335322 // qs node as the pivot node to fetch time range data
336323 QueryNode qsNode =
@@ -387,37 +374,6 @@ QueryNode buildAndFilterTree(EntitiesRequest entitiesRequest) {
387374 }
388375 }
389376
390- private Map <AttributeSource , Filter > buildSourceToAndFilterMap (Filter filter ) {
391- Operator operator = filter .getOperator ();
392- if (operator == Operator .AND ) {
393- return filter .getChildFilterList ().stream ()
394- .map (this ::buildSourceToAndFilterMap )
395- .flatMap (map -> map .entrySet ().stream ())
396- .collect (
397- Collectors .toUnmodifiableMap (
398- Entry ::getKey ,
399- Entry ::getValue ,
400- (value1 , value2 ) ->
401- Filter .newBuilder ()
402- .setOperator (Operator .AND )
403- .addChildFilter (value1 )
404- .addChildFilter (value2 )
405- .build ()));
406-
407- } else if (operator == Operator .OR ) {
408- return Collections .emptyMap ();
409- } else {
410- List <AttributeSource > attributeSources = getAttributeSources (filter .getLhs ());
411- if (attributeSources .isEmpty ()) {
412- return emptyMap ();
413- }
414-
415- return attributeSources .contains (QS )
416- ? Map .of (QS , filter )
417- : Map .of (attributeSources .get (0 ), filter );
418- }
419- }
420-
421377 private QueryNode checkAndAddSortAndPaginationNode (
422378 QueryNode childNode , EntityExecutionContext executionContext ) {
423379 EntitiesRequest entitiesRequest = executionContext .getEntitiesRequest ();
@@ -479,12 +435,4 @@ private QueryNode createQsDataFetcherNodeWithLimitAndOffset(EntitiesRequest enti
479435 private QueryNode createPaginateOnlyNode (QueryNode queryNode , EntitiesRequest entitiesRequest ) {
480436 return new PaginateOnlyNode (queryNode , entitiesRequest .getLimit (), entitiesRequest .getOffset ());
481437 }
482-
483- public List <AttributeSource > getAttributeSources (Expression expression ) {
484- Set <String > attributeIds = ExpressionReader .extractAttributeIds (expression );
485- return attributeIds .stream ()
486- .map (attributeId -> attributeMetadataMap .get (attributeId ).getSourcesList ())
487- .flatMap (Collection ::stream )
488- .collect (Collectors .toUnmodifiableList ());
489- }
490438}
0 commit comments