Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/format-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ Heuristics such as select-list thresholds and line-break preferences are documen
- Single-quoted string literal contents are preserved as written, including doubled quotes and over-escaped forms.
- Quoted identifier contents are not recased.

## JOIN Token Preservation

- `JOIN` stays `JOIN`.
- `INNER JOIN` stays `INNER JOIN`.

## Parse Fallback vs Strict Mode

Default behavior (`strict = false` / no `--strict`):
Expand Down
1 change: 1 addition & 0 deletions docs/style-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ FROM t;
- Clause order: `SELECT`, `FROM`, `WHERE`, `GROUP BY`, `HAVING`, `WINDOW` (if any), `QUALIFY` (if supported), `ORDER BY`, `LIMIT`/`FETCH`, `OFFSET`
- Each clause starts on its own line (except small inline `SELECT`)
- `FROM` base relation on its own line; each `JOIN` on a new line aligned with `FROM`
- Join token style is preserved (`JOIN` remains `JOIN`; `INNER JOIN` remains `INNER JOIN`)
- `ON` is indented one level under its join
- `WHERE` / `HAVING` / `QUALIFY` break logical conditions across lines
- `GROUP BY` renders one item per line when more than one expression is present
Expand Down
2 changes: 1 addition & 1 deletion fixtures/ansi/expected/01.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SELECT
ORDER BY f.order_ts
) AS order_seq
FROM analytics_space."fact_orders" f
INNER JOIN analytics_space."dim_customers" c
JOIN analytics_space."dim_customers" c
ON c.customer_id = f.customer_id
LEFT JOIN (
SELECT
Expand Down
2 changes: 1 addition & 1 deletion fixtures/ansi/expected/07.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SELECT *
FROM dim_customers c
INNER JOIN fact_orders o USING customer_id
JOIN fact_orders o USING customer_id
CROSS JOIN dim_dates d
NATURAL LEFT JOIN dim_flags f;
2 changes: 1 addition & 1 deletion fixtures/ansi/out/01.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SELECT
ORDER BY f.order_ts
) AS order_seq
FROM analytics_space."fact_orders" f
INNER JOIN analytics_space."dim_customers" c
JOIN analytics_space."dim_customers" c
ON c.customer_id = f.customer_id
LEFT JOIN (
SELECT
Expand Down
2 changes: 1 addition & 1 deletion fixtures/ansi/out/07.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SELECT *
FROM dim_customers c
INNER JOIN fact_orders o USING customer_id
JOIN fact_orders o USING customer_id
CROSS JOIN dim_dates d
NATURAL LEFT JOIN dim_flags f;
19 changes: 14 additions & 5 deletions fixtures/dremio/expected/03.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,32 @@ CREATE TABLE demoCatalog.reporting."tables".orders_partitioned AS
CASE WHEN o.change_time IS NULL THEN 0 ELSE 1 END AS is_changed,
CASE WHEN o.cancel_time IS NULL THEN 0 ELSE 1 END AS is_canceled
FROM demoCatalog.reporting."tables"."orders" o
INNER JOIN demoCatalog.reporting."tables"."cart_orders" co
JOIN demoCatalog.reporting."tables"."cart_orders" co
ON co.order_id = o.id
INNER JOIN demoCatalog.reporting."tables"."order_revenues" orev
JOIN demoCatalog.reporting."tables"."order_revenues" orev
ON orev.order_id = o.id
INNER JOIN demoCatalog.reporting."tables"."sites" s
JOIN demoCatalog.reporting."tables"."sites" s
ON s.id = co.site_id
LEFT JOIN (
SELECT
i.order_id,
SUM(i.revenue) AS revenue_share
FROM demoCatalog.reporting."tables"."order_revenue_items" i
INNER JOIN demoCatalog.reporting."tables"."product_types" pt
JOIN demoCatalog.reporting."tables"."product_types" pt
ON i.product_type_id = pt.id
WHERE pt.revenue_group_id = 17
GROUP BY i.order_id
) dist
ON dist.order_id = o.id
WHERE NOT EXISTS (SELECT 1 FROM demoCatalog.reporting."tables"."order_items" AS oi JOIN demoCatalog.reporting."tables"."customer_items" AS ci ON ci.id = oi.customer_item_id WHERE oi.order_id = o.id AND ci.product_type_id = 620)
WHERE NOT EXISTS
(
SELECT
1
FROM demoCatalog.reporting."tables"."order_items" oi
JOIN demoCatalog.reporting."tables"."customer_items" ci
ON ci.id = oi.customer_item_id
WHERE oi.order_id = o.id
AND ci.product_type_id = 620
)
AND (o.is_test_order = FALSE)
);
2 changes: 1 addition & 1 deletion fixtures/dremio/expected/04.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SELECT
FROM arctic_catalog.analytics_space.orders_history o
AT BRANCH feature_campaign_x
AS OF TIMESTAMP '2024-10-01 12:00:00'
INNER JOIN arctic_catalog.analytics_space.order_items_history i
JOIN arctic_catalog.analytics_space.order_items_history i
ON i.order_id = o.order_id
AND i.valid_from <= o.order_ts
AND (
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dremio/expected/05.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SELECT
COUNT(*) AS num_orders,
AVG(o.order_amount) AS avg_order_value
FROM arctic_catalog.analytics_space."fact_orders" o
INNER JOIN arctic_catalog.analytics_space."dim_customers" c
JOIN arctic_catalog.analytics_space."dim_customers" c
ON c.customer_id = o.customer_id
WHERE order_ts >= TIMESTAMP '2024-01-01 00:00:00'
GROUP BY
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dremio/expected/07.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ SELECT
SUM(o.order_amount) AS total_revenue,
AVG(o.order_amount) AS avg_order_value
FROM arctic_catalog.analytics_space."fact_orders" o
INNER JOIN arctic_catalog.analytics_space."dim_customers" c
JOIN arctic_catalog.analytics_space."dim_customers" c
ON c.customer_id = o.customer_id
WHERE order_ts >= TIMESTAMP '2024-01-01 00:00:00'
GROUP BY
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dremio/expected/11.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ SELECT
o.created_at AS order_created_at,
coalesce(md5(c.email), '') AS email_hash
FROM demoCatalog.sales.staging.analytics.orders o
INNER JOIN demoCatalog.sales.staging.crm.customers c
JOIN demoCatalog.sales.staging.crm.customers c
ON c.order_id = o.id;
19 changes: 14 additions & 5 deletions fixtures/dremio/out/03.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,32 @@ CREATE TABLE demoCatalog.reporting."tables".orders_partitioned AS
CASE WHEN o.change_time IS NULL THEN 0 ELSE 1 END AS is_changed,
CASE WHEN o.cancel_time IS NULL THEN 0 ELSE 1 END AS is_canceled
FROM demoCatalog.reporting."tables"."orders" o
INNER JOIN demoCatalog.reporting."tables"."cart_orders" co
JOIN demoCatalog.reporting."tables"."cart_orders" co
ON co.order_id = o.id
INNER JOIN demoCatalog.reporting."tables"."order_revenues" orev
JOIN demoCatalog.reporting."tables"."order_revenues" orev
ON orev.order_id = o.id
INNER JOIN demoCatalog.reporting."tables"."sites" s
JOIN demoCatalog.reporting."tables"."sites" s
ON s.id = co.site_id
LEFT JOIN (
SELECT
i.order_id,
SUM(i.revenue) AS revenue_share
FROM demoCatalog.reporting."tables"."order_revenue_items" i
INNER JOIN demoCatalog.reporting."tables"."product_types" pt
JOIN demoCatalog.reporting."tables"."product_types" pt
ON i.product_type_id = pt.id
WHERE pt.revenue_group_id = 17
GROUP BY i.order_id
) dist
ON dist.order_id = o.id
WHERE NOT EXISTS (SELECT 1 FROM demoCatalog.reporting."tables"."order_items" AS oi JOIN demoCatalog.reporting."tables"."customer_items" AS ci ON ci.id = oi.customer_item_id WHERE oi.order_id = o.id AND ci.product_type_id = 620)
WHERE NOT EXISTS
(
SELECT
1
FROM demoCatalog.reporting."tables"."order_items" oi
JOIN demoCatalog.reporting."tables"."customer_items" ci
ON ci.id = oi.customer_item_id
WHERE oi.order_id = o.id
AND ci.product_type_id = 620
)
AND (o.is_test_order = FALSE)
);
2 changes: 1 addition & 1 deletion fixtures/dremio/out/04.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SELECT
FROM arctic_catalog.analytics_space.orders_history o
AT BRANCH feature_campaign_x
AS OF TIMESTAMP '2024-10-01 12:00:00'
INNER JOIN arctic_catalog.analytics_space.order_items_history i
JOIN arctic_catalog.analytics_space.order_items_history i
ON i.order_id = o.order_id
AND i.valid_from <= o.order_ts
AND (
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dremio/out/05.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SELECT
COUNT(*) AS num_orders,
AVG(o.order_amount) AS avg_order_value
FROM arctic_catalog.analytics_space."fact_orders" o
INNER JOIN arctic_catalog.analytics_space."dim_customers" c
JOIN arctic_catalog.analytics_space."dim_customers" c
ON c.customer_id = o.customer_id
WHERE order_ts >= TIMESTAMP '2024-01-01 00:00:00'
GROUP BY
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dremio/out/07.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ SELECT
SUM(o.order_amount) AS total_revenue,
AVG(o.order_amount) AS avg_order_value
FROM arctic_catalog.analytics_space."fact_orders" o
INNER JOIN arctic_catalog.analytics_space."dim_customers" c
JOIN arctic_catalog.analytics_space."dim_customers" c
ON c.customer_id = o.customer_id
WHERE order_ts >= TIMESTAMP '2024-01-01 00:00:00'
GROUP BY
Expand Down
2 changes: 1 addition & 1 deletion fixtures/dremio/out/11.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ SELECT
o.created_at AS order_created_at,
coalesce(md5(c.email), '') AS email_hash
FROM demoCatalog.sales.staging.analytics.orders o
INNER JOIN demoCatalog.sales.staging.crm.customers c
JOIN demoCatalog.sales.staging.crm.customers c
ON c.order_id = o.id;
2 changes: 1 addition & 1 deletion src/format/sql/from_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ fn format_join(
alias_tracker: &mut super::RelationAliasTracker,
) -> Doc {
let (prefix, constraint, asof_match) = match &join.join_operator {
JoinOperator::Join(constraint) => ("INNER JOIN", Some(constraint), None),
JoinOperator::Join(constraint) => ("JOIN", Some(constraint), None),
JoinOperator::Inner(constraint) => ("INNER JOIN", Some(constraint), None),
JoinOperator::Left(constraint) => ("LEFT JOIN", Some(constraint), None),
JoinOperator::LeftOuter(constraint) => ("LEFT JOIN", Some(constraint), None),
Expand Down
18 changes: 15 additions & 3 deletions src/format/sql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,7 @@ WHERE NOT EXISTS (
let out = format_str(sql, &cfg);
assert_eq!(
out.trim(),
"CREATE TABLE demoCatalog.reporting.\"tables\".orders_partitioned AS\n(\n SELECT\n o.id AS order_id,\n CURRENT_TIMESTAMP AS sync_time,\n o.order_number AS order_number,\n co.site_id AS site_id,\n s.brand_id AS brand_id,\n s.country_id AS site_country_id,\n o.created_at AS created_at,\n COALESCE(dist.revenue_share, 0) AS distribution_amount,\n CASE WHEN o.change_time IS NULL THEN 0 ELSE 1 END AS is_changed,\n CASE WHEN o.cancel_time IS NULL THEN 0 ELSE 1 END AS is_canceled\n FROM demoCatalog.reporting.\"tables\".\"orders\" o\n INNER JOIN demoCatalog.reporting.\"tables\".\"cart_orders\" co\n ON co.order_id = o.id\n INNER JOIN demoCatalog.reporting.\"tables\".\"order_revenues\" orev\n ON orev.order_id = o.id\n INNER JOIN demoCatalog.reporting.\"tables\".\"sites\" s\n ON s.id = co.site_id\n LEFT JOIN (\n SELECT\n i.order_id,\n SUM(i.revenue) AS revenue_share\n FROM demoCatalog.reporting.\"tables\".\"order_revenue_items\" i\n INNER JOIN demoCatalog.reporting.\"tables\".\"product_types\" pt\n ON i.product_type_id = pt.id\n WHERE pt.revenue_group_id = 17\n GROUP BY i.order_id\n ) dist\n ON dist.order_id = o.id\n WHERE NOT EXISTS\n (\n SELECT\n 1\n FROM demoCatalog.reporting.\"tables\".\"order_items\" oi\n INNER JOIN demoCatalog.reporting.\"tables\".\"customer_items\" ci\n ON ci.id = oi.customer_item_id\n WHERE oi.order_id = o.id\n AND ci.product_type_id = 620\n )\n AND (o.is_test_order = FALSE)\n);"
"CREATE TABLE demoCatalog.reporting.\"tables\".orders_partitioned AS\n(\n SELECT\n o.id AS order_id,\n CURRENT_TIMESTAMP AS sync_time,\n o.order_number AS order_number,\n co.site_id AS site_id,\n s.brand_id AS brand_id,\n s.country_id AS site_country_id,\n o.created_at AS created_at,\n COALESCE(dist.revenue_share, 0) AS distribution_amount,\n CASE WHEN o.change_time IS NULL THEN 0 ELSE 1 END AS is_changed,\n CASE WHEN o.cancel_time IS NULL THEN 0 ELSE 1 END AS is_canceled\n FROM demoCatalog.reporting.\"tables\".\"orders\" o\n JOIN demoCatalog.reporting.\"tables\".\"cart_orders\" co\n ON co.order_id = o.id\n JOIN demoCatalog.reporting.\"tables\".\"order_revenues\" orev\n ON orev.order_id = o.id\n JOIN demoCatalog.reporting.\"tables\".\"sites\" s\n ON s.id = co.site_id\n LEFT JOIN (\n SELECT\n i.order_id,\n SUM(i.revenue) AS revenue_share\n FROM demoCatalog.reporting.\"tables\".\"order_revenue_items\" i\n JOIN demoCatalog.reporting.\"tables\".\"product_types\" pt\n ON i.product_type_id = pt.id\n WHERE pt.revenue_group_id = 17\n GROUP BY i.order_id\n ) dist\n ON dist.order_id = o.id\n WHERE NOT EXISTS\n (\n SELECT\n 1\n FROM demoCatalog.reporting.\"tables\".\"order_items\" oi\n JOIN demoCatalog.reporting.\"tables\".\"customer_items\" ci\n ON ci.id = oi.customer_item_id\n WHERE oi.order_id = o.id\n AND ci.product_type_id = 620\n )\n AND (o.is_test_order = FALSE)\n);"
);
}

Expand Down Expand Up @@ -1905,6 +1905,18 @@ INSERT INTO a SELECT * FROM s.t AT BRANCH release AS OF TIMESTAMP '2025-01-01 00
);
}

#[test]
fn preserves_join_token_style() {
let cfg = FormatterConfig::default();
let sql =
"SELECT * FROM a JOIN b ON a.id = b.id;\nSELECT * FROM a INNER JOIN b ON a.id = b.id;";
let out = format_str(sql, &cfg);
assert_eq!(
out.trim(),
"SELECT *\nFROM a\nJOIN b\n ON a.id = b.id;\n\nSELECT *\nFROM a\nINNER JOIN b\n ON a.id = b.id;"
);
}

#[test]
fn formats_insert_select() {
let cfg = FormatterConfig::default();
Expand Down Expand Up @@ -2041,7 +2053,7 @@ INSERT INTO a SELECT * FROM s.t AT BRANCH release AS OF TIMESTAMP '2025-01-01 00
let out = format_str(sql, &cfg);
assert_eq!(
out.trim(),
"SELECT *\nFROM t\nINNER JOIN u\n ON t.id = u.id\n AND t.tenant = u.tenant"
"SELECT *\nFROM t\nJOIN u\n ON t.id = u.id\n AND t.tenant = u.tenant"
);
}

Expand Down Expand Up @@ -2274,7 +2286,7 @@ SELECT
o.created_at AS order_created_at,
COALESCE(MD5(c.email), '') AS email_hash
FROM demoCatalog.sales.staging.analytics.orders o
INNER JOIN demoCatalog.sales.staging.crm.customers c
JOIN demoCatalog.sales.staging.crm.customers c
ON c.order_id = o.id;"
);
}
Expand Down
Loading