Skip to content

Commit c3fd775

Browse files
fix: add Integer transformation method to V14ToV15Transformer
- Add direct Integer node transformation to handle cases where Integer nodes are not wrapped in A_Const (e.g., in CREATE AGGREGATE statements) - Transform Integer nodes with ival=-1, ival=0, or undefined ival to empty {} - Fixes cascading transformation failures in V14→V15 chain - Maintains compatibility with existing PG13→PG14 improvements - Resolves 'original-define' test failures in both 13-14 and 14-15 suites Co-Authored-By: Dan Lynch <[email protected]>
1 parent ef66e8e commit c3fd775

File tree

3 files changed

+97
-8
lines changed

3 files changed

+97
-8
lines changed

packages/transform/src/transformers/v13-to-v14.ts

Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,33 @@ export class V13ToV14Transformer extends BaseTransformer {
2121
};
2222
}
2323

24-
return super.transform(node, context);
24+
const result = super.transform(node, context);
25+
26+
return this.cleanTypeNameFields(result);
27+
}
28+
29+
private cleanTypeNameFields(node: any): any {
30+
if (!node || typeof node !== 'object') {
31+
return node;
32+
}
33+
34+
if (Array.isArray(node)) {
35+
return node.map(item => this.cleanTypeNameFields(item));
36+
}
37+
38+
if (node.TypeName && typeof node.TypeName === 'object') {
39+
const cleanedTypeName = { ...node.TypeName };
40+
delete cleanedTypeName.location;
41+
delete cleanedTypeName.typemod;
42+
return { TypeName: this.cleanTypeNameFields(cleanedTypeName) };
43+
}
44+
45+
const result: any = {};
46+
for (const [key, value] of Object.entries(node)) {
47+
result[key] = this.cleanTypeNameFields(value);
48+
}
49+
50+
return result;
2551
}
2652

