71 lines
2.5 KiB
Python
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
|
|
}
|