Skip to content

Commit ded0583

Browse files
authored
Merge pull request #3 from azurechen97/release/0.2.0
Release/0.2.0
2 parents 0c4b1d1 + 46e60e0 commit ded0583

5 files changed

Lines changed: 80 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Changelog
2+
3+
## [0.2.0] - 2026-03-31
4+
5+
### Added
6+
7+
**Generator (MaxCompute SQL output)**
8+
9+
- `DATEADD` / `DATEADD` with negated delta for `DateSub` (e.g. BigQuery `DATE_SUB``DATEADD(dt, -3, 'DAY')`)
10+
- `DATEDIFF` with optional unit argument
11+
- `DATETRUNC` / `TRUNC_TIME` with full week-unit support (`'week'``'week(monday)'`)
12+
- `DATEPART` via named `extract_sql` method
13+
- `GETDATE()` for `CurrentTimestamp`, `NOW()` for `CurrentDatetime`
14+
- `TOLOWER` / `TOUPPER` for `Lower` / `Upper`
15+
- `FROM_JSON` for `ParseJSON`, `GET_USER_ID()` for `CurrentUser`, `TO_MILLIS` for `UnixMillis`
16+
- `APPROX_DISTINCT`, `ARG_MAX`, `ARG_MIN`
17+
- `WM_CONCAT(sep, col)` via named `groupconcat_sql` method (with default separator guard)
18+
- `TO_CHAR` via named `tochar_sql` method
19+
- Type mapping: `VARCHAR` / `CHAR` / `TEXT``STRING`; `DATETIME` preserved
20+
21+
**Parser (read direction)**
22+
23+
- Statistical aggregates: `STDDEV_SAMP`, `COVAR_POP`, `COVAR_SAMP`, `CORR`, `MEDIAN`, `PERCENTILE_APPROX`, `BITWISE_AND_AGG`, `BITWISE_OR_AGG`, `BITWISE_XOR_AGG`
24+
- `MAX_BY` / `MIN_BY` as aliases for `ARG_MAX` / `ARG_MIN`
25+
26+
### Fixed
27+
28+
- `TO_DATE` format string preserved as-is (Hive was converting Oracle-style `mm``%M`)
29+
- `WEEKDAY` round-trips as `WEEKDAY(dt)` in MaxCompute output (other dialects still get the `(DAYOFWEEK + 5) % 7` arithmetic)
30+
- `DATETRUNC` week-unit emits valid `'week(monday)'` string literal instead of bare `WEEK(MONDAY)`
31+
- `groupconcat_sql` defaults separator to `','` when absent (prevents invalid `WM_CONCAT(col)`)
32+
- Python >=3.9 compatibility (removed `ipykernel`, relaxed `pytest` floor)
33+
- Added `sqlglot<31` upper bound to prevent unexpected breakage on major releases
34+
35+
### Infrastructure
36+
37+
- GitHub Actions CI across Python 3.9 / 3.10 / 3.11 / 3.12
38+
- README with usage examples and function coverage table
39+
40+
## [0.1.0] - 2026-03-01
41+
42+
Initial release.
43+
44+
- MaxCompute dialect registered via Python entry points
45+
- Parser: ~40 date/time, string, array, and map functions
46+
- DDL: `LIFECYCLE`, `RANGE CLUSTERED BY`, `AUTO PARTITIONED BY`

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "sqlglot-maxcompute"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
description = "MaxCompute dialect plugin for SQLGlot"
55
readme = "README.md"
66
license = { text = "MIT" }

