Skip to content

Commit 9adf7f7

Browse files
committed
fix: truncate table with option in pg
1 parent ac574e2 commit 9adf7f7

File tree

6 files changed

+60
-7
lines changed

6 files changed

+60
-7
lines changed

pegjs/postgresql.pegjs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,28 +1335,46 @@ drop_stmt
13351335
};
13361336
}
13371337

1338+
truncate_table_name
1339+
= t:table_name __ s:STAR? {
1340+
// => table_name & { suffix?: string }
1341+
tableList.add(`truncate::${t.db}::${t.table}`)
1342+
if (s) t.suffix = s
1343+
return t
1344+
}
1345+
truncate_table_name_list
1346+
= head:truncate_table_name tail:(__ COMMA __ truncate_table_name)* {
1347+
// => truncate_table_name[]
1348+
return createList(head, tail)
1349+
}
13381350
truncate_stmt
13391351
= a:KW_TRUNCATE __
13401352
kw:KW_TABLE? __
1341-
t:table_ref_list {
1353+
on: 'ONLY'i? __
1354+
t:truncate_table_name_list __
1355+
id: (('RESTART'i / 'CONTINUE'i) __ 'IDENTITY'i)? __
1356+
op:('CASCADE'i / 'RESTRICT'i)? {
13421357
/*
13431358
export interface truncate_stmt_node {
13441359
type: 'trucate';
13451360
keyword: 'table';
1361+
prefix?: string;
13461362
name: table_ref_list;
1363+
suffix: string[];
13471364
}
13481365
=> AstStatement<truncate_stmt_node>
13491366
*/
1350-
if(t) t.forEach(tt => tableList.add(`${a}::${tt.db}::${tt.table}`));
13511367
return {
13521368
tableList: Array.from(tableList),
13531369
columnList: columnListTableAlias(columnList),
13541370
ast: {
13551371
type: a.toLowerCase(),
13561372
keyword: kw && kw.toLowerCase() || 'table',
1357-
name: t
1373+
prefix: on,
1374+
name: t,
1375+
suffix: [id && [id[0], id[2]].join(' '), op].filter(v => v).map(v => ({ type: 'origin', value: v }))
13581376
}
1359-
};
1377+
}
13601378
}
13611379

13621380
use_stmt

src/command.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function callToSQL(stmt) {
1313
}
1414

