MCPcopy Create free account
hub / github.com/RedisGraph/RedisGraph / reduce_cond_op

Function reduce_cond_op

src/execution_plan/optimizations/utilize_indices.c:424–509  ·  view source on GitHub ↗

try to replace given Conditional Traverse operation and a set of Filter operations with a single Index Scan operation

Source from the content-addressed store, hash-verified

422// try to replace given Conditional Traverse operation and a set of Filter operations with
423// a single Index Scan operation
424void reduce_cond_op(ExecutionPlan *plan, OpCondTraverse *cond) {
425 // make sure there's an index for scanned label
426 const char *edge = AlgebraicExpression_Edge(cond->ae);
427 if(!edge) return;
428
429 QGEdge *e = QueryGraph_GetEdgeByAlias(cond->op.plan->query_graph, edge);
430 if(QGEdge_RelationCount(e) != 1) return;
431
432 const char *label = QGEdge_Relation(e, 0);
433 GraphContext *gc = QueryCtx_GetGraphCtx();
434 Index idx = GraphContext_GetIndex(gc, label, NULL, 0, IDX_EXACT_MATCH,
435 SCHEMA_EDGE);
436 if(idx == NULL) return;
437
438 // get all applicable filter for index
439 OpFilter **filters = _applicableFilters((OpBase *)cond, edge, idx);
440
441 // no filters, return
442 uint filters_count = array_len(filters);
443 if(filters_count == 0) goto cleanup;
444
445 RSIndex *rs_idx = Index_RSIndex(idx);
446 FT_FilterNode *root = _Concat_Filters(filters);
447 OpBase *indexOp = NewEdgeIndexScanOp(cond->op.plan, cond->graph, e, rs_idx,
448 root);
449
450 // The OPType_ALL_NODE_SCAN operation is redundant
451 // because OPType_EDGE_BY_INDEX_SCAN will resolve source nodes
452 if(cond->op.children[0]->type == OPType_ALL_NODE_SCAN) {
453 OpBase *allNodeScan = cond->op.children[0];
454 // remove all node scan op
455 ExecutionPlan_RemoveOp(plan, allNodeScan);
456 OpBase_Free(allNodeScan);
457 }
458
459
460 const char *other_alias = AlgebraicExpression_Dest(cond->ae);
461 QGNode *other_node = QueryGraph_GetNodeByAlias(cond->op.plan->query_graph, other_alias);
462 ASSERT(other_node != NULL);
463 uint other_label_count = QGNode_LabelCount(other_node);
464 if(other_label_count > 0) {
465 // create func expression
466 const char *func_name = "hasLabels";
467 AR_ExpNode *op = AR_EXP_NewOpNode(func_name, true, 2);
468
469 // create node expression
470 AR_ExpNode *node_exp = AR_EXP_NewVariableOperandNode(other_alias);
471
472 // create labels expression
473 SIValue labels = SI_Array(other_label_count);
474 for (uint i = 0; i < other_label_count; i++) {
475 SIArray_Append(&labels, SI_ConstStringVal((char *)other_node->labels[i]));
476 }
477 AR_ExpNode *labels_exp = AR_EXP_NewConstOperandNode(labels);
478
479 // set function arguments
480 op->op.children[0] = node_exp;
481 op->op.children[1] = labels_exp;

Callers 1

utilizeIndicesFunction · 0.85

Calls 15

AlgebraicExpression_EdgeFunction · 0.85
QGEdge_RelationCountFunction · 0.85
QGEdge_RelationFunction · 0.85
QueryCtx_GetGraphCtxFunction · 0.85
GraphContext_GetIndexFunction · 0.85
_applicableFiltersFunction · 0.85
array_lenFunction · 0.85
Index_RSIndexFunction · 0.85
_Concat_FiltersFunction · 0.85
NewEdgeIndexScanOpFunction · 0.85
ExecutionPlan_RemoveOpFunction · 0.85

Tested by

no test coverage detected