src/sqlglot_maxcompute/maxcompute.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ class Parser(Hive.Parser):
150150
"SECOND": exp.Second.from_arg_list,
151151
"QUARTER": exp.Quarter.from_arg_list,
152152
"WEEKDAY": lambda args: exp.paren(exp.DayOfWeek(this=seq_get(args, 0)) + 5, copy=False) % 7,
153+
# MAX_BY / MIN_BY are Spark/Trino names for the same semantics
154+
"MAX_BY": exp.ArgMax.from_arg_list,
155+
"MIN_BY": exp.ArgMin.from_arg_list,
153156
"WEEKOFYEAR": exp.WeekOfYear.from_arg_list,
154157
# Last/next day
155158
"LAST_DAY": exp.LastDay.from_arg_list,
@@ -332,6 +335,21 @@ def groupconcat_sql(self, expression: exp.GroupConcat) -> str:
332335
def tochar_sql(self, expression: exp.ToChar) -> str:
333336
return self.func("TO_CHAR", expression.this, expression.args.get("format"))
334337

338+
def mod_sql(self, expression: exp.Mod) -> str:
339+
# Reverse the WEEKDAY parser transform: (DAYOFWEEK(x) + 5) % 7 → WEEKDAY(x)
340+
rhs = expression.expression
341+
lhs = expression.this
342+
if (
343+
isinstance(rhs, exp.Literal) and rhs.this == "7"
344+
and isinstance(lhs, exp.Paren)
345+
and isinstance(lhs.this, exp.Add)
346+
and isinstance(lhs.this.this, exp.DayOfWeek)
347+
and isinstance(lhs.this.expression, exp.Literal)
348+
and lhs.this.expression.this == "5"
349+
):
350+
return self.func("WEEKDAY", lhs.this.this.this)
351+
return super().mod_sql(expression)
352+
335353
def extract_sql(self, expression: exp.Extract) -> str:
336354
# Named extract_sql (public) so sqlglot's auto-dispatch picks it up for exp.Extract nodes.
337355
unit = expression.this

tests/test_maxcompute.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,15 @@ def test_date_extraction(self):
9898
},
9999
)
100100

101-
# WEEKDAY → (DAYOFWEEK(dt) + 5) % 7
101+
# WEEKDAY → (DAYOFWEEK(dt) + 5) % 7 in other dialects, but round-trips as WEEKDAY in MaxCompute
102102
expr = self.parse_one("WEEKDAY(dt)")
103103
self.assertIsInstance(expr, exp.Mod)
104104
self.validate_all(
105105
"WEEKDAY(dt)",
106106
write={
107107
"spark": "(DAYOFWEEK(dt) + 5) % 7",
108108
"duckdb": "(DAYOFWEEK(dt) + 5) % 7",
109+
"maxcompute": "WEEKDAY(dt)",
109110
},
110111
)
111112

@@ -666,7 +667,7 @@ def test_aggregate_roundtrip(self):
666667
# APPROX_DISTINCT round-trip
667668
self.validate_identity("SELECT APPROX_DISTINCT(x)")
668669

669-
# Cross-dialect: MAX_BY → ARG_MAX, MIN_BY → ARG_MIN
670+
# Cross-dialect: MAX_BY → ARG_MAX, MIN_BY → ARG_MIN (read from Spark)
670671
self.validate_all(
671672
"SELECT MAX_BY(x, y)",
672673
read={"spark": "SELECT MAX_BY(x, y)"},
@@ -678,6 +679,16 @@ def test_aggregate_roundtrip(self):
678679
write={"maxcompute": "SELECT ARG_MIN(x, y)"},
679680
)
680681

682+
# Read MaxCompute MAX_BY/MIN_BY directly (aliases in MaxCompute parser)
683+
self.validate_all(
684+
"SELECT MAX_BY(x, y)",
685+
write={"maxcompute": "SELECT ARG_MAX(x, y)"},
686+
)
687+
self.validate_all(
688+
"SELECT MIN_BY(x, y)",
689+
write={"maxcompute": "SELECT ARG_MIN(x, y)"},
690+
)
691+
681692
def test_misc_roundtrip(self):
682693
# FROM_JSON round-trip
683694
self.validate_identity("SELECT FROM_JSON(s, 'schema')")

uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)