Skip to content

Commit cef7d9e

Browse files
committed
feat: support generator table rows in snowflake
1 parent a11d9c6 commit cef7d9e

3 files changed

Lines changed: 49 additions & 1 deletion

File tree

pegjs/snowflake.pegjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2436,6 +2436,14 @@ table_join
24362436
};
24372437
}
24382438

2439+
table_generator_option
2440+
= t:('ROWCOUNT'i / 'TIMELIMIT'i) __ '=>' __ v:literal_numeric {
2441+
return {
2442+
type: t.toLowerCase(),
2443+
symbol: '=>',
2444+
value: v
2445+
}
2446+
}
24392447

24402448
//NOTE that, the table assigned to `var` shouldn't write in `table_join`
24412449
table_base
@@ -2453,6 +2461,17 @@ table_base
24532461
...getLocationObject(),
24542462
};
24552463
}
2464+
/ KW_TABLE __ LPAREN __ 'GENERATOR'i __ LPAREN __ g:(table_generator_option)* __ RPAREN __ RPAREN __ alias:value_alias_clause? {
2465+
return {
2466+
expr: {
2467+
keyword: 'table',
2468+
type: 'generator',
2469+
generators: g,
2470+
},
2471+
as: alias,
2472+
...getLocationObject(),
2473+
};
2474+
}
24562475
/ l:('LATERAL'i)? __ LPAREN __ stmt:(union_stmt / value_clause) __ RPAREN __ alias:value_alias_clause? {
24572476
// => { prefix?: string; expr: union_stmt | value_clause; as?: alias_clause; }
24582477
if (Array.isArray(stmt)) stmt = { type: 'values', values: stmt }

src/tables.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { columnRefToSQL } from './column'
33
import { exprToSQL } from './expr'
44
import { valuesToSQL } from './insert'
55
import { intervalToSQL } from './interval'
6-
import { commonOptionConnector, hasVal, identifierToSql, literalToSQL, toUpper } from './util'
6+
import { commonOptionConnector, commonTypeValue, hasVal, identifierToSql, literalToSQL, toUpper } from './util'
77

88
function unnestToSQL(unnestExpr) {
99
const { type, as, expr, with_offset: withOffset } = unnestExpr
@@ -98,6 +98,12 @@ function temporalTableToSQL(stmt) {
9898
return [toUpper(keyword), temporalTableOptionToSQL(expr)].filter(hasVal).join(' ')
9999
}
100100

101+
function generateVirtualTable(stmt) {
102+
const { keyword, type, generators } = stmt
103+
const generatorSQL = generators.map(generator => commonTypeValue(generator).join(' ')).join(', ')
104+
return `${toUpper(keyword)}(${toUpper(type)}(${generatorSQL}))`
105+
}
106+
101107
function tableToSQL(tableInfo) {
102108
if (toUpper(tableInfo.type) === 'UNNEST') return unnestToSQL(tableInfo)
103109
const { table, db, as, expr, operator, prefix: prefixStr, schema, server, suffix, tablesample, temporal_table, table_hint } = tableInfo
@@ -119,6 +125,9 @@ function tableToSQL(tableInfo) {
119125
case 'tumble':
120126
tableName = tableTumbleToSQL(expr)
121127
break
128+
case 'generator':
129+
tableName = generateVirtualTable(expr)
130+
break
122131
default:
123132
tableName = exprToSQL(expr)
124133
}

test/snowflake.spec.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,26 @@ describe('snowflake', () => {
263263
'SELECT * FROM (((SELECT * FROM "some_table") UNION ALL (SELECT * FROM "some_table")) UNION ALL (SELECT * FROM "some_table"))'
264264
]
265265
},
266+
{
267+
title: 'generate virtual table rows',
268+
sql: [
269+
`select *, date(concat(left(date,7),'-01')) as date_start_month, left(date,7) as month from
270+
((select
271+
dateadd(day, '-' || seq4(), current_date()) as date
272+
from
273+
table(generator(rowcount => 1095))
274+
where date>='2022-10-01') as dates
275+
left join
276+
(select id, name, category, start_date, end_date, days, cost, cost/days as cost_per_day
277+
from
278+
(select id, name, category, start_date, end_date, cost, datediff('day',start_date, end_date)+1 as days
279+
from ui_other_costs
280+
group by 1,2,3,4,5,6)
281+
group by 1,2,3,4,5,6,7) as cost)
282+
where dates.date between cost.start_date and cost.end_date`,
283+
`SELECT *, date(concat(left("date", 7), '-01')) AS "date_start_month", left("date", 7) AS "month" FROM ((SELECT dateadd("day", '-' || seq4(), CURRENT_DATE()) AS "date" FROM TABLE(GENERATOR(ROWCOUNT => 1095)) WHERE "date" >= '2022-10-01') AS "dates" LEFT JOIN (SELECT "id", "name", "category", "start_date", "end_date", "days", "cost", "cost" / "days" AS "cost_per_day" FROM (SELECT "id", "name", "category", "start_date", "end_date", "cost", datediff('day', "start_date", "end_date") + 1 AS "days" FROM "ui_other_costs" GROUP BY 1, 2, 3, 4, 5, 6) GROUP BY 1, 2, 3, 4, 5, 6, 7) AS "cost") WHERE "dates"."date" BETWEEN "cost"."start_date" AND "cost"."end_date"`
284+
]
285+
}
266286
]
267287
SQL_LIST.forEach(sqlInfo => {
268288
const { title, sql } = sqlInfo

0 commit comments

Comments
 (0)