PBI-Measure-CallGraph/dax_parser.py
2025-03-15 21:32:56 +08:00

71 lines
2.5 KiB
Python

import re
class DaxParser:
"""Class to parse DAX expressions and build dependency graphs."""
def __init__(self):
"""Initialize the DAX parser."""
# Regular expression to match measure references in DAX
# This is a simplified pattern and may need refinement for complex DAX
self.measure_ref_pattern = r'\[([^\]]+)\]'
def extract_measure_references(self, dax_expression, all_measure_names):
"""
Extract references to other measures from a DAX expression.
Args:
dax_expression (str): The DAX expression to parse
all_measure_names (list): List of all measure names in the model
Returns:
list: Names of measures referenced in the expression
"""
if not dax_expression:
return []
# Find all potential measure references (anything in square brackets)
potential_refs = re.findall(self.measure_ref_pattern, dax_expression)
# Filter to only include actual measure names
# This helps avoid false positives like column references
measure_refs = [ref for ref in potential_refs if ref in all_measure_names]
return list(set(measure_refs)) # Remove duplicates
def build_call_graph(self, measures):
"""
Build a call graph of measure dependencies.
Args:
measures (list): List of measure dictionaries with 'name' and 'expression' keys
Returns:
dict: A graph representation with nodes and links
"""
# Extract all measure names
all_measure_names = [measure['name'] for measure in measures]
# Create nodes for the graph
nodes = [{'id': measure['name'], 'expression': measure['expression']} for measure in measures]
# Create links (dependencies) for the graph
links = []
for measure in measures:
source = measure['name']
expression = measure['expression']
# Find references to other measures in this expression
references = self.extract_measure_references(expression, all_measure_names)
# Add links for each reference
for target in references:
links.append({
'source': source,
'target': target
})
return {
'nodes': nodes,
'links': links
}