Skip to content

Commit c764e21

Browse files
authored
Merge pull request #283 from gwinchesters/fix/window-frame-exclude-clause
fix(deparser): emit EXCLUDE clause in window frame specifications
2 parents ab3eacd + d88c859 commit c764e21

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

__fixtures__/generated/generated.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,9 @@
896896
"original/upstream/window-127.sql": "SELECT a, b,\n SUM(b) OVER(ORDER BY A ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)\nFROM (VALUES(1,1::numeric),(2,2),(3,'NaN'),(4,3),(5,4)) t(a,b)",
897897
"original/upstream/window-128.sql": "SELECT to_char(SUM(n::float8) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING),'999999999999999999999D9')\n FROM (VALUES(1,1e20),(2,1)) n(i,n)",
898898
"original/upstream/window-129.sql": "SELECT i, b, bool_and(b) OVER w, bool_or(b) OVER w\n FROM (VALUES (1,true), (2,true), (3,false), (4,false), (5,true)) v(i,b)\n WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)",
899+
"original/upstream/window-130.sql": "SELECT COUNT(i) OVER (ORDER BY i RANGE BETWEEN 2 PRECEDING AND CURRENT ROW EXCLUDE CURRENT ROW)\n\tFROM (VALUES(1,1),(2,2),(3,3),(4,4)) t(i,v)",
900+
"original/upstream/window-131.sql": "SELECT COUNT(i) OVER (ORDER BY i RANGE BETWEEN 2 PRECEDING AND CURRENT ROW EXCLUDE GROUP)\n\tFROM (VALUES(1,1),(2,2),(3,3),(4,4)) t(i,v)",
901+
"original/upstream/window-132.sql": "SELECT COUNT(i) OVER (ORDER BY i RANGE BETWEEN 2 PRECEDING AND CURRENT ROW EXCLUDE TIES)\n\tFROM (VALUES(1,1),(2,2),(3,3),(4,4)) t(i,v)",
899902
"original/upstream/varchar-1.sql": "CREATE TABLE VARCHAR_TBL(f1 varchar(1))",
900903
"original/upstream/varchar-2.sql": "INSERT INTO VARCHAR_TBL (f1) VALUES ('a')",
901904
"original/upstream/varchar-3.sql": "INSERT INTO VARCHAR_TBL (f1) VALUES ('A')",

__fixtures__/kitchen-sink/original/upstream/window.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,3 +641,12 @@ SELECT to_char(SUM(n::float8) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FO
641641
SELECT i, b, bool_and(b) OVER w, bool_or(b) OVER w
642642
FROM (VALUES (1,true), (2,true), (3,false), (4,false), (5,true)) v(i,b)
643643
WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING);
644+
645+
SELECT COUNT(i) OVER (ORDER BY i RANGE BETWEEN 2 PRECEDING AND CURRENT ROW EXCLUDE CURRENT ROW)
646+
FROM (VALUES(1,1),(2,2),(3,3),(4,4)) t(i,v);
647+
648+
SELECT COUNT(i) OVER (ORDER BY i RANGE BETWEEN 2 PRECEDING AND CURRENT ROW EXCLUDE GROUP)
649+
FROM (VALUES(1,1),(2,2),(3,3),(4,4)) t(i,v);
650+
651+
SELECT COUNT(i) OVER (ORDER BY i RANGE BETWEEN 2 PRECEDING AND CURRENT ROW EXCLUDE TIES)
652+
FROM (VALUES(1,1),(2,2),(3,3),(4,4)) t(i,v);

packages/deparser/__tests__/kitchen-sink/original-upstream-window.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ it('original-upstream-window', async () => {
132132
"original/upstream/window-126.sql",
133133
"original/upstream/window-127.sql",
134134
"original/upstream/window-128.sql",
135-
"original/upstream/window-129.sql"
135+
"original/upstream/window-129.sql",
136+
"original/upstream/window-130.sql",
137+
"original/upstream/window-131.sql",
138+
"original/upstream/window-132.sql"
136139
]);
137140
});

packages/deparser/src/deparser.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3209,6 +3209,8 @@ export class Deparser implements DeparserVisitor {
32093209
if (!node.frameOptions) return null;
32103210

32113211
const frameOptions = node.frameOptions;
3212+
const EXCLUDE_MASK = 0x8000 | 0x10000 | 0x20000;
3213+
const baseFrameOptions = frameOptions & ~EXCLUDE_MASK;
32123214
const frameParts: string[] = [];
32133215

32143216
if (frameOptions & 0x01) { // FRAMEOPTION_NONDEFAULT
@@ -3226,26 +3228,26 @@ export class Deparser implements DeparserVisitor {
32263228
const boundsParts: string[] = [];
32273229

32283230
// Handle specific frameOptions values that have known mappings
3229-
if (frameOptions === 789) {
3231+
if (baseFrameOptions === 789) {
32303232
boundsParts.push('CURRENT ROW');
32313233
boundsParts.push('AND UNBOUNDED FOLLOWING');
3232-
} else if (frameOptions === 1077) {
3234+
} else if (baseFrameOptions === 1077) {
32333235
boundsParts.push('UNBOUNDED PRECEDING');
32343236
boundsParts.push('AND CURRENT ROW');
3235-
} else if (frameOptions === 18453) {
3237+
} else if (baseFrameOptions === 18453) {
32363238
if (node.startOffset && node.endOffset) {
32373239
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
32383240
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
32393241
}
3240-
} else if (frameOptions === 1557) {
3242+
} else if (baseFrameOptions === 1557) {
32413243
boundsParts.push('CURRENT ROW');
32423244
boundsParts.push('AND CURRENT ROW');
3243-
} else if (frameOptions === 16917) {
3245+
} else if (baseFrameOptions === 16917) {
32443246
boundsParts.push('CURRENT ROW');
32453247
if (node.endOffset) {
32463248
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
32473249
}
3248-
} else if (frameOptions === 1058) {
3250+
} else if (baseFrameOptions === 1058) {
32493251
return null;
32503252
} else {
32513253
// Handle start bound - prioritize explicit offset values over bit flags
@@ -3292,6 +3294,15 @@ export class Deparser implements DeparserVisitor {
32923294
frameParts.push(boundsParts.join(' '));
32933295
}
32943296

3297+
// EXCLUDE clause
3298+
if (frameOptions & 0x8000) { // FRAMEOPTION_EXCLUDE_CURRENT_ROW
3299+
frameParts.push('EXCLUDE CURRENT ROW');
3300+
} else if (frameOptions & 0x10000) { // FRAMEOPTION_EXCLUDE_GROUP
3301+
frameParts.push('EXCLUDE GROUP');
3302+
} else if (frameOptions & 0x20000) { // FRAMEOPTION_EXCLUDE_TIES
3303+
frameParts.push('EXCLUDE TIES');
3304+
}
3305+
32953306
return frameParts.join(' ');
32963307
}
32973308

0 commit comments

Comments
 (0)