1515
function commonCmdToSQL(stmt) {
16-
const { type, keyword, name, prefix } = stmt
16+
const { type, keyword, name, prefix, suffix } = stmt
1717
const clauses = [toUpper(type), toUpper(keyword), toUpper(prefix)]
1818
switch (keyword) {
1919
case 'table':
@@ -36,6 +36,7 @@ function commonCmdToSQL(stmt) {
3636
default:
3737
break
3838
}
39+
if (suffix) clauses.push(suffix.map(exprToSQL).filter(hasVal).join(' '))
3940
return clauses.filter(hasVal).join(' ')
4041
}
4142

src/tables.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function tableTumbleToSQL(tumble) {
7474

7575
function tableToSQL(tableInfo) {
7676
if (toUpper(tableInfo.type) === 'UNNEST') return unnestToSQL(tableInfo)
77-
const { table, db, as, expr, operator, prefix: prefixStr, schema, server, tablesample, table_hint } = tableInfo
77+
const { table, db, as, expr, operator, prefix: prefixStr, schema, server, suffix, tablesample, table_hint } = tableInfo
7878
const serverName = identifierToSql(server)
7979
const database = identifierToSql(db)
8080
const schemaStr = identifierToSql(schema)
@@ -97,7 +97,7 @@ function tableToSQL(tableInfo) {
9797
tableName = exprToSQL(expr)
9898
}
9999
}
100-
tableName = [toUpper(prefixStr), tableName].filter(hasVal).join(' ')
100+
tableName = [toUpper(prefixStr), tableName, toUpper(suffix)].filter(hasVal).join(' ')
101101
let str = [serverName, database, schemaStr, tableName].filter(hasVal).join('.')
102102
if (tableInfo.parentheses) str = `(${str})`
103103
const result = [str]

test/postgres.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,20 @@ describe('Postgres', () => {
14221422
'SELECT * FROM "schema"."func"("start_time", "end_time")'
14231423
]
14241424
},
1425+
{
1426+
title: 'truncate table',
1427+
sql: [
1428+
'TRUNCATE TABLE employee RESTART IDENTITY cascade',
1429+
'TRUNCATE TABLE "employee" RESTART IDENTITY CASCADE'
1430+
]
1431+
},
1432+
{
1433+
title: 'truncate all table',
1434+
sql: [
1435+
'TRUNCATE TABLE ONLY employee * CONTINUE IDENTITY RESTRICT',
1436+
'TRUNCATE TABLE ONLY "employee" * CONTINUE IDENTITY RESTRICT'
1437+
]
1438+
},
14251439
]
14261440
function neatlyNestTestedSQL(sqlList){
14271441
sqlList.forEach(sqlInfo => {

test/redshift.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ describe('redshift', () => {
1515
Last_VALUE(hermes_health_score IGNORE NULLS) OVER ( partition by sf_account_id, month_id ) as hermes_health_score_monthly, row_number() OVER ( PARTITION BY sf_account_id, date_trunc('week', date_)
1616
ORDER BY date_ desc ) AS o_key_week FROM dwh.dwh_health_score_hermes WHERE date_trunc('month', date_) >= '2023-01-01' Qualify o_key_week = 1`
1717
expect(getParsedSql(sql)).to.be.equal(`SELECT sf_account_id, date_trunc('week', date_) AS "week_id", date_trunc('month', date_) AS "month_id", Last_VALUE(hermes_health_score IGNORE NULLS) OVER (PARTITION BY sf_account_id, week_id) AS "hermes_health_score", Last_VALUE(hermes_health_score IGNORE NULLS) OVER (PARTITION BY sf_account_id, month_id) AS "hermes_health_score_monthly", row_number() OVER (PARTITION BY sf_account_id, date_trunc('week', date_) ORDER BY date_ DESC) AS "o_key_week" FROM "dwh"."dwh_health_score_hermes" WHERE date_trunc('month', date_) >= '2023-01-01' QUALIFY o_key_week = 1`)
18+
sql = `with pv as (
19+
select
20+
action_date,
21+
visitor_id_v,
22+
visit_country_name,
23+
referer_channel_group,
24+
email,
25+
sgid,
26+
mp."brand/non-brand" as is_brand
27+
from
28+
dwh_fact_pageviews pv
29+
left join ppc_keywords_mapping mp using (campaign_keyword)
30+
)
31+
select is_brand as "b/nb" from pv where mp."brand/non-brand" = 'brand'`
32+
expect(getParsedSql(sql)).to.be.equal(`WITH "pv" AS (SELECT action_date, visitor_id_v, visit_country_name, referer_channel_group, email, sgid, "mp"."brand/non-brand" AS "is_brand" FROM "dwh_fact_pageviews" AS "pv" LEFT JOIN "ppc_keywords_mapping" AS "mp" USING ("campaign_keyword")) SELECT is_brand AS "b/nb" FROM "pv" WHERE "mp"."brand/non-brand" = 'brand'`)
1833
})
1934

2035
})

test/transactsql.spec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ describe('transactsql', () => {
150150
expect(getParsedSql(sql)).to.equal('SELECT [source].[dbo].[movie].[id] FROM [source].[dbo].[movie]')
151151
sql = 'SELECT * FROM source.dbo.movie WHERE source.dbo.movie.genre_id = 1'
152152
expect(getParsedSql(sql)).to.equal('SELECT * FROM [source].[dbo].[movie] WHERE [source].[dbo].[movie].[genre_id] = 1')
153+
sql = 'SELECT TOP 1000 [production].[categories].[category_name], COUNT([production].[products].[product_id]) AS [product_count]\n' +
154+
'FROM [production].[products]\n' +
155+
'INNER JOIN [production].[categories] ON [production].[products].[category_id] = [production].[categories].[category_id]\n' +
156+
'GROUP BY [production].[categories].[category_name]'
157+
expect(getParsedSql(sql)).to.be.equal("SELECT TOP 1000 [production].[categories].[category_name], COUNT([production].[products].[product_id]) AS [product_count] FROM [production].[products] INNER JOIN [production].[categories] ON [production].[products].[category_id] = [production].[categories].[category_id] GROUP BY [production].[categories].[category_name]")
153158
})
154159

155160
it('should support with clause', () => {

0 commit comments

Comments
 (0)