Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

duckdb-kql

CI Oracle PyPI Python versions License: MIT Typed

Run Kusto KQL queries on DuckDB, from Python. Pure Python, no server, no JVM.

Status: pre-alpha. The API is settling but not frozen. Coverage is real and measured — see Coverage — and anything outside it raises rather than guessing.

import duckdb_kql

con = duckdb_kql.connect()
con.sql("CREATE TABLE Logs AS SELECT * FROM 'logs.parquet'")

df = duckdb_kql.df(con, """
    Logs
    | where Timestamp > ago(1d) and Level == "Error"
    | summarize Count = count() by bin(Timestamp, 1h), Component
    | sort by Timestamp asc
""")

New here? Start with Getting started.

Install

Install only the layer you need — each adds one dependency.

pip install duckdb-kql              # translate KQL to SQL         (antlr4 only)
pip install 'duckdb-kql[duckdb]'    # ... and run it               (+ duckdb)
pip install 'duckdb-kql[kusto]'     # ... via the Kusto SDK API    (+ pandas)
pip install 'duckdb-kql[all]'       # everything

Python 3.10 or newer. Fully typed — the package ships py.typed, so your type checker sees real types across all three layers (details).

No-runtime-dependency option

Translate at build time and the output has no dependency on this package at all — not even Python. Only your CI machine installs it.

duckdb-kql translate queries/ -o build/sql/ --check   # fails the build if a .sql is stale

See Build-time translation.

Query it from the Azure Data Explorer UI

duckdb-kql serve puts a local Kusto REST endpoint in front of a DuckDB file, so Kusto's own tools can query it. Standard library only — no new dependency.

duckdb-kql serve analytics.duckdb     # http://127.0.0.1:31415

Open https://dataexplorer.azure.com, choose Add connection, and paste that URL. It listens on loopback only and cannot be told otherwise, because it answers unauthenticated queries: see A local Kusto endpoint.

Three layers

Layer Import Needs For
0 duckdb_kql antlr4-python3-runtime KQL text in, DuckDB SQL out. No database involved.
1 duckdb_kql.engine + duckdb Running the translated SQL.
2 duckdb_kql.kusto + pandas A drop-in for azure-kusto-data's KustoClient.

Importing duckdb_kql never imports duckdb, so Layer 0 genuinely installs and runs without a database.

Layer 0 — translate

>>> import duckdb_kql
>>> duckdb_kql.to_sql("print x = 1 + 1")
'SELECT (CAST(1 AS BIGINT) + CAST(1 AS BIGINT)) AS "x"'

>>> duckdb_kql.validate("Logs | where Level ==")
[Diagnostic(span=SourceSpan(line=1, column=21), message="mismatched input '<EOF>' ...")]

Layer 1 — execute

import duckdb_kql

con = duckdb_kql.connect("analytics.duckdb")   # duckdb.connect + TimeZone=UTC
rel = duckdb_kql.kql(con, "StormEvents | summarize n = count() by State")
rel.fetchall()

Layer 2 — the Kusto SDK interface

For code already written against azure-kusto-data: change the import and the connection string, leave the queries alone.

from duckdb_kql.kusto import KustoClient, ClientRequestProperties
from duckdb_kql.kusto.helpers import dataframe_from_result_table

client = KustoClient("analytics.duckdb")
props = ClientRequestProperties()
props.set_parameter("state", user_input)

response = client.execute("Storm", """
    declare query_parameters(state:string);
    StormEvents | where State == state | take 10
""", props)

df = dataframe_from_result_table(response.primary_results[0])

Details, including what it refuses and why: docs/kusto-client.md.

Query parameters

Never build a query by concatenating strings. Declare parameters and pass values; they are bound as values, so the generated SQL contains no caller-controlled text at all.

duckdb_kql.kql(con, """
    declare query_parameters(state:string);
    StormEvents | where State == state
""", {"state": user_input})     # safe whatever user_input contains

Coverage

Measured against the real KQL engine (the Kusto Emulator), not asserted.

Doc-corpus cases matching ground truth 245 of 1036 (0 mismatches)
Azure Monitor's published KQL subset 114 / 119 (96%)
Tabular operators 16 / 41
Scalar functions / aggregates / binary operators 110 / 19 / 33

Supported operators: where, project, project-away, project-rename, extend, summarize, join, mv-expand, distinct, count, sort / order by, take / limit, render; sources print, datatable, range, and tables; plus let and declare query_parameters.

The support matrix lists every operator, function and type — supported or not — with the known limitations and Kusto discrepancies for each. It is generated from the translator's own registries and probed at build time, so it cannot claim support that does not exist.