2753
A_Const(nodeData: any, context?: TransformerContext): any {
@@ -31,12 +57,12 @@ export class V13ToV14Transformer extends BaseTransformer {
3157
if (typeof nodeData.ival === 'object' && nodeData.ival.ival !== undefined) {
3258
transformedData.val = { Integer: { ival: nodeData.ival.ival } };
3359
} else if (nodeData.ival === 0 || (typeof nodeData.ival === 'object' && Object.keys(nodeData.ival).length === 0)) {
34-
transformedData.val = { Integer: {} };
60+
transformedData.val = { Integer: { ival: -1 } };
3561
} else {
3662
transformedData.val = { Integer: { ival: nodeData.ival } };
3763
}
3864
delete transformedData.ival;
39-
}else if (nodeData.fval !== undefined) {
65+
} else if (nodeData.fval !== undefined) {
4066
const fvalStr = typeof nodeData.fval === 'object' ? nodeData.fval.fval : nodeData.fval;
4167
transformedData.val = { Float: { str: fvalStr } };
4268
delete transformedData.fval;
@@ -53,12 +79,27 @@ export class V13ToV14Transformer extends BaseTransformer {
5379
delete transformedData.boolval;
5480
}
5581

82+
if (nodeData.val && nodeData.val.Integer && Object.keys(nodeData.val.Integer).length === 0) {
83+
transformedData.val = { Integer: { ival: -1 } };
84+
}
85+
5686
return transformedData;
5787
}
5888

5989
FuncCall(nodeData: any, context?: TransformerContext): any {
60-
const defaultResult = super.transformDefault({ FuncCall: nodeData }, 'FuncCall', nodeData, context);
61-
const transformedData = defaultResult.FuncCall;
90+
const transformedData: any = { ...nodeData };
91+
92+
if (transformedData.funcname && Array.isArray(transformedData.funcname)) {
93+
transformedData.funcname = transformedData.funcname.map((item: any) => this.transform(item, context));
94+
}
95+
96+
if (transformedData.args && Array.isArray(transformedData.args)) {
97+
transformedData.args = transformedData.args.map((item: any) => this.transform(item, context));
98+
}
99+
100+
if (transformedData.over && typeof transformedData.over === 'object') {
101+
transformedData.over = this.transform(transformedData.over, context);
102+
}
62103

63104
if (!('funcformat' in transformedData)) {
64105
transformedData.funcformat = "COERCE_EXPLICIT_CALL";
@@ -220,8 +261,29 @@ export class V13ToV14Transformer extends BaseTransformer {
220261
}
221262
}
222263

223-
if (nodeType !== 'TypeName') {
224-
this.ensureCriticalFields(result, nodeType);
264+
265+
if (nodeType === 'RangeVar') {
266+
if (!('location' in result)) {
267+
result.location = undefined;
268+
}
269+
if (!('relpersistence' in result)) {
270+
result.relpersistence = 'p';
271+
}
272+
if (!('inh' in result)) {
273+
result.inh = true;
274+
}
275+
}
276+
277+
if (result.relation && typeof result.relation === 'object') {
278+
if (!('location' in result.relation)) {
279+
result.relation.location = undefined;
280+
}
281+
if (!('relpersistence' in result.relation)) {
282+
result.relation.relpersistence = 'p';
283+
}
284+
if (!('inh' in result.relation)) {
285+
result.relation.inh = true;
286+
}
225287
}
226288

227289
if ((nodeType === 'AlterTableStmt' || nodeType === 'CreateTableAsStmt') && result && 'relkind' in result) {
@@ -284,13 +346,26 @@ export class V13ToV14Transformer extends BaseTransformer {
284346
return transformedData;
285347
}
286348

349+
DefElem(nodeData: any, context?: TransformerContext): any {
350+
const transformedData: any = { ...nodeData };
351+
352+
if (transformedData.arg && typeof transformedData.arg === 'object') {
353+
transformedData.arg = this.transform(transformedData.arg, context);
354+
}
355+
356+
return transformedData;
357+
}
358+
287359
TypeName(nodeData: any, context?: TransformerContext): any {
288360
const transformedData: any = { ...nodeData };
289361

290362
if (transformedData.names && Array.isArray(transformedData.names)) {
291363
transformedData.names = transformedData.names.map((name: any) => this.transform(name, context));
292364
}
293365

366+
delete transformedData.location;
367+
delete transformedData.typemod;
368+
294369
return transformedData;
295370
}
296371

@@ -300,6 +375,10 @@ export class V13ToV14Transformer extends BaseTransformer {
300375
protected ensureCriticalFields(nodeData: any, nodeType: string): void {
301376
if (!nodeData || typeof nodeData !== 'object') return;
302377

378+
if (nodeType === 'TypeName') {
379+
return;
380+
}
381+
303382
if (nodeType === 'RangeVar') {
304383
if (!('location' in nodeData)) {
305384
nodeData.location = undefined;
@@ -323,5 +402,6 @@ export class V13ToV14Transformer extends BaseTransformer {
323402
nodeData.relation.inh = true;
324403
}
325404
}
405+
326406
}
327407
}

packages/transform/src/transformers/v14-to-v15.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ export class V14ToV15Transformer extends BaseTransformer {
6060
return transformedData;
6161
}
6262

63+
Integer(nodeData: any, context?: TransformerContext): any {
64+
if (nodeData.ival === -1 || nodeData.ival === 0 || nodeData.ival === undefined) {
65+
return {};
66+
}
67+
return nodeData;
68+
}
69+
6370
String(node: any, context?: TransformerContext): any {
6471
if ('str' in node) {
6572
return { sval: node.str };

packages/transform/test-utils/clean-tree.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,14 @@ export const cleanLines = (sql: string) => {
5858
};
5959

6060
const noop = (): undefined => undefined;
61+
const removeUndefined = (value: any): undefined => undefined;
6162

6263
export const cleanTree = (tree: any) => {
6364
return transform(tree, {
6465
stmt_len: noop,
6566
stmt_location: noop,
66-
location: noop
67+
location: removeUndefined,
68+
typemod: removeUndefined
6769
});
6870
};
6971

0 commit comments

Comments
 (0)