@@ -559,14 +559,14 @@ export class Deparser implements DeparserVisitor {
559559 switch ( kind ) {
560560 case 'AEXPR_OP' :
561561 if ( lexpr && rexpr ) {
562- const operator = this . deparseOperatorName ( name ) ;
562+ const operator = this . deparseOperatorName ( name , context ) ;
563563 let leftExpr = this . visit ( lexpr , context ) ;
564564 let rightExpr = this . visit ( rexpr , context ) ;
565565
566566 // Check if left expression needs parentheses
567567 let leftNeedsParens = false ;
568568 if ( lexpr && 'A_Expr' in lexpr && lexpr . A_Expr ?. kind === 'AEXPR_OP' ) {
569- const leftOp = this . deparseOperatorName ( ListUtils . unwrapList ( lexpr . A_Expr . name ) ) ;
569+ const leftOp = this . deparseOperatorName ( ListUtils . unwrapList ( lexpr . A_Expr . name ) , context ) ;
570570 if ( this . needsParentheses ( leftOp , operator , 'left' ) ) {
571571 leftNeedsParens = true ;
572572 }
@@ -581,7 +581,7 @@ export class Deparser implements DeparserVisitor {
581581 // Check if right expression needs parentheses
582582 let rightNeedsParens = false ;
583583 if ( rexpr && 'A_Expr' in rexpr && rexpr . A_Expr ?. kind === 'AEXPR_OP' ) {
584- const rightOp = this . deparseOperatorName ( ListUtils . unwrapList ( rexpr . A_Expr . name ) ) ;
584+ const rightOp = this . deparseOperatorName ( ListUtils . unwrapList ( rexpr . A_Expr . name ) , context ) ;
585585 if ( this . needsParentheses ( rightOp , operator , 'right' ) ) {
586586 rightNeedsParens = true ;
587587 }
@@ -596,22 +596,22 @@ export class Deparser implements DeparserVisitor {
596596 return this . formatter . format ( [ leftExpr , operator , rightExpr ] ) ;
597597 } else if ( rexpr ) {
598598 return this . formatter . format ( [
599- this . deparseOperatorName ( name ) ,
599+ this . deparseOperatorName ( name , context ) ,
600600 this . visit ( rexpr , context )
601601 ] ) ;
602602 }
603603 break ;
604604 case 'AEXPR_OP_ANY' :
605605 return this . formatter . format ( [
606606 this . visit ( lexpr , context ) ,
607- this . deparseOperatorName ( name ) ,
607+ this . deparseOperatorName ( name , context ) ,
608608 'ANY' ,
609609 this . formatter . parens ( this . visit ( rexpr , context ) )
610610 ] ) ;
611611 case 'AEXPR_OP_ALL' :
612612 return this . formatter . format ( [
613613 this . visit ( lexpr , context ) ,
614- this . deparseOperatorName ( name ) ,
614+ this . deparseOperatorName ( name , context ) ,
615615 'ALL' ,
616616 this . formatter . parens ( this . visit ( rexpr , context ) )
617617 ] ) ;
@@ -660,7 +660,7 @@ export class Deparser implements DeparserVisitor {
660660 ] . join ( ', ' ) )
661661 ] ) ;
662662 case 'AEXPR_IN' :
663- const inOperator = this . deparseOperatorName ( name ) ;
663+ const inOperator = this . deparseOperatorName ( name , context ) ;
664664 if ( inOperator === '<>' || inOperator === '!=' ) {
665665 return this . formatter . format ( [
666666 this . visit ( lexpr , context ) ,
@@ -675,7 +675,7 @@ export class Deparser implements DeparserVisitor {
675675 ] ) ;
676676 }
677677 case 'AEXPR_LIKE' :
678- const likeOp = this . deparseOperatorName ( name ) ;
678+ const likeOp = this . deparseOperatorName ( name , context ) ;
679679 if ( likeOp === '!~~' ) {
680680 return this . formatter . format ( [
681681 this . visit ( lexpr , context ) ,
@@ -690,7 +690,7 @@ export class Deparser implements DeparserVisitor {
690690 ] ) ;
691691 }
692692 case 'AEXPR_ILIKE' :
693- const ilikeOp = this . deparseOperatorName ( name ) ;
693+ const ilikeOp = this . deparseOperatorName ( name , context ) ;
694694 if ( ilikeOp === '!~~*' ) {
695695 return this . formatter . format ( [
696696 this . visit ( lexpr , context ) ,
@@ -705,7 +705,7 @@ export class Deparser implements DeparserVisitor {
705705 ] ) ;
706706 }
707707 case 'AEXPR_SIMILAR' :
708- const similarOp = this . deparseOperatorName ( name ) ;
708+ const similarOp = this . deparseOperatorName ( name , context ) ;
709709 let rightExpr : string ;
710710
711711 if ( rexpr && 'FuncCall' in rexpr &&
@@ -763,7 +763,7 @@ export class Deparser implements DeparserVisitor {
763763 throw new Error ( `Unhandled A_Expr kind: ${ kind } ` ) ;
764764 }
765765
766- deparseOperatorName ( name : t . Node [ ] ) : string {
766+ deparseOperatorName ( name : t . Node [ ] , context : DeparserContext ) : string {
767767 if ( ! name || name . length === 0 ) {
768768 return '' ;
769769 }
@@ -772,7 +772,7 @@ export class Deparser implements DeparserVisitor {
772772 if ( n . String ) {
773773 return n . String . sval || n . String . str ;
774774 }
775- return this . visit ( n , new DeparserContext ( { } ) ) ;
775+ return this . visit ( n , context ) ;
776776 } ) ;
777777
778778 if ( parts . length > 1 ) {
@@ -1420,7 +1420,7 @@ export class Deparser implements DeparserVisitor {
14201420
14211421 // Add parentheses around timestamp if it contains arithmetic operations
14221422 if ( args [ 1 ] && 'A_Expr' in args [ 1 ] && args [ 1 ] . A_Expr ?. kind === 'AEXPR_OP' ) {
1423- const op = this . deparseOperatorName ( ListUtils . unwrapList ( args [ 1 ] . A_Expr . name ) ) ;
1423+ const op = this . deparseOperatorName ( ListUtils . unwrapList ( args [ 1 ] . A_Expr . name ) , context ) ;
14241424 if ( op === '+' || op === '-' || op === '*' || op === '/' ) {
14251425 timestamp = this . formatter . parens ( timestamp ) ;
14261426 }
@@ -1497,7 +1497,7 @@ export class Deparser implements DeparserVisitor {
14971497 }
14981498
14991499 // Handle window frame specifications using the dedicated formatWindowFrame method
1500- const frameClause = this . formatWindowFrame ( node . over ) ;
1500+ const frameClause = this . formatWindowFrame ( node . over , context . spawn ( 'FuncCall' ) ) ;
15011501 if ( frameClause ) {
15021502 windowParts . push ( frameClause ) ;
15031503 }
@@ -2969,7 +2969,7 @@ export class Deparser implements DeparserVisitor {
29692969 case 'ANY_SUBLINK' :
29702970 if ( node . testexpr && node . operName ) {
29712971 const testExpr = this . visit ( node . testexpr , context ) ;
2972- const operator = this . deparseOperatorName ( node . operName ) ;
2972+ const operator = this . deparseOperatorName ( node . operName , context ) ;
29732973 return `${ testExpr } ${ operator } ANY ${ subselect } ` ;
29742974 } else if ( node . testexpr ) {
29752975 const testExpr = this . visit ( node . testexpr , context ) ;
@@ -2979,7 +2979,7 @@ export class Deparser implements DeparserVisitor {
29792979 case 'ALL_SUBLINK' :
29802980 if ( node . testexpr && node . operName ) {
29812981 const testExpr = this . visit ( node . testexpr , context ) ;
2982- const operator = this . deparseOperatorName ( node . operName ) ;
2982+ const operator = this . deparseOperatorName ( node . operName , context ) ;
29832983 return `${ testExpr } ${ operator } ALL ${ subselect } ` ;
29842984 }
29852985 return subselect ;
@@ -3032,7 +3032,7 @@ export class Deparser implements DeparserVisitor {
30323032
30333033 // Only add frame clause if frameOptions indicates non-default framing
30343034 if ( node . frameOptions && node . frameOptions !== 1058 ) {
3035- const frameClause = this . formatWindowFrame ( node ) ;
3035+ const frameClause = this . formatWindowFrame ( node , context . spawn ( 'WindowDef' ) ) ;
30363036 if ( frameClause ) {
30373037 windowParts . push ( frameClause ) ;
30383038 }
@@ -3053,7 +3053,7 @@ export class Deparser implements DeparserVisitor {
30533053 return output . join ( ' ' ) ;
30543054 }
30553055
3056- formatWindowFrame ( node : any ) : string | null {
3056+ formatWindowFrame ( node : any , context : DeparserContext ) : string | null {
30573057 if ( ! node . frameOptions ) return null ;
30583058
30593059 const frameOptions = node . frameOptions ;
@@ -3082,28 +3082,28 @@ export class Deparser implements DeparserVisitor {
30823082 boundsParts . push ( 'AND CURRENT ROW' ) ;
30833083 } else if ( frameOptions === 18453 ) {
30843084 if ( node . startOffset && node . endOffset ) {
3085- boundsParts . push ( `${ this . visit ( node . startOffset , new DeparserContext ( { } ) ) } PRECEDING` ) ;
3086- boundsParts . push ( `AND ${ this . visit ( node . endOffset , new DeparserContext ( { } ) ) } FOLLOWING` ) ;
3085+ boundsParts . push ( `${ this . visit ( node . startOffset , context ) } PRECEDING` ) ;
3086+ boundsParts . push ( `AND ${ this . visit ( node . endOffset , context ) } FOLLOWING` ) ;
30873087 }
30883088 } else if ( frameOptions === 1557 ) {
30893089 boundsParts . push ( 'CURRENT ROW' ) ;
30903090 boundsParts . push ( 'AND CURRENT ROW' ) ;
30913091 } else if ( frameOptions === 16917 ) {
30923092 boundsParts . push ( 'CURRENT ROW' ) ;
30933093 if ( node . endOffset ) {
3094- boundsParts . push ( `AND ${ this . visit ( node . endOffset , new DeparserContext ( { } ) ) } FOLLOWING` ) ;
3094+ boundsParts . push ( `AND ${ this . visit ( node . endOffset , context ) } FOLLOWING` ) ;
30953095 }
30963096 } else if ( frameOptions === 1058 ) {
30973097 return null ;
30983098 } else {
30993099 // Handle start bound - prioritize explicit offset values over bit flags
31003100 if ( node . startOffset ) {
31013101 if ( frameOptions & 0x400 ) { // FRAMEOPTION_START_VALUE_PRECEDING
3102- boundsParts . push ( `${ this . visit ( node . startOffset , new DeparserContext ( { } ) ) } PRECEDING` ) ;
3102+ boundsParts . push ( `${ this . visit ( node . startOffset , context ) } PRECEDING` ) ;
31033103 } else if ( frameOptions & 0x800 ) { // FRAMEOPTION_START_VALUE_FOLLOWING
3104- boundsParts . push ( `${ this . visit ( node . startOffset , new DeparserContext ( { } ) ) } FOLLOWING` ) ;
3104+ boundsParts . push ( `${ this . visit ( node . startOffset , context ) } FOLLOWING` ) ;
31053105 } else {
3106- boundsParts . push ( `${ this . visit ( node . startOffset , new DeparserContext ( { } ) ) } PRECEDING` ) ;
3106+ boundsParts . push ( `${ this . visit ( node . startOffset , context ) } PRECEDING` ) ;
31073107 }
31083108 } else if ( frameOptions & 0x10 ) { // FRAMEOPTION_START_UNBOUNDED_PRECEDING
31093109 boundsParts . push ( 'UNBOUNDED PRECEDING' ) ;
@@ -3115,11 +3115,11 @@ export class Deparser implements DeparserVisitor {
31153115 if ( node . endOffset ) {
31163116 if ( boundsParts . length > 0 ) {
31173117 if ( frameOptions & 0x1000 ) { // FRAMEOPTION_END_VALUE_PRECEDING
3118- boundsParts . push ( `AND ${ this . visit ( node . endOffset , new DeparserContext ( { } ) ) } PRECEDING` ) ;
3118+ boundsParts . push ( `AND ${ this . visit ( node . endOffset , context ) } PRECEDING` ) ;
31193119 } else if ( frameOptions & 0x2000 ) { // FRAMEOPTION_END_VALUE_FOLLOWING
3120- boundsParts . push ( `AND ${ this . visit ( node . endOffset , new DeparserContext ( { } ) ) } FOLLOWING` ) ;
3120+ boundsParts . push ( `AND ${ this . visit ( node . endOffset , context ) } FOLLOWING` ) ;
31213121 } else {
3122- boundsParts . push ( `AND ${ this . visit ( node . endOffset , new DeparserContext ( { } ) ) } FOLLOWING` ) ;
3122+ boundsParts . push ( `AND ${ this . visit ( node . endOffset , context ) } FOLLOWING` ) ;
31233123 }
31243124 }
31253125 } else if ( frameOptions & 0x80 ) { // FRAMEOPTION_END_UNBOUNDED_FOLLOWING
0 commit comments