Skip to content

Commit 048aba4

Browse files
committed
feat: support range expr as window frame in snowflake
1 parent 2669cc6 commit 048aba4

3 files changed

Lines changed: 33 additions & 1 deletion

File tree

pegjs/snowflake.pegjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,6 +2687,13 @@ window_frame_clause
26872687
// => string
26882688
return `rows between ${p.value} and ${f.value}`
26892689
}
2690+
/ 'RANGE'i __ KW_BETWEEN __ i:interval_expr __ 'PRECEDING'i __ KW_AND __ f:interval_expr __ 'PRECEDING'i {
2691+
return {
2692+
type: 'range',
2693+
between: i,
2694+
and: f
2695+
}
2696+
}
26902697

26912698
window_frame_following
26922699
= s:window_frame_value __ 'FOLLOWING'i {

src/window.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
import { hasVal, toUpper } from './util'
22
import { exprToSQL, orderOrPartitionByToSQL } from './expr'
3+
import { intervalToSQL } from './interval'
34
import { overToSQL } from './over'
45

6+
function rangeExprToSQL(rangeExpr) {
7+
if (!rangeExpr) return
8+
if (typeof rangeExpr === 'string') return toUpper(rangeExpr)
9+
const { type, between, and } = rangeExpr
10+
const result = [toUpper(type), 'BETWEEN', intervalToSQL(between), 'PRECEDING', 'AND', intervalToSQL(and), 'PRECEDING']
11+
return result.filter(hasVal).join(' ')
12+
}
513
function windowSpecificationToSQL(windowSpec) {
614
const {
715
name,
@@ -13,7 +21,7 @@ function windowSpecificationToSQL(windowSpec) {
1321
name,
1422
orderOrPartitionByToSQL(partitionby, 'partition by'),
1523
orderOrPartitionByToSQL(orderby, 'order by'),
16-
toUpper(windowFrame),
24+
rangeExprToSQL(windowFrame),
1725
]
1826
return result.filter(hasVal).join(' ')
1927
}

test/snowflake.spec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,23 @@ describe('snowflake', () => {
467467
'SELECT "my_column"::FLOAT AS "my_number", "my_column"::FLOAT4 AS "my_number2", "my_column"::FLOAT8 AS "my_number3" FROM "my_table"'
468468
]
469469
},
470+
{
471+
title: 'over window frame',
472+
sql: [
473+
`SELECT
474+
user_id,
475+
date(derived_tstamp) AS event_date,
476+
price_point,
477+
MAX(price_point) OVER (
478+
PARTITION BY user_id
479+
ORDER BY date(derived_tstamp)
480+
RANGE BETWEEN INTERVAL '29 DAYS' PRECEDING AND INTERVAL '1 DAY' PRECEDING
481+
) AS max_price_point_last_30_days
482+
FROM
483+
some_table;`,
484+
`SELECT "user_id", date("derived_tstamp") AS "event_date", "price_point", MAX("price_point") OVER (PARTITION BY "user_id" ORDER BY date("derived_tstamp") ASC RANGE BETWEEN INTERVAL '29 DAYS' PRECEDING AND INTERVAL '1 DAY' PRECEDING) AS "max_price_point_last_30_days" FROM "some_table"`
485+
]
486+
},
470487
]
471488
SQL_LIST.forEach(sqlInfo => {
472489
const { title, sql } = sqlInfo

0 commit comments

Comments
 (0)