Why refusal matters

The failure mode this project is built to avoid is not a crash — it is a query that runs and returns a different answer than Kusto would. KQL and SQL look alike in places where they behave differently: % is a mathematical modulo in KQL and takes the dividend's sign in DuckDB; extract's arguments are in the opposite order; KQL weeks start on Sunday; make_datetime truncates where make_timestamp rounds. Every mapping is verified against the emulator rather than inferred from documentation, and where an honest mapping does not exist — hash_xxhash64, datetime_part('nanosecond') — the answer is an error, not an approximation.

Documentation

Document What it covers
Getting started Install, first query, the three layers
KQL support matrix Every operator and function, supported or not, each with its gotchas
Build-time CLI Translating .kql to .sql in CI, to avoid a runtime dependency
Local Kusto endpoint duckdb-kql serve — query a DuckDB file from the Azure Data Explorer UI
API reference Every public function and type
Kusto SDK compatibility What Layer 2 implements, no-ops, and refuses
Azure Monitor profile Coverage against a published KQL subset
docs/TRANSLATION.md Normative KQL→DuckDB mapping spec (R1–R12)
docs/implementation-plan.md Architecture and milestones
docs/test-plan.md Corpus harvesting, oracle, divergence catalog
docs/kql-on-duckdb-landscape.md Survey of existing KQL-on-DuckDB work
docs/implementation-options.md Six approaches considered, with the chosen one
docs/m0-grammar-spike.md Grammar viability result
docs/frequency-scan-results.md What KQL constructs actually get used
docs/licensing.md Third-party licensing review
demo/ Notebook tour of all three layers, with outputs
CONTRIBUTING.md How to add a mapping, and when not to
SECURITY.md Reporting vulnerabilities; what is in scope
Releases What changed, and when

Design

The parser is generated by ANTLR from Microsoft's own Apache-2.0 KQL grammar. Translation targets DuckDB SQL as a chain of CTEs — one per KQL operator — so DuckDB does all execution and optimization, and the generated SQL stays readable.

Development

pip install -e ".[dev]"
pytest

tools/regen_parser.sh        # regenerate the parser (maintainers; needs Java)

The acceptance suite compares against the Kusto Emulator, which runs in Docker; see docs/oracle-harness.md. It is a development and CI tool only — never a runtime dependency, and never redistributed.

License

MIT — see LICENSE. Vendors an Apache-2.0 grammar and MIT-licensed documentation samples; see THIRD-PARTY-NOTICES.md.

Download files

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

Source Distribution

duckdb_kql-0.0.1.dev4.tar.gz (554.3 kB view details)

Uploaded Source

Built Distribution

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

duckdb_kql-0.0.1.dev4-py3-none-any.whl (338.2 kB view details)

Uploaded Python 3

File details

Details for the file duckdb_kql-0.0.1.dev4.tar.gz.

File metadata

  • Download URL: duckdb_kql-0.0.1.dev4.tar.gz
  • Upload date:
  • Size: 554.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for duckdb_kql-0.0.1.dev4.tar.gz
Algorithm Hash digest
SHA256 b1e40a79961052aa149688b83859ac2331402a2ae348d50f85f004581040c7fd
MD5 3c0e4286b6b93bd6ffbe59f9d4e33b61
BLAKE2b-256 9a25fd127db46bb2d3c784b0d54979364c4bda130fd7d358e715941bba4f0bfd

See more details on using hashes here.

Provenance

The following attestation bundles were made for duckdb_kql-0.0.1.dev4.tar.gz:

Publisher: release.yml on mmaitre314/duckdb-kql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duckdb_kql-0.0.1.dev4-py3-none-any.whl.

File metadata

  • Download URL: duckdb_kql-0.0.1.dev4-py3-none-any.whl
  • Upload date:
  • Size: 338.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for duckdb_kql-0.0.1.dev4-py3-none-any.whl
Algorithm Hash digest
SHA256 ae1510ea2a1f0cede13c0f77dd44e9939a74b15837583ac8351454448621ef36
MD5 c7ddf08e59b4aebe13c1f929da6f4880
BLAKE2b-256 1b4b64b647cac2860d3d14cd4f03431c9b59746b4f2980911e995355350dc7ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for duckdb_kql-0.0.1.dev4-py3-none-any.whl:

Publisher: release.yml on mmaitre314/duckdb-kql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.0.15

2 files

0.0.14

2 files

0.0.13

2 files

0.0.12

2 files

0.0.11

2 files

0.0.10

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

This release

0.0.1.dev4 This release

2 files

Supported by

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