Skip to main content

A powerful DAX to SQL parser and translator with multi-dialect support.

Project description

A powerful Python library for parsing DAX (Data Analysis Expressions) queries and translating them into various SQL dialects (optimized for Trino).

Key Features

  • Unified API: Simple DaxParser class for all your translation needs.
  • Metadata-Aware: Automatic column resolution and implicit JOIN injection based on your data model relationships.
  • Multi-Dialect Support: Deeply optimized for Trino, with an extensible architecture for other engines.
  • Multi-Schema/Catalog Resolution: Support for dotted table names and dynamic schema remapping.
  • Detailed Error Reporting: Precise DaxParsingError with character offsets, ideal for IDEs and gateways.
  • Advanced DAX Support:
    • Complex filtering (FILTER, CALCULATETABLE)
    • Aggregations (SUMMARIZE, ADDCOLUMNS, SELECTCOLUMNS)
    • Table operators (UNION, INTERSECT, EXCEPT, GENERATE, CROSSJOIN)
    • Variables (VAR...RETURN)
    • Logical operators and expressions (IN, &&, ||, etc.)

Installation

pip install dax-sql-parser

Quick Start

from dax_sql_parser import DaxParser

# Initialize the parser
parser = DaxParser(default_dialect="trino")

# Translate a simple query
dax = "EVALUATE 'Sales'"
sql = parser.to_sql(dax)
print(sql)
# SELECT * FROM "Sales"

# Use schema mapping
parser = DaxParser(schema_mapping={"S": "raw.sales_data"})
sql = parser.to_sql("EVALUATE S")
print(sql)
# SELECT * FROM "raw"."sales_data"

Metadata and Implicit Joins

To support unqualified column references and automatic joins (critical for simple BI queries), provide a MetadataResolver.

from dax_sql_parser import DaxParser
from dax_sql_parser.core.metadata import MetadataResolver, TableMetadata, Relationship

# 1. Define your model
product = TableMetadata(name="Product")
product.add_column("ProductID", data_type="int")
product.add_column("Color", data_type="string")

sales = TableMetadata(name="Sales")
sales.add_column("ProductID", data_type="int")
sales.add_column("Amount", data_type="decimal")

# 2. Define relationships
rel = Relationship(from_table="Sales", from_column="ProductID", 
                   to_table="Product", to_column="ProductID")

metadata = MetadataResolver(tables=[product, sales], relationships=[rel])

# 3. Initialize parser with metadata
parser = DaxParser(metadata=metadata)

# 4. Resolve unqualified [Color] and inject JOIN
dax = "EVALUATE FILTER('Sales', [Color] = \"Red\")"
sql = parser.to_sql(dax)
# SELECT * FROM Sales INNER JOIN Product ON ... WHERE Product.Color = 'Red'

Extending Dialects

dax-sql-parser is designed to be easily extensible. To add a new SQL dialect:

  1. Create a Dialect Class: Inherit from BaseDialect and implement get_function_mappings.
  2. Register the Dialect: Use DialectRegistry.register().
from dax_sql_parser.core.dialects.base import BaseDialect
from dax_sql_parser.core.dialects.registry import DialectRegistry
import sqlglot.expressions as exp

class MySnowflakeDialect(BaseDialect):
    @property
    def name(self) -> str:
        return "snowflake"

    def get_function_mappings(self):
        return {
            "MEDIAN": lambda args: exp.Anonymous(this="MEDIAN", expressions=args)
        }

DialectRegistry.register(MySnowflakeDialect())

Development & Testing

This project uses uv for dependency management and building.

Setup

  1. Install uv: Follow the official installation guide.
  2. Clone the repository:
    git clone https://github.com/shohamyamin/dax-sql-parser.git
    cd dax-sql-parser
    
  3. Sync dependencies:
    uv sync
    

Working with Grammar

The parser is based on ANTLR4. If you modify the grammar file src/dax_sql_parser/grammar/Dax.g4, you need to regenerate the Python files:

# Using antlr4-tools (installed via dev dependencies)
antlr4 -Dlanguage=Python3 -visitor -o src/dax_sql_parser/grammar/ src/dax_sql_parser/grammar/Dax.g4

Running Tests

Run the comprehensive test suite with pytest:

uv run pytest

To run with coverage report:

uv run pytest --cov=dax_sql_parser --cov-report=term-missing

Building the Package

To build the source distribution and wheel:

uv build

The artifacts will be generated in the dist/ directory.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dax_sql_parser-0.1.0.tar.gz (32.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dax_sql_parser-0.1.0-py3-none-any.whl (40.5 kB view details)

Uploaded Python 3

File details

Details for the file dax_sql_parser-0.1.0.tar.gz.

File metadata

  • Download URL: dax_sql_parser-0.1.0.tar.gz
  • Upload date:
  • Size: 32.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dax_sql_parser-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3d1881743fe50f0e0687f14fbbfc746311d06032272f67e3c531b50f1403eec4
MD5 2145170e9e2603ecb6fbd64c89800216
BLAKE2b-256 5e782ba35bda732d35abcde34da627fb65be86c9707d97694f25cb8c0bb1b189

See more details on using hashes here.

File details

Details for the file dax_sql_parser-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dax_sql_parser-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 40.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dax_sql_parser-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c354e17e09aec238bdd6b193065fc9ea463ace5c7b793a547a174b27ad0a2f93
MD5 c1fcbee9318be0ed3ce8a7109a1b012c
BLAKE2b-256 a55511793a84f727c732fea3d683b6fb6a7474ca40395e39c8c4b59e67429bcb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page