Skip to content

Commit 6a392ac

Browse files
author
Charles Larivier
committed
feat(mbql): add Query to compile MBQL
Signed-off-by: Charles Larivier <charles@dribbble.com>
1 parent cc0d00a commit 6a392ac

File tree

5 files changed

+116
-0
lines changed

5 files changed

+116
-0
lines changed

src/metabase/mbql/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from metabase.mbql.query import Query

src/metabase/mbql/aggregations.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from metabase.mbql.base import Mbql
2+
3+
4+
class Aggregation(Mbql):
5+
mbql: str
6+
7+
def compile(self):
8+
return [self.mbql]
9+
10+
11+
class ColumnAggregation(Aggregation):
12+
def __init__(self, field_id: int):
13+
self.field_id = field_id
14+
15+
def compile(self):
16+
return [self.mbql, ["field", self.field_id, None]]
17+
18+
19+
class Count(Aggregation):
20+
mbql = "count"
21+
22+
23+
class Sum(ColumnAggregation):
24+
mbql = "sum"
25+
26+
27+
class Max(ColumnAggregation):
28+
mbql = "max"
29+
30+
31+
class Min(ColumnAggregation):
32+
mbql = "min"

src/metabase/mbql/base.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from typing import List
2+
3+
4+
class Mbql:
5+
def compile(self):
6+
raise NotImplementedError()
7+
8+
def __repr__(self):
9+
return str(self.compile())
10+
11+
12+
class Field(Mbql):
13+
def __init__(self, id: int, option=None):
14+
self.id = id
15+
self.option = option
16+
17+
def compile(self) -> List:
18+
return ["field", self.id, self.option]

src/metabase/mbql/groupby.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from enum import Enum
2+
3+
from metabase.mbql.base import Field
4+
5+
6+
class TemporalOption(Enum):
7+
MINUTE = {"temporal-unit": "minute"}
8+
HOUR = {"temporal-unit": "hour"}
9+
DAY = {"temporal-unit": "day"}
10+
WEEK = {"temporal-unit": "week"}
11+
MONTH = {"temporal-unit": "month"}
12+
QUARTER = {"temporal-unit": "quarter"}
13+
YEAR = {"temporal-unit": "year"}
14+
MINUTE_OF_HOUR = {"temporal-unit": "minute-of-hour"}
15+
HOUR_OF_DAY = {"temporal-unit": "hour-of-day"}
16+
DAY_OF_WEEK = {"temporal-unit": "day-of-week"}
17+
DAY_OF_MONTH = {"temporal-unit": "day-of-month"}
18+
DAY_OF_YEAR = {"temporal-unit": "day-of-year"}
19+
WEEK_OF_YEAR = {"temporal-unit": "week-of-year"}
20+
MONTH_OF_YEAR = {"temporal-unit": "month-of-year"}
21+
QUARTER_OF_YEAR = {"temporal-unit": "quarter-of-year"}
22+
23+
24+
class BinOption(Enum):
25+
AUTO = {"binning": {"strategy": "default"}}
26+
BINS_10 = {"binning": {"strategy": "num-bins", "num-bins": 10}}
27+
BINS_50 = {"binning": {"strategy": "num-bins", "num-bins": 50}}
28+
BINS_100 = {"binning": {"strategy": "num-bins", "num-bins": 100}}
29+
NONE = None
30+
31+
32+
class GroupBy(Field):
33+
def __init__(self, field_id: int, option=None):
34+
super(GroupBy, self).__init__(id=field_id, option=option)
35+
36+
37+
class TemporalGroupBy(GroupBy):
38+
def __init__(self, field_id: int, option: TemporalOption):
39+
super(TemporalGroupBy, self).__init__(field_id=field_id, option=option.value)
40+
41+
42+
class BinnedGroupBy(GroupBy):
43+
def __init__(self, field_id: int, option: BinOption):
44+
super(BinnedGroupBy, self).__init__(field_id=field_id, option=option.value)

src/metabase/mbql/query.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from dataclasses import dataclass, field
2+
from typing import List, Union
3+
4+
from metabase.mbql.aggregations import Aggregation
5+
from metabase.mbql.groupby import GroupBy
6+
7+
8+
@dataclass
9+
class Query:
10+
table_id: int
11+
aggregations: List[Union[Aggregation, Metric]]
12+
group_by: List[GroupBy] = field(default_factory=list)
13+
filters: List[Filter] = field(default_factory=list)
14+
15+
def compile(self):
16+
return {
17+
"source-table": self.table_id,
18+
"aggregation": [agg.compile() for agg in self.aggregations],
19+
"breakout": [],
20+
"filter": [],
21+
}

0 commit comments

Comments
 